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_re_netmap.h | |
| parent | 2b69bb1f27973488452bb60c6587ef3971d0218f (diff) | |
Notes
Diffstat (limited to 'sys/dev/netmap/if_re_netmap.h')
| -rw-r--r-- | sys/dev/netmap/if_re_netmap.h | 143 |
1 files changed, 79 insertions, 64 deletions
diff --git a/sys/dev/netmap/if_re_netmap.h b/sys/dev/netmap/if_re_netmap.h index efccf3a795bc..105660c4d106 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; + 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; - for (i = 0; i < sc->rl_ldata.rl_rx_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)); - 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, |
