]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.bak/.git/commitdiff
patch netback-thread
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:20 +0000 (11:54 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:20 +0000 (11:54 +0100)
drivers/xen/netback/netback.c

index 20891ceb86a7416da6e8ee3b21e9478a04505be4..0dd6b563f4b92c73ebd4d66d6414a7c2e2a0d7de 100644 (file)
@@ -37,6 +37,7 @@
 #include "common.h"
 #include <xen/balloon.h>
 #include <xen/interface/memory.h>
+#include <linux/kthread.h>
 
 /*define NETBE_DEBUG_INTERRUPT*/
 
@@ -64,11 +65,9 @@ static netif_rx_response_t *make_rx_response(netif_t *netif,
                                             u16      size,
                                             u16      flags);
 
-static void net_tx_action(unsigned long unused);
-static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
-
-static void net_rx_action(unsigned long unused);
-static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
+static void net_rx_action(void);
+static void net_tx_action(void);
+static DECLARE_WAIT_QUEUE_HEAD(netbk_action_wq);
 
 static struct timer_list net_timer;
 static struct timer_list netbk_tx_pending_timer;
@@ -193,7 +192,7 @@ static inline void maybe_schedule_tx_action(void)
        smp_mb();
        if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
            !list_empty(&net_schedule_list))
-               tasklet_schedule(&net_tx_tasklet);
+               wake_up(&netbk_action_wq);
 }
 
 static struct sk_buff *netbk_copy_skb(struct sk_buff *skb)
@@ -381,7 +380,7 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        skb_queue_tail(&rx_queue, skb);
-       tasklet_schedule(&net_rx_tasklet);
+       wake_up(&netbk_action_wq);
 
        return 0;
 
@@ -679,7 +678,12 @@ struct skb_cb_overlay {
        int meta_slots_used;
 };
 
-static void net_rx_action(unsigned long unused)
+static inline int net_rx_action_work_to_do(void)
+{
+       return !skb_queue_empty(&rx_queue);
+}
+
+static void net_rx_action(void)
 {
        netif_t *netif = NULL;
        s8 status;
@@ -883,9 +887,11 @@ static void net_rx_action(unsigned long unused)
                notify_remote_via_irq(irq);
        }
 
+#if 0
        /* More work to do? */
        if (!skb_queue_empty(&rx_queue) && !timer_pending(&net_timer))
-               tasklet_schedule(&net_rx_tasklet);
+               wake_up(&netbk_action_wq);
+#endif
 #if 0
        else
                xen_network_done_notify();
@@ -894,12 +900,12 @@ static void net_rx_action(unsigned long unused)
 
 static void net_alarm(unsigned long unused)
 {
-       tasklet_schedule(&net_rx_tasklet);
+       wake_up(&netbk_action_wq);
 }
 
 static void netbk_tx_pending_timeout(unsigned long unused)
 {
-       tasklet_schedule(&net_tx_tasklet);
+       wake_up(&netbk_action_wq);
 }
 
 struct net_device_stats *netif_be_get_stats(struct net_device *dev)
@@ -1333,8 +1339,20 @@ static int netbk_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso)
        return 0;
 }
 
+static inline int net_tx_action_work_to_do(void)
+{
+       if (dealloc_cons != dealloc_prod)
+               return 1;
+
+       if (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+               !list_empty(&net_schedule_list))
+               return 1;
+
+       return 0;
+}
+
 /* Called after netfront has transmitted */
-static void net_tx_action(unsigned long unused)
+static void net_tx_action(void)
 {
        struct list_head *ent;
        struct sk_buff *skb;
@@ -1566,7 +1584,7 @@ static void net_tx_action(unsigned long unused)
                        continue;
                }
 
-               netif_rx(skb);
+               netif_rx_ni(skb);
                netif->dev->last_rx = jiffies;
        }
 
@@ -1592,7 +1610,7 @@ static void netif_idx_release(u16 pending_idx)
        dealloc_prod++;
        spin_unlock_irqrestore(&_lock, flags);
 
-       tasklet_schedule(&net_tx_tasklet);
+       wake_up(&netbk_action_wq);
 }
 
 static void netif_page_release(struct page *page, unsigned int order)
@@ -1669,6 +1687,24 @@ static netif_rx_response_t *make_rx_response(netif_t *netif,
        return resp;
 }
 
+static int netbk_action_thread(void *unused)
+{
+       while (1) {
+               wait_event_interruptible(netbk_action_wq,
+                       net_rx_action_work_to_do() || net_tx_action_work_to_do());
+               cond_resched();
+
+               if (net_rx_action_work_to_do())
+                       net_rx_action();
+
+               if (net_tx_action_work_to_do())
+                       net_tx_action();
+       }
+
+       return 0;
+}
+
+
 #ifdef NETBE_DEBUG_INTERRUPT
 static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1707,6 +1743,7 @@ static int __init netback_init(void)
 {
        int i;
        struct page *page;
+       struct task_struct *task;
 
        if (!is_running_on_xen())
                return -ENODEV;
@@ -1760,6 +1797,10 @@ static int __init netback_init(void)
 
        netif_xenbus_init();
 
+       task = kthread_run(netbk_action_thread, NULL, "netback");
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+
 #ifdef NETBE_DEBUG_INTERRUPT
        (void)bind_virq_to_irqhandler(VIRQ_DEBUG,
                                      0,