The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/pseries/phyp_llan.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright 2013 Nathan Whitehorn
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/sockio.h>
   35 #include <sys/endian.h>
   36 #include <sys/lock.h>
   37 #include <sys/mbuf.h>
   38 #include <sys/module.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mutex.h>
   41 #include <sys/kernel.h>
   42 #include <sys/socket.h>
   43 
   44 #include <net/bpf.h>
   45 #include <net/if.h>
   46 #include <net/if_var.h>
   47 #include <net/ethernet.h>
   48 #include <net/if_dl.h>
   49 #include <net/if_media.h>
   50 #include <net/if_types.h>
   51 
   52 #include <dev/ofw/openfirm.h>
   53 #include <dev/ofw/ofw_bus.h>
   54 #include <dev/ofw/ofw_bus_subr.h>
   55 #include <machine/bus.h>
   56 #include <machine/resource.h>
   57 #include <sys/bus.h>
   58 #include <sys/rman.h>
   59 
   60 #include <powerpc/pseries/phyp-hvcall.h>
   61 
   62 #define LLAN_MAX_RX_PACKETS     100
   63 #define LLAN_MAX_TX_PACKETS     100
   64 #define LLAN_RX_BUF_LEN         8*PAGE_SIZE
   65 
   66 #define LLAN_BUFDESC_VALID      (1ULL << 63)
   67 #define LLAN_ADD_MULTICAST      0x1
   68 #define LLAN_DEL_MULTICAST      0x2
   69 #define LLAN_CLEAR_MULTICAST    0x3
   70 
   71 struct llan_xfer {
   72         struct mbuf *rx_mbuf;
   73         bus_dmamap_t rx_dmamap;
   74         uint64_t rx_bufdesc;
   75 };
   76 
   77 struct llan_receive_queue_entry { /* PAPR page 539 */
   78         uint8_t control;
   79         uint8_t reserved;
   80         uint16_t offset;
   81         uint32_t length;
   82         uint64_t handle;
   83 } __packed;
   84 
   85 struct llan_softc {
   86         device_t        dev;
   87         struct mtx      io_lock;
   88 
   89         cell_t          unit;
   90         uint8_t         mac_address[8];
   91 
   92         struct ifmedia  media;
   93 
   94         int             irqid;
   95         struct resource *irq;
   96         void            *irq_cookie;
   97 
   98         bus_dma_tag_t   rx_dma_tag;
   99         bus_dma_tag_t   rxbuf_dma_tag;
  100         bus_dma_tag_t   tx_dma_tag;
  101 
  102         bus_dmamap_t    tx_dma_map;
  103 
  104         struct llan_receive_queue_entry *rx_buf;
  105         int             rx_dma_slot;
  106         int             rx_valid_val;
  107         bus_dmamap_t    rx_buf_map;
  108         bus_addr_t      rx_buf_phys;
  109         bus_size_t      rx_buf_len;
  110         bus_addr_t      input_buf_phys;
  111         bus_addr_t      filter_buf_phys;
  112         struct llan_xfer rx_xfer[LLAN_MAX_RX_PACKETS];
  113 
  114         struct ifnet    *ifp;
  115 };
  116 
  117 static int      llan_probe(device_t);
  118 static int      llan_attach(device_t);
  119 static void     llan_intr(void *xsc);
  120 static void     llan_init(void *xsc);
  121 static void     llan_start(struct ifnet *ifp);
  122 static int      llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
  123 static void     llan_media_status(struct ifnet *ifp, struct ifmediareq *ifmr);
  124 static int      llan_media_change(struct ifnet *ifp);
  125 static void     llan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs,
  126                     int err);
  127 static int      llan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx);
  128 static int      llan_set_multicast(struct llan_softc *sc);
  129 
  130 static device_method_t  llan_methods[] = {
  131         DEVMETHOD(device_probe,         llan_probe),
  132         DEVMETHOD(device_attach,        llan_attach),
  133         
  134         DEVMETHOD_END
  135 };
  136 
  137 static driver_t llan_driver = {
  138         "llan",
  139         llan_methods,
  140         sizeof(struct llan_softc)
  141 };
  142 
  143 DRIVER_MODULE(llan, vdevice, llan_driver, 0, 0);
  144 
  145 static int
  146 llan_probe(device_t dev)
  147 {
  148         if (!ofw_bus_is_compatible(dev,"IBM,l-lan"))
  149                 return (ENXIO);
  150 
  151         device_set_desc(dev, "POWER Hypervisor Virtual Ethernet");
  152         return (0);
  153 }
  154 
  155 static int
  156 llan_attach(device_t dev)
  157 {
  158         struct llan_softc *sc;
  159         phandle_t node;
  160         int i;
  161         ssize_t len;
  162 
  163         sc = device_get_softc(dev);
  164         sc->dev = dev;
  165 
  166         /* Get firmware properties */
  167         node = ofw_bus_get_node(dev);
  168         len = OF_getprop(node, "local-mac-address", sc->mac_address,
  169             sizeof(sc->mac_address));
  170         /* If local-mac-address property has only 6 bytes (ETHER_ADDR_LEN)
  171          * instead of 8 (sizeof(sc->mac_address)), then its value must be
  172          * shifted 2 bytes to the right. */
  173         if (len == ETHER_ADDR_LEN) {
  174                 bcopy(sc->mac_address, &sc->mac_address[2], len);
  175                 /* Zero out the first 2 bytes. */
  176                 bzero(sc->mac_address, 2);
  177         }
  178         OF_getencprop(node, "reg", &sc->unit, sizeof(sc->unit));
  179 
  180         mtx_init(&sc->io_lock, "llan", NULL, MTX_DEF);
  181 
  182         /* Setup interrupt */
  183         sc->irqid = 0;
  184         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
  185             RF_ACTIVE);
  186 
  187         if (!sc->irq) {
  188                 device_printf(dev, "Could not allocate IRQ\n");
  189                 mtx_destroy(&sc->io_lock);
  190                 return (ENXIO);
  191         }
  192 
  193         bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE |
  194             INTR_ENTROPY, NULL, llan_intr, sc, &sc->irq_cookie);
  195 
  196         /* Setup DMA */
  197         bus_dma_tag_create(bus_get_dma_tag(dev), 16, 0,
  198             BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
  199             LLAN_RX_BUF_LEN, 1, BUS_SPACE_MAXSIZE_32BIT,
  200             0, NULL, NULL, &sc->rx_dma_tag);
  201         bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0,
  202             BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
  203             BUS_SPACE_MAXSIZE, 1, BUS_SPACE_MAXSIZE_32BIT,
  204             0, NULL, NULL, &sc->rxbuf_dma_tag);
  205         bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
  206             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
  207             BUS_SPACE_MAXSIZE, 6, BUS_SPACE_MAXSIZE_32BIT, 0,
  208             busdma_lock_mutex, &sc->io_lock, &sc->tx_dma_tag);
  209 
  210         bus_dmamem_alloc(sc->rx_dma_tag, (void **)&sc->rx_buf,
  211             BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rx_buf_map);
  212         bus_dmamap_load(sc->rx_dma_tag, sc->rx_buf_map, sc->rx_buf,
  213             LLAN_RX_BUF_LEN, llan_rx_load_cb, sc, 0);
  214 
  215         /* TX DMA maps */
  216         bus_dmamap_create(sc->tx_dma_tag, 0, &sc->tx_dma_map);
  217 
  218         /* RX DMA */
  219         for (i = 0; i < LLAN_MAX_RX_PACKETS; i++) {
  220                 bus_dmamap_create(sc->rxbuf_dma_tag, 0,
  221                     &sc->rx_xfer[i].rx_dmamap);
  222                 sc->rx_xfer[i].rx_mbuf = NULL;
  223         }
  224 
  225         /* Attach to network stack */
  226         sc->ifp = if_alloc(IFT_ETHER);
  227         sc->ifp->if_softc = sc;
  228 
  229         if_initname(sc->ifp, device_get_name(dev), device_get_unit(dev));
  230         sc->ifp->if_mtu = ETHERMTU; /* XXX max-frame-size from OF? */
  231         sc->ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  232         sc->ifp->if_hwassist = 0; /* XXX: ibm,illan-options */
  233         sc->ifp->if_capabilities = 0;
  234         sc->ifp->if_capenable = 0;
  235         sc->ifp->if_start = llan_start;
  236         sc->ifp->if_ioctl = llan_ioctl;
  237         sc->ifp->if_init = llan_init;
  238 
  239         ifmedia_init(&sc->media, IFM_IMASK, llan_media_change,
  240             llan_media_status);
  241         ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
  242         ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
  243 
  244         IFQ_SET_MAXLEN(&sc->ifp->if_snd, LLAN_MAX_TX_PACKETS);
  245         sc->ifp->if_snd.ifq_drv_maxlen = LLAN_MAX_TX_PACKETS;
  246         IFQ_SET_READY(&sc->ifp->if_snd);
  247 
  248         ether_ifattach(sc->ifp, &sc->mac_address[2]);
  249 
  250         /* We don't have link state reporting, so make it always up */
  251         if_link_state_change(sc->ifp, LINK_STATE_UP);
  252 
  253         return (0);
  254 }
  255 
  256 static int
  257 llan_media_change(struct ifnet *ifp)
  258 {
  259         struct llan_softc *sc = ifp->if_softc;
  260 
  261         if (IFM_TYPE(sc->media.ifm_media) != IFM_ETHER)
  262                 return (EINVAL);
  263 
  264         if (IFM_SUBTYPE(sc->media.ifm_media) != IFM_AUTO)
  265                 return (EINVAL);
  266 
  267         return (0);
  268 }
  269 
  270 static void
  271 llan_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
  272 {
  273 
  274         ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE | IFM_UNKNOWN | IFM_FDX;
  275         ifmr->ifm_active = IFM_ETHER;
  276 }
  277 
  278 static void
  279 llan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int err)
  280 {
  281         struct llan_softc *sc = xsc;
  282 
  283         sc->rx_buf_phys = segs[0].ds_addr;
  284         sc->rx_buf_len = segs[0].ds_len - 2*PAGE_SIZE;
  285         sc->input_buf_phys = segs[0].ds_addr + segs[0].ds_len - PAGE_SIZE;
  286         sc->filter_buf_phys = segs[0].ds_addr + segs[0].ds_len - 2*PAGE_SIZE;
  287 }
  288 
  289 static void
  290 llan_init(void *xsc)
  291 {
  292         struct llan_softc *sc = xsc;
  293         uint64_t rx_buf_desc;
  294         uint64_t macaddr;
  295         int i;
  296 
  297         mtx_lock(&sc->io_lock);
  298 
  299         phyp_hcall(H_FREE_LOGICAL_LAN, sc->unit);
  300 
  301         /* Create buffers (page 539) */
  302         sc->rx_dma_slot = 0;
  303         sc->rx_valid_val = 1;
  304 
  305         rx_buf_desc = LLAN_BUFDESC_VALID;
  306         rx_buf_desc |= (sc->rx_buf_len << 32);
  307         rx_buf_desc |= sc->rx_buf_phys;
  308         memcpy(&macaddr, sc->mac_address, 8);
  309         phyp_hcall(H_REGISTER_LOGICAL_LAN, sc->unit, sc->input_buf_phys,
  310             rx_buf_desc, sc->filter_buf_phys, macaddr);
  311 
  312         for (i = 0; i < LLAN_MAX_RX_PACKETS; i++)
  313                 llan_add_rxbuf(sc, &sc->rx_xfer[i]);
  314 
  315         phyp_hcall(H_VIO_SIGNAL, sc->unit, 1); /* Enable interrupts */
  316 
  317         /* Tell stack we're up */
  318         sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
  319         sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  320 
  321         mtx_unlock(&sc->io_lock);
  322 
  323         /* Check for pending receives scheduled before interrupt enable */
  324         llan_intr(sc);
  325 }
  326 
  327 static int
  328 llan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx)
  329 {
  330         struct mbuf *m;
  331         bus_dma_segment_t segs[1];
  332         int error, nsegs;
  333 
  334         mtx_assert(&sc->io_lock, MA_OWNED);
  335 
  336         m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
  337         if (m == NULL)
  338                 return (ENOBUFS);
  339 
  340         m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
  341         if (rx->rx_mbuf != NULL) {
  342                 bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap,
  343                     BUS_DMASYNC_POSTREAD);
  344                 bus_dmamap_unload(sc->rxbuf_dma_tag, rx->rx_dmamap);
  345         }
  346 
  347         /* Save pointer to buffer structure */
  348         m_copyback(m, 0, 8, (void *)&rx);
  349 
  350         error = bus_dmamap_load_mbuf_sg(sc->rxbuf_dma_tag, rx->rx_dmamap, m,
  351             segs, &nsegs, BUS_DMA_NOWAIT);
  352         if (error != 0) {
  353                 device_printf(sc->dev,
  354                     "cannot load RX DMA map %p, error = %d\n", rx, error);
  355                 m_freem(m);
  356                 return (error);
  357         }
  358 
  359         /* If nsegs is wrong then the stack is corrupt. */
  360         KASSERT(nsegs == 1,
  361             ("%s: too many DMA segments (%d)", __func__, nsegs));
  362         rx->rx_mbuf = m;
  363 
  364         bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap, BUS_DMASYNC_PREREAD);
  365 
  366         rx->rx_bufdesc = LLAN_BUFDESC_VALID;
  367         rx->rx_bufdesc |= (((uint64_t)segs[0].ds_len) << 32);
  368         rx->rx_bufdesc |= segs[0].ds_addr;
  369         error = phyp_hcall(H_ADD_LOGICAL_LAN_BUFFER, sc->unit, rx->rx_bufdesc);
  370         if (error != 0) {
  371                 m_freem(m);
  372                 rx->rx_mbuf = NULL;
  373                 return (ENOBUFS);
  374         }
  375 
  376         return (0);
  377 }
  378 
  379 static void
  380 llan_intr(void *xsc)
  381 {
  382         struct llan_softc *sc = xsc;
  383         struct llan_xfer *rx;
  384         struct mbuf *m;
  385 
  386         mtx_lock(&sc->io_lock);
  387 restart:
  388         phyp_hcall(H_VIO_SIGNAL, sc->unit, 0);
  389 
  390         while ((sc->rx_buf[sc->rx_dma_slot].control >> 7) == sc->rx_valid_val) {
  391                 rx = (struct llan_xfer *)sc->rx_buf[sc->rx_dma_slot].handle;
  392                 m = rx->rx_mbuf;
  393                 m_adj(m, sc->rx_buf[sc->rx_dma_slot].offset - 8);
  394                 m->m_len = sc->rx_buf[sc->rx_dma_slot].length;
  395 
  396                 /* llan_add_rxbuf does DMA sync and unload as well as requeue */
  397                 if (llan_add_rxbuf(sc, rx) != 0) {
  398                         if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
  399                         continue;
  400                 }
  401 
  402                 if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1);
  403                 m_adj(m, sc->rx_buf[sc->rx_dma_slot].offset);
  404                 m->m_len = sc->rx_buf[sc->rx_dma_slot].length;
  405                 m->m_pkthdr.rcvif = sc->ifp;
  406                 m->m_pkthdr.len = m->m_len;
  407                 sc->rx_dma_slot++;
  408 
  409                 if (sc->rx_dma_slot >= sc->rx_buf_len/sizeof(sc->rx_buf[0])) {
  410                         sc->rx_dma_slot = 0;
  411                         sc->rx_valid_val = !sc->rx_valid_val;
  412                 }
  413 
  414                 mtx_unlock(&sc->io_lock);
  415                 (*sc->ifp->if_input)(sc->ifp, m);
  416                 mtx_lock(&sc->io_lock);
  417         }
  418 
  419         phyp_hcall(H_VIO_SIGNAL, sc->unit, 1);
  420 
  421         /*
  422          * H_VIO_SIGNAL enables interrupts for future packets only.
  423          * Make sure none were queued between the end of the loop and the
  424          * enable interrupts call.
  425          */
  426         if ((sc->rx_buf[sc->rx_dma_slot].control >> 7) == sc->rx_valid_val)
  427                 goto restart;
  428 
  429         mtx_unlock(&sc->io_lock);
  430 }
  431 
  432 static void
  433 llan_send_packet(void *xsc, bus_dma_segment_t *segs, int nsegs,
  434     bus_size_t mapsize, int error)
  435 {
  436         struct llan_softc *sc = xsc;
  437         uint64_t bufdescs[6];
  438         int i, err;
  439 
  440         bzero(bufdescs, sizeof(bufdescs));
  441 
  442         for (i = 0; i < nsegs; i++) {
  443                 bufdescs[i] = LLAN_BUFDESC_VALID;
  444                 bufdescs[i] |= (((uint64_t)segs[i].ds_len) << 32);
  445                 bufdescs[i] |= segs[i].ds_addr;
  446         }
  447 
  448         err = phyp_hcall(H_SEND_LOGICAL_LAN, sc->unit, bufdescs[0],
  449             bufdescs[1], bufdescs[2], bufdescs[3], bufdescs[4], bufdescs[5], 0);
  450         /*
  451          * The hypercall returning implies completion -- or that the call will
  452          * not complete. In principle, we should try a few times if we get back
  453          * H_BUSY based on the continuation token in R4. For now, just drop
  454          * the packet in such cases.
  455          */
  456         if (err == H_SUCCESS)
  457                 if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1);
  458         else
  459                 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
  460 }
  461 
  462 static void
  463 llan_start_locked(struct ifnet *ifp)
  464 {
  465         struct llan_softc *sc = ifp->if_softc;
  466         int nsegs;
  467         struct mbuf *mb_head, *m;
  468 
  469         mtx_assert(&sc->io_lock, MA_OWNED);
  470 
  471         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
  472             IFF_DRV_RUNNING)
  473                 return;
  474 
  475         while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
  476                 IFQ_DRV_DEQUEUE(&ifp->if_snd, mb_head);
  477 
  478                 if (mb_head == NULL)
  479                         break;
  480 
  481                 BPF_MTAP(ifp, mb_head);
  482 
  483                 for (m = mb_head, nsegs = 0; m != NULL; m = m->m_next)
  484                         nsegs++;
  485                 if (nsegs > 6) {
  486                         m = m_collapse(mb_head, M_NOWAIT, 6);
  487                         if (m == NULL) {
  488                                 m_freem(mb_head);
  489                                 continue;
  490                         }
  491                 }
  492 
  493                 bus_dmamap_load_mbuf(sc->tx_dma_tag, sc->tx_dma_map,
  494                         mb_head, llan_send_packet, sc, 0);
  495                 bus_dmamap_unload(sc->tx_dma_tag, sc->tx_dma_map);
  496                 m_freem(mb_head);
  497         }
  498 }
  499 
  500 static void
  501 llan_start(struct ifnet *ifp)
  502 {
  503         struct llan_softc *sc = ifp->if_softc;
  504 
  505         mtx_lock(&sc->io_lock);
  506         llan_start_locked(ifp);
  507         mtx_unlock(&sc->io_lock);
  508 }
  509 
  510 static u_int
  511 llan_set_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
  512 {
  513         struct llan_softc *sc = arg;
  514         uint64_t macaddr = 0;
  515 
  516         memcpy((uint8_t *)&macaddr + 2, LLADDR(sdl), 6);
  517         phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_ADD_MULTICAST, macaddr);
  518 
  519         return (1);
  520 }
  521 
  522 static int
  523 llan_set_multicast(struct llan_softc *sc)
  524 {
  525         struct ifnet *ifp = sc->ifp;
  526 
  527         mtx_assert(&sc->io_lock, MA_OWNED);
  528 
  529         phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_CLEAR_MULTICAST, 0);
  530 
  531         if_foreach_llmaddr(ifp, llan_set_maddr, sc);
  532 
  533         return (0);
  534 }
  535 
  536 static int
  537 llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  538 {
  539         int err = 0;
  540         struct llan_softc *sc = ifp->if_softc;
  541 
  542         switch (cmd) {
  543         case SIOCADDMULTI:
  544         case SIOCDELMULTI:
  545                 mtx_lock(&sc->io_lock);
  546                 if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
  547                         llan_set_multicast(sc);
  548                 mtx_unlock(&sc->io_lock);
  549                 break;
  550         case SIOCGIFMEDIA:
  551         case SIOCSIFMEDIA:
  552                 err = ifmedia_ioctl(ifp, (struct ifreq *)data, &sc->media, cmd);
  553                 break;
  554         case SIOCSIFFLAGS:
  555         default:
  556                 err = ether_ioctl(ifp, cmd, data);
  557                 break;
  558         }
  559 
  560         return (err);
  561 }

Cache object: ed8c70fd4b08d8fdc3633a9bfbf896e5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.