[pisa-src] r2144 - in trunk/kernel: Makefile pisa.c

  • From: Mircea Gherzan <mircea.gherzan@xxxxxxxxxxxxxx>
  • To: pisa-src@xxxxxxxxxxxxx
  • Date: Sun, 14 Mar 2010 22:30:18 +0100

Author: gherzan
Date: Sun Mar 14 22:30:18 2010
New Revision: 2144

Log:
kpisa: add TX workqueue stubs

Also update the Makefile with a small ping in the run target.

Modified:
   trunk/kernel/Makefile
   trunk/kernel/pisa.c

Modified: trunk/kernel/Makefile
==============================================================================
--- trunk/kernel/Makefile       Sun Mar 14 21:47:27 2010        (r2143)
+++ trunk/kernel/Makefile       Sun Mar 14 22:30:18 2010        (r2144)
@@ -21,8 +21,8 @@
        clear
        sudo insmod pisa.ko
        /sbin/ifconfig -a | grep Link
-       sleep 1
-       ps -ef | grep tx
        sudo ifconfig pisa0 192.168.10.1 netmask 255.255.0.0
+       ps -ef | grep pisa
+       ping -c 1 -W 1 -I pisa0 192.168.10.2 || true
        sudo rmmod pisa
        dmesg | tail

Modified: trunk/kernel/pisa.c
==============================================================================
--- trunk/kernel/pisa.c Sun Mar 14 21:47:27 2010        (r2143)
+++ trunk/kernel/pisa.c Sun Mar 14 22:30:18 2010        (r2144)
@@ -15,6 +15,8 @@
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_arp.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
 
 #include <net/rtnetlink.h>
 
@@ -45,17 +47,68 @@
 struct pisa_priv {
        struct workqueue_struct *tx_wq;
        struct work_struct      tx_work;
+       struct sk_buff_head     tx_list;
+       int                     tx_connected;
 };
 
+
+static int pisa_send(struct sk_buff *skb)
+{
+       struct net_device *dev = skb->dev;
+       struct pisa_priv *priv __maybe_unused = netdev_priv(dev);
+
+       /* TODO can a better decision be taken here? */
+       if (!priv->tx_connected) {
+               dprintk("not connected, dropping skb %p", skb);
+               return -ENXIO;
+       }
+
+       dprintk("sending skb %p via socket", skb);
+       /* TODO */
+
+       return 0;
+}
+
+static void pisa_tx_wq_handler(struct work_struct *work)
+{
+       struct pisa_priv *priv = container_of(work, struct pisa_priv, tx_work);
+       struct sk_buff *skb = NULL;
+       struct net_device *dev __maybe_unused = NULL;
+       int err;
+
+       spin_lock_bh(&priv->tx_list.lock);
+       while (!skb_queue_empty(&priv->tx_list)) {
+
+               /* The "normal" dequeue function disables IRQs, but we only
+                * need serialization with bottom halves, so we use this.
+                */
+               skb = __skb_dequeue(&priv->tx_list);
+               spin_unlock_bh(&priv->tx_list.lock);
+
+               err = pisa_send(skb);
+               if (unlikely(err)) {
+                       /* TODO update stats */
+               }
+
+               kfree_skb(skb);
+
+               spin_lock_bh(&priv->tx_list.lock);
+       }
+       spin_unlock_bh(&priv->tx_list.lock);
+}
+
 static int pisa_init_netdev(struct net_device *dev)
 {
        struct pisa_priv *priv = netdev_priv(dev);
        char wq_name[PISA_NAME_LEN];
 
+       skb_queue_head_init(&priv->tx_list);
+       INIT_WORK(&priv->tx_work, pisa_tx_wq_handler);
+
        snprintf(wq_name, PISA_NAME_LEN, "%s_tx", dev->name);
 
        dprintk("creating own workqueue");
-       priv->tx_wq = create_workqueue(dev->name);
+       priv->tx_wq = create_workqueue(wq_name);
 
        return (priv->tx_wq) ? 0 : -ENOMEM;
 }
@@ -80,6 +133,15 @@
 {
        struct pisa_priv *priv = netdev_priv(dev);
 
+       /* The _xmit calls are serialized, but we still need to sync
+        * with the working queues that run in process context.
+        * The "normal" call disables interrupts, but we don't need this
+        * and therefore we use the "unlocked" variant.
+        */
+       spin_lock(&priv->tx_list.lock);
+       __skb_queue_tail(&priv->tx_list, skb);
+       spin_unlock(&priv->tx_list.lock);
+
        schedule_work(&priv->tx_work);
 
        return NETDEV_TX_OK;
@@ -96,7 +158,7 @@
 {
        struct pisa_priv *priv = netdev_priv(dev);
 
-       dprintk("destroying %s", dev->name);
+       dprintk("destroying");
 
        free_netdev(dev);
 

Other related posts:

  • » [pisa-src] r2144 - in trunk/kernel: Makefile pisa.c - Mircea Gherzan