+++ /dev/null
-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);