168b8534bSLuigi Rizzo /* 21a26580eSLuigi Rizzo * Copyright (C) 2011-2012 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$ 28*64ae02c3SLuigi Rizzo * $Id: netmap_kern.h 10602 2012-02-21 16:47:55Z luigi $ 2968b8534bSLuigi Rizzo * 3068b8534bSLuigi Rizzo * The header contains the definitions of constants and function 3168b8534bSLuigi Rizzo * prototypes used only in kernelspace. 3268b8534bSLuigi Rizzo */ 3368b8534bSLuigi Rizzo 3468b8534bSLuigi Rizzo #ifndef _NET_NETMAP_KERN_H_ 3568b8534bSLuigi Rizzo #define _NET_NETMAP_KERN_H_ 3668b8534bSLuigi Rizzo 371a26580eSLuigi Rizzo #if defined(__FreeBSD__) 381a26580eSLuigi Rizzo #define NM_LOCK_T struct mtx 391a26580eSLuigi Rizzo #define NM_SELINFO_T struct selinfo 401a26580eSLuigi Rizzo #define MBUF_LEN(m) ((m)->m_pkthdr.len) 411a26580eSLuigi Rizzo #define NM_SEND_UP(ifp, m) ((ifp)->if_input)(ifp, m) 42*64ae02c3SLuigi Rizzo #elif defined (linux) 431a26580eSLuigi Rizzo #define NM_LOCK_T spinlock_t 441a26580eSLuigi Rizzo #define NM_SELINFO_T wait_queue_head_t 451a26580eSLuigi Rizzo #define MBUF_LEN(m) ((m)->len) 461a26580eSLuigi Rizzo #define NM_SEND_UP(ifp, m) netif_rx(m) 471a26580eSLuigi Rizzo #else 481a26580eSLuigi Rizzo #error unsupported platform 491a26580eSLuigi Rizzo #endif 501a26580eSLuigi Rizzo 5168b8534bSLuigi Rizzo #ifdef MALLOC_DECLARE 5268b8534bSLuigi Rizzo MALLOC_DECLARE(M_NETMAP); 5368b8534bSLuigi Rizzo #endif 5468b8534bSLuigi Rizzo 5568b8534bSLuigi Rizzo #define ND(format, ...) 5668b8534bSLuigi Rizzo #define D(format, ...) \ 5768b8534bSLuigi Rizzo do { \ 5868b8534bSLuigi Rizzo struct timeval __xxts; \ 5968b8534bSLuigi Rizzo microtime(&__xxts); \ 6068b8534bSLuigi Rizzo printf("%03d.%06d %s [%d] " format "\n", \ 6168b8534bSLuigi Rizzo (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ 6268b8534bSLuigi Rizzo __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 6368b8534bSLuigi Rizzo } while (0) 6468b8534bSLuigi Rizzo 6568b8534bSLuigi Rizzo struct netmap_adapter; 6668b8534bSLuigi Rizzo 6768b8534bSLuigi Rizzo /* 68*64ae02c3SLuigi Rizzo * private, kernel view of a ring. Keeps track of the status of 69*64ae02c3SLuigi Rizzo * a ring across system calls. 70*64ae02c3SLuigi Rizzo * 71*64ae02c3SLuigi Rizzo * nr_hwcur index of the next buffer to refill. 72*64ae02c3SLuigi Rizzo * It corresponds to ring->cur - ring->reserved 73*64ae02c3SLuigi Rizzo * 74*64ae02c3SLuigi Rizzo * nr_hwavail the number of slots "owned" by userspace. 75*64ae02c3SLuigi Rizzo * nr_hwavail =:= ring->avail + ring->reserved 7668b8534bSLuigi Rizzo * 771a26580eSLuigi Rizzo * The indexes in the NIC and netmap rings are offset by nkr_hwofs slots. 7868b8534bSLuigi Rizzo * This is so that, on a reset, buffers owned by userspace are not 7968b8534bSLuigi Rizzo * modified by the kernel. In particular: 801a26580eSLuigi Rizzo * RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides with 8168b8534bSLuigi Rizzo * the next empty buffer as known by the hardware (next_to_check or so). 8268b8534bSLuigi Rizzo * TX rings: hwcur + hwofs coincides with next_to_send 8368b8534bSLuigi Rizzo */ 8468b8534bSLuigi Rizzo struct netmap_kring { 8568b8534bSLuigi Rizzo struct netmap_ring *ring; 8668b8534bSLuigi Rizzo u_int nr_hwcur; 8768b8534bSLuigi Rizzo int nr_hwavail; 882157a17cSLuigi Rizzo u_int nr_kflags; /* private driver flags */ 892157a17cSLuigi Rizzo #define NKR_PENDINTR 0x1 // Pending interrupt. 9068b8534bSLuigi Rizzo u_int nkr_num_slots; 9168b8534bSLuigi Rizzo 92506cc70cSLuigi Rizzo int nkr_hwofs; /* offset between NIC and netmap ring */ 931a26580eSLuigi Rizzo struct netmap_adapter *na; 941a26580eSLuigi Rizzo NM_SELINFO_T si; /* poll/select wait queue */ 951a26580eSLuigi Rizzo NM_LOCK_T q_lock; /* used if no device lock available */ 962157a17cSLuigi Rizzo } __attribute__((__aligned__(64))); 9768b8534bSLuigi Rizzo 9868b8534bSLuigi Rizzo /* 991a26580eSLuigi Rizzo * This struct extends the 'struct adapter' (or 10068b8534bSLuigi Rizzo * equivalent) device descriptor. It contains all fields needed to 10168b8534bSLuigi Rizzo * support netmap operation. 10268b8534bSLuigi Rizzo */ 10368b8534bSLuigi Rizzo struct netmap_adapter { 10468b8534bSLuigi Rizzo int refcount; /* number of user-space descriptors using this 10568b8534bSLuigi Rizzo interface, which is equal to the number of 10668b8534bSLuigi Rizzo struct netmap_if objs in the mapped region. */ 10768b8534bSLuigi Rizzo 10868b8534bSLuigi Rizzo int separate_locks; /* set if the interface suports different 10968b8534bSLuigi Rizzo locks for rx, tx and core. */ 11068b8534bSLuigi Rizzo 111*64ae02c3SLuigi Rizzo u_int num_rx_queues; /* number of tx/rx queue pairs: this is 11268b8534bSLuigi Rizzo a duplicate field needed to simplify the 11368b8534bSLuigi Rizzo signature of ``netmap_detach``. */ 114*64ae02c3SLuigi Rizzo u_int num_tx_queues; // if nonzero, overrides num_queues XXX 11568b8534bSLuigi Rizzo 11668b8534bSLuigi Rizzo u_int num_tx_desc; /* number of descriptor in each queue */ 11768b8534bSLuigi Rizzo u_int num_rx_desc; 118*64ae02c3SLuigi Rizzo u_int buff_size; // XXX deprecate, use NETMAP_BUF_SIZE 11968b8534bSLuigi Rizzo 1201a26580eSLuigi Rizzo //u_int flags; // XXX unused 12168b8534bSLuigi Rizzo /* tx_rings and rx_rings are private but allocated 12268b8534bSLuigi Rizzo * as a contiguous chunk of memory. Each array has 12368b8534bSLuigi Rizzo * N+1 entries, for the adapter queues and for the host queue. 12468b8534bSLuigi Rizzo */ 12568b8534bSLuigi Rizzo struct netmap_kring *tx_rings; /* array of TX rings. */ 12668b8534bSLuigi Rizzo struct netmap_kring *rx_rings; /* array of RX rings. */ 12768b8534bSLuigi Rizzo 128*64ae02c3SLuigi Rizzo NM_SELINFO_T tx_si, rx_si; /* global wait queues */ 129*64ae02c3SLuigi Rizzo 13068b8534bSLuigi Rizzo /* copy of if_qflush and if_transmit pointers, to intercept 13168b8534bSLuigi Rizzo * packets from the network stack when netmap is active. 13268b8534bSLuigi Rizzo * XXX probably if_qflush is not necessary. 13368b8534bSLuigi Rizzo */ 1341a26580eSLuigi Rizzo //void (*if_qflush)(struct ifnet *); // XXX unused 13568b8534bSLuigi Rizzo int (*if_transmit)(struct ifnet *, struct mbuf *); 13668b8534bSLuigi Rizzo 13768b8534bSLuigi Rizzo /* references to the ifnet and device routines, used by 13868b8534bSLuigi Rizzo * the generic netmap functions. 13968b8534bSLuigi Rizzo */ 14068b8534bSLuigi Rizzo struct ifnet *ifp; /* adapter is ifp->if_softc */ 14168b8534bSLuigi Rizzo 1421a26580eSLuigi Rizzo NM_LOCK_T core_lock; /* used if no device lock available */ 1431a26580eSLuigi Rizzo 14468b8534bSLuigi Rizzo int (*nm_register)(struct ifnet *, int onoff); 1451a26580eSLuigi Rizzo void (*nm_lock)(struct ifnet *, int what, u_int ringid); 1461a26580eSLuigi Rizzo int (*nm_txsync)(struct ifnet *, u_int ring, int lock); 1471a26580eSLuigi Rizzo int (*nm_rxsync)(struct ifnet *, u_int ring, int lock); 148*64ae02c3SLuigi Rizzo #ifdef linux 149*64ae02c3SLuigi Rizzo struct net_device_ops nm_ndo; 150*64ae02c3SLuigi Rizzo #endif /* linux */ 15168b8534bSLuigi Rizzo }; 15268b8534bSLuigi Rizzo 15368b8534bSLuigi Rizzo /* 15468b8534bSLuigi Rizzo * The combination of "enable" (ifp->if_capabilities &IFCAP_NETMAP) 15568b8534bSLuigi Rizzo * and refcount gives the status of the interface, namely: 15668b8534bSLuigi Rizzo * 15768b8534bSLuigi Rizzo * enable refcount Status 15868b8534bSLuigi Rizzo * 15968b8534bSLuigi Rizzo * FALSE 0 normal operation 16068b8534bSLuigi Rizzo * FALSE != 0 -- (impossible) 16168b8534bSLuigi Rizzo * TRUE 1 netmap mode 16268b8534bSLuigi Rizzo * TRUE 0 being deleted. 16368b8534bSLuigi Rizzo */ 16468b8534bSLuigi Rizzo 16568b8534bSLuigi Rizzo #define NETMAP_DELETING(_na) ( ((_na)->refcount == 0) && \ 16668b8534bSLuigi Rizzo ( (_na)->ifp->if_capenable & IFCAP_NETMAP) ) 16768b8534bSLuigi Rizzo 16868b8534bSLuigi Rizzo /* 16968b8534bSLuigi Rizzo * parameters for (*nm_lock)(adapter, what, index) 17068b8534bSLuigi Rizzo */ 17168b8534bSLuigi Rizzo enum { 17268b8534bSLuigi Rizzo NETMAP_NO_LOCK = 0, 17368b8534bSLuigi Rizzo NETMAP_CORE_LOCK, NETMAP_CORE_UNLOCK, 17468b8534bSLuigi Rizzo NETMAP_TX_LOCK, NETMAP_TX_UNLOCK, 17568b8534bSLuigi Rizzo NETMAP_RX_LOCK, NETMAP_RX_UNLOCK, 1761a26580eSLuigi Rizzo #ifdef __FreeBSD__ 1771a26580eSLuigi Rizzo #define NETMAP_REG_LOCK NETMAP_CORE_LOCK 1781a26580eSLuigi Rizzo #define NETMAP_REG_UNLOCK NETMAP_CORE_UNLOCK 1791a26580eSLuigi Rizzo #else 1801a26580eSLuigi Rizzo NETMAP_REG_LOCK, NETMAP_REG_UNLOCK 1811a26580eSLuigi Rizzo #endif 18268b8534bSLuigi Rizzo }; 18368b8534bSLuigi Rizzo 18468b8534bSLuigi Rizzo /* 18568b8534bSLuigi Rizzo * The following are support routines used by individual drivers to 18668b8534bSLuigi Rizzo * support netmap operation. 18768b8534bSLuigi Rizzo * 18868b8534bSLuigi Rizzo * netmap_attach() initializes a struct netmap_adapter, allocating the 18968b8534bSLuigi Rizzo * struct netmap_ring's and the struct selinfo. 19068b8534bSLuigi Rizzo * 19168b8534bSLuigi Rizzo * netmap_detach() frees the memory allocated by netmap_attach(). 19268b8534bSLuigi Rizzo * 19368b8534bSLuigi Rizzo * netmap_start() replaces the if_transmit routine of the interface, 19468b8534bSLuigi Rizzo * and is used to intercept packets coming from the stack. 19568b8534bSLuigi Rizzo * 19668b8534bSLuigi Rizzo * netmap_load_map/netmap_reload_map are helper routines to set/reset 19768b8534bSLuigi Rizzo * the dmamap for a packet buffer 19868b8534bSLuigi Rizzo * 19968b8534bSLuigi Rizzo * netmap_reset() is a helper routine to be called in the driver 20068b8534bSLuigi Rizzo * when reinitializing a ring. 20168b8534bSLuigi Rizzo */ 20268b8534bSLuigi Rizzo int netmap_attach(struct netmap_adapter *, int); 20368b8534bSLuigi Rizzo void netmap_detach(struct ifnet *); 20468b8534bSLuigi Rizzo int netmap_start(struct ifnet *, struct mbuf *); 20568b8534bSLuigi Rizzo enum txrx { NR_RX = 0, NR_TX = 1 }; 20668b8534bSLuigi Rizzo struct netmap_slot *netmap_reset(struct netmap_adapter *na, 20768b8534bSLuigi Rizzo enum txrx tx, int n, u_int new_cur); 20868b8534bSLuigi Rizzo int netmap_ring_reinit(struct netmap_kring *); 20968b8534bSLuigi Rizzo 2105819da83SLuigi Rizzo extern int netmap_buf_size; 2115819da83SLuigi Rizzo #define NETMAP_BUF_SIZE netmap_buf_size 2122157a17cSLuigi Rizzo extern int netmap_mitigate; 2135819da83SLuigi Rizzo extern int netmap_no_pendintr; 21468b8534bSLuigi Rizzo extern u_int netmap_total_buffers; 21568b8534bSLuigi Rizzo extern char *netmap_buffer_base; 21668b8534bSLuigi Rizzo extern int netmap_verbose; // XXX debugging 21768b8534bSLuigi Rizzo enum { /* verbose flags */ 21868b8534bSLuigi Rizzo NM_VERB_ON = 1, /* generic verbose */ 21968b8534bSLuigi Rizzo NM_VERB_HOST = 0x2, /* verbose host stack */ 22068b8534bSLuigi Rizzo NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ 22168b8534bSLuigi Rizzo NM_VERB_TXSYNC = 0x20, 22268b8534bSLuigi Rizzo NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ 22368b8534bSLuigi Rizzo NM_VERB_TXINTR = 0x200, 22468b8534bSLuigi Rizzo NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ 22568b8534bSLuigi Rizzo NM_VERB_NIC_TXSYNC = 0x2000, 22668b8534bSLuigi Rizzo }; 22768b8534bSLuigi Rizzo 22868b8534bSLuigi Rizzo /* 229d0c7b075SLuigi Rizzo * NA returns a pointer to the struct netmap adapter from the ifp, 230d0c7b075SLuigi Rizzo * WNA is used to write it. 23168b8534bSLuigi Rizzo */ 232d0c7b075SLuigi Rizzo #ifndef WNA 233d0c7b075SLuigi Rizzo #define WNA(_ifp) (_ifp)->if_pspare[0] 234d0c7b075SLuigi Rizzo #endif 235d0c7b075SLuigi Rizzo #define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) 23668b8534bSLuigi Rizzo 23768b8534bSLuigi Rizzo 2386dba29a2SLuigi Rizzo /* Callback invoked by the dma machinery after a successfull dmamap_load */ 2396dba29a2SLuigi Rizzo static void netmap_dmamap_cb(__unused void *arg, 2406dba29a2SLuigi Rizzo __unused bus_dma_segment_t * segs, __unused int nseg, __unused int error) 2416dba29a2SLuigi Rizzo { 2426dba29a2SLuigi Rizzo } 2436dba29a2SLuigi Rizzo 2446dba29a2SLuigi Rizzo /* bus_dmamap_load wrapper: call aforementioned function if map != NULL. 2456dba29a2SLuigi Rizzo * XXX can we do it without a callback ? 2466dba29a2SLuigi Rizzo */ 2476dba29a2SLuigi Rizzo static inline void 2486dba29a2SLuigi Rizzo netmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 2496dba29a2SLuigi Rizzo { 2506dba29a2SLuigi Rizzo if (map) 2516dba29a2SLuigi Rizzo bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 2526dba29a2SLuigi Rizzo netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 2536dba29a2SLuigi Rizzo } 2546dba29a2SLuigi Rizzo 2556dba29a2SLuigi Rizzo /* update the map when a buffer changes. */ 2566dba29a2SLuigi Rizzo static inline void 2576dba29a2SLuigi Rizzo netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) 2586dba29a2SLuigi Rizzo { 2596dba29a2SLuigi Rizzo if (map) { 2606dba29a2SLuigi Rizzo bus_dmamap_unload(tag, map); 2616dba29a2SLuigi Rizzo bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, 2626dba29a2SLuigi Rizzo netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); 2636dba29a2SLuigi Rizzo } 2646dba29a2SLuigi Rizzo } 2656dba29a2SLuigi Rizzo 2665644ccecSLuigi Rizzo /* 2675644ccecSLuigi Rizzo * functions to map NIC to KRING indexes (n2k) and vice versa (k2n) 2685644ccecSLuigi Rizzo */ 2695644ccecSLuigi Rizzo static inline int 270*64ae02c3SLuigi Rizzo netmap_idx_n2k(struct netmap_kring *kr, int idx) 2715644ccecSLuigi Rizzo { 272*64ae02c3SLuigi Rizzo int n = kr->nkr_num_slots; 273*64ae02c3SLuigi Rizzo idx += kr->nkr_hwofs; 274*64ae02c3SLuigi Rizzo if (idx < 0) 275*64ae02c3SLuigi Rizzo return idx + n; 276*64ae02c3SLuigi Rizzo else if (idx < n) 277*64ae02c3SLuigi Rizzo return idx; 2785644ccecSLuigi Rizzo else 279*64ae02c3SLuigi Rizzo return idx - n; 2805644ccecSLuigi Rizzo } 2815644ccecSLuigi Rizzo 2825644ccecSLuigi Rizzo 2835644ccecSLuigi Rizzo static inline int 284*64ae02c3SLuigi Rizzo netmap_idx_k2n(struct netmap_kring *kr, int idx) 2855644ccecSLuigi Rizzo { 286*64ae02c3SLuigi Rizzo int n = kr->nkr_num_slots; 287*64ae02c3SLuigi Rizzo idx -= kr->nkr_hwofs; 288*64ae02c3SLuigi Rizzo if (idx < 0) 289*64ae02c3SLuigi Rizzo return idx + n; 290*64ae02c3SLuigi Rizzo else if (idx < n) 291*64ae02c3SLuigi Rizzo return idx; 2925644ccecSLuigi Rizzo else 293*64ae02c3SLuigi Rizzo return idx - n; 2945644ccecSLuigi Rizzo } 2955644ccecSLuigi Rizzo 2965644ccecSLuigi Rizzo 29768b8534bSLuigi Rizzo /* 2986e10c8b8SLuigi Rizzo * NMB return the virtual address of a buffer (buffer 0 on bad index) 2996e10c8b8SLuigi Rizzo * PNMB also fills the physical address 30068b8534bSLuigi Rizzo */ 3016e10c8b8SLuigi Rizzo static inline void * 30268b8534bSLuigi Rizzo NMB(struct netmap_slot *slot) 30368b8534bSLuigi Rizzo { 30468b8534bSLuigi Rizzo uint32_t i = slot->buf_idx; 30568b8534bSLuigi Rizzo return (i >= netmap_total_buffers) ? netmap_buffer_base : 30668b8534bSLuigi Rizzo netmap_buffer_base + (i *NETMAP_BUF_SIZE); 30768b8534bSLuigi Rizzo } 30868b8534bSLuigi Rizzo 3096e10c8b8SLuigi Rizzo static inline void * 3106e10c8b8SLuigi Rizzo PNMB(struct netmap_slot *slot, uint64_t *pp) 3116e10c8b8SLuigi Rizzo { 3126e10c8b8SLuigi Rizzo uint32_t i = slot->buf_idx; 3136e10c8b8SLuigi Rizzo void *ret = (i >= netmap_total_buffers) ? netmap_buffer_base : 3146e10c8b8SLuigi Rizzo netmap_buffer_base + (i *NETMAP_BUF_SIZE); 3156e10c8b8SLuigi Rizzo *pp = vtophys(ret); 3166e10c8b8SLuigi Rizzo return ret; 3176e10c8b8SLuigi Rizzo } 3186e10c8b8SLuigi Rizzo 3191a26580eSLuigi Rizzo /* default functions to handle rx/tx interrupts */ 3201a26580eSLuigi Rizzo int netmap_rx_irq(struct ifnet *, int, int *); 3211a26580eSLuigi Rizzo #define netmap_tx_irq(_n, _q) netmap_rx_irq(_n, _q, NULL) 3221a26580eSLuigi Rizzo #ifdef __linux__ 3231a26580eSLuigi Rizzo #define bus_dmamap_sync(_a, _b, _c) // wmb() or rmb() ? 3241a26580eSLuigi Rizzo netdev_tx_t netmap_start_linux(struct sk_buff *skb, struct net_device *dev); 3251a26580eSLuigi Rizzo #endif 32668b8534bSLuigi Rizzo #endif /* _NET_NETMAP_KERN_H_ */ 327