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
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to