use __builtin_prefetch() for prefetch.

merge in the remaining part of the linux-specific glue so i do not need
to maintain two different distributions.
This commit is contained in:
Luigi Rizzo 2012-07-27 10:52:21 +00:00
parent ba3fd9d86a
commit 01c7d25ff4

View File

@ -58,9 +58,11 @@
#include "bsd_glue.h"
static netdev_tx_t netmap_start_linux(struct sk_buff *skb, struct net_device *dev);
#endif /* linux */
#ifdef __APPLE__
#include "osx_glue.h"
#endif
#endif /* __APPLE__ */
#ifdef __FreeBSD__
#include <sys/cdefs.h> /* prerequisite */
__FBSDID("$FreeBSD$");
@ -155,6 +157,7 @@ SYSCTL_INT(_dev_netmap, OID_AUTO, copy, CTLFLAG_RW, &netmap_copy, 0 , "");
#define NM_BRIDGES 4 /* number of bridges */
int netmap_bridge = NM_BDG_BATCH; /* bridge batch size */
SYSCTL_INT(_dev_netmap, OID_AUTO, bridge, CTLFLAG_RW, &netmap_bridge, 0 , "");
#ifdef linux
#define ADD_BDG_REF(ifp) (NA(ifp)->if_refcount++)
#define DROP_BDG_REF(ifp) (NA(ifp)->if_refcount-- <= 1)
@ -165,6 +168,7 @@ SYSCTL_INT(_dev_netmap, OID_AUTO, bridge, CTLFLAG_RW, &netmap_bridge, 0 , "");
#include <sys/endian.h>
#include <sys/refcount.h>
#endif /* __FreeBSD__ */
#define prefetch(x) __builtin_prefetch(x)
#endif /* !linux */
static void bdg_netmap_attach(struct ifnet *ifp);
@ -175,12 +179,6 @@ struct nm_bdg_fwd { /* forwarding entry for a bridge */
uint64_t dst; /* dst mask */
uint32_t src; /* src index ? */
uint16_t len; /* src len */
#if 0
uint64_t src_mac; /* ignore 2 MSBytes */
uint64_t dst_mac; /* ignore 2 MSBytes */
uint32_t dst_idx; /* dst index in fwd table */
uint32_t dst_buf; /* where we copy to */
#endif
};
struct nm_hash_ent {
@ -217,17 +215,6 @@ struct nm_bridge nm_bridges[NM_BRIDGES];
* NA(ifp)->bdg_port port index
*/
#ifndef linux
static inline void prefetch (const void *x)
{
#if defined(__i386__) || defined(__amd64__)
__asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x));
#else
(void)x;
#endif
}
#endif /* !linux */
// XXX only for multiples of 64 bytes, non overlapped.
static inline void
pkt_copy(void *_src, void *_dst, int l)
@ -540,15 +527,19 @@ netmap_sync_to_host(struct netmap_adapter *na)
*
* This routine also does the selrecord if called from the poll handler
* (we know because td != NULL).
*
* NOTE: on linux, selrecord() is defined as a macro and uses pwait
* as an additional hidden argument.
*/
static void
netmap_sync_from_host(struct netmap_adapter *na, struct thread *td)
netmap_sync_from_host(struct netmap_adapter *na, struct thread *td, void *pwait)
{
struct netmap_kring *kring = &na->rx_rings[na->num_rx_rings];
struct netmap_ring *ring = kring->ring;
u_int j, n, lim = kring->nkr_num_slots;
u_int k = ring->cur, resvd = ring->reserved;
(void)pwait; /* disable unused warnings */
na->nm_lock(na->ifp, NETMAP_CORE_LOCK, 0);
if (k >= lim) {
netmap_ring_reinit(kring);
@ -953,7 +944,7 @@ netmap_ioctl(__unused struct cdev *dev, u_long cmd, caddr_t data,
if (cmd == NIOCTXSYNC)
netmap_sync_to_host(na);
else
netmap_sync_from_host(na, NULL);
netmap_sync_from_host(na, NULL, NULL);
break;
}
/* find the last ring to scan */
@ -1025,13 +1016,12 @@ netmap_ioctl(__unused struct cdev *dev, u_long cmd, caddr_t data,
* Device-dependent parts (locking and sync of tx/rx rings)
* are done through callbacks.
*
* On linux, pwait is the poll table.
* If pwait == NULL someone else already woke up before. We can report
* events but they are filtered upstream.
* If pwait != NULL, then pwait->key contains the list of events.
* On linux, arguments are really pwait, the poll table, and 'td' is struct file *
* The first one is remapped to pwait as selrecord() uses the name as an
* hidden argument.
*/
static int
netmap_poll(__unused struct cdev *dev, int events, struct thread *td)
netmap_poll(struct cdev *dev, int events, struct thread *td)
{
struct netmap_priv_d *priv = NULL;
struct netmap_adapter *na;
@ -1040,6 +1030,9 @@ netmap_poll(__unused struct cdev *dev, int events, struct thread *td)
u_int core_lock, i, check_all, want_tx, want_rx, revents = 0;
u_int lim_tx, lim_rx;
enum {NO_CL, NEED_CL, LOCKED_CL }; /* see below */
void *pwait = dev; /* linux compatibility */
(void)pwait;
if (devfs_get_cdevpriv((void **)&priv) != 0 || priv == NULL)
return POLLERR;
@ -1069,7 +1062,7 @@ netmap_poll(__unused struct cdev *dev, int events, struct thread *td)
if (want_rx) {
kring = &na->rx_rings[lim_rx];
if (kring->ring->avail == 0)
netmap_sync_from_host(na, td);
netmap_sync_from_host(na, td, dev);
if (kring->ring->avail > 0) {
revents |= want_rx;
}
@ -1535,6 +1528,146 @@ netmap_rx_irq(struct ifnet *ifp, int q, int *work_done)
}
#ifdef linux /* linux-specific routines */
/*
* Remap linux arguments into the FreeBSD call.
* - pwait is the poll table, passed as 'dev';
* If pwait == NULL someone else already woke up before. We can report
* events but they are filtered upstream.
* If pwait != NULL, then pwait->key contains the list of events.
* - events is computed from pwait as above.
* - file is passed as 'td';
*/
static u_int
linux_netmap_poll(struct file * file, struct poll_table_struct *pwait)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
int events = pwait ? pwait->key : POLLIN | POLLOUT;
#else /* in 3.4.0 field 'key' was renamed to '_key' */
int events = pwait ? pwait->_key : POLLIN | POLLOUT;
#endif
return netmap_poll((void *)pwait, events, (void *)file);
}
static int
netmap_mmap(__unused struct file *f, struct vm_area_struct *vma)
{
int lut_skip, i, j;
int user_skip = 0;
struct lut_entry *l_entry;
const struct netmap_obj_pool *p[] = {
nm_mem->nm_if_pool,
nm_mem->nm_ring_pool,
nm_mem->nm_buf_pool };
/*
* vma->vm_start: start of mapping user address space
* vma->vm_end: end of the mapping user address space
*/
// XXX security checks
for (i = 0; i < 3; i++) { /* loop through obj_pools */
/*
* In each pool memory is allocated in clusters
* of size _clustsize , each containing clustentries
* entries. For each object k we already store the
* vtophys malling in lut[k] so we use that, scanning
* the lut[] array in steps of clustentries,
* and we map each cluster (not individual pages,
* it would be overkill).
*/
for (lut_skip = 0, j = 0; j < p[i]->_numclusters; j++) {
l_entry = &p[i]->lut[lut_skip];
if (remap_pfn_range(vma, vma->vm_start + user_skip,
l_entry->paddr >> PAGE_SHIFT, p[i]->_clustsize,
vma->vm_page_prot))
return -EAGAIN; // XXX check return value
lut_skip += p[i]->clustentries;
user_skip += p[i]->_clustsize;
}
}
return 0;
}
static netdev_tx_t
netmap_start_linux(struct sk_buff *skb, struct net_device *dev)
{
netmap_start(dev, skb);
return (NETDEV_TX_OK);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
#define LIN_IOCTL_NAME .ioctl
int
linux_netmap_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long data /* arg */)
#else
#define LIN_IOCTL_NAME .unlocked_ioctl
long
linux_netmap_ioctl(struct file *file, u_int cmd, u_long data /* arg */)
#endif
{
int ret;
struct nmreq nmr;
bzero(&nmr, sizeof(nmr));
if (data && copy_from_user(&nmr, (void *)data, sizeof(nmr) ) != 0)
return -EFAULT;
ret = netmap_ioctl(NULL, cmd, (caddr_t)&nmr, 0, (void *)file);
if (data && copy_to_user((void*)data, &nmr, sizeof(nmr) ) != 0)
return -EFAULT;
return -ret;
}
static int
netmap_release(__unused struct inode *inode, struct file *file)
{
if (file->private_data)
netmap_dtor(file->private_data);
return (0);
}
static struct file_operations netmap_fops = {
.mmap = netmap_mmap,
LIN_IOCTL_NAME = linux_netmap_ioctl,
.poll = linux_netmap_poll,
.release = netmap_release,
};
static struct miscdevice netmap_cdevsw = { /* same name as FreeBSD */
MISC_DYNAMIC_MINOR,
"netmap",
&netmap_fops,
};
static int netmap_init(void);
static void netmap_fini(void);
module_init(netmap_init);
module_exit(netmap_fini);
/* export certain symbols to other modules */
EXPORT_SYMBOL(netmap_attach); // driver attach routines
EXPORT_SYMBOL(netmap_detach); // driver detach routines
EXPORT_SYMBOL(netmap_ring_reinit); // ring init on error
EXPORT_SYMBOL(netmap_buffer_lut);
EXPORT_SYMBOL(netmap_total_buffers); // index check
EXPORT_SYMBOL(netmap_buffer_base);
EXPORT_SYMBOL(netmap_reset); // ring init routines
EXPORT_SYMBOL(netmap_buf_size);
EXPORT_SYMBOL(netmap_rx_irq); // default irq handler
EXPORT_SYMBOL(netmap_no_pendintr); // XXX mitigation - should go away
MODULE_AUTHOR("http://info.iet.unipi.it/~luigi/netmap/");
MODULE_DESCRIPTION("The netmap packet I/O framework");
MODULE_LICENSE("Dual BSD/GPL"); /* the code here is all BSD. */
#else /* __FreeBSD__ */
static struct cdevsw netmap_cdevsw = {
.d_version = D_VERSION,
.d_name = "netmap",
@ -1542,6 +1675,7 @@ static struct cdevsw netmap_cdevsw = {
.d_ioctl = netmap_ioctl,
.d_poll = netmap_poll,
};
#endif /* __FreeBSD__ */
#ifdef NM_BRIDGE
/*