diff options
| author | Luigi Rizzo <luigi@FreeBSD.org> | 2011-12-05 12:06:53 +0000 |
|---|---|---|
| committer | Luigi Rizzo <luigi@FreeBSD.org> | 2011-12-05 12:06:53 +0000 |
| commit | 506cc70cce95cb51b029fa4055a38e59b667b76e (patch) | |
| tree | a556ee936d46b8051dced8959c9019517fa2c641 /sys/dev/netmap/if_em_netmap.h | |
| parent | 2b69bb1f27973488452bb60c6587ef3971d0218f (diff) | |
Notes
Diffstat (limited to 'sys/dev/netmap/if_em_netmap.h')
| -rw-r--r-- | sys/dev/netmap/if_em_netmap.h | 167 |
1 files changed, 91 insertions, 76 deletions
diff --git a/sys/dev/netmap/if_em_netmap.h b/sys/dev/netmap/if_em_netmap.h index 0e220e755d68d..681a652aa9f34 100644 --- a/sys/dev/netmap/if_em_netmap.h +++ b/sys/dev/netmap/if_em_netmap.h @@ -9,7 +9,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -25,9 +25,12 @@ /* * $FreeBSD$ - * $Id: if_em_netmap.h 9662 2011-11-16 13:18:06Z luigi $ + * $Id: if_em_netmap.h 9802 2011-12-02 18:42:37Z luigi $ * * netmap changes for if_em. + * + * For structure and details on the individual functions please see + * ixgbe_netmap.h */ #include <net/netmap.h> @@ -58,12 +61,7 @@ em_netmap_attach(struct adapter *adapter) na.nm_rxsync = em_netmap_rxsync; na.nm_lock = em_netmap_lock_wrapper; na.nm_register = em_netmap_reg; - /* - * adapter->rx_mbuf_sz is set by SIOCSETMTU, but in netmap mode - * we allocate the buffers on the first register. So we must - * disallow a SIOCSETMTU when if_capenable & IFCAP_NETMAP is set. - */ - na.buff_size = MCLBYTES; + na.buff_size = NETMAP_BUF_SIZE; netmap_attach(&na, adapter->num_queues); } @@ -100,6 +98,7 @@ em_netmap_lock_wrapper(void *_a, int what, u_int queueid) } +// XXX do we need to block/unblock the tasks ? static void em_netmap_block_tasks(struct adapter *adapter) { @@ -162,9 +161,6 @@ em_netmap_reg(struct ifnet *ifp, int onoff) if (onoff) { ifp->if_capenable |= IFCAP_NETMAP; - /* save if_transmit for later restore. - * XXX also if_start and if_qflush ? - */ na->if_transmit = ifp->if_transmit; ifp->if_transmit = netmap_start; @@ -179,15 +175,13 @@ fail: ifp->if_transmit = na->if_transmit; ifp->if_capenable &= ~IFCAP_NETMAP; em_init_locked(adapter); /* also enable intr */ - } em_netmap_unblock_tasks(adapter); return (error); } /* - * Reconcile hardware and user view of the transmit ring, see - * ixgbe.c for details. + * Reconcile hardware and user view of the transmit ring. */ static int em_netmap_txsync(void *a, u_int ring_nr, int do_lock) @@ -197,13 +191,13 @@ em_netmap_txsync(void *a, u_int ring_nr, int do_lock) struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->tx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - int j, k, n, lim = kring->nkr_num_slots - 1; + 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; k = ring->cur; - if ( (kring->nr_kflags & NR_REINIT) || k > lim) + if (k > lim) return netmap_ring_reinit(kring); if (do_lock) @@ -211,35 +205,20 @@ em_netmap_txsync(void *a, u_int ring_nr, int do_lock) bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, BUS_DMASYNC_POSTREAD); - /* record completed transmissions TODO - * - * instead of using TDH, we could read the transmitted status bit. + /* check for new packets to send. + * j indexes the netmap ring, l indexes the nic ring, and + * j = kring->nr_hwcur, l = E1000_TDT (not tracked), + * j == (l + kring->nkr_hwofs) % ring_size */ - j = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); - if (j >= kring->nkr_num_slots) { /* XXX can happen */ - D("TDH wrap %d", j); - j -= kring->nkr_num_slots; - } - int delta = j - txr->next_to_clean; - if (delta) { - /* new transmissions were completed, increment - ring->nr_hwavail. */ - if (delta < 0) - delta += kring->nkr_num_slots; - txr->next_to_clean = j; - kring->nr_hwavail += delta; - } - - /* update avail to what the hardware knows */ - ring->avail = kring->nr_hwavail; - j = kring->nr_hwcur; if (j != k) { /* we have packets to send */ - n = 0; + l = j - kring->nkr_hwofs; + if (l < 0) + l += lim + 1; while (j != k) { struct netmap_slot *slot = &ring->slot[j]; - struct e1000_tx_desc *curr = &txr->tx_base[j]; - struct em_buffer *txbuf = &txr->tx_buffers[j]; + struct e1000_tx_desc *curr = &txr->tx_base[l]; + struct em_buffer *txbuf = &txr->tx_buffers[l]; int flags = ((slot->flags & NS_REPORT) || j == 0 || j == report_frequency) ? E1000_TXD_CMD_RS : 0; @@ -254,42 +233,61 @@ em_netmap_txsync(void *a, u_int ring_nr, int do_lock) slot->flags &= ~NS_REPORT; curr->upper.data = 0; curr->lower.data = - htole32( - adapter->txd_cmd | - (E1000_TXD_CMD_EOP | flags) | - slot->len); + htole32(adapter->txd_cmd | len | + (E1000_TXD_CMD_EOP | flags) ); if (slot->flags & NS_BUF_CHANGED) { curr->buffer_addr = htole64(vtophys(addr)); - /* buffer has changed, unload and reload map */ + /* buffer has changed, reload map */ netmap_reload_map(txr->txtag, txbuf->map, - addr, na->buff_size); + addr, na->buff_size); slot->flags &= ~NS_BUF_CHANGED; } bus_dmamap_sync(txr->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); j = (j == lim) ? 0 : j + 1; + l = (l == lim) ? 0 : l + 1; n++; } - kring->nr_hwcur = ring->cur; + kring->nr_hwcur = k; /* decrease avail by number of sent packets */ - ring->avail -= n; - kring->nr_hwavail = ring->avail; + kring->nr_hwavail -= n; bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), - ring->cur); + E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), l); } + + if (n == 0 || kring->nr_hwavail < 1) { + int delta; + + /* record completed transmissions using THD. */ + l = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); + if (l >= kring->nkr_num_slots) { /* XXX can happen */ + D("TDH wrap %d", l); + l -= kring->nkr_num_slots; + } + delta = l - txr->next_to_clean; + if (delta) { + /* some completed, increment hwavail. */ + if (delta < 0) + delta += kring->nkr_num_slots; + txr->next_to_clean = l; + kring->nr_hwavail += delta; + } + } + /* update avail to what the hardware knows */ + ring->avail = kring->nr_hwavail; + if (do_lock) EM_TX_UNLOCK(txr); return 0; } /* - * Reconcile kernel and user view of the receive ring, see ixgbe.c + * Reconcile kernel and user view of the receive ring. */ static int em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) @@ -299,10 +297,10 @@ em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - int j, k, n, lim = kring->nkr_num_slots - 1; + int j, k, l, n, lim = kring->nkr_num_slots - 1; k = ring->cur; - if ( (kring->nr_kflags & NR_REINIT) || k > lim) + if (k > lim) return netmap_ring_reinit(kring); if (do_lock) @@ -311,36 +309,52 @@ em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - /* acknowledge all the received packets. */ - j = rxr->next_to_check; + /* import newly received packets into the netmap ring. + * j is an index in the netmap ring, l in the NIC ring, and + * j = (kring->nr_hwcur + kring->nr_hwavail) % ring_size + * l = rxr->next_to_check; + * and + * j == (l + kring->nkr_hwofs) % ring_size + */ + l = rxr->next_to_check; + j = l + kring->nkr_hwofs; + /* here nkr_hwofs can be negative so must check for j < 0 */ + if (j < 0) + j += lim + 1; + else if (j > lim) + j -= lim + 1; for (n = 0; ; n++) { - struct e1000_rx_desc *curr = &rxr->rx_base[j]; + struct e1000_rx_desc *curr = &rxr->rx_base[l]; if ((curr->status & E1000_RXD_STAT_DD) == 0) break; ring->slot[j].len = le16toh(curr->length); - bus_dmamap_sync(rxr->tag, rxr->rx_buffers[j].map, + bus_dmamap_sync(rxr->tag, rxr->rx_buffers[l].map, BUS_DMASYNC_POSTREAD); j = (j == lim) ? 0 : j + 1; + /* make sure next_to_refresh follows next_to_check */ + rxr->next_to_refresh = l; // XXX + l = (l == lim) ? 0 : l + 1; } if (n) { - rxr->next_to_check = j; + rxr->next_to_check = l; kring->nr_hwavail += n; } - /* skip past packets that userspace has already processed: - * making them available for reception. - * advance nr_hwcur and issue a bus_dmamap_sync on the - * buffers so it is safe to write to them. - * Also increase nr_hwavail - */ + /* skip past packets that userspace has already processed */ j = kring->nr_hwcur; if (j != k) { /* userspace has read some packets. */ n = 0; + l = j - kring->nkr_hwofs; /* NIC ring index */ + /* here nkr_hwofs can be negative so check for l > lim */ + if (l < 0) + l += lim + 1; + else if (l > lim) + l -= lim + 1; while (j != k) { struct netmap_slot *slot = &ring->slot[j]; - struct e1000_rx_desc *curr = &rxr->rx_base[j]; - struct em_buffer *rxbuf = &rxr->rx_buffers[j]; + struct e1000_rx_desc *curr = &rxr->rx_base[l]; + struct em_buffer *rxbuf = &rxr->rx_buffers[l]; void *addr = NMB(slot); if (addr == netmap_buffer_base) { /* bad buf */ @@ -352,28 +366,29 @@ em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) curr->status = 0; if (slot->flags & NS_BUF_CHANGED) { curr->buffer_addr = htole64(vtophys(addr)); - /* buffer has changed, unload and reload map */ + /* buffer has changed, reload map */ netmap_reload_map(rxr->rxtag, rxbuf->map, - addr, na->buff_size); + addr, na->buff_size); slot->flags &= ~NS_BUF_CHANGED; } bus_dmamap_sync(rxr->rxtag, rxbuf->map, - BUS_DMASYNC_PREREAD); + BUS_DMASYNC_PREREAD); j = (j == lim) ? 0 : j + 1; + l = (l == lim) ? 0 : l + 1; n++; } kring->nr_hwavail -= n; - kring->nr_hwcur = ring->cur; + kring->nr_hwcur = k; bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* * IMPORTANT: we must leave one free slot in the ring, - * so move j back by one unit + * so move l back by one unit */ - j = (j == 0) ? lim : j - 1; - E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), j); + l = (l == 0) ? lim : l - 1; + E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), l); } /* tell userspace that there are new packets */ ring->avail = kring->nr_hwavail ; |
