#include "common.h"
#include <xen/balloon.h>
#include <xen/interface/memory.h>
+#include <linux/kthread.h>
/*define NETBE_DEBUG_INTERRUPT*/
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;
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)
}
skb_queue_tail(&rx_queue, skb);
- tasklet_schedule(&net_rx_tasklet);
+ wake_up(&netbk_action_wq);
return 0;
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;
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();
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)
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;
continue;
}
- netif_rx(skb);
+ netif_rx_ni(skb);
netif->dev->last_rx = jiffies;
}
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)
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)
{
{
int i;
struct page *page;
+ struct task_struct *task;
if (!is_running_on_xen())
return -ENODEV;
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,