168b8534bSLuigi Rizzo /* 22579e2d7SLuigi Rizzo * Copyright (C) 2011-2013 Matteo Landi, 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 * 2968b8534bSLuigi Rizzo * The header contains the definitions of constants and function 3068b8534bSLuigi Rizzo * prototypes used only in kernelspace. 3168b8534bSLuigi Rizzo */ 3268b8534bSLuigi Rizzo 3368b8534bSLuigi Rizzo #ifndef _NET_NETMAP_KERN_H_ 3468b8534bSLuigi Rizzo #define _NET_NETMAP_KERN_H_ 3568b8534bSLuigi Rizzo 361a26580eSLuigi Rizzo #if defined(__FreeBSD__) 37d4b42e08SLuigi Rizzo 38*ce3ee1e7SLuigi Rizzo #define likely(x) __builtin_expect((long)!!(x), 1L) 39*ce3ee1e7SLuigi Rizzo #define unlikely(x) __builtin_expect((long)!!(x), 0L) 40f196ce38SLuigi Rizzo 411a26580eSLuigi Rizzo #define NM_LOCK_T struct mtx 421a26580eSLuigi Rizzo #define NM_SELINFO_T struct selinfo 431a26580eSLuigi Rizzo #define MBUF_LEN(m) ((m)->m_pkthdr.len) 441a26580eSLuigi Rizzo #define NM_SEND_UP(ifp, m) ((ifp)->if_input)(ifp, m) 45d4b42e08SLuigi Rizzo 46*ce3ee1e7SLuigi Rizzo #define NM_ATOMIC_T volatile int 47*ce3ee1e7SLuigi Rizzo 4864ae02c3SLuigi Rizzo #elif defined (linux) 49d4b42e08SLuigi Rizzo 502579e2d7SLuigi Rizzo #define NM_LOCK_T safe_spinlock_t // see bsd_glue.h 511a26580eSLuigi Rizzo #define NM_SELINFO_T wait_queue_head_t 521a26580eSLuigi Rizzo #define MBUF_LEN(m) ((m)->len) 531a26580eSLuigi Rizzo #define NM_SEND_UP(ifp, m) netif_rx(m) 54f196ce38SLuigi Rizzo 55*ce3ee1e7SLuigi Rizzo #define NM_ATOMIC_T volatile long unsigned int 56*ce3ee1e7SLuigi Rizzo 57f196ce38SLuigi Rizzo #ifndef DEV_NETMAP 58f196ce38SLuigi Rizzo #define DEV_NETMAP 59*ce3ee1e7SLuigi Rizzo #endif /* DEV_NETMAP */ 60f196ce38SLuigi Rizzo 61f196ce38SLuigi Rizzo /* 628241616dSLuigi Rizzo * IFCAP_NETMAP goes into net_device's priv_flags (if_capenable). 638241616dSLuigi Rizzo * This was 16 bits up to linux 2.6.36, so we need a 16 bit value on older 64f196ce38SLuigi Rizzo * platforms and tolerate the clash with IFF_DYNAMIC and IFF_BRIDGE_PORT. 658241616dSLuigi Rizzo * For the 32-bit value, 0x100000 has no clashes until at least 3.5.1 66f196ce38SLuigi Rizzo */ 67f196ce38SLuigi Rizzo #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) 68f196ce38SLuigi Rizzo #define IFCAP_NETMAP 0x8000 69f196ce38SLuigi Rizzo #else 70f18be576SLuigi Rizzo #define IFCAP_NETMAP 0x200000 71f196ce38SLuigi Rizzo #endif 72f196ce38SLuigi Rizzo 73f196ce38SLuigi Rizzo #elif defined (__APPLE__) 74d4b42e08SLuigi Rizzo 758241616dSLuigi Rizzo #warning apple support is incomplete. 76f196ce38SLuigi Rizzo #define likely(x) __builtin_expect(!!(x), 1) 77f196ce38SLuigi Rizzo #define unlikely(x) __builtin_expect(!!(x), 0) 78f196ce38SLuigi Rizzo #define NM_LOCK_T IOLock * 79f196ce38SLuigi Rizzo #define NM_SELINFO_T struct selinfo 80f196ce38SLuigi Rizzo #define MBUF_LEN(m) ((m)->m_pkthdr.len) 81f196ce38SLuigi Rizzo #define NM_SEND_UP(ifp, m) ((ifp)->if_input)(ifp, m) 82f196ce38SLuigi Rizzo 831a26580eSLuigi Rizzo #else 84d4b42e08SLuigi Rizzo 851a26580eSLuigi Rizzo #error unsupported platform 86d4b42e08SLuigi Rizzo 87d4b42e08SLuigi Rizzo #endif /* end - platform-specific code */ 881a26580eSLuigi Rizzo 8968b8534bSLuigi Rizzo #define ND(format, ...) 9068b8534bSLuigi Rizzo #define D(format, ...) \ 9168b8534bSLuigi Rizzo do { \ 9268b8534bSLuigi Rizzo struct timeval __xxts; \ 9368b8534bSLuigi Rizzo microtime(&__xxts); \ 9468b8534bSLuigi Rizzo printf("%03d.%06d %s [%d] " format "\n", \ 9568b8534bSLuigi Rizzo (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ 9668b8534bSLuigi Rizzo __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 9768b8534bSLuigi Rizzo } while (0) 9868b8534bSLuigi Rizzo 998241616dSLuigi Rizzo /* rate limited, lps indicates how many per second */ 1008241616dSLuigi Rizzo #define RD(lps, format, ...) \ 1018241616dSLuigi Rizzo do { \ 1028241616dSLuigi Rizzo static int t0, __cnt; \ 1038241616dSLuigi Rizzo if (t0 != time_second) { \ 1048241616dSLuigi Rizzo t0 = time_second; \ 1058241616dSLuigi Rizzo __cnt = 0; \ 1068241616dSLuigi Rizzo } \ 1078241616dSLuigi Rizzo if (__cnt++ < lps) \ 1088241616dSLuigi Rizzo D(format, ##__VA_ARGS__); \ 1098241616dSLuigi Rizzo } while (0) 1108241616dSLuigi Rizzo 11168b8534bSLuigi Rizzo struct netmap_adapter; 112f18be576SLuigi Rizzo struct nm_bdg_fwd; 113f18be576SLuigi Rizzo struct nm_bridge; 114f18be576SLuigi Rizzo struct netmap_priv_d; 11568b8534bSLuigi Rizzo 116*ce3ee1e7SLuigi Rizzo const char *nm_dump_buf(char *p, int len, int lim, char *dst); 117*ce3ee1e7SLuigi Rizzo 11868b8534bSLuigi Rizzo /* 11964ae02c3SLuigi Rizzo * private, kernel view of a ring. Keeps track of the status of 12064ae02c3SLuigi Rizzo * a ring across system calls. 12164ae02c3SLuigi Rizzo * 12264ae02c3SLuigi Rizzo * nr_hwcur index of the next buffer to refill. 12364ae02c3SLuigi Rizzo * It corresponds to ring->cur - ring->reserved 12464ae02c3SLuigi Rizzo * 12564ae02c3SLuigi Rizzo * nr_hwavail the number of slots "owned" by userspace. 12664ae02c3SLuigi Rizzo * nr_hwavail =:= ring->avail + ring->reserved 12768b8534bSLuigi Rizzo * 1281a26580eSLuigi Rizzo * The indexes in the NIC and netmap rings are offset by nkr_hwofs slots. 12968b8534bSLuigi Rizzo * This is so that, on a reset, buffers owned by userspace are not 13068b8534bSLuigi Rizzo * modified by the kernel. In particular: 1311a26580eSLuigi Rizzo * RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides with 13268b8534bSLuigi Rizzo * the next empty buffer as known by the hardware (next_to_check or so). 13368b8534bSLuigi Rizzo * TX rings: hwcur + hwofs coincides with next_to_send 1341dce924dSLuigi Rizzo * 135*ce3ee1e7SLuigi Rizzo * Clients cannot issue concurrent syscall on a ring. The system 136*ce3ee1e7SLuigi Rizzo * detects this and reports an error using two flags, 137*ce3ee1e7SLuigi Rizzo * NKR_WBUSY and NKR_RBUSY 1381dce924dSLuigi Rizzo * For received packets, slot->flags is set to nkr_slot_flags 1391dce924dSLuigi Rizzo * so we can provide a proper initial value (e.g. set NS_FORWARD 1401dce924dSLuigi Rizzo * when operating in 'transparent' mode). 141*ce3ee1e7SLuigi Rizzo * 142*ce3ee1e7SLuigi Rizzo * The following fields are used to implement lock-free copy of packets 143*ce3ee1e7SLuigi Rizzo * from input to output ports in VALE switch: 144*ce3ee1e7SLuigi Rizzo * nkr_hwlease buffer after the last one being copied. 145*ce3ee1e7SLuigi Rizzo * A writer in nm_bdg_flush reserves N buffers 146*ce3ee1e7SLuigi Rizzo * from nr_hwlease, advances it, then does the 147*ce3ee1e7SLuigi Rizzo * copy outside the lock. 148*ce3ee1e7SLuigi Rizzo * In RX rings (used for VALE ports), 149*ce3ee1e7SLuigi Rizzo * nkr_hwcur + nkr_hwavail <= nkr_hwlease < nkr_hwcur+N-1 150*ce3ee1e7SLuigi Rizzo * In TX rings (used for NIC or host stack ports) 151*ce3ee1e7SLuigi Rizzo * nkr_hwcur <= nkr_hwlease < nkr_hwcur+ nkr_hwavail 152*ce3ee1e7SLuigi Rizzo * nkr_leases array of nkr_num_slots where writers can report 153*ce3ee1e7SLuigi Rizzo * completion of their block. NR_NOSLOT (~0) indicates 154*ce3ee1e7SLuigi Rizzo * that the writer has not finished yet 155*ce3ee1e7SLuigi Rizzo * nkr_lease_idx index of next free slot in nr_leases, to be assigned 156*ce3ee1e7SLuigi Rizzo * 157*ce3ee1e7SLuigi Rizzo * The kring is manipulated by txsync/rxsync and generic netmap function. 158*ce3ee1e7SLuigi Rizzo * q_lock is used to arbitrate access to the kring from within the netmap 159*ce3ee1e7SLuigi Rizzo * code, and this and other protections guarantee that there is never 160*ce3ee1e7SLuigi Rizzo * more than 1 concurrent call to txsync or rxsync. So we are free 161*ce3ee1e7SLuigi Rizzo * to manipulate the kring from within txsync/rxsync without any extra 162*ce3ee1e7SLuigi Rizzo * locks. 16368b8534bSLuigi Rizzo */ 16468b8534bSLuigi Rizzo struct netmap_kring { 16568b8534bSLuigi Rizzo struct netmap_ring *ring; 166*ce3ee1e7SLuigi Rizzo uint32_t nr_hwcur; 167*ce3ee1e7SLuigi Rizzo uint32_t nr_hwavail; 168*ce3ee1e7SLuigi Rizzo uint32_t nr_kflags; /* private driver flags */ 1692157a17cSLuigi Rizzo #define NKR_PENDINTR 0x1 // Pending interrupt. 170*ce3ee1e7SLuigi Rizzo uint32_t nkr_num_slots; 171*ce3ee1e7SLuigi Rizzo int32_t nkr_hwofs; /* offset between NIC and netmap ring */ 17268b8534bSLuigi Rizzo 1731dce924dSLuigi Rizzo uint16_t nkr_slot_flags; /* initial value for flags */ 1741a26580eSLuigi Rizzo struct netmap_adapter *na; 175f18be576SLuigi Rizzo struct nm_bdg_fwd *nkr_ft; 176*ce3ee1e7SLuigi Rizzo uint32_t *nkr_leases; 177*ce3ee1e7SLuigi Rizzo #define NR_NOSLOT ((uint32_t)~0) 178*ce3ee1e7SLuigi Rizzo uint32_t nkr_hwlease; 179*ce3ee1e7SLuigi Rizzo uint32_t nkr_lease_idx; 180*ce3ee1e7SLuigi Rizzo 1811a26580eSLuigi Rizzo NM_SELINFO_T si; /* poll/select wait queue */ 182*ce3ee1e7SLuigi Rizzo NM_LOCK_T q_lock; /* protects kring and ring. */ 183*ce3ee1e7SLuigi Rizzo NM_ATOMIC_T nr_busy; /* prevent concurrent syscalls */ 184*ce3ee1e7SLuigi Rizzo 185*ce3ee1e7SLuigi Rizzo volatile int nkr_stopped; 1862157a17cSLuigi Rizzo } __attribute__((__aligned__(64))); 18768b8534bSLuigi Rizzo 188*ce3ee1e7SLuigi Rizzo 189*ce3ee1e7SLuigi Rizzo /* return the next index, with wraparound */ 190*ce3ee1e7SLuigi Rizzo static inline uint32_t 191*ce3ee1e7SLuigi Rizzo nm_next(uint32_t i, uint32_t lim) 192*ce3ee1e7SLuigi Rizzo { 193*ce3ee1e7SLuigi Rizzo return unlikely (i == lim) ? 0 : i + 1; 194*ce3ee1e7SLuigi Rizzo } 195*ce3ee1e7SLuigi Rizzo 196*ce3ee1e7SLuigi Rizzo /* 197*ce3ee1e7SLuigi Rizzo * 198*ce3ee1e7SLuigi Rizzo * Here is the layout for the Rx and Tx rings. 199*ce3ee1e7SLuigi Rizzo 200*ce3ee1e7SLuigi Rizzo RxRING TxRING 201*ce3ee1e7SLuigi Rizzo 202*ce3ee1e7SLuigi Rizzo +-----------------+ +-----------------+ 203*ce3ee1e7SLuigi Rizzo | | | | 204*ce3ee1e7SLuigi Rizzo |XXX free slot XXX| |XXX free slot XXX| 205*ce3ee1e7SLuigi Rizzo +-----------------+ +-----------------+ 206*ce3ee1e7SLuigi Rizzo | |<-hwcur | |<-hwcur 207*ce3ee1e7SLuigi Rizzo | reserved h | | (ready | 208*ce3ee1e7SLuigi Rizzo +----------- w -+ | to be | 209*ce3ee1e7SLuigi Rizzo cur->| a | | sent) h | 210*ce3ee1e7SLuigi Rizzo | v | +---------- w | 211*ce3ee1e7SLuigi Rizzo | a | cur->| (being a | 212*ce3ee1e7SLuigi Rizzo | i | | prepared) v | 213*ce3ee1e7SLuigi Rizzo | avail l | | a | 214*ce3ee1e7SLuigi Rizzo +-----------------+ + a ------ i + 215*ce3ee1e7SLuigi Rizzo | | ... | v l |<-hwlease 216*ce3ee1e7SLuigi Rizzo | (being | ... | a | ... 217*ce3ee1e7SLuigi Rizzo | prepared) | ... | i | ... 218*ce3ee1e7SLuigi Rizzo +-----------------+ ... | l | ... 219*ce3ee1e7SLuigi Rizzo | |<-hwlease +-----------------+ 220*ce3ee1e7SLuigi Rizzo | | | | 221*ce3ee1e7SLuigi Rizzo | | | | 222*ce3ee1e7SLuigi Rizzo | | | | 223*ce3ee1e7SLuigi Rizzo | | | | 224*ce3ee1e7SLuigi Rizzo +-----------------+ +-----------------+ 225*ce3ee1e7SLuigi Rizzo 226*ce3ee1e7SLuigi Rizzo * The cur/avail (user view) and hwcur/hwavail (kernel view) 227*ce3ee1e7SLuigi Rizzo * are used in the normal operation of the card. 228*ce3ee1e7SLuigi Rizzo * 229*ce3ee1e7SLuigi Rizzo * When a ring is the output of a switch port (Rx ring for 230*ce3ee1e7SLuigi Rizzo * a VALE port, Tx ring for the host stack or NIC), slots 231*ce3ee1e7SLuigi Rizzo * are reserved in blocks through 'hwlease' which points 232*ce3ee1e7SLuigi Rizzo * to the next unused slot. 233*ce3ee1e7SLuigi Rizzo * On an Rx ring, hwlease is always after hwavail, 234*ce3ee1e7SLuigi Rizzo * and completions cause avail to advance. 235*ce3ee1e7SLuigi Rizzo * On a Tx ring, hwlease is always between cur and hwavail, 236*ce3ee1e7SLuigi Rizzo * and completions cause cur to advance. 237*ce3ee1e7SLuigi Rizzo * 238*ce3ee1e7SLuigi Rizzo * nm_kr_space() returns the maximum number of slots that 239*ce3ee1e7SLuigi Rizzo * can be assigned. 240*ce3ee1e7SLuigi Rizzo * nm_kr_lease() reserves the required number of buffers, 241*ce3ee1e7SLuigi Rizzo * advances nkr_hwlease and also returns an entry in 242*ce3ee1e7SLuigi Rizzo * a circular array where completions should be reported. 243*ce3ee1e7SLuigi Rizzo */ 244*ce3ee1e7SLuigi Rizzo 245*ce3ee1e7SLuigi Rizzo 246*ce3ee1e7SLuigi Rizzo 247*ce3ee1e7SLuigi Rizzo 248*ce3ee1e7SLuigi Rizzo 24968b8534bSLuigi Rizzo /* 2501a26580eSLuigi Rizzo * This struct extends the 'struct adapter' (or 25168b8534bSLuigi Rizzo * equivalent) device descriptor. It contains all fields needed to 25268b8534bSLuigi Rizzo * support netmap operation. 25368b8534bSLuigi Rizzo */ 25468b8534bSLuigi Rizzo struct netmap_adapter { 2558241616dSLuigi Rizzo /* 2568241616dSLuigi Rizzo * On linux we do not have a good way to tell if an interface 2578241616dSLuigi Rizzo * is netmap-capable. So we use the following trick: 2588241616dSLuigi Rizzo * NA(ifp) points here, and the first entry (which hopefully 2598241616dSLuigi Rizzo * always exists and is at least 32 bits) contains a magic 2608241616dSLuigi Rizzo * value which we can use to detect that the interface is good. 2618241616dSLuigi Rizzo */ 2628241616dSLuigi Rizzo uint32_t magic; 2638241616dSLuigi Rizzo uint32_t na_flags; /* future place for IFCAP_NETMAP */ 2648241616dSLuigi Rizzo #define NAF_SKIP_INTR 1 /* use the regular interrupt handler. 2658241616dSLuigi Rizzo * useful during initialization 2668241616dSLuigi Rizzo */ 267f18be576SLuigi Rizzo #define NAF_SW_ONLY 2 /* forward packets only to sw adapter */ 268*ce3ee1e7SLuigi Rizzo #define NAF_BDG_MAYSLEEP 4 /* the bridge is allowed to sleep when 269*ce3ee1e7SLuigi Rizzo * forwarding packets coming from this 270*ce3ee1e7SLuigi Rizzo * interface 271*ce3ee1e7SLuigi Rizzo */ 272*ce3ee1e7SLuigi Rizzo #define NAF_MEM_OWNER 8 /* the adapter is responsible for the 273*ce3ee1e7SLuigi Rizzo * deallocation of the memory allocator 274*ce3ee1e7SLuigi Rizzo */ 27568b8534bSLuigi Rizzo int refcount; /* number of user-space descriptors using this 27668b8534bSLuigi Rizzo interface, which is equal to the number of 27768b8534bSLuigi Rizzo struct netmap_if objs in the mapped region. */ 278d76bf4ffSLuigi Rizzo /* 279d76bf4ffSLuigi Rizzo * The selwakeup in the interrupt thread can use per-ring 280d76bf4ffSLuigi Rizzo * and/or global wait queues. We track how many clients 281d76bf4ffSLuigi Rizzo * of each type we have so we can optimize the drivers, 282d76bf4ffSLuigi Rizzo * and especially avoid huge contention on the locks. 283d76bf4ffSLuigi Rizzo */ 284d76bf4ffSLuigi Rizzo int na_single; /* threads attached to a single hw queue */ 285d76bf4ffSLuigi Rizzo int na_multi; /* threads attached to multiple hw queues */ 28668b8534bSLuigi Rizzo 28724e57ec9SEd Maste u_int num_rx_rings; /* number of adapter receive rings */ 28824e57ec9SEd Maste u_int num_tx_rings; /* number of adapter transmit rings */ 28968b8534bSLuigi Rizzo 29068b8534bSLuigi Rizzo u_int num_tx_desc; /* number of descriptor in each queue */ 29168b8534bSLuigi Rizzo u_int num_rx_desc; 29268b8534bSLuigi Rizzo 29368b8534bSLuigi Rizzo /* tx_rings and rx_rings are private but allocated 29468b8534bSLuigi Rizzo * as a contiguous chunk of memory. Each array has 29568b8534bSLuigi Rizzo * N+1 entries, for the adapter queues and for the host queue. 29668b8534bSLuigi Rizzo */ 29768b8534bSLuigi Rizzo struct netmap_kring *tx_rings; /* array of TX rings. */ 29868b8534bSLuigi Rizzo struct netmap_kring *rx_rings; /* array of RX rings. */ 29968b8534bSLuigi Rizzo 30064ae02c3SLuigi Rizzo NM_SELINFO_T tx_si, rx_si; /* global wait queues */ 30164ae02c3SLuigi Rizzo 30268b8534bSLuigi Rizzo /* copy of if_qflush and if_transmit pointers, to intercept 30368b8534bSLuigi Rizzo * packets from the network stack when netmap is active. 30468b8534bSLuigi Rizzo */ 30568b8534bSLuigi Rizzo int (*if_transmit)(struct ifnet *, struct mbuf *); 30668b8534bSLuigi Rizzo 30768b8534bSLuigi Rizzo /* references to the ifnet and device routines, used by 30868b8534bSLuigi Rizzo * the generic netmap functions. 30968b8534bSLuigi Rizzo */ 31068b8534bSLuigi Rizzo struct ifnet *ifp; /* adapter is ifp->if_softc */ 31168b8534bSLuigi Rizzo 3121a26580eSLuigi Rizzo NM_LOCK_T core_lock; /* used if no device lock available */ 3131a26580eSLuigi Rizzo 31468b8534bSLuigi Rizzo int (*nm_register)(struct ifnet *, int onoff); 315*ce3ee1e7SLuigi Rizzo 316*ce3ee1e7SLuigi Rizzo int (*nm_txsync)(struct ifnet *, u_int ring, int flags); 317*ce3ee1e7SLuigi Rizzo int (*nm_rxsync)(struct ifnet *, u_int ring, int flags); 318*ce3ee1e7SLuigi Rizzo #define NAF_FORCE_READ 1 319*ce3ee1e7SLuigi Rizzo #define NAF_FORCE_RECLAIM 2 320ae10d1afSLuigi Rizzo /* return configuration information */ 321ae10d1afSLuigi Rizzo int (*nm_config)(struct ifnet *, u_int *txr, u_int *txd, 322ae10d1afSLuigi Rizzo u_int *rxr, u_int *rxd); 323f196ce38SLuigi Rizzo 324849bec0eSLuigi Rizzo /* 325849bec0eSLuigi Rizzo * Bridge support: 326849bec0eSLuigi Rizzo * 327849bec0eSLuigi Rizzo * bdg_port is the port number used in the bridge; 328849bec0eSLuigi Rizzo * na_bdg_refcount is a refcount used for bridge ports, 329849bec0eSLuigi Rizzo * when it goes to 0 we can detach+free this port 330849bec0eSLuigi Rizzo * (a bridge port is always attached if it exists; 331849bec0eSLuigi Rizzo * it is not always registered) 332f18be576SLuigi Rizzo * na_bdg points to the bridge this NA is attached to. 333849bec0eSLuigi Rizzo */ 334f196ce38SLuigi Rizzo int bdg_port; 335849bec0eSLuigi Rizzo int na_bdg_refcount; 336f18be576SLuigi Rizzo struct nm_bridge *na_bdg; 337f18be576SLuigi Rizzo /* When we attach a physical interface to the bridge, we 338f18be576SLuigi Rizzo * allow the controlling process to terminate, so we need 339f18be576SLuigi Rizzo * a place to store the netmap_priv_d data structure. 340f18be576SLuigi Rizzo * This is only done when physical interfaces are attached to a bridge. 341f18be576SLuigi Rizzo */ 342f18be576SLuigi Rizzo struct netmap_priv_d *na_kpriv; 343*ce3ee1e7SLuigi Rizzo 344*ce3ee1e7SLuigi Rizzo /* memory allocator */ 345*ce3ee1e7SLuigi Rizzo struct netmap_mem_d *nm_mem; 34664ae02c3SLuigi Rizzo #ifdef linux 34764ae02c3SLuigi Rizzo struct net_device_ops nm_ndo; 34864ae02c3SLuigi Rizzo #endif /* linux */ 34968b8534bSLuigi Rizzo }; 35068b8534bSLuigi Rizzo 35168b8534bSLuigi Rizzo /* 352*ce3ee1e7SLuigi Rizzo * Available space in the ring. 353*ce3ee1e7SLuigi Rizzo */ 354*ce3ee1e7SLuigi Rizzo static inline uint32_t 355*ce3ee1e7SLuigi Rizzo nm_kr_space(struct netmap_kring *k, int is_rx) 356*ce3ee1e7SLuigi Rizzo { 357*ce3ee1e7SLuigi Rizzo int space; 358*ce3ee1e7SLuigi Rizzo 359*ce3ee1e7SLuigi Rizzo if (is_rx) { 360*ce3ee1e7SLuigi Rizzo int busy = k->nkr_hwlease - k->nr_hwcur; 361*ce3ee1e7SLuigi Rizzo if (busy < 0) 362*ce3ee1e7SLuigi Rizzo busy += k->nkr_num_slots; 363*ce3ee1e7SLuigi Rizzo space = k->nkr_num_slots - 1 - busy; 364*ce3ee1e7SLuigi Rizzo } else { 365*ce3ee1e7SLuigi Rizzo space = k->nr_hwcur + k->nr_hwavail - k->nkr_hwlease; 366*ce3ee1e7SLuigi Rizzo if (space < 0) 367*ce3ee1e7SLuigi Rizzo space += k->nkr_num_slots; 368*ce3ee1e7SLuigi Rizzo } 369*ce3ee1e7SLuigi Rizzo #if 0 370*ce3ee1e7SLuigi Rizzo // sanity check 371*ce3ee1e7SLuigi Rizzo if (k->nkr_hwlease >= k->nkr_num_slots || 372*ce3ee1e7SLuigi Rizzo k->nr_hwcur >= k->nkr_num_slots || 373*ce3ee1e7SLuigi Rizzo k->nr_hwavail >= k->nkr_num_slots || 374*ce3ee1e7SLuigi Rizzo busy < 0 || 375*ce3ee1e7SLuigi Rizzo busy >= k->nkr_num_slots) { 376*ce3ee1e7SLuigi Rizzo D("invalid kring, cur %d avail %d lease %d lease_idx %d lim %d", k->nr_hwcur, k->nr_hwavail, k->nkr_hwlease, 377*ce3ee1e7SLuigi Rizzo k->nkr_lease_idx, k->nkr_num_slots); 378*ce3ee1e7SLuigi Rizzo } 379*ce3ee1e7SLuigi Rizzo #endif 380*ce3ee1e7SLuigi Rizzo return space; 381*ce3ee1e7SLuigi Rizzo } 382*ce3ee1e7SLuigi Rizzo 383*ce3ee1e7SLuigi Rizzo 384*ce3ee1e7SLuigi Rizzo /* return update position */ 385*ce3ee1e7SLuigi Rizzo static inline uint32_t 386*ce3ee1e7SLuigi Rizzo nm_kr_rxpos(struct netmap_kring *k) 387*ce3ee1e7SLuigi Rizzo { 388*ce3ee1e7SLuigi Rizzo uint32_t pos = k->nr_hwcur + k->nr_hwavail; 389*ce3ee1e7SLuigi Rizzo if (pos >= k->nkr_num_slots) 390*ce3ee1e7SLuigi Rizzo pos -= k->nkr_num_slots; 391*ce3ee1e7SLuigi Rizzo #if 0 392*ce3ee1e7SLuigi Rizzo if (pos >= k->nkr_num_slots || 393*ce3ee1e7SLuigi Rizzo k->nkr_hwlease >= k->nkr_num_slots || 394*ce3ee1e7SLuigi Rizzo k->nr_hwcur >= k->nkr_num_slots || 395*ce3ee1e7SLuigi Rizzo k->nr_hwavail >= k->nkr_num_slots || 396*ce3ee1e7SLuigi Rizzo k->nkr_lease_idx >= k->nkr_num_slots) { 397*ce3ee1e7SLuigi Rizzo D("invalid kring, cur %d avail %d lease %d lease_idx %d lim %d", k->nr_hwcur, k->nr_hwavail, k->nkr_hwlease, 398*ce3ee1e7SLuigi Rizzo k->nkr_lease_idx, k->nkr_num_slots); 399*ce3ee1e7SLuigi Rizzo } 400*ce3ee1e7SLuigi Rizzo #endif 401*ce3ee1e7SLuigi Rizzo return pos; 402*ce3ee1e7SLuigi Rizzo } 403*ce3ee1e7SLuigi Rizzo 404*ce3ee1e7SLuigi Rizzo 405*ce3ee1e7SLuigi Rizzo /* make a lease on the kring for N positions. return the 406*ce3ee1e7SLuigi Rizzo * lease index 407*ce3ee1e7SLuigi Rizzo */ 408*ce3ee1e7SLuigi Rizzo static inline uint32_t 409*ce3ee1e7SLuigi Rizzo nm_kr_lease(struct netmap_kring *k, u_int n, int is_rx) 410*ce3ee1e7SLuigi Rizzo { 411*ce3ee1e7SLuigi Rizzo uint32_t lim = k->nkr_num_slots - 1; 412*ce3ee1e7SLuigi Rizzo uint32_t lease_idx = k->nkr_lease_idx; 413*ce3ee1e7SLuigi Rizzo 414*ce3ee1e7SLuigi Rizzo k->nkr_leases[lease_idx] = NR_NOSLOT; 415*ce3ee1e7SLuigi Rizzo k->nkr_lease_idx = nm_next(lease_idx, lim); 416*ce3ee1e7SLuigi Rizzo 417*ce3ee1e7SLuigi Rizzo if (n > nm_kr_space(k, is_rx)) { 418*ce3ee1e7SLuigi Rizzo D("invalid request for %d slots", n); 419*ce3ee1e7SLuigi Rizzo panic("x"); 420*ce3ee1e7SLuigi Rizzo } 421*ce3ee1e7SLuigi Rizzo /* XXX verify that there are n slots */ 422*ce3ee1e7SLuigi Rizzo k->nkr_hwlease += n; 423*ce3ee1e7SLuigi Rizzo if (k->nkr_hwlease > lim) 424*ce3ee1e7SLuigi Rizzo k->nkr_hwlease -= lim + 1; 425*ce3ee1e7SLuigi Rizzo 426*ce3ee1e7SLuigi Rizzo if (k->nkr_hwlease >= k->nkr_num_slots || 427*ce3ee1e7SLuigi Rizzo k->nr_hwcur >= k->nkr_num_slots || 428*ce3ee1e7SLuigi Rizzo k->nr_hwavail >= k->nkr_num_slots || 429*ce3ee1e7SLuigi Rizzo k->nkr_lease_idx >= k->nkr_num_slots) { 430*ce3ee1e7SLuigi Rizzo D("invalid kring %s, cur %d avail %d lease %d lease_idx %d lim %d", 431*ce3ee1e7SLuigi Rizzo k->na->ifp->if_xname, 432*ce3ee1e7SLuigi Rizzo k->nr_hwcur, k->nr_hwavail, k->nkr_hwlease, 433*ce3ee1e7SLuigi Rizzo k->nkr_lease_idx, k->nkr_num_slots); 434*ce3ee1e7SLuigi Rizzo } 435*ce3ee1e7SLuigi Rizzo return lease_idx; 436*ce3ee1e7SLuigi Rizzo } 437*ce3ee1e7SLuigi Rizzo 438*ce3ee1e7SLuigi Rizzo 439*ce3ee1e7SLuigi Rizzo /* 440*ce3ee1e7SLuigi Rizzo * XXX NETMAP_DELETING() is unused 441*ce3ee1e7SLuigi Rizzo * 4428241616dSLuigi Rizzo * The combination of "enable" (ifp->if_capenable & IFCAP_NETMAP) 44368b8534bSLuigi Rizzo * and refcount gives the status of the interface, namely: 44468b8534bSLuigi Rizzo * 44568b8534bSLuigi Rizzo * enable refcount Status 44668b8534bSLuigi Rizzo * 44768b8534bSLuigi Rizzo * FALSE 0 normal operation 44868b8534bSLuigi Rizzo * FALSE != 0 -- (impossible) 44968b8534bSLuigi Rizzo * TRUE 1 netmap mode 45068b8534bSLuigi Rizzo * TRUE 0 being deleted. 45168b8534bSLuigi Rizzo */ 45268b8534bSLuigi Rizzo 45368b8534bSLuigi Rizzo #define NETMAP_DELETING(_na) ( ((_na)->refcount == 0) && \ 45468b8534bSLuigi Rizzo ( (_na)->ifp->if_capenable & IFCAP_NETMAP) ) 45568b8534bSLuigi Rizzo 456849bec0eSLuigi Rizzo 45768b8534bSLuigi Rizzo /* 45868b8534bSLuigi Rizzo * The following are support routines used by individual drivers to 45968b8534bSLuigi Rizzo * support netmap operation. 46068b8534bSLuigi Rizzo * 46168b8534bSLuigi Rizzo * netmap_attach() initializes a struct netmap_adapter, allocating the 46268b8534bSLuigi Rizzo * struct netmap_ring's and the struct selinfo. 46368b8534bSLuigi Rizzo * 46468b8534bSLuigi Rizzo * netmap_detach() frees the memory allocated by netmap_attach(). 46568b8534bSLuigi Rizzo * 466*ce3ee1e7SLuigi Rizzo * netmap_transmit() replaces the if_transmit routine of the interface, 46768b8534bSLuigi Rizzo * and is used to intercept packets coming from the stack. 46868b8534bSLuigi Rizzo * 46968b8534bSLuigi Rizzo * netmap_load_map/netmap_reload_map are helper routines to set/reset 47068b8534bSLuigi Rizzo * the dmamap for a packet buffer 47168b8534bSLuigi Rizzo * 47268b8534bSLuigi Rizzo * netmap_reset() is a helper routine to be called in the driver 47368b8534bSLuigi Rizzo * when reinitializing a ring. 47468b8534bSLuigi Rizzo */ 475*ce3ee1e7SLuigi Rizzo int netmap_attach(struct netmap_adapter *, u_int); 47668b8534bSLuigi Rizzo void netmap_detach(struct ifnet *); 477*ce3ee1e7SLuigi Rizzo int netmap_transmit(struct ifnet *, struct mbuf *); 47868b8534bSLuigi Rizzo enum txrx { NR_RX = 0, NR_TX = 1 }; 47968b8534bSLuigi Rizzo struct netmap_slot *netmap_reset(struct netmap_adapter *na, 480*ce3ee1e7SLuigi Rizzo enum txrx tx, u_int n, u_int new_cur); 48168b8534bSLuigi Rizzo int netmap_ring_reinit(struct netmap_kring *); 48268b8534bSLuigi Rizzo 483*ce3ee1e7SLuigi Rizzo u_int nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg); 484*ce3ee1e7SLuigi Rizzo 485f18be576SLuigi Rizzo /* 486f18be576SLuigi Rizzo * The following bridge-related interfaces are used by other kernel modules 487f18be576SLuigi Rizzo * In the version that only supports unicast or broadcast, the lookup 488f18be576SLuigi Rizzo * function can return 0 .. NM_BDG_MAXPORTS-1 for regular ports, 489f18be576SLuigi Rizzo * NM_BDG_MAXPORTS for broadcast, NM_BDG_MAXPORTS+1 for unknown. 490f18be576SLuigi Rizzo * XXX in practice "unknown" might be handled same as broadcast. 491f18be576SLuigi Rizzo */ 492f18be576SLuigi Rizzo typedef u_int (*bdg_lookup_fn_t)(char *buf, u_int len, uint8_t *ring_nr, 493f18be576SLuigi Rizzo struct netmap_adapter *); 494f18be576SLuigi Rizzo int netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func); 495f18be576SLuigi Rizzo u_int netmap_bdg_learning(char *, u_int, uint8_t *, struct netmap_adapter *); 496f18be576SLuigi Rizzo #define NM_NAME "vale" /* prefix for the bridge port name */ 497f18be576SLuigi Rizzo #define NM_BDG_MAXPORTS 254 /* up to 32 for bitmap, 254 ok otherwise */ 498f18be576SLuigi Rizzo #define NM_BDG_BROADCAST NM_BDG_MAXPORTS 499f18be576SLuigi Rizzo #define NM_BDG_NOPORT (NM_BDG_MAXPORTS+1) 500f18be576SLuigi Rizzo 501b3d53016SLuigi Rizzo extern u_int netmap_buf_size; 502849bec0eSLuigi Rizzo #define NETMAP_BUF_SIZE netmap_buf_size // XXX remove 5032157a17cSLuigi Rizzo extern int netmap_mitigate; 5045819da83SLuigi Rizzo extern int netmap_no_pendintr; 50568b8534bSLuigi Rizzo extern u_int netmap_total_buffers; 50668b8534bSLuigi Rizzo extern char *netmap_buffer_base; 50768b8534bSLuigi Rizzo extern int netmap_verbose; // XXX debugging 50868b8534bSLuigi Rizzo enum { /* verbose flags */ 50968b8534bSLuigi Rizzo NM_VERB_ON = 1, /* generic verbose */ 51068b8534bSLuigi Rizzo NM_VERB_HOST = 0x2, /* verbose host stack */ 51168b8534bSLuigi Rizzo NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ 51268b8534bSLuigi Rizzo NM_VERB_TXSYNC = 0x20, 51368b8534bSLuigi Rizzo NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ 51468b8534bSLuigi Rizzo NM_VERB_TXINTR = 0x200, 51568b8534bSLuigi Rizzo NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ 51668b8534bSLuigi Rizzo NM_VERB_NIC_TXSYNC = 0x2000, 51768b8534bSLuigi Rizzo }; 51868b8534bSLuigi Rizzo 51968b8534bSLuigi Rizzo /* 520d0c7b075SLuigi Rizzo * NA returns a pointer to the struct netmap adapter from the ifp, 521d0c7b075SLuigi Rizzo * WNA is used to write it. 522f18be576SLuigi Rizzo * SWNA() is used for the "host stack" endpoint associated 523f18be576SLuigi Rizzo * to an interface. It is allocated together with the main NA(), 524f18be576SLuigi Rizzo * as an array of two objects. 52568b8534bSLuigi Rizzo */ 526d0c7b075SLuigi Rizzo #ifndef WNA 527d0c7b075SLuigi Rizzo #define WNA(_ifp) (_ifp)->if_pspare[0] 528d0c7b075SLuigi Rizzo #endif 529d0c7b075SLuigi Rizzo #define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) 530f18be576SLuigi Rizzo #define SWNA(_ifp) (NA(_ifp) + 1) 53168b8534bSLuigi Rizzo 5328241616dSLuigi Rizzo /* 5338241616dSLuigi Rizzo * Macros to determine if an interface is netmap capable or netmap enabled. 5348241616dSLuigi Rizzo * See the magic field in struct netmap_adapter. 5358241616dSLuigi Rizzo */ 5368241616dSLuigi Rizzo #ifdef __FreeBSD__ 5378241616dSLuigi Rizzo /* 5388241616dSLuigi Rizzo * on FreeBSD just use if_capabilities and if_capenable. 5398241616dSLuigi Rizzo */ 5408241616dSLuigi Rizzo #define NETMAP_CAPABLE(ifp) (NA(ifp) && \ 5418241616dSLuigi Rizzo (ifp)->if_capabilities & IFCAP_NETMAP ) 5428241616dSLuigi Rizzo 5438241616dSLuigi Rizzo #define NETMAP_SET_CAPABLE(ifp) \ 5448241616dSLuigi Rizzo (ifp)->if_capabilities |= IFCAP_NETMAP 5458241616dSLuigi Rizzo 5468241616dSLuigi Rizzo #else /* linux */ 5478241616dSLuigi Rizzo 5488241616dSLuigi Rizzo /* 5498241616dSLuigi Rizzo * on linux: 5508241616dSLuigi Rizzo * we check if NA(ifp) is set and its first element has a related 5518241616dSLuigi Rizzo * magic value. The capenable is within the struct netmap_adapter. 5528241616dSLuigi Rizzo */ 5538241616dSLuigi Rizzo #define NETMAP_MAGIC 0x52697a7a 5548241616dSLuigi Rizzo 5558241616dSLuigi Rizzo #define NETMAP_CAPABLE(ifp) (NA(ifp) && \ 5568241616dSLuigi Rizzo ((uint32_t)(uintptr_t)NA(ifp) ^ NA(ifp)->magic) == NETMAP_MAGIC ) 5578241616dSLuigi Rizzo 5588241616dSLuigi Rizzo #define NETMAP_SET_CAPABLE(ifp) \ 5598241616dSLuigi Rizzo NA(ifp)->magic = ((uint32_t)(uintptr_t)NA(ifp)) ^ NETMAP_MAGIC 5608241616dSLuigi Rizzo 5618241616dSLuigi Rizzo #endif /* linux */ 56268b8534bSLuigi Rizzo 563f196ce38SLuigi Rizzo #ifdef __FreeBSD__ 5646dba29a2SLuigi Rizzo /* Callback invoked by the dma machinery after a successfull dmamap_load */ 5656dba29a2SLuigi Rizzo static void netmap_dmamap_cb(__unused void *arg, 5666dba29a2SLuigi Rizzo __unused bus_dma_segment_t * segs, __unused int nseg, __unused int error) 5676dba29a2SLuigi Rizzo { 5686dba29a2SLuigi Rizzo } 5696dba29a2SLuigi Rizzo 5706dba29a2SLuigi Rizzo /* bus_dmamap_load wrapper: call aforementioned function if map != NULL. 5716dba29a2SLuigi Rizzo * XXX can we do it without a callback ? 5726dba29a2SLuigi Rizzo */ 5736dba29a2SLuigi Rizzo static inline void 5746dba29a2SLuigi Rizzo netmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 5756dba29a2SLuigi Rizzo { 5766dba29a2SLuigi Rizzo if (map) 5776dba29a2SLuigi Rizzo bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 5786dba29a2SLuigi Rizzo netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 5796dba29a2SLuigi Rizzo } 5806dba29a2SLuigi Rizzo 5816dba29a2SLuigi Rizzo /* update the map when a buffer changes. */ 5826dba29a2SLuigi Rizzo static inline void 5836dba29a2SLuigi Rizzo netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 5846dba29a2SLuigi Rizzo { 5856dba29a2SLuigi Rizzo if (map) { 5866dba29a2SLuigi Rizzo bus_dmamap_unload(tag, map); 5876dba29a2SLuigi Rizzo bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 5886dba29a2SLuigi Rizzo netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 5896dba29a2SLuigi Rizzo } 5906dba29a2SLuigi Rizzo } 591f196ce38SLuigi Rizzo #else /* linux */ 592f196ce38SLuigi Rizzo 593f196ce38SLuigi Rizzo /* 594f196ce38SLuigi Rizzo * XXX How do we redefine these functions: 595f196ce38SLuigi Rizzo * 596f196ce38SLuigi Rizzo * on linux we need 597f196ce38SLuigi Rizzo * dma_map_single(&pdev->dev, virt_addr, len, direction) 598f196ce38SLuigi Rizzo * dma_unmap_single(&adapter->pdev->dev, phys_addr, len, direction 599f196ce38SLuigi Rizzo * The len can be implicit (on netmap it is NETMAP_BUF_SIZE) 600f196ce38SLuigi Rizzo * unfortunately the direction is not, so we need to change 601f196ce38SLuigi Rizzo * something to have a cross API 602f196ce38SLuigi Rizzo */ 603f196ce38SLuigi Rizzo #define netmap_load_map(_t, _m, _b) 604f196ce38SLuigi Rizzo #define netmap_reload_map(_t, _m, _b) 605f196ce38SLuigi Rizzo #if 0 606f196ce38SLuigi Rizzo struct e1000_buffer *buffer_info = &tx_ring->buffer_info[l]; 607f196ce38SLuigi Rizzo /* set time_stamp *before* dma to help avoid a possible race */ 608f196ce38SLuigi Rizzo buffer_info->time_stamp = jiffies; 609f196ce38SLuigi Rizzo buffer_info->mapped_as_page = false; 610f196ce38SLuigi Rizzo buffer_info->length = len; 611f196ce38SLuigi Rizzo //buffer_info->next_to_watch = l; 612f196ce38SLuigi Rizzo /* reload dma map */ 613f196ce38SLuigi Rizzo dma_unmap_single(&adapter->pdev->dev, buffer_info->dma, 614f196ce38SLuigi Rizzo NETMAP_BUF_SIZE, DMA_TO_DEVICE); 615f196ce38SLuigi Rizzo buffer_info->dma = dma_map_single(&adapter->pdev->dev, 616f196ce38SLuigi Rizzo addr, NETMAP_BUF_SIZE, DMA_TO_DEVICE); 617f196ce38SLuigi Rizzo 618f196ce38SLuigi Rizzo if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) { 619f196ce38SLuigi Rizzo D("dma mapping error"); 620f196ce38SLuigi Rizzo /* goto dma_error; See e1000_put_txbuf() */ 621f196ce38SLuigi Rizzo /* XXX reset */ 622f196ce38SLuigi Rizzo } 623f196ce38SLuigi Rizzo tx_desc->buffer_addr = htole64(buffer_info->dma); //XXX 624f196ce38SLuigi Rizzo 625f196ce38SLuigi Rizzo #endif 626f196ce38SLuigi Rizzo 627f196ce38SLuigi Rizzo /* 628f196ce38SLuigi Rizzo * The bus_dmamap_sync() can be one of wmb() or rmb() depending on direction. 629f196ce38SLuigi Rizzo */ 630f196ce38SLuigi Rizzo #define bus_dmamap_sync(_a, _b, _c) 631f196ce38SLuigi Rizzo 632f196ce38SLuigi Rizzo #endif /* linux */ 6336dba29a2SLuigi Rizzo 634*ce3ee1e7SLuigi Rizzo 6355644ccecSLuigi Rizzo /* 6365644ccecSLuigi Rizzo * functions to map NIC to KRING indexes (n2k) and vice versa (k2n) 6375644ccecSLuigi Rizzo */ 6385644ccecSLuigi Rizzo static inline int 63964ae02c3SLuigi Rizzo netmap_idx_n2k(struct netmap_kring *kr, int idx) 6405644ccecSLuigi Rizzo { 64164ae02c3SLuigi Rizzo int n = kr->nkr_num_slots; 64264ae02c3SLuigi Rizzo idx += kr->nkr_hwofs; 64364ae02c3SLuigi Rizzo if (idx < 0) 64464ae02c3SLuigi Rizzo return idx + n; 64564ae02c3SLuigi Rizzo else if (idx < n) 64664ae02c3SLuigi Rizzo return idx; 6475644ccecSLuigi Rizzo else 64864ae02c3SLuigi Rizzo return idx - n; 6495644ccecSLuigi Rizzo } 6505644ccecSLuigi Rizzo 6515644ccecSLuigi Rizzo 6525644ccecSLuigi Rizzo static inline int 65364ae02c3SLuigi Rizzo netmap_idx_k2n(struct netmap_kring *kr, int idx) 6545644ccecSLuigi Rizzo { 65564ae02c3SLuigi Rizzo int n = kr->nkr_num_slots; 65664ae02c3SLuigi Rizzo idx -= kr->nkr_hwofs; 65764ae02c3SLuigi Rizzo if (idx < 0) 65864ae02c3SLuigi Rizzo return idx + n; 65964ae02c3SLuigi Rizzo else if (idx < n) 66064ae02c3SLuigi Rizzo return idx; 6615644ccecSLuigi Rizzo else 66264ae02c3SLuigi Rizzo return idx - n; 6635644ccecSLuigi Rizzo } 6645644ccecSLuigi Rizzo 6655644ccecSLuigi Rizzo 666d76bf4ffSLuigi Rizzo /* Entries of the look-up table. */ 667d76bf4ffSLuigi Rizzo struct lut_entry { 668d76bf4ffSLuigi Rizzo void *vaddr; /* virtual address. */ 669849bec0eSLuigi Rizzo vm_paddr_t paddr; /* physical address. */ 670d76bf4ffSLuigi Rizzo }; 671d76bf4ffSLuigi Rizzo 672d76bf4ffSLuigi Rizzo struct netmap_obj_pool; 673d76bf4ffSLuigi Rizzo extern struct lut_entry *netmap_buffer_lut; 674d76bf4ffSLuigi Rizzo #define NMB_VA(i) (netmap_buffer_lut[i].vaddr) 675d76bf4ffSLuigi Rizzo #define NMB_PA(i) (netmap_buffer_lut[i].paddr) 676d76bf4ffSLuigi Rizzo 67768b8534bSLuigi Rizzo /* 6786e10c8b8SLuigi Rizzo * NMB return the virtual address of a buffer (buffer 0 on bad index) 6796e10c8b8SLuigi Rizzo * PNMB also fills the physical address 68068b8534bSLuigi Rizzo */ 6816e10c8b8SLuigi Rizzo static inline void * 68268b8534bSLuigi Rizzo NMB(struct netmap_slot *slot) 68368b8534bSLuigi Rizzo { 68468b8534bSLuigi Rizzo uint32_t i = slot->buf_idx; 685f196ce38SLuigi Rizzo return (unlikely(i >= netmap_total_buffers)) ? NMB_VA(0) : NMB_VA(i); 68668b8534bSLuigi Rizzo } 68768b8534bSLuigi Rizzo 6886e10c8b8SLuigi Rizzo static inline void * 6896e10c8b8SLuigi Rizzo PNMB(struct netmap_slot *slot, uint64_t *pp) 6906e10c8b8SLuigi Rizzo { 6916e10c8b8SLuigi Rizzo uint32_t i = slot->buf_idx; 692d76bf4ffSLuigi Rizzo void *ret = (i >= netmap_total_buffers) ? NMB_VA(0) : NMB_VA(i); 6932579e2d7SLuigi Rizzo 694d76bf4ffSLuigi Rizzo *pp = (i >= netmap_total_buffers) ? NMB_PA(0) : NMB_PA(i); 6956e10c8b8SLuigi Rizzo return ret; 6966e10c8b8SLuigi Rizzo } 6976e10c8b8SLuigi Rizzo 6981a26580eSLuigi Rizzo /* default functions to handle rx/tx interrupts */ 699*ce3ee1e7SLuigi Rizzo int netmap_rx_irq(struct ifnet *, u_int, u_int *); 7001a26580eSLuigi Rizzo #define netmap_tx_irq(_n, _q) netmap_rx_irq(_n, _q, NULL) 701f196ce38SLuigi Rizzo 702*ce3ee1e7SLuigi Rizzo #ifdef __FreeBSD__ 703*ce3ee1e7SLuigi Rizzo MALLOC_DECLARE(M_NETMAP); 704*ce3ee1e7SLuigi Rizzo #endif /* __FreeBSD__ */ 705*ce3ee1e7SLuigi Rizzo 706*ce3ee1e7SLuigi Rizzo 707*ce3ee1e7SLuigi Rizzo void netmap_disable_all_rings(struct ifnet *); 708*ce3ee1e7SLuigi Rizzo void netmap_enable_all_rings(struct ifnet *); 709*ce3ee1e7SLuigi Rizzo 71068b8534bSLuigi Rizzo #endif /* _NET_NETMAP_KERN_H_ */ 711