svn commit: r238837 - head/sys/dev/netmap
Luigi Rizzo
luigi at FreeBSD.org
Fri Jul 27 10:52:22 UTC 2012
Author: luigi
Date: Fri Jul 27 10:52:21 2012
New Revision: 238837
URL: http://svn.freebsd.org/changeset/base/238837
Log:
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.
Modified:
head/sys/dev/netmap/netmap.c
Modified: head/sys/dev/netmap/netmap.c
==============================================================================
--- head/sys/dev/netmap/netmap.c Fri Jul 27 10:41:54 2012 (r238836)
+++ head/sys/dev/netmap/netmap.c Fri Jul 27 10:52:21 2012 (r238837)
@@ -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,
#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
#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
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_adapte
*
* 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 @@ error:
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 @@ error:
* 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, i
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, i
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,
}
+#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
/*
More information about the svn-src-head
mailing list