summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2012-03-21 19:12:08 +0000
committerShaun Ruffell <sruffell@digium.com>2012-03-21 19:12:08 +0000
commitd75f326e15374b0bb6a9a71f2d3c50cff24d3b37 (patch)
treec01fcbc1021ed106f0e43305a532e7e348cf0731
parent457e7b264fa784bbf54ecc115a89e80d3f2a1e29 (diff)
dahdi_dynamic_eth: Move tx packet flushing to process context.
The masterspan can be, and often is, called with interrupts disabled but dev_queue_xmit() needs to be called with interrupts enabled. This potentially fixes a deadlock. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10562 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.6@10570 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/dahdi_dynamic_eth.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/dahdi/dahdi_dynamic_eth.c b/drivers/dahdi/dahdi_dynamic_eth.c
index 46699f5..0fc660f 100644
--- a/drivers/dahdi/dahdi_dynamic_eth.c
+++ b/drivers/dahdi/dahdi_dynamic_eth.c
@@ -191,15 +191,44 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
spin_unlock_irqrestore(&zlock, flags);
}
-
-static int ztdeth_flush(void)
+/**
+ * dahdi_dynamic_flush_work_fn - Flush all pending transactions.
+ *
+ * This function is run in a work queue since we can't guarantee interrupts
+ * will be enabled when we're called, and dev_queue_xmit() requires that
+ * interrupts be enabled.
+ *
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+static void dahdi_dynamic_flush_work_fn(void *data)
+#else
+static void dahdi_dynamic_flush_work_fn(struct work_struct *work)
+#endif
{
struct sk_buff *skb;
-
/* Handle all transmissions now */
while ((skb = skb_dequeue(&skbs))) {
dev_queue_xmit(skb);
}
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
+ dahdi_dynamic_flush_work_fn, NULL);
+#else
+static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
+ dahdi_dynamic_flush_work_fn);
+#endif
+
+/**
+ * ztdeth_flush - Flush all pending transactions.
+ *
+ * This function is called in interrupt context while processing the master
+ * span.
+ */
+static int ztdeth_flush(void)
+{
+ schedule_work(&dahdi_dynamic_eth_flush_work);
return 0;
}
@@ -422,6 +451,7 @@ static int __init ztdeth_init(void)
static void __exit ztdeth_exit(void)
{
+ cancel_work_sync(&dahdi_dynamic_eth_flush_work);
dev_remove_pack(&ztdeth_ptype);
unregister_netdevice_notifier(&ztdeth_nblock);
dahdi_dynamic_unregister_driver(&ztd_eth);