aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEilon Greenstein <eilong@broadcom.com>2009-01-15 00:22:18 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-15 11:28:10 -0500
commit1cf167f27ad2720af11ee8aa350009342f909e70 (patch)
tree3733c5516e5518cdab133895e515cc4355a216e0 /drivers
parentc53a6ee88b0a91bd012ef1b7988c0b93dae6f24d (diff)
bnx2x: Using singlethread work queue
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/bnx2x.h2
-rw-r--r--drivers/net/bnx2x_main.c20
2 files changed, 16 insertions, 6 deletions
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index fd705d1295a7..96a8889afbe1 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -811,7 +811,7 @@ struct bnx2x {
811 int pm_cap; 811 int pm_cap;
812 int pcie_cap; 812 int pcie_cap;
813 813
814 struct work_struct sp_task; 814 struct delayed_work sp_task;
815 struct work_struct reset_task; 815 struct work_struct reset_task;
816 816
817 struct timer_list timer; 817 struct timer_list timer;
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 4be05847f86f..cc6ffba74592 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -95,6 +95,7 @@ MODULE_PARM_DESC(debug, "default debug msglevel");
95module_param(use_multi, int, 0); 95module_param(use_multi, int, 0);
96MODULE_PARM_DESC(use_multi, "use per-CPU queues"); 96MODULE_PARM_DESC(use_multi, "use per-CPU queues");
97#endif 97#endif
98static struct workqueue_struct *bnx2x_wq;
98 99
99enum bnx2x_board_type { 100enum bnx2x_board_type {
100 BCM57710 = 0, 101 BCM57710 = 0,
@@ -671,7 +672,8 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
671 synchronize_irq(bp->pdev->irq); 672 synchronize_irq(bp->pdev->irq);
672 673
673 /* make sure sp_task is not running */ 674 /* make sure sp_task is not running */
674 cancel_work_sync(&bp->sp_task); 675 cancel_delayed_work(&bp->sp_task);
676 flush_workqueue(bnx2x_wq);
675} 677}
676 678
677/* fast path */ 679/* fast path */
@@ -1660,7 +1662,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
1660 1662
1661 1663
1662 if (unlikely(status & 0x1)) { 1664 if (unlikely(status & 0x1)) {
1663 schedule_work(&bp->sp_task); 1665 queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
1664 1666
1665 status &= ~0x1; 1667 status &= ~0x1;
1666 if (!status) 1668 if (!status)
@@ -2820,7 +2822,7 @@ static void bnx2x_attn_int(struct bnx2x *bp)
2820 2822
2821static void bnx2x_sp_task(struct work_struct *work) 2823static void bnx2x_sp_task(struct work_struct *work)
2822{ 2824{
2823 struct bnx2x *bp = container_of(work, struct bnx2x, sp_task); 2825 struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
2824 u16 status; 2826 u16 status;
2825 2827
2826 2828
@@ -2875,7 +2877,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
2875 return IRQ_HANDLED; 2877 return IRQ_HANDLED;
2876#endif 2878#endif
2877 2879
2878 schedule_work(&bp->sp_task); 2880 queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
2879 2881
2880 return IRQ_HANDLED; 2882 return IRQ_HANDLED;
2881} 2883}
@@ -7501,7 +7503,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
7501 7503
7502 mutex_init(&bp->port.phy_mutex); 7504 mutex_init(&bp->port.phy_mutex);
7503 7505
7504 INIT_WORK(&bp->sp_task, bnx2x_sp_task); 7506 INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
7505 INIT_WORK(&bp->reset_task, bnx2x_reset_task); 7507 INIT_WORK(&bp->reset_task, bnx2x_reset_task);
7506 7508
7507 rc = bnx2x_get_hwinfo(bp); 7509 rc = bnx2x_get_hwinfo(bp);
@@ -10519,12 +10521,20 @@ static struct pci_driver bnx2x_pci_driver = {
10519 10521
10520static int __init bnx2x_init(void) 10522static int __init bnx2x_init(void)
10521{ 10523{
10524 bnx2x_wq = create_singlethread_workqueue("bnx2x");
10525 if (bnx2x_wq == NULL) {
10526 printk(KERN_ERR PFX "Cannot create workqueue\n");
10527 return -ENOMEM;
10528 }
10529
10522 return pci_register_driver(&bnx2x_pci_driver); 10530 return pci_register_driver(&bnx2x_pci_driver);
10523} 10531}
10524 10532
10525static void __exit bnx2x_cleanup(void) 10533static void __exit bnx2x_cleanup(void)
10526{ 10534{
10527 pci_unregister_driver(&bnx2x_pci_driver); 10535 pci_unregister_driver(&bnx2x_pci_driver);
10536
10537 destroy_workqueue(bnx2x_wq);
10528} 10538}
10529 10539
10530module_init(bnx2x_init); 10540module_init(bnx2x_init);