Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Jul 2012 10:52:21 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238837 - head/sys/dev/netmap
Message-ID:  <201207271052.q6RAqLxV096608@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207271052.q6RAqLxV096608>