aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/netmap/if_em_netmap.h
diff options
context:
space:
mode:
authorLuigi Rizzo <luigi@FreeBSD.org>2011-12-05 12:06:53 +0000
committerLuigi Rizzo <luigi@FreeBSD.org>2011-12-05 12:06:53 +0000
commit506cc70cce95cb51b029fa4055a38e59b667b76e (patch)
treea556ee936d46b8051dced8959c9019517fa2c641 /sys/dev/netmap/if_em_netmap.h
parent2b69bb1f27973488452bb60c6587ef3971d0218f (diff)
Notes
Diffstat (limited to 'sys/dev/netmap/if_em_netmap.h')
-rw-r--r--sys/dev/netmap/if_em_netmap.h167
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 ;