]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
imported patch netback-thread netback-defensive.patch
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:02 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:02 +0000 (12:06 +0000)
drivers/xen/netback/netback.c

index c91849d9dc0fd72e81f3b6261fb244ea4f838b85..11518632765b6bc7ac15f6c28ce4faca50e9d07a 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*/
 
@@ -65,11 +66,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;
@@ -194,7 +193,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)
@@ -378,7 +377,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;
 
@@ -676,7 +675,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;
@@ -880,9 +884,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();
@@ -891,12 +897,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)
@@ -1326,8 +1332,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;
@@ -1559,7 +1577,7 @@ static void net_tx_action(unsigned long unused)
                        continue;
                }
 
-               netif_rx(skb);
+               netif_rx_ni(skb);
                netif->dev->last_rx = jiffies;
        }
 
@@ -1585,7 +1603,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)
@@ -1661,6 +1679,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)
 {
@@ -1699,6 +1735,7 @@ static int __init netback_init(void)
 {
        int i;
        struct page *page;
+       struct task_struct *task;
 
        if (!is_running_on_xen())
                return -ENODEV;
@@ -1752,6 +1789,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,