summaryrefslogtreecommitdiffstats
path: root/sys/dev/netmap/if_re_netmap.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/netmap/if_re_netmap.h')
-rw-r--r--sys/dev/netmap/if_re_netmap.h147
1 files changed, 81 insertions, 66 deletions
diff --git a/sys/dev/netmap/if_re_netmap.h b/sys/dev/netmap/if_re_netmap.h
index efccf3a..105660c 100644
--- a/sys/dev/netmap/if_re_netmap.h
+++ b/sys/dev/netmap/if_re_netmap.h
@@ -25,7 +25,7 @@
/*
* $FreeBSD$
- * $Id: if_re_netmap.h 9662 2011-11-16 13:18:06Z luigi $
+ * $Id: if_re_netmap.h 9802 2011-12-02 18:42:37Z luigi $
*
* netmap support for if_re
*/
@@ -56,7 +56,7 @@ re_netmap_attach(struct rl_softc *sc)
na.nm_rxsync = re_netmap_rxsync;
na.nm_lock = re_netmap_lock_wrapper;
na.nm_register = re_netmap_reg;
- na.buff_size = MCLBYTES;
+ na.buff_size = NETMAP_BUF_SIZE;
netmap_attach(&na, 1);
}
@@ -99,7 +99,7 @@ re_netmap_reg(struct ifnet *ifp, int onoff)
struct netmap_adapter *na = NA(ifp);
int error = 0;
- if (!na)
+ if (na == NULL)
return EINVAL;
/* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
@@ -109,9 +109,8 @@ re_netmap_reg(struct ifnet *ifp, int onoff)
if (onoff) {
ifp->if_capenable |= IFCAP_NETMAP;
- /* save if_transmit and restore it */
+ /* save if_transmit to restore it later */
na->if_transmit = ifp->if_transmit;
- /* XXX if_start and if_qflush ??? */
ifp->if_transmit = netmap_start;
re_init_locked(adapter);
@@ -127,23 +126,12 @@ fail:
ifp->if_capenable &= ~IFCAP_NETMAP;
re_init_locked(adapter); /* also enables intr */
}
- return (error);
-
+ return (error);
}
/*
* Reconcile kernel and user view of the transmit ring.
- *
- * Userspace has filled tx slots up to cur (excluded).
- * The last unused slot previously known to the kernel was nr_hwcur,
- * and the last interrupt reported nr_hwavail slots available
- * (using the special value -1 to indicate idle transmit ring).
- * The function must first update avail to what the kernel
- * knows (translating the -1 to nkr_num_slots - 1),
- * subtract the newly used slots (cur - nr_hwcur)
- * from both avail and nr_hwavail, and set nr_hwcur = cur
- * issuing a dmamap_sync on all slots.
*/
static int
re_netmap_txsync(void *a, u_int ring_nr, int do_lock)
@@ -153,10 +141,10 @@ re_netmap_txsync(void *a, u_int ring_nr, int do_lock)
struct netmap_adapter *na = NA(sc->rl_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, 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)
@@ -167,17 +155,18 @@ re_netmap_txsync(void *a, u_int ring_nr, int do_lock)
sc->rl_ldata.rl_tx_list_map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ /* XXX move after the transmissions */
/* record completed transmissions */
- for (n = 0, j = sc->rl_ldata.rl_tx_considx;
- j != sc->rl_ldata.rl_tx_prodidx;
- n++, j = RL_TX_DESC_NXT(sc, j)) {
+ for (n = 0, l = sc->rl_ldata.rl_tx_considx;
+ l != sc->rl_ldata.rl_tx_prodidx;
+ n++, l = RL_TX_DESC_NXT(sc, l)) {
uint32_t cmdstat =
- le32toh(sc->rl_ldata.rl_tx_list[j].rl_cmdstat);
+ le32toh(sc->rl_ldata.rl_tx_list[l].rl_cmdstat);
if (cmdstat & RL_TDESC_STAT_OWN)
break;
}
if (n > 0) {
- sc->rl_ldata.rl_tx_considx = j;
+ sc->rl_ldata.rl_tx_considx = l;
sc->rl_ldata.rl_tx_free += n;
kring->nr_hwavail += n;
}
@@ -185,13 +174,13 @@ re_netmap_txsync(void *a, u_int ring_nr, int do_lock)
/* update avail to what the hardware knows */
ring->avail = kring->nr_hwavail;
- /* we trust prodidx, not hwcur */
- j = kring->nr_hwcur = sc->rl_ldata.rl_tx_prodidx;
+ j = kring->nr_hwcur;
if (j != k) { /* we have new packets to send */
n = 0;
+ l = sc->rl_ldata.rl_tx_prodidx;
while (j != k) {
struct netmap_slot *slot = &ring->slot[j];
- struct rl_desc *desc = &sc->rl_ldata.rl_tx_list[j];
+ struct rl_desc *desc = &sc->rl_ldata.rl_tx_list[l];
int cmd = slot->len | RL_TDESC_CMD_EOF |
RL_TDESC_CMD_OWN | RL_TDESC_CMD_SOF ;
void *addr = NMB(slot);
@@ -200,10 +189,11 @@ re_netmap_txsync(void *a, u_int ring_nr, int do_lock)
if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) {
if (do_lock)
RL_UNLOCK(sc);
+ // XXX what about prodidx ?
return netmap_ring_reinit(kring);
}
- if (j == lim) /* mark end of ring */
+ if (l == lim) /* mark end of ring */
cmd |= RL_TDESC_CMD_EOR;
if (slot->flags & NS_BUF_CHANGED) {
@@ -212,17 +202,19 @@ re_netmap_txsync(void *a, u_int ring_nr, int do_lock)
desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr));
/* buffer has changed, unload and reload map */
netmap_reload_map(sc->rl_ldata.rl_tx_mtag,
- txd[j].tx_dmamap, addr, na->buff_size);
+ txd[l].tx_dmamap, addr, na->buff_size);
slot->flags &= ~NS_BUF_CHANGED;
}
slot->flags &= ~NS_REPORT;
desc->rl_cmdstat = htole32(cmd);
bus_dmamap_sync(sc->rl_ldata.rl_tx_mtag,
- txd[j].tx_dmamap, BUS_DMASYNC_PREWRITE);
+ txd[l].tx_dmamap, BUS_DMASYNC_PREWRITE);
j = (j == lim) ? 0 : j + 1;
+ l = (l == lim) ? 0 : l + 1;
n++;
}
- sc->rl_ldata.rl_tx_prodidx = kring->nr_hwcur = ring->cur;
+ sc->rl_ldata.rl_tx_prodidx = l;
+ kring->nr_hwcur = k;
/* decrease avail by number of sent packets */
ring->avail -= n;
@@ -243,15 +235,6 @@ re_netmap_txsync(void *a, u_int ring_nr, int do_lock)
/*
* Reconcile kernel and user view of the receive ring.
- *
- * Userspace has read rx slots up to cur (excluded).
- * The last unread slot previously known to the kernel was nr_hwcur,
- * and the last interrupt reported nr_hwavail slots available.
- * We must subtract the newly consumed slots (cur - nr_hwcur)
- * from nr_hwavail, clearing the descriptors for the next
- * read, tell the hardware that they are available,
- * and set nr_hwcur = cur and avail = nr_hwavail.
- * issuing a dmamap_sync on all slots.
*/
static int
re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
@@ -261,10 +244,10 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
struct netmap_adapter *na = NA(sc->rl_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)
@@ -280,9 +263,10 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
* cleared (all buffers could have it cleared. The easiest one
* is to limit the amount of data reported up to 'lim'
*/
- j = sc->rl_ldata.rl_rx_prodidx;
+ l = sc->rl_ldata.rl_rx_prodidx; /* next pkt to check */
+ j = l + kring->nkr_hwofs;
for (n = kring->nr_hwavail; n < lim ; n++) {
- struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[j];
+ struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[l];
uint32_t rxstat = le32toh(cur_rx->rl_cmdstat);
uint32_t total_len;
@@ -294,11 +278,12 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
kring->ring->slot[j].len = total_len;
/* sync was in re_newbuf() */
bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag,
- rxd[j].rx_dmamap, BUS_DMASYNC_POSTREAD);
- j = RL_RX_DESC_NXT(sc, j);
+ rxd[l].rx_dmamap, BUS_DMASYNC_POSTREAD);
+ j = (j == lim) ? 0 : j + 1;
+ l = (l == lim) ? 0 : l + 1;
}
if (n != kring->nr_hwavail) {
- sc->rl_ldata.rl_rx_prodidx = j;
+ sc->rl_ldata.rl_rx_prodidx = l;
sc->rl_ifp->if_ipackets += n - kring->nr_hwavail;
kring->nr_hwavail = n;
}
@@ -312,9 +297,12 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
j = kring->nr_hwcur;
if (j != k) { /* userspace has read some packets. */
n = 0;
+ l = kring->nr_hwcur - kring->nkr_hwofs;
+ if (l < 0)
+ l += lim + 1;
while (j != k) {
struct netmap_slot *slot = ring->slot + j;
- struct rl_desc *desc = &sc->rl_ldata.rl_rx_list[j];
+ struct rl_desc *desc = &sc->rl_ldata.rl_rx_list[l];
int cmd = na->buff_size | RL_RDESC_CMD_OWN;
void *addr = NMB(slot);
@@ -324,7 +312,7 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
return netmap_ring_reinit(kring);
}
- if (j == lim) /* mark end of ring */
+ if (l == lim) /* mark end of ring */
cmd |= RL_RDESC_CMD_EOR;
desc->rl_cmdstat = htole32(cmd);
@@ -334,12 +322,13 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr));
desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr));
netmap_reload_map(sc->rl_ldata.rl_rx_mtag,
- rxd[j].rx_dmamap, addr, na->buff_size);
+ rxd[l].rx_dmamap, addr, na->buff_size);
slot->flags &= ~NS_BUF_CHANGED;
}
bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag,
- rxd[j].rx_dmamap, BUS_DMASYNC_PREREAD);
+ rxd[l].rx_dmamap, BUS_DMASYNC_PREREAD);
j = (j == lim) ? 0 : j + 1;
+ l = (l == lim) ? 0 : l + 1;
n++;
}
kring->nr_hwavail -= n;
@@ -351,18 +340,22 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock)
BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
}
/* tell userspace that there are new packets */
- ring->avail = kring->nr_hwavail ;
+ ring->avail = kring->nr_hwavail;
if (do_lock)
RL_UNLOCK(sc);
return 0;
}
+/*
+ * Additional routines to init the tx and rx rings.
+ * In other drivers we do that inline in the main code.
+ */
static void
re_netmap_tx_init(struct rl_softc *sc)
{
struct rl_txdesc *txd;
struct rl_desc *desc;
- int i;
+ int i, n;
struct netmap_adapter *na = NA(sc->rl_ifp);
struct netmap_slot *slot = netmap_reset(na, NR_TX, 0, 0);
@@ -372,11 +365,20 @@ re_netmap_tx_init(struct rl_softc *sc)
/* in netmap mode, overwrite addresses and maps */
txd = sc->rl_ldata.rl_tx_desc;
desc = sc->rl_ldata.rl_tx_list;
+ n = sc->rl_ldata.rl_tx_desc_cnt;
+
+ /* l points in the netmap ring, i points in the NIC ring */
+ for (i = 0; i < n; i++) {
+ void *addr;
+ uint64_t paddr;
+ struct netmap_kring *kring = &na->tx_rings[0];
+ int l = i + kring->nkr_hwofs;
- for (i = 0; i < sc->rl_ldata.rl_tx_desc_cnt; i++) {
- void *addr = NMB(slot+i);
- uint64_t paddr = vtophys(addr);
+ if (l >= n)
+ l -= n;
+ addr = NMB(slot + l);
+ paddr = vtophys(addr);
desc[i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr));
desc[i].rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr));
netmap_load_map(sc->rl_ldata.rl_tx_mtag,
@@ -387,26 +389,39 @@ re_netmap_tx_init(struct rl_softc *sc)
static void
re_netmap_rx_init(struct rl_softc *sc)
{
- /* slot is NULL if we are not in netmap mode */
struct netmap_adapter *na = NA(sc->rl_ifp);
struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0);
struct rl_desc *desc = sc->rl_ldata.rl_rx_list;
uint32_t cmdstat;
- int i;
+ int i, n;
if (!slot)
return;
-
- for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) {
- void *addr = NMB(slot+i);
- uint64_t paddr = vtophys(addr);
-
+ n = sc->rl_ldata.rl_rx_desc_cnt;
+ for (i = 0; i < n; i++) {
+ void *addr;
+ uint64_t paddr;
+ struct netmap_kring *kring = &na->rx_rings[0];
+ int l = i + kring->nkr_hwofs;
+
+ if (l >= n)
+ l -= n;
+
+ addr = NMB(slot + l);
+ paddr = vtophys(addr);
desc[i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr));
desc[i].rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr));
- cmdstat = slot[i].len = na->buff_size; // XXX
- if (i == sc->rl_ldata.rl_rx_desc_cnt - 1)
+ cmdstat = na->buff_size;
+ if (i == n - 1)
cmdstat |= RL_RDESC_CMD_EOR;
- desc[i].rl_cmdstat = htole32(cmdstat | RL_RDESC_CMD_OWN);
+ /*
+ * userspace knows that hwavail packets were ready before the
+ * reset, so we need to tell the NIC that last hwavail
+ * descriptors of the ring are still owned by the driver.
+ */
+ if (i < n - 1 - kring->nr_hwavail) // XXX + 1 ?
+ cmdstat |= RL_RDESC_CMD_OWN;
+ desc[i].rl_cmdstat = htole32(cmdstat);
netmap_reload_map(sc->rl_ldata.rl_rx_mtag,
sc->rl_ldata.rl_rx_desc[i].rx_dmamap,
OpenPOWER on IntegriCloud