1718cf2ccSPedro F. Giffuni /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 417885a7bSLuigi Rizzo * Copyright (C) 2011-2014 Luigi Rizzo. All rights reserved. 568b8534bSLuigi Rizzo * 668b8534bSLuigi Rizzo * Redistribution and use in source and binary forms, with or without 768b8534bSLuigi Rizzo * modification, are permitted provided that the following conditions 868b8534bSLuigi Rizzo * are met: 968b8534bSLuigi Rizzo * 1. Redistributions of source code must retain the above copyright 1068b8534bSLuigi Rizzo * notice, this list of conditions and the following disclaimer. 1168b8534bSLuigi Rizzo * 2. Redistributions in binary form must reproduce the above copyright 1268b8534bSLuigi Rizzo * notice, this list of conditions and the following disclaimer in the 1368b8534bSLuigi Rizzo * documentation and/or other materials provided with the distribution. 1468b8534bSLuigi Rizzo * 1568b8534bSLuigi Rizzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1668b8534bSLuigi Rizzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1768b8534bSLuigi Rizzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1868b8534bSLuigi Rizzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1968b8534bSLuigi Rizzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2068b8534bSLuigi Rizzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2168b8534bSLuigi Rizzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2268b8534bSLuigi Rizzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2368b8534bSLuigi Rizzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2468b8534bSLuigi Rizzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2568b8534bSLuigi Rizzo * SUCH DAMAGE. 2668b8534bSLuigi Rizzo */ 2768b8534bSLuigi Rizzo 2868b8534bSLuigi Rizzo /* 2968b8534bSLuigi Rizzo * $FreeBSD$ 3068b8534bSLuigi Rizzo * 31f9790aebSLuigi Rizzo * netmap support for: re 32f9790aebSLuigi Rizzo * 33f9790aebSLuigi Rizzo * For more details on netmap support please see ixgbe_netmap.h 3468b8534bSLuigi Rizzo */ 3568b8534bSLuigi Rizzo 3664ae02c3SLuigi Rizzo 3768b8534bSLuigi Rizzo #include <net/netmap.h> 3868b8534bSLuigi Rizzo #include <sys/selinfo.h> 3968b8534bSLuigi Rizzo #include <vm/vm.h> 4068b8534bSLuigi Rizzo #include <vm/pmap.h> /* vtophys ? */ 4168b8534bSLuigi Rizzo #include <dev/netmap/netmap_kern.h> 4268b8534bSLuigi Rizzo 4368b8534bSLuigi Rizzo 4468b8534bSLuigi Rizzo /* 45f9790aebSLuigi Rizzo * Register/unregister. We are already under netmap lock. 4668b8534bSLuigi Rizzo */ 4768b8534bSLuigi Rizzo static int 48f9790aebSLuigi Rizzo re_netmap_reg(struct netmap_adapter *na, int onoff) 4968b8534bSLuigi Rizzo { 50f9790aebSLuigi Rizzo struct ifnet *ifp = na->ifp; 5168b8534bSLuigi Rizzo struct rl_softc *adapter = ifp->if_softc; 5268b8534bSLuigi Rizzo 53f9790aebSLuigi Rizzo RL_LOCK(adapter); 54f9790aebSLuigi Rizzo re_stop(adapter); /* also clears IFF_DRV_RUNNING */ 5568b8534bSLuigi Rizzo if (onoff) { 56f9790aebSLuigi Rizzo nm_set_native_flags(na); 5768b8534bSLuigi Rizzo } else { 58f9790aebSLuigi Rizzo nm_clear_native_flags(na); 5968b8534bSLuigi Rizzo } 60f9790aebSLuigi Rizzo re_init_locked(adapter); /* also enables intr */ 61f9790aebSLuigi Rizzo RL_UNLOCK(adapter); 62f9790aebSLuigi Rizzo return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); 6368b8534bSLuigi Rizzo } 6468b8534bSLuigi Rizzo 6568b8534bSLuigi Rizzo 6668b8534bSLuigi Rizzo /* 6768b8534bSLuigi Rizzo * Reconcile kernel and user view of the transmit ring. 6868b8534bSLuigi Rizzo */ 6968b8534bSLuigi Rizzo static int 704bf50f18SLuigi Rizzo re_netmap_txsync(struct netmap_kring *kring, int flags) 7168b8534bSLuigi Rizzo { 724bf50f18SLuigi Rizzo struct netmap_adapter *na = kring->na; 73f9790aebSLuigi Rizzo struct ifnet *ifp = na->ifp; 7468b8534bSLuigi Rizzo struct netmap_ring *ring = kring->ring; 75f9790aebSLuigi Rizzo u_int nm_i; /* index into the netmap ring */ 76f9790aebSLuigi Rizzo u_int nic_i; /* index into the NIC ring */ 7717885a7bSLuigi Rizzo u_int n; 78f9790aebSLuigi Rizzo u_int const lim = kring->nkr_num_slots - 1; 7917885a7bSLuigi Rizzo u_int const head = kring->rhead; 8068b8534bSLuigi Rizzo 81f9790aebSLuigi Rizzo /* device-specific */ 82f9790aebSLuigi Rizzo struct rl_softc *sc = ifp->if_softc; 83f9790aebSLuigi Rizzo struct rl_txdesc *txd = sc->rl_ldata.rl_tx_desc; 84f9790aebSLuigi Rizzo 8568b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, 8668b8534bSLuigi Rizzo sc->rl_ldata.rl_tx_list_map, 87f9790aebSLuigi Rizzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); // XXX extra postwrite ? 8868b8534bSLuigi Rizzo 89f9790aebSLuigi Rizzo /* 90f9790aebSLuigi Rizzo * First part: process new packets to send. 91f9790aebSLuigi Rizzo */ 92f9790aebSLuigi Rizzo nm_i = kring->nr_hwcur; 9317885a7bSLuigi Rizzo if (nm_i != head) { /* we have new packets to send */ 94f9790aebSLuigi Rizzo nic_i = sc->rl_ldata.rl_tx_prodidx; 95f9790aebSLuigi Rizzo // XXX or netmap_idx_k2n(kring, nm_i); 9668b8534bSLuigi Rizzo 9717885a7bSLuigi Rizzo for (n = 0; nm_i != head; n++) { 98f9790aebSLuigi Rizzo struct netmap_slot *slot = &ring->slot[nm_i]; 99f9790aebSLuigi Rizzo u_int len = slot->len; 1006e10c8b8SLuigi Rizzo uint64_t paddr; 1014bf50f18SLuigi Rizzo void *addr = PNMB(na, slot, &paddr); 10268b8534bSLuigi Rizzo 103f9790aebSLuigi Rizzo /* device-specific */ 104f9790aebSLuigi Rizzo struct rl_desc *desc = &sc->rl_ldata.rl_tx_list[nic_i]; 105f9790aebSLuigi Rizzo int cmd = slot->len | RL_TDESC_CMD_EOF | 106f9790aebSLuigi Rizzo RL_TDESC_CMD_OWN | RL_TDESC_CMD_SOF ; 10768b8534bSLuigi Rizzo 1084bf50f18SLuigi Rizzo NM_CHECK_ADDR_LEN(na, addr, len); 109f9790aebSLuigi Rizzo 110f9790aebSLuigi Rizzo if (nic_i == lim) /* mark end of ring */ 11168b8534bSLuigi Rizzo cmd |= RL_TDESC_CMD_EOR; 11268b8534bSLuigi Rizzo 11368b8534bSLuigi Rizzo if (slot->flags & NS_BUF_CHANGED) { 114f9790aebSLuigi Rizzo /* buffer has changed, reload map */ 11568b8534bSLuigi Rizzo desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 11668b8534bSLuigi Rizzo desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 1174bf50f18SLuigi Rizzo netmap_reload_map(na, sc->rl_ldata.rl_tx_mtag, 118f9790aebSLuigi Rizzo txd[nic_i].tx_dmamap, addr); 11968b8534bSLuigi Rizzo } 120f9790aebSLuigi Rizzo slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); 12168b8534bSLuigi Rizzo 122f9790aebSLuigi Rizzo /* Fill the slot in the NIC ring. */ 123f9790aebSLuigi Rizzo desc->rl_cmdstat = htole32(cmd); 124f9790aebSLuigi Rizzo 125f9790aebSLuigi Rizzo /* make sure changes to the buffer are synced */ 126f9790aebSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_tx_mtag, 127f9790aebSLuigi Rizzo txd[nic_i].tx_dmamap, 128f9790aebSLuigi Rizzo BUS_DMASYNC_PREWRITE); 129f9790aebSLuigi Rizzo 130f9790aebSLuigi Rizzo nm_i = nm_next(nm_i, lim); 131f9790aebSLuigi Rizzo nic_i = nm_next(nic_i, lim); 132f9790aebSLuigi Rizzo } 133f9790aebSLuigi Rizzo sc->rl_ldata.rl_tx_prodidx = nic_i; 13417885a7bSLuigi Rizzo kring->nr_hwcur = head; 135f9790aebSLuigi Rizzo 136f9790aebSLuigi Rizzo /* synchronize the NIC ring */ 13768b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, 13868b8534bSLuigi Rizzo sc->rl_ldata.rl_tx_list_map, 139f9790aebSLuigi Rizzo BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 14068b8534bSLuigi Rizzo 14168b8534bSLuigi Rizzo /* start ? */ 14268b8534bSLuigi Rizzo CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); 14368b8534bSLuigi Rizzo } 144f9790aebSLuigi Rizzo 145f9790aebSLuigi Rizzo /* 146f9790aebSLuigi Rizzo * Second part: reclaim buffers for completed transmissions. 147f9790aebSLuigi Rizzo */ 14817885a7bSLuigi Rizzo if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) { 149f9790aebSLuigi Rizzo nic_i = sc->rl_ldata.rl_tx_considx; 150f9790aebSLuigi Rizzo for (n = 0; nic_i != sc->rl_ldata.rl_tx_prodidx; 151f9790aebSLuigi Rizzo n++, nic_i = RL_TX_DESC_NXT(sc, nic_i)) { 152f9790aebSLuigi Rizzo uint32_t cmdstat = 153f9790aebSLuigi Rizzo le32toh(sc->rl_ldata.rl_tx_list[nic_i].rl_cmdstat); 154f9790aebSLuigi Rizzo if (cmdstat & RL_TDESC_STAT_OWN) 155f9790aebSLuigi Rizzo break; 156f9790aebSLuigi Rizzo } 157f9790aebSLuigi Rizzo if (n > 0) { 158f9790aebSLuigi Rizzo sc->rl_ldata.rl_tx_considx = nic_i; 159f9790aebSLuigi Rizzo sc->rl_ldata.rl_tx_free += n; 16017885a7bSLuigi Rizzo kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); 161f9790aebSLuigi Rizzo } 162f9790aebSLuigi Rizzo } 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 1724bf50f18SLuigi Rizzo re_netmap_rxsync(struct netmap_kring *kring, int flags) 17368b8534bSLuigi Rizzo { 1744bf50f18SLuigi 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 */ 179f9790aebSLuigi Rizzo u_int const lim = kring->nkr_num_slots - 1; 180847bf383SLuigi Rizzo u_int const head = kring->rhead; 181ce3ee1e7SLuigi Rizzo int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; 18268b8534bSLuigi Rizzo 183f9790aebSLuigi Rizzo /* device-specific */ 184f9790aebSLuigi Rizzo struct rl_softc *sc = ifp->if_softc; 185f9790aebSLuigi Rizzo struct rl_rxdesc *rxd = sc->rl_ldata.rl_rx_desc; 186f9790aebSLuigi Rizzo 18717885a7bSLuigi Rizzo if (head > lim) 18868b8534bSLuigi Rizzo return netmap_ring_reinit(kring); 18968b8534bSLuigi Rizzo 19068b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag, 19168b8534bSLuigi Rizzo sc->rl_ldata.rl_rx_list_map, 19268b8534bSLuigi Rizzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 19368b8534bSLuigi Rizzo 19468b8534bSLuigi Rizzo /* 195f9790aebSLuigi Rizzo * First part: import newly received packets. 19664ae02c3SLuigi Rizzo * 197f9790aebSLuigi Rizzo * This device uses all the buffers in the ring, so we need 19868b8534bSLuigi Rizzo * another termination condition in addition to RL_RDESC_STAT_OWN 19917885a7bSLuigi Rizzo * cleared (all buffers could have it cleared). The easiest one 20017885a7bSLuigi Rizzo * is to stop right before nm_hwcur. 20168b8534bSLuigi Rizzo */ 20264ae02c3SLuigi Rizzo if (netmap_no_pendintr || force_update) { 20317885a7bSLuigi Rizzo uint32_t stop_i = nm_prev(kring->nr_hwcur, lim); 2041dce924dSLuigi Rizzo 205f9790aebSLuigi Rizzo nic_i = sc->rl_ldata.rl_rx_prodidx; /* next pkt to check */ 206f9790aebSLuigi Rizzo nm_i = netmap_idx_n2k(kring, nic_i); 207f9790aebSLuigi Rizzo 20817885a7bSLuigi Rizzo while (nm_i != stop_i) { 209f9790aebSLuigi Rizzo struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[nic_i]; 21068b8534bSLuigi Rizzo uint32_t rxstat = le32toh(cur_rx->rl_cmdstat); 21168b8534bSLuigi Rizzo uint32_t total_len; 21268b8534bSLuigi Rizzo 21368b8534bSLuigi Rizzo if ((rxstat & RL_RDESC_STAT_OWN) != 0) 21468b8534bSLuigi Rizzo break; 21568b8534bSLuigi Rizzo total_len = rxstat & sc->rl_rxlenmask; 21668b8534bSLuigi Rizzo /* XXX subtract crc */ 21768b8534bSLuigi Rizzo total_len = (total_len < 4) ? 0 : total_len - 4; 218f9790aebSLuigi Rizzo ring->slot[nm_i].len = total_len; 2194f80b14cSVincenzo Maffione ring->slot[nm_i].flags = 0; 22068b8534bSLuigi Rizzo /* sync was in re_newbuf() */ 22168b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, 222f9790aebSLuigi Rizzo rxd[nic_i].rx_dmamap, BUS_DMASYNC_POSTREAD); 223c8dfaf38SGleb Smirnoff // if_inc_counter(sc->rl_ifp, IFCOUNTER_IPACKETS, 1); 224f9790aebSLuigi Rizzo nm_i = nm_next(nm_i, lim); 225f9790aebSLuigi Rizzo nic_i = nm_next(nic_i, lim); 22668b8534bSLuigi Rizzo } 227f9790aebSLuigi Rizzo sc->rl_ldata.rl_rx_prodidx = nic_i; 22817885a7bSLuigi Rizzo kring->nr_hwtail = nm_i; 22964ae02c3SLuigi Rizzo kring->nr_kflags &= ~NKR_PENDINTR; 23064ae02c3SLuigi Rizzo } 23168b8534bSLuigi Rizzo 232f9790aebSLuigi Rizzo /* 233f9790aebSLuigi Rizzo * Second part: skip past packets that userspace has released. 234f9790aebSLuigi Rizzo */ 235f9790aebSLuigi Rizzo nm_i = kring->nr_hwcur; 23617885a7bSLuigi Rizzo if (nm_i != head) { 237f9790aebSLuigi Rizzo nic_i = netmap_idx_k2n(kring, nm_i); 238*8bfedf58SDimitry Andric while (nm_i != head) { 239f9790aebSLuigi Rizzo struct netmap_slot *slot = &ring->slot[nm_i]; 2406e10c8b8SLuigi Rizzo uint64_t paddr; 2414bf50f18SLuigi Rizzo void *addr = PNMB(na, slot, &paddr); 24268b8534bSLuigi Rizzo 243f9790aebSLuigi Rizzo struct rl_desc *desc = &sc->rl_ldata.rl_rx_list[nic_i]; 2444bf50f18SLuigi Rizzo int cmd = NETMAP_BUF_SIZE(na) | RL_RDESC_CMD_OWN; 24568b8534bSLuigi Rizzo 2464bf50f18SLuigi Rizzo if (addr == NETMAP_BUF_BASE(na)) /* bad buf */ 247f9790aebSLuigi Rizzo goto ring_reset; 248f9790aebSLuigi Rizzo 249f9790aebSLuigi Rizzo if (nic_i == lim) /* mark end of ring */ 25068b8534bSLuigi Rizzo cmd |= RL_RDESC_CMD_EOR; 25168b8534bSLuigi Rizzo 25268b8534bSLuigi Rizzo if (slot->flags & NS_BUF_CHANGED) { 253f9790aebSLuigi Rizzo /* buffer has changed, reload map */ 25464ae02c3SLuigi Rizzo desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 25564ae02c3SLuigi Rizzo desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 2564bf50f18SLuigi Rizzo netmap_reload_map(na, sc->rl_ldata.rl_rx_mtag, 257f9790aebSLuigi Rizzo rxd[nic_i].rx_dmamap, addr); 25868b8534bSLuigi Rizzo slot->flags &= ~NS_BUF_CHANGED; 25968b8534bSLuigi Rizzo } 26064ae02c3SLuigi Rizzo desc->rl_cmdstat = htole32(cmd); 26168b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, 262f9790aebSLuigi Rizzo rxd[nic_i].rx_dmamap, 263f9790aebSLuigi Rizzo BUS_DMASYNC_PREREAD); 264f9790aebSLuigi Rizzo nm_i = nm_next(nm_i, lim); 265f9790aebSLuigi Rizzo nic_i = nm_next(nic_i, lim); 26668b8534bSLuigi Rizzo } 26717885a7bSLuigi Rizzo kring->nr_hwcur = head; 26868b8534bSLuigi Rizzo 26968b8534bSLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag, 27068b8534bSLuigi Rizzo sc->rl_ldata.rl_rx_list_map, 271f9790aebSLuigi Rizzo BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 27268b8534bSLuigi Rizzo } 273f9790aebSLuigi Rizzo 27468b8534bSLuigi Rizzo return 0; 275f9790aebSLuigi Rizzo 276f9790aebSLuigi Rizzo ring_reset: 277f9790aebSLuigi Rizzo return netmap_ring_reinit(kring); 27868b8534bSLuigi Rizzo } 27968b8534bSLuigi Rizzo 280f9790aebSLuigi Rizzo 281506cc70cSLuigi Rizzo /* 282506cc70cSLuigi Rizzo * Additional routines to init the tx and rx rings. 283506cc70cSLuigi Rizzo * In other drivers we do that inline in the main code. 284506cc70cSLuigi Rizzo */ 28568b8534bSLuigi Rizzo static void 28668b8534bSLuigi Rizzo re_netmap_tx_init(struct rl_softc *sc) 28768b8534bSLuigi Rizzo { 28868b8534bSLuigi Rizzo struct rl_txdesc *txd; 28968b8534bSLuigi Rizzo struct rl_desc *desc; 290506cc70cSLuigi Rizzo int i, n; 29168b8534bSLuigi Rizzo struct netmap_adapter *na = NA(sc->rl_ifp); 292f9790aebSLuigi Rizzo struct netmap_slot *slot; 29368b8534bSLuigi Rizzo 294f9790aebSLuigi Rizzo slot = netmap_reset(na, NR_TX, 0, 0); 2954bf50f18SLuigi Rizzo /* slot is NULL if we are not in native netmap mode */ 29668b8534bSLuigi Rizzo if (!slot) 2974bf50f18SLuigi Rizzo return; 29868b8534bSLuigi Rizzo /* in netmap mode, overwrite addresses and maps */ 29968b8534bSLuigi Rizzo txd = sc->rl_ldata.rl_tx_desc; 30068b8534bSLuigi Rizzo desc = sc->rl_ldata.rl_tx_list; 301506cc70cSLuigi Rizzo n = sc->rl_ldata.rl_tx_desc_cnt; 30268b8534bSLuigi Rizzo 303506cc70cSLuigi Rizzo /* l points in the netmap ring, i points in the NIC ring */ 304506cc70cSLuigi Rizzo for (i = 0; i < n; i++) { 305506cc70cSLuigi Rizzo uint64_t paddr; 3062ff91c17SVincenzo Maffione int l = netmap_idx_n2k(na->tx_rings[0], i); 3074bf50f18SLuigi Rizzo void *addr = PNMB(na, slot + l, &paddr); 308506cc70cSLuigi Rizzo 30968b8534bSLuigi Rizzo desc[i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 31068b8534bSLuigi Rizzo desc[i].rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 3114bf50f18SLuigi Rizzo netmap_load_map(na, sc->rl_ldata.rl_tx_mtag, 3126e10c8b8SLuigi Rizzo txd[i].tx_dmamap, addr); 31368b8534bSLuigi Rizzo } 31468b8534bSLuigi Rizzo } 31568b8534bSLuigi Rizzo 31668b8534bSLuigi Rizzo static void 31768b8534bSLuigi Rizzo re_netmap_rx_init(struct rl_softc *sc) 31868b8534bSLuigi Rizzo { 31968b8534bSLuigi Rizzo struct netmap_adapter *na = NA(sc->rl_ifp); 32068b8534bSLuigi Rizzo struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0); 32168b8534bSLuigi Rizzo struct rl_desc *desc = sc->rl_ldata.rl_rx_list; 32268b8534bSLuigi Rizzo uint32_t cmdstat; 32317885a7bSLuigi Rizzo uint32_t nic_i, max_avail; 32417885a7bSLuigi Rizzo uint32_t const n = sc->rl_ldata.rl_rx_desc_cnt; 32568b8534bSLuigi Rizzo 32668b8534bSLuigi Rizzo if (!slot) 32768b8534bSLuigi Rizzo return; 3285644ccecSLuigi Rizzo /* 32917885a7bSLuigi Rizzo * Do not release the slots owned by userspace, 33017885a7bSLuigi Rizzo * and also keep one empty. 3315644ccecSLuigi Rizzo */ 3322ff91c17SVincenzo Maffione max_avail = n - 1 - nm_kr_rxspace(na->rx_rings[0]); 33317885a7bSLuigi Rizzo for (nic_i = 0; nic_i < n; nic_i++) { 334506cc70cSLuigi Rizzo void *addr; 335506cc70cSLuigi Rizzo uint64_t paddr; 3362ff91c17SVincenzo Maffione uint32_t nm_i = netmap_idx_n2k(na->rx_rings[0], nic_i); 33768b8534bSLuigi Rizzo 3384bf50f18SLuigi Rizzo addr = PNMB(na, slot + nm_i, &paddr); 3396e10c8b8SLuigi Rizzo 3404bf50f18SLuigi Rizzo netmap_reload_map(na, sc->rl_ldata.rl_rx_mtag, 34117885a7bSLuigi Rizzo sc->rl_ldata.rl_rx_desc[nic_i].rx_dmamap, addr); 3426e10c8b8SLuigi Rizzo bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, 34317885a7bSLuigi Rizzo sc->rl_ldata.rl_rx_desc[nic_i].rx_dmamap, BUS_DMASYNC_PREREAD); 34417885a7bSLuigi Rizzo desc[nic_i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); 34517885a7bSLuigi Rizzo desc[nic_i].rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); 3464bf50f18SLuigi Rizzo cmdstat = NETMAP_BUF_SIZE(na); 34717885a7bSLuigi Rizzo if (nic_i == n - 1) /* mark the end of ring */ 34868b8534bSLuigi Rizzo cmdstat |= RL_RDESC_CMD_EOR; 34917885a7bSLuigi Rizzo if (nic_i < max_avail) 350506cc70cSLuigi Rizzo cmdstat |= RL_RDESC_CMD_OWN; 35117885a7bSLuigi Rizzo desc[nic_i].rl_cmdstat = htole32(cmdstat); 35268b8534bSLuigi Rizzo } 35368b8534bSLuigi Rizzo } 35464ae02c3SLuigi Rizzo 35564ae02c3SLuigi Rizzo 35664ae02c3SLuigi Rizzo static void 35764ae02c3SLuigi Rizzo re_netmap_attach(struct rl_softc *sc) 35864ae02c3SLuigi Rizzo { 35964ae02c3SLuigi Rizzo struct netmap_adapter na; 36064ae02c3SLuigi Rizzo 36164ae02c3SLuigi Rizzo bzero(&na, sizeof(na)); 36264ae02c3SLuigi Rizzo 36364ae02c3SLuigi Rizzo na.ifp = sc->rl_ifp; 364ce3ee1e7SLuigi Rizzo na.na_flags = NAF_BDG_MAYSLEEP; 36564ae02c3SLuigi Rizzo na.num_tx_desc = sc->rl_ldata.rl_tx_desc_cnt; 36664ae02c3SLuigi Rizzo na.num_rx_desc = sc->rl_ldata.rl_rx_desc_cnt; 36764ae02c3SLuigi Rizzo na.nm_txsync = re_netmap_txsync; 36864ae02c3SLuigi Rizzo na.nm_rxsync = re_netmap_rxsync; 36964ae02c3SLuigi Rizzo na.nm_register = re_netmap_reg; 370f9790aebSLuigi Rizzo na.num_tx_rings = na.num_rx_rings = 1; 371f9790aebSLuigi Rizzo netmap_attach(&na); 37264ae02c3SLuigi Rizzo } 373f9790aebSLuigi Rizzo 37464ae02c3SLuigi Rizzo /* end of file */ 375