168b8534bSLuigi Rizzo /* 217885a7bSLuigi Rizzo * Copyright (C) 2011-2014 Luigi Rizzo. All rights reserved. 368b8534bSLuigi Rizzo * 468b8534bSLuigi Rizzo * Redistribution and use in source and binary forms, with or without 568b8534bSLuigi Rizzo * modification, are permitted provided that the following conditions 668b8534bSLuigi Rizzo * are met: 768b8534bSLuigi Rizzo * 1. Redistributions of source code must retain the above copyright 868b8534bSLuigi Rizzo * notice, this list of conditions and the following disclaimer. 968b8534bSLuigi Rizzo * 2. Redistributions in binary form must reproduce the above copyright 1068b8534bSLuigi Rizzo * notice, this list of conditions and the following disclaimer in the 1168b8534bSLuigi Rizzo * documentation and/or other materials provided with the distribution. 1268b8534bSLuigi Rizzo * 1368b8534bSLuigi Rizzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1468b8534bSLuigi Rizzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1568b8534bSLuigi Rizzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1668b8534bSLuigi Rizzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1768b8534bSLuigi Rizzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1868b8534bSLuigi Rizzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1968b8534bSLuigi Rizzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2068b8534bSLuigi Rizzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2168b8534bSLuigi Rizzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2268b8534bSLuigi Rizzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2368b8534bSLuigi Rizzo * SUCH DAMAGE. 2468b8534bSLuigi Rizzo */ 2568b8534bSLuigi Rizzo 2668b8534bSLuigi Rizzo /* 2768b8534bSLuigi Rizzo * $FreeBSD$ 2868b8534bSLuigi Rizzo * 29f9790aebSLuigi Rizzo * netmap support for: re 30f9790aebSLuigi Rizzo * 31f9790aebSLuigi Rizzo * For more details on netmap support please see ixgbe_netmap.h 3268b8534bSLuigi Rizzo */ 3368b8534bSLuigi Rizzo 3464ae02c3SLuigi Rizzo 3568b8534bSLuigi Rizzo #include <net/netmap.h> 3668b8534bSLuigi Rizzo #include <sys/selinfo.h> 3768b8534bSLuigi Rizzo #include <vm/vm.h> 3868b8534bSLuigi Rizzo #include <vm/pmap.h> /* vtophys ? */ 3968b8534bSLuigi Rizzo #include <dev/netmap/netmap_kern.h> 4068b8534bSLuigi Rizzo 4168b8534bSLuigi Rizzo 4268b8534bSLuigi Rizzo /* 43f9790aebSLuigi Rizzo * Register/unregister. We are already under netmap lock. 4468b8534bSLuigi Rizzo */ 4568b8534bSLuigi Rizzo static int 46f9790aebSLuigi Rizzo re_netmap_reg(struct netmap_adapter *na, int onoff) 4768b8534bSLuigi Rizzo { 48f9790aebSLuigi Rizzo struct ifnet *ifp = na->ifp; 4968b8534bSLuigi Rizzo struct rl_softc *adapter = ifp->if_softc; 5068b8534bSLuigi Rizzo 51f9790aebSLuigi Rizzo RL_LOCK(adapter); 52f9790aebSLuigi Rizzo re_stop(adapter); /* also clears IFF_DRV_RUNNING */ 5368b8534bSLuigi Rizzo if (onoff) { 54f9790aebSLuigi Rizzo nm_set_native_flags(na); 5568b8534bSLuigi Rizzo } else { 56f9790aebSLuigi Rizzo nm_clear_native_flags(na); 5768b8534bSLuigi Rizzo } 58f9790aebSLuigi Rizzo re_init_locked(adapter); /* also enables intr */ 59f9790aebSLuigi Rizzo RL_UNLOCK(adapter); 60f9790aebSLuigi Rizzo return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); 6168b8534bSLuigi Rizzo } 6268b8534bSLuigi Rizzo 6368b8534bSLuigi Rizzo 6468b8534bSLuigi Rizzo /* 6568b8534bSLuigi Rizzo * Reconcile kernel and user view of the transmit ring. 6668b8534bSLuigi Rizzo */ 6768b8534bSLuigi Rizzo static int 68*4bf50f18SLuigi Rizzo re_netmap_txsync(struct netmap_kring *kring, int flags) 6968b8534bSLuigi Rizzo { 70*4bf50f18SLuigi Rizzo struct netmap_adapter *na = kring->na; 71f9790aebSLuigi Rizzo struct ifnet *ifp = na->ifp; 7268b8534bSLuigi Rizzo struct netmap_ring *ring = kring->ring; 73f9790aebSLuigi Rizzo u_int nm_i; /* index into the netmap ring */ 74f9790aebSLuigi Rizzo u_int nic_i; /* index into the NIC ring */ 7517885a7bSLuigi Rizzo u_int n; 76f9790aebSLuigi Rizzo u_int const lim = kring->nkr_num_slots - 1; 7717885a7bSLuigi Rizzo u_int const head = kring->rhead; 7868b8534bSLuigi Rizzo 79f9790aebSLuigi Rizzo /* device-specific */ 80f9790aebSLuigi Rizzo struct rl_softc *sc = ifp->if_softc; 81f9790aebSLuigi Rizzo struct rl_txdesc *txd = sc->rl_ldata.rl_tx_desc; 82f9790aebSLuigi Rizzo 8368b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, 8468b8534bSLuigi Rizzo sc->rl_ldata.rl_tx_list_map, 85f9790aebSLuigi Rizzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); // XXX extra postwrite ? 8668b8534bSLuigi Rizzo 87f9790aebSLuigi Rizzo /* 88f9790aebSLuigi Rizzo * First part: process new packets to send. 89f9790aebSLuigi Rizzo */ 90f9790aebSLuigi Rizzo nm_i = kring->nr_hwcur; 9117885a7bSLuigi Rizzo if (nm_i != head) { /* we have new packets to send */ 92f9790aebSLuigi Rizzo nic_i = sc->rl_ldata.rl_tx_prodidx; 93f9790aebSLuigi Rizzo // XXX or netmap_idx_k2n(kring, nm_i); 9468b8534bSLuigi Rizzo 9517885a7bSLuigi Rizzo for (n = 0; nm_i != head; n++) { 96f9790aebSLuigi Rizzo struct netmap_slot *slot = &ring->slot[nm_i]; 97f9790aebSLuigi Rizzo u_int len = slot->len; 986e10c8b8SLuigi Rizzo uint64_t paddr; 99*4bf50f18SLuigi Rizzo void *addr = PNMB(na, slot, &paddr); 10068b8534bSLuigi Rizzo 101f9790aebSLuigi Rizzo /* device-specific */ 102f9790aebSLuigi Rizzo struct rl_desc *desc = &sc->rl_ldata.rl_tx_list[nic_i]; 103f9790aebSLuigi Rizzo int cmd = slot->len | RL_TDESC_CMD_EOF | 104f9790aebSLuigi Rizzo RL_TDESC_CMD_OWN | RL_TDESC_CMD_SOF ; 10568b8534bSLuigi Rizzo 106*4bf50f18SLuigi Rizzo NM_CHECK_ADDR_LEN(na, addr, len); 107f9790aebSLuigi Rizzo 108f9790aebSLuigi Rizzo if (nic_i == lim) /* mark end of ring */ 10968b8534bSLuigi Rizzo cmd |= RL_TDESC_CMD_EOR; 11068b8534bSLuigi Rizzo 11168b8534bSLuigi Rizzo if (slot->flags & NS_BUF_CHANGED) { 112f9790aebSLuigi Rizzo /* buffer has changed, reload map */ 11368b8534bSLuigi Rizzo desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 11468b8534bSLuigi Rizzo desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 115*4bf50f18SLuigi Rizzo netmap_reload_map(na, sc->rl_ldata.rl_tx_mtag, 116f9790aebSLuigi Rizzo txd[nic_i].tx_dmamap, addr); 11768b8534bSLuigi Rizzo } 118f9790aebSLuigi Rizzo slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); 11968b8534bSLuigi Rizzo 120f9790aebSLuigi Rizzo /* Fill the slot in the NIC ring. */ 121f9790aebSLuigi Rizzo desc->rl_cmdstat = htole32(cmd); 122f9790aebSLuigi Rizzo 123f9790aebSLuigi Rizzo /* make sure changes to the buffer are synced */ 124f9790aebSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_tx_mtag, 125f9790aebSLuigi Rizzo txd[nic_i].tx_dmamap, 126f9790aebSLuigi Rizzo BUS_DMASYNC_PREWRITE); 127f9790aebSLuigi Rizzo 128f9790aebSLuigi Rizzo nm_i = nm_next(nm_i, lim); 129f9790aebSLuigi Rizzo nic_i = nm_next(nic_i, lim); 130f9790aebSLuigi Rizzo } 131f9790aebSLuigi Rizzo sc->rl_ldata.rl_tx_prodidx = nic_i; 13217885a7bSLuigi Rizzo kring->nr_hwcur = head; 133f9790aebSLuigi Rizzo 134f9790aebSLuigi Rizzo /* synchronize the NIC ring */ 13568b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, 13668b8534bSLuigi Rizzo sc->rl_ldata.rl_tx_list_map, 137f9790aebSLuigi Rizzo BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 13868b8534bSLuigi Rizzo 13968b8534bSLuigi Rizzo /* start ? */ 14068b8534bSLuigi Rizzo CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); 14168b8534bSLuigi Rizzo } 142f9790aebSLuigi Rizzo 143f9790aebSLuigi Rizzo /* 144f9790aebSLuigi Rizzo * Second part: reclaim buffers for completed transmissions. 145f9790aebSLuigi Rizzo */ 14617885a7bSLuigi Rizzo if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) { 147f9790aebSLuigi Rizzo nic_i = sc->rl_ldata.rl_tx_considx; 148f9790aebSLuigi Rizzo for (n = 0; nic_i != sc->rl_ldata.rl_tx_prodidx; 149f9790aebSLuigi Rizzo n++, nic_i = RL_TX_DESC_NXT(sc, nic_i)) { 150f9790aebSLuigi Rizzo uint32_t cmdstat = 151f9790aebSLuigi Rizzo le32toh(sc->rl_ldata.rl_tx_list[nic_i].rl_cmdstat); 152f9790aebSLuigi Rizzo if (cmdstat & RL_TDESC_STAT_OWN) 153f9790aebSLuigi Rizzo break; 154f9790aebSLuigi Rizzo } 155f9790aebSLuigi Rizzo if (n > 0) { 156f9790aebSLuigi Rizzo sc->rl_ldata.rl_tx_considx = nic_i; 157f9790aebSLuigi Rizzo sc->rl_ldata.rl_tx_free += n; 15817885a7bSLuigi Rizzo kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); 159f9790aebSLuigi Rizzo } 160f9790aebSLuigi Rizzo } 161f9790aebSLuigi Rizzo 16217885a7bSLuigi Rizzo nm_txsync_finalize(kring); 163f9790aebSLuigi Rizzo 16468b8534bSLuigi Rizzo return 0; 16568b8534bSLuigi Rizzo } 16668b8534bSLuigi Rizzo 16768b8534bSLuigi Rizzo 16868b8534bSLuigi Rizzo /* 16968b8534bSLuigi Rizzo * Reconcile kernel and user view of the receive ring. 17068b8534bSLuigi Rizzo */ 17168b8534bSLuigi Rizzo static int 172*4bf50f18SLuigi Rizzo re_netmap_rxsync(struct netmap_kring *kring, int flags) 17368b8534bSLuigi Rizzo { 174*4bf50f18SLuigi Rizzo struct netmap_adapter *na = kring->na; 175f9790aebSLuigi Rizzo struct ifnet *ifp = na->ifp; 17668b8534bSLuigi Rizzo struct netmap_ring *ring = kring->ring; 177f9790aebSLuigi Rizzo u_int nm_i; /* index into the netmap ring */ 178f9790aebSLuigi Rizzo u_int nic_i; /* index into the NIC ring */ 17917885a7bSLuigi Rizzo u_int n; 180f9790aebSLuigi Rizzo u_int const lim = kring->nkr_num_slots - 1; 18117885a7bSLuigi Rizzo u_int const head = nm_rxsync_prologue(kring); 182ce3ee1e7SLuigi Rizzo int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; 18368b8534bSLuigi Rizzo 184f9790aebSLuigi Rizzo /* device-specific */ 185f9790aebSLuigi Rizzo struct rl_softc *sc = ifp->if_softc; 186f9790aebSLuigi Rizzo struct rl_rxdesc *rxd = sc->rl_ldata.rl_rx_desc; 187f9790aebSLuigi Rizzo 18817885a7bSLuigi Rizzo if (head > lim) 18968b8534bSLuigi Rizzo return netmap_ring_reinit(kring); 19068b8534bSLuigi Rizzo 19168b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag, 19268b8534bSLuigi Rizzo sc->rl_ldata.rl_rx_list_map, 19368b8534bSLuigi Rizzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 19468b8534bSLuigi Rizzo 19568b8534bSLuigi Rizzo /* 196f9790aebSLuigi Rizzo * First part: import newly received packets. 19764ae02c3SLuigi Rizzo * 198f9790aebSLuigi Rizzo * This device uses all the buffers in the ring, so we need 19968b8534bSLuigi Rizzo * another termination condition in addition to RL_RDESC_STAT_OWN 20017885a7bSLuigi Rizzo * cleared (all buffers could have it cleared). The easiest one 20117885a7bSLuigi Rizzo * is to stop right before nm_hwcur. 20268b8534bSLuigi Rizzo */ 20364ae02c3SLuigi Rizzo if (netmap_no_pendintr || force_update) { 2041dce924dSLuigi Rizzo uint16_t slot_flags = kring->nkr_slot_flags; 20517885a7bSLuigi Rizzo uint32_t stop_i = nm_prev(kring->nr_hwcur, lim); 2061dce924dSLuigi Rizzo 207f9790aebSLuigi Rizzo nic_i = sc->rl_ldata.rl_rx_prodidx; /* next pkt to check */ 208f9790aebSLuigi Rizzo nm_i = netmap_idx_n2k(kring, nic_i); 209f9790aebSLuigi Rizzo 21017885a7bSLuigi Rizzo while (nm_i != stop_i) { 211f9790aebSLuigi Rizzo struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[nic_i]; 21268b8534bSLuigi Rizzo uint32_t rxstat = le32toh(cur_rx->rl_cmdstat); 21368b8534bSLuigi Rizzo uint32_t total_len; 21468b8534bSLuigi Rizzo 21568b8534bSLuigi Rizzo if ((rxstat & RL_RDESC_STAT_OWN) != 0) 21668b8534bSLuigi Rizzo break; 21768b8534bSLuigi Rizzo total_len = rxstat & sc->rl_rxlenmask; 21868b8534bSLuigi Rizzo /* XXX subtract crc */ 21968b8534bSLuigi Rizzo total_len = (total_len < 4) ? 0 : total_len - 4; 220f9790aebSLuigi Rizzo ring->slot[nm_i].len = total_len; 221f9790aebSLuigi Rizzo ring->slot[nm_i].flags = slot_flags; 22268b8534bSLuigi Rizzo /* sync was in re_newbuf() */ 22368b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, 224f9790aebSLuigi Rizzo rxd[nic_i].rx_dmamap, BUS_DMASYNC_POSTREAD); 22517885a7bSLuigi Rizzo // sc->rl_ifp->if_ipackets++; 226f9790aebSLuigi Rizzo nm_i = nm_next(nm_i, lim); 227f9790aebSLuigi Rizzo nic_i = nm_next(nic_i, lim); 22868b8534bSLuigi Rizzo } 229f9790aebSLuigi Rizzo sc->rl_ldata.rl_rx_prodidx = nic_i; 23017885a7bSLuigi Rizzo kring->nr_hwtail = nm_i; 23164ae02c3SLuigi Rizzo kring->nr_kflags &= ~NKR_PENDINTR; 23264ae02c3SLuigi Rizzo } 23368b8534bSLuigi Rizzo 234f9790aebSLuigi Rizzo /* 235f9790aebSLuigi Rizzo * Second part: skip past packets that userspace has released. 236f9790aebSLuigi Rizzo */ 237f9790aebSLuigi Rizzo nm_i = kring->nr_hwcur; 23817885a7bSLuigi Rizzo if (nm_i != head) { 239f9790aebSLuigi Rizzo nic_i = netmap_idx_k2n(kring, nm_i); 24017885a7bSLuigi Rizzo for (n = 0; nm_i != head; n++) { 241f9790aebSLuigi Rizzo struct netmap_slot *slot = &ring->slot[nm_i]; 2426e10c8b8SLuigi Rizzo uint64_t paddr; 243*4bf50f18SLuigi Rizzo void *addr = PNMB(na, slot, &paddr); 24468b8534bSLuigi Rizzo 245f9790aebSLuigi Rizzo struct rl_desc *desc = &sc->rl_ldata.rl_rx_list[nic_i]; 246*4bf50f18SLuigi Rizzo int cmd = NETMAP_BUF_SIZE(na) | RL_RDESC_CMD_OWN; 24768b8534bSLuigi Rizzo 248*4bf50f18SLuigi Rizzo if (addr == NETMAP_BUF_BASE(na)) /* bad buf */ 249f9790aebSLuigi Rizzo goto ring_reset; 250f9790aebSLuigi Rizzo 251f9790aebSLuigi Rizzo if (nic_i == lim) /* mark end of ring */ 25268b8534bSLuigi Rizzo cmd |= RL_RDESC_CMD_EOR; 25368b8534bSLuigi Rizzo 25468b8534bSLuigi Rizzo if (slot->flags & NS_BUF_CHANGED) { 255f9790aebSLuigi Rizzo /* buffer has changed, reload map */ 25664ae02c3SLuigi Rizzo desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 25764ae02c3SLuigi Rizzo desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 258*4bf50f18SLuigi Rizzo netmap_reload_map(na, sc->rl_ldata.rl_rx_mtag, 259f9790aebSLuigi Rizzo rxd[nic_i].rx_dmamap, addr); 26068b8534bSLuigi Rizzo slot->flags &= ~NS_BUF_CHANGED; 26168b8534bSLuigi Rizzo } 26264ae02c3SLuigi Rizzo desc->rl_cmdstat = htole32(cmd); 26368b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, 264f9790aebSLuigi Rizzo rxd[nic_i].rx_dmamap, 265f9790aebSLuigi Rizzo BUS_DMASYNC_PREREAD); 266f9790aebSLuigi Rizzo nm_i = nm_next(nm_i, lim); 267f9790aebSLuigi Rizzo nic_i = nm_next(nic_i, lim); 26868b8534bSLuigi Rizzo } 26917885a7bSLuigi Rizzo kring->nr_hwcur = head; 27068b8534bSLuigi Rizzo 27168b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag, 27268b8534bSLuigi Rizzo sc->rl_ldata.rl_rx_list_map, 273f9790aebSLuigi Rizzo BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 27468b8534bSLuigi Rizzo } 275f9790aebSLuigi Rizzo 276f9790aebSLuigi Rizzo /* tell userspace that there might be new packets */ 27717885a7bSLuigi Rizzo nm_rxsync_finalize(kring); 278f9790aebSLuigi Rizzo 27968b8534bSLuigi Rizzo return 0; 280f9790aebSLuigi Rizzo 281f9790aebSLuigi Rizzo ring_reset: 282f9790aebSLuigi Rizzo return netmap_ring_reinit(kring); 28368b8534bSLuigi Rizzo } 28468b8534bSLuigi Rizzo 285f9790aebSLuigi Rizzo 286506cc70cSLuigi Rizzo /* 287506cc70cSLuigi Rizzo * Additional routines to init the tx and rx rings. 288506cc70cSLuigi Rizzo * In other drivers we do that inline in the main code. 289506cc70cSLuigi Rizzo */ 29068b8534bSLuigi Rizzo static void 29168b8534bSLuigi Rizzo re_netmap_tx_init(struct rl_softc *sc) 29268b8534bSLuigi Rizzo { 29368b8534bSLuigi Rizzo struct rl_txdesc *txd; 29468b8534bSLuigi Rizzo struct rl_desc *desc; 295506cc70cSLuigi Rizzo int i, n; 29668b8534bSLuigi Rizzo struct netmap_adapter *na = NA(sc->rl_ifp); 297f9790aebSLuigi Rizzo struct netmap_slot *slot; 29868b8534bSLuigi Rizzo 299f9790aebSLuigi Rizzo slot = netmap_reset(na, NR_TX, 0, 0); 300*4bf50f18SLuigi Rizzo /* slot is NULL if we are not in native netmap mode */ 30168b8534bSLuigi Rizzo if (!slot) 302*4bf50f18SLuigi Rizzo return; 30368b8534bSLuigi Rizzo /* in netmap mode, overwrite addresses and maps */ 30468b8534bSLuigi Rizzo txd = sc->rl_ldata.rl_tx_desc; 30568b8534bSLuigi Rizzo desc = sc->rl_ldata.rl_tx_list; 306506cc70cSLuigi Rizzo n = sc->rl_ldata.rl_tx_desc_cnt; 30768b8534bSLuigi Rizzo 308506cc70cSLuigi Rizzo /* l points in the netmap ring, i points in the NIC ring */ 309506cc70cSLuigi Rizzo for (i = 0; i < n; i++) { 310506cc70cSLuigi Rizzo uint64_t paddr; 31164ae02c3SLuigi Rizzo int l = netmap_idx_n2k(&na->tx_rings[0], i); 312*4bf50f18SLuigi Rizzo void *addr = PNMB(na, slot + l, &paddr); 313506cc70cSLuigi Rizzo 31468b8534bSLuigi Rizzo desc[i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 31568b8534bSLuigi Rizzo desc[i].rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 316*4bf50f18SLuigi Rizzo netmap_load_map(na, sc->rl_ldata.rl_tx_mtag, 3176e10c8b8SLuigi Rizzo txd[i].tx_dmamap, addr); 31868b8534bSLuigi Rizzo } 31968b8534bSLuigi Rizzo } 32068b8534bSLuigi Rizzo 32168b8534bSLuigi Rizzo static void 32268b8534bSLuigi Rizzo re_netmap_rx_init(struct rl_softc *sc) 32368b8534bSLuigi Rizzo { 32468b8534bSLuigi Rizzo struct netmap_adapter *na = NA(sc->rl_ifp); 32568b8534bSLuigi Rizzo struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0); 32668b8534bSLuigi Rizzo struct rl_desc *desc = sc->rl_ldata.rl_rx_list; 32768b8534bSLuigi Rizzo uint32_t cmdstat; 32817885a7bSLuigi Rizzo uint32_t nic_i, max_avail; 32917885a7bSLuigi Rizzo uint32_t const n = sc->rl_ldata.rl_rx_desc_cnt; 33068b8534bSLuigi Rizzo 33168b8534bSLuigi Rizzo if (!slot) 33268b8534bSLuigi Rizzo return; 3335644ccecSLuigi Rizzo /* 33417885a7bSLuigi Rizzo * Do not release the slots owned by userspace, 33517885a7bSLuigi Rizzo * and also keep one empty. 3365644ccecSLuigi Rizzo */ 33717885a7bSLuigi Rizzo max_avail = n - 1 - nm_kr_rxspace(&na->rx_rings[0]); 33817885a7bSLuigi Rizzo for (nic_i = 0; nic_i < n; nic_i++) { 339506cc70cSLuigi Rizzo void *addr; 340506cc70cSLuigi Rizzo uint64_t paddr; 34117885a7bSLuigi Rizzo uint32_t nm_i = netmap_idx_n2k(&na->rx_rings[0], nic_i); 34268b8534bSLuigi Rizzo 343*4bf50f18SLuigi Rizzo addr = PNMB(na, slot + nm_i, &paddr); 3446e10c8b8SLuigi Rizzo 345*4bf50f18SLuigi Rizzo netmap_reload_map(na, sc->rl_ldata.rl_rx_mtag, 34617885a7bSLuigi Rizzo sc->rl_ldata.rl_rx_desc[nic_i].rx_dmamap, addr); 3476e10c8b8SLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, 34817885a7bSLuigi Rizzo sc->rl_ldata.rl_rx_desc[nic_i].rx_dmamap, BUS_DMASYNC_PREREAD); 34917885a7bSLuigi Rizzo desc[nic_i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 35017885a7bSLuigi Rizzo desc[nic_i].rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 351*4bf50f18SLuigi Rizzo cmdstat = NETMAP_BUF_SIZE(na); 35217885a7bSLuigi Rizzo if (nic_i == n - 1) /* mark the end of ring */ 35368b8534bSLuigi Rizzo cmdstat |= RL_RDESC_CMD_EOR; 35417885a7bSLuigi Rizzo if (nic_i < max_avail) 355506cc70cSLuigi Rizzo cmdstat |= RL_RDESC_CMD_OWN; 35617885a7bSLuigi Rizzo desc[nic_i].rl_cmdstat = htole32(cmdstat); 35768b8534bSLuigi Rizzo } 35868b8534bSLuigi Rizzo } 35964ae02c3SLuigi Rizzo 36064ae02c3SLuigi Rizzo 36164ae02c3SLuigi Rizzo static void 36264ae02c3SLuigi Rizzo re_netmap_attach(struct rl_softc *sc) 36364ae02c3SLuigi Rizzo { 36464ae02c3SLuigi Rizzo struct netmap_adapter na; 36564ae02c3SLuigi Rizzo 36664ae02c3SLuigi Rizzo bzero(&na, sizeof(na)); 36764ae02c3SLuigi Rizzo 36864ae02c3SLuigi Rizzo na.ifp = sc->rl_ifp; 369ce3ee1e7SLuigi Rizzo na.na_flags = NAF_BDG_MAYSLEEP; 37064ae02c3SLuigi Rizzo na.num_tx_desc = sc->rl_ldata.rl_tx_desc_cnt; 37164ae02c3SLuigi Rizzo na.num_rx_desc = sc->rl_ldata.rl_rx_desc_cnt; 37264ae02c3SLuigi Rizzo na.nm_txsync = re_netmap_txsync; 37364ae02c3SLuigi Rizzo na.nm_rxsync = re_netmap_rxsync; 37464ae02c3SLuigi Rizzo na.nm_register = re_netmap_reg; 375f9790aebSLuigi Rizzo na.num_tx_rings = na.num_rx_rings = 1; 376f9790aebSLuigi Rizzo netmap_attach(&na); 37764ae02c3SLuigi Rizzo } 378f9790aebSLuigi Rizzo 37964ae02c3SLuigi Rizzo /* end of file */ 380