diff options
| author | Luigi Rizzo <luigi@FreeBSD.org> | 2012-05-17 15:02:51 +0000 |
|---|---|---|
| committer | Luigi Rizzo <luigi@FreeBSD.org> | 2012-05-17 15:02:51 +0000 |
| commit | ff78552d0cd5733e887481436794860af5c87275 (patch) | |
| tree | 75820565dca0a52fecc351a34300ef7b41b3fff9 /sys/dev/netmap/if_lem_netmap.h | |
| parent | 5da0d12406866662f5214acb681caee06bb7b97f (diff) | |
Notes
Diffstat (limited to 'sys/dev/netmap/if_lem_netmap.h')
| -rw-r--r-- | sys/dev/netmap/if_lem_netmap.h | 212 |
1 files changed, 105 insertions, 107 deletions
diff --git a/sys/dev/netmap/if_lem_netmap.h b/sys/dev/netmap/if_lem_netmap.h index 5ce93b914847..9f24580a9e8d 100644 --- a/sys/dev/netmap/if_lem_netmap.h +++ b/sys/dev/netmap/if_lem_netmap.h @@ -23,14 +23,14 @@ * SUCH DAMAGE. */ + /* * $FreeBSD$ - * $Id: if_lem_netmap.h 9802 2011-12-02 18:42:37Z luigi $ + * $Id: if_lem_netmap.h 10627 2012-02-23 19:37:15Z luigi $ * - * netmap support for if_lem.c + * netmap support for "lem" * - * For structure and details on the individual functions please see - * ixgbe_netmap.h + * For details on netmap support please see ixgbe_netmap.h */ #include <net/netmap.h> @@ -39,32 +39,6 @@ #include <vm/pmap.h> /* vtophys ? */ #include <dev/netmap/netmap_kern.h> -static int lem_netmap_reg(struct ifnet *, int onoff); -static int lem_netmap_txsync(struct ifnet *, u_int, int); -static int lem_netmap_rxsync(struct ifnet *, u_int, int); -static void lem_netmap_lock_wrapper(struct ifnet *, int, u_int); - - -SYSCTL_NODE(_dev, OID_AUTO, lem, CTLFLAG_RW, 0, "lem card"); - -static void -lem_netmap_attach(struct adapter *adapter) -{ - struct netmap_adapter na; - - bzero(&na, sizeof(na)); - - na.ifp = adapter->ifp; - na.separate_locks = 1; - na.num_tx_desc = adapter->num_tx_desc; - na.num_rx_desc = adapter->num_rx_desc; - na.nm_txsync = lem_netmap_txsync; - na.nm_rxsync = lem_netmap_rxsync; - na.nm_lock = lem_netmap_lock_wrapper; - na.nm_register = lem_netmap_reg; - netmap_attach(&na, 1); -} - static void lem_netmap_lock_wrapper(struct ifnet *ifp, int what, u_int ringid) @@ -96,7 +70,7 @@ lem_netmap_lock_wrapper(struct ifnet *ifp, int what, u_int ringid) /* - * Register/unregister routine + * Register/unregister */ static int lem_netmap_reg(struct ifnet *ifp, int onoff) @@ -113,7 +87,6 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - /* lem_netmap_block_tasks(adapter); */ #ifndef EM_LEGACY_IRQ // XXX do we need this ? taskqueue_block(adapter->tq); taskqueue_drain(adapter->tq, &adapter->rxtx_task); @@ -122,9 +95,6 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) if (onoff) { ifp->if_capenable |= IFCAP_NETMAP; - /* save if_transmit to restore it when exiting. - * XXX what about if_start and if_qflush ? - */ na->if_transmit = ifp->if_transmit; ifp->if_transmit = netmap_start; @@ -135,10 +105,10 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) } } else { fail: - /* restore non-netmap mode */ + /* return to non-netmap mode */ ifp->if_transmit = na->if_transmit; ifp->if_capenable &= ~IFCAP_NETMAP; - lem_init_locked(adapter); /* also enables intr */ + lem_init_locked(adapter); /* also enable intr */ } #ifndef EM_LEGACY_IRQ @@ -156,14 +126,15 @@ static int lem_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->tx_rings[0]; + struct netmap_adapter *na = NA(ifp); + struct netmap_kring *kring = &na->tx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - int j, k, l, n = 0, lim = kring->nkr_num_slots - 1; + u_int j, k, l, n = 0, lim = kring->nkr_num_slots - 1; /* generate an interrupt approximately every half ring */ int report_frequency = kring->nkr_num_slots >> 1; + /* take a copy of ring->cur now, and never read it again */ k = ring->cur; if (k > lim) return netmap_ring_reinit(kring); @@ -172,25 +143,25 @@ lem_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) EM_TX_LOCK(adapter); bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_POSTREAD); - - /* update avail to what the hardware knows */ - ring->avail = kring->nr_hwavail; - - j = kring->nr_hwcur; /* points into the netmap ring */ + /* + * Process new packets to send. j is the current index in the + * netmap ring, l is the corresponding index in the NIC ring. + */ + j = kring->nr_hwcur; if (j != k) { /* we have new packets to send */ - l = j - kring->nkr_hwofs; /* points into the NIC ring */ - if (l < 0) - l += lim + 1; - while (j != k) { + l = netmap_idx_k2n(kring, j); + for (n = 0; j != k; n++) { + /* slot is the current slot in the netmap ring */ struct netmap_slot *slot = &ring->slot[j]; + /* curr is the current slot in the nic ring */ struct e1000_tx_desc *curr = &adapter->tx_desc_base[l]; struct em_buffer *txbuf = &adapter->tx_buffer_area[l]; - uint64_t paddr; - void *addr = PNMB(slot, &paddr); int flags = ((slot->flags & NS_REPORT) || j == 0 || j == report_frequency) ? E1000_TXD_CMD_RS : 0; - int len = slot->len; + uint64_t paddr; + void *addr = PNMB(slot, &paddr); + u_int len = slot->len; if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { if (do_lock) @@ -199,28 +170,24 @@ lem_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) } slot->flags &= ~NS_REPORT; - curr->upper.data = 0; - curr->lower.data = - htole32( adapter->txd_cmd | len | - (E1000_TXD_CMD_EOP | flags) ); if (slot->flags & NS_BUF_CHANGED) { - curr->buffer_addr = htole64(paddr); /* buffer has changed, reload map */ netmap_reload_map(adapter->txtag, txbuf->map, addr); + curr->buffer_addr = htole64(paddr); slot->flags &= ~NS_BUF_CHANGED; } + curr->upper.data = 0; + curr->lower.data = + htole32( adapter->txd_cmd | len | + (E1000_TXD_CMD_EOP | flags) ); bus_dmamap_sync(adapter->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); j = (j == lim) ? 0 : j + 1; l = (l == lim) ? 0 : l + 1; - n++; } - kring->nr_hwcur = k; - - /* decrease avail by number of sent packets */ + kring->nr_hwcur = k; /* the saved ring->cur */ kring->nr_hwavail -= n; - ring->avail = kring->nr_hwavail; bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -233,19 +200,21 @@ lem_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) /* record completed transmissions using TDH */ l = E1000_READ_REG(&adapter->hw, E1000_TDH(0)); - if (l >= kring->nkr_num_slots) { /* can it happen ? */ + if (l >= kring->nkr_num_slots) { /* XXX can it happen ? */ D("bad TDH %d", l); l -= kring->nkr_num_slots; } delta = l - adapter->next_tx_to_clean; if (delta) { + /* some tx completed, increment hwavail. */ if (delta < 0) delta += kring->nkr_num_slots; adapter->next_tx_to_clean = l; kring->nr_hwavail += delta; - ring->avail = kring->nr_hwavail; } } + /* update avail to what the kernel knows */ + ring->avail = kring->nr_hwavail; if (do_lock) EM_TX_UNLOCK(adapter); @@ -260,57 +229,68 @@ static int lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->rx_rings[0]; + struct netmap_adapter *na = NA(ifp); + struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - int j, k, l, n, lim = kring->nkr_num_slots - 1; + int j, l, n, lim = kring->nkr_num_slots - 1; + int force_update = do_lock || kring->nr_kflags & NKR_PENDINTR; + u_int k = ring->cur, resvd = ring->reserved; - k = ring->cur; if (k > lim) return netmap_ring_reinit(kring); if (do_lock) EM_RX_LOCK(adapter); + /* XXX check sync modes */ bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - /* import newly received packets into the netmap ring */ - l = adapter->next_rx_desc_to_check; /* points into the NIC ring */ - j = l + kring->nkr_hwofs; /* points into the netmap ring */ - if (j > lim) - j -= lim + 1; - for (n = 0; ; n++) { - struct e1000_rx_desc *curr = &adapter->rx_desc_base[l]; - int len; - - if ((curr->status & E1000_RXD_STAT_DD) == 0) - break; - len = le16toh(curr->length) - 4; // CRC + /* + * Import newly received packets into the netmap ring. + * j is an index in the netmap ring, l in the NIC ring. + */ + l = adapter->next_rx_desc_to_check; + j = netmap_idx_n2k(kring, l); + if (netmap_no_pendintr || force_update) { + for (n = 0; ; n++) { + struct e1000_rx_desc *curr = &adapter->rx_desc_base[l]; + uint32_t staterr = le32toh(curr->status); + int len; - if (len < 0) { - D("bogus pkt size at %d", j); - len = 0; + if ((staterr & E1000_RXD_STAT_DD) == 0) + break; + len = le16toh(curr->length) - 4; // CRC + if (len < 0) { + D("bogus pkt size at %d", j); + len = 0; + } + ring->slot[j].len = len; + bus_dmamap_sync(adapter->rxtag, + adapter->rx_buffer_area[l].map, + BUS_DMASYNC_POSTREAD); + j = (j == lim) ? 0 : j + 1; + l = (l == lim) ? 0 : l + 1; } - ring->slot[j].len = len; - bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[l].map, - BUS_DMASYNC_POSTREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; - } - if (n) { - adapter->next_rx_desc_to_check = l; - kring->nr_hwavail += n; + if (n) { /* update the state variables */ + adapter->next_rx_desc_to_check = l; + kring->nr_hwavail += n; + } + kring->nr_kflags &= ~NKR_PENDINTR; } - /* skip past packets that userspace has already processed */ - j = kring->nr_hwcur; /* netmap ring index */ - if (j != k) { /* userspace has read some packets. */ - n = 0; - l = j - kring->nkr_hwofs; /* NIC ring index */ - if (l < 0) - l += lim + 1; - while (j != k) { + /* skip past packets that userspace has released */ + j = kring->nr_hwcur; /* netmap ring index */ + if (resvd > 0) { + if (resvd + ring->avail >= lim + 1) { + D("XXX invalid reserve/avail %d %d", resvd, ring->avail); + ring->reserved = resvd = 0; // XXX panic... + } + k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; + } + if (j != k) { /* userspace has released some packets. */ + l = netmap_idx_k2n(kring, j); /* NIC ring index */ + for (n = 0; j != k; n++) { struct netmap_slot *slot = &ring->slot[j]; struct e1000_rx_desc *curr = &adapter->rx_desc_base[l]; struct em_buffer *rxbuf = &adapter->rx_buffer_area[l]; @@ -322,20 +302,20 @@ lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) EM_RX_UNLOCK(adapter); return netmap_ring_reinit(kring); } - curr->status = 0; + if (slot->flags & NS_BUF_CHANGED) { - curr->buffer_addr = htole64(paddr); - /* buffer has changed, and reload map */ + /* buffer has changed, reload map */ netmap_reload_map(adapter->rxtag, rxbuf->map, addr); + curr->buffer_addr = htole64(paddr); slot->flags &= ~NS_BUF_CHANGED; } + curr->status = 0; bus_dmamap_sync(adapter->rxtag, rxbuf->map, BUS_DMASYNC_PREREAD); j = (j == lim) ? 0 : j + 1; l = (l == lim) ? 0 : l + 1; - n++; } kring->nr_hwavail -= n; kring->nr_hwcur = k; @@ -348,12 +328,30 @@ lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) l = (l == 0) ? lim : l - 1; E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), l); } - /* tell userspace that there are new packets */ - ring->avail = kring->nr_hwavail ; - + ring->avail = kring->nr_hwavail - resvd; if (do_lock) EM_RX_UNLOCK(adapter); return 0; } + + +static void +lem_netmap_attach(struct adapter *adapter) +{ + struct netmap_adapter na; + + bzero(&na, sizeof(na)); + + na.ifp = adapter->ifp; + na.separate_locks = 1; + na.num_tx_desc = adapter->num_tx_desc; + na.num_rx_desc = adapter->num_rx_desc; + na.nm_txsync = lem_netmap_txsync; + na.nm_rxsync = lem_netmap_rxsync; + na.nm_lock = lem_netmap_lock_wrapper; + na.nm_register = lem_netmap_reg; + netmap_attach(&na, 1); +} + /* end of file */ |
