]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.25/patches.drivers/bnx2x-Using-singlethread-work-queue.patch
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / bnx2x-Using-singlethread-work-queue.patch
diff --git a/src/patches/suse-2.6.27.25/patches.drivers/bnx2x-Using-singlethread-work-queue.patch b/src/patches/suse-2.6.27.25/patches.drivers/bnx2x-Using-singlethread-work-queue.patch
new file mode 100644 (file)
index 0000000..72c2714
--- /dev/null
@@ -0,0 +1,114 @@
+From 1cf167f27ad2720af11ee8aa350009342f909e70 Mon Sep 17 00:00:00 2001
+From: Eilon Greenstein <eilong@broadcom.com>
+Date: Wed, 14 Jan 2009 21:22:18 -0800
+Subject: bnx2x: Using singlethread work queue
+Acked-by: Karsten Keil <kkeil@novell.com>
+Reference: bnc#472500
+
+Since slow-path events, including link update, are handled in
+work-queue, a race condition was introduced in the self-test that
+sometimes caused the link status to fail: the self-test was running
+under RTNL lock, and if the link-watch was scheduled it stoped the
+shared work-queue (waiting for the RTNL lock) and so the link update
+event was not handled until the self-test ended (releasing the RTNL
+lock) with failure (since the link status was not updated)
+
+Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/bnx2x.h      |    2 +-
+ drivers/net/bnx2x_main.c |   20 +++++++++++++++-----
+ 2 files changed, 16 insertions(+), 6 deletions(-)
+
+Index: linux-2.6.27-bnx2x_2/drivers/net/bnx2x.h
+===================================================================
+--- linux-2.6.27-bnx2x_2.orig/drivers/net/bnx2x.h
++++ linux-2.6.27-bnx2x_2/drivers/net/bnx2x.h
+@@ -811,7 +811,7 @@ struct bnx2x {
+       int                     pm_cap;
+       int                     pcie_cap;
+-      struct work_struct      sp_task;
++      struct delayed_work     sp_task;
+       struct work_struct      reset_task;
+       struct timer_list       timer;
+Index: linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c
+===================================================================
+--- linux-2.6.27-bnx2x_2.orig/drivers/net/bnx2x_main.c
++++ linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c
+@@ -95,6 +95,7 @@ MODULE_PARM_DESC(debug, "default debug m
+ module_param(use_multi, int, 0);
+ MODULE_PARM_DESC(use_multi, "use per-CPU queues");
+ #endif
++static struct workqueue_struct *bnx2x_wq;
+ enum bnx2x_board_type {
+       BCM57710 = 0,
+@@ -671,7 +672,8 @@ static void bnx2x_int_disable_sync(struc
+               synchronize_irq(bp->pdev->irq);
+       /* make sure sp_task is not running */
+-      cancel_work_sync(&bp->sp_task);
++      cancel_delayed_work(&bp->sp_task);
++      flush_workqueue(bnx2x_wq);
+ }
+ /* fast path */
+@@ -1663,7 +1665,7 @@ static irqreturn_t bnx2x_interrupt(int i
+       if (unlikely(status & 0x1)) {
+-              schedule_work(&bp->sp_task);
++              queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
+               status &= ~0x1;
+               if (!status)
+@@ -2823,7 +2825,7 @@ static void bnx2x_attn_int(struct bnx2x 
+ static void bnx2x_sp_task(struct work_struct *work)
+ {
+-      struct bnx2x *bp = container_of(work, struct bnx2x, sp_task);
++      struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
+       u16 status;
+@@ -2878,7 +2880,7 @@ static irqreturn_t bnx2x_msix_sp_int(int
+               return IRQ_HANDLED;
+ #endif
+-      schedule_work(&bp->sp_task);
++      queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
+       return IRQ_HANDLED;
+ }
+@@ -7504,7 +7506,7 @@ static int __devinit bnx2x_init_bp(struc
+       mutex_init(&bp->port.phy_mutex);
+-      INIT_WORK(&bp->sp_task, bnx2x_sp_task);
++      INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
+       INIT_WORK(&bp->reset_task, bnx2x_reset_task);
+       rc = bnx2x_get_hwinfo(bp);
+@@ -10522,12 +10524,20 @@ static struct pci_driver bnx2x_pci_drive
+ static int __init bnx2x_init(void)
+ {
++      bnx2x_wq = create_singlethread_workqueue("bnx2x");
++      if (bnx2x_wq == NULL) {
++              printk(KERN_ERR PFX "Cannot create workqueue\n");
++              return -ENOMEM;
++      }
++
+       return pci_register_driver(&bnx2x_pci_driver);
+ }
+ static void __exit bnx2x_cleanup(void)
+ {
+       pci_unregister_driver(&bnx2x_pci_driver);
++
++      destroy_workqueue(bnx2x_wq);
+ }
+ module_init(bnx2x_init);