aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/3c59x.c
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2009-09-24 04:31:52 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-24 18:39:26 -0400
commit704cc92e9ffe29458ea8831ae097c631b1160c01 (patch)
tree5ef8846d23a73deb54e9694a936185402986e250 /drivers/net/3c59x.c
parenta43912ab1925788765208da5cd664b6f8e011d08 (diff)
3c59x: Get rid of "Trying to free already-free IRQ"
Following trace pops up if we try to suspend with 3c59x ethernet NIC brought down: root@b1:~# ifconfig eth16 down root@b1:~# echo mem > /sys/power/state ... 3c59x 0000:00:10.0: suspend 3c59x 0000:00:10.0: PME# disabled Trying to free already-free IRQ 48 ------------[ cut here ]------------ Badness at c00554e4 [verbose debug info unavailable] NIP: c00554e4 LR: c00554e4 CTR: c019a098 REGS: c7975c60 TRAP: 0700 Not tainted (2.6.31-rc4) MSR: 00021032 <ME,CE,IR,DR> CR: 28242422 XER: 20000000 TASK = c79cb0c0[1746] 'bash' THREAD: c7974000 ... NIP [c00554e4] __free_irq+0x108/0x1b0 LR [c00554e4] __free_irq+0x108/0x1b0 Call Trace: [c7975d10] [c00554e4] __free_irq+0x108/0x1b0 (unreliable) [c7975d30] [c005559c] free_irq+0x10/0x24 [c7975d40] [c01e21ec] vortex_suspend+0x70/0xc4 [c7975d60] [c017e584] pci_legacy_suspend+0x58/0x100 This is because the driver manages interrupts without checking for netif_running(). Though, there are few other issues with suspend/resume in this driver. The intention of calling free_irq() in suspend() was to avoid any possible spurious interrupts (see commit 5b039e681b8c5f30aac9cc04385 "3c59x PM fixes"). But, - On resume, the driver was requesting IRQ just after pci_set_master(), but before vortex_up() (which actually resets 3c59x chips). - Issuing free_irq() on a shared IRQ doesn't guarantee that a buggy HW won't trigger spurious interrupts in another driver that requested the same interrupt. So, if we want to protect from unexpected interrupts, then on suspend we should issue disable_irq(), not free_irq(). Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/3c59x.c')
-rw-r--r--drivers/net/3c59x.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 7adff4d0960d..b9eeadf01b74 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -813,10 +813,10 @@ static int vortex_suspend(struct pci_dev *pdev, pm_message_t state)
813 if (netif_running(dev)) { 813 if (netif_running(dev)) {
814 netif_device_detach(dev); 814 netif_device_detach(dev);
815 vortex_down(dev, 1); 815 vortex_down(dev, 1);
816 disable_irq(dev->irq);
816 } 817 }
817 pci_save_state(pdev); 818 pci_save_state(pdev);
818 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); 819 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
819 free_irq(dev->irq, dev);
820 pci_disable_device(pdev); 820 pci_disable_device(pdev);
821 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 821 pci_set_power_state(pdev, pci_choose_state(pdev, state));
822 } 822 }
@@ -839,18 +839,12 @@ static int vortex_resume(struct pci_dev *pdev)
839 return err; 839 return err;
840 } 840 }
841 pci_set_master(pdev); 841 pci_set_master(pdev);
842 if (request_irq(dev->irq, vp->full_bus_master_rx ?
843 &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) {
844 pr_warning("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
845 pci_disable_device(pdev);
846 return -EBUSY;
847 }
848 if (netif_running(dev)) { 842 if (netif_running(dev)) {
849 err = vortex_up(dev); 843 err = vortex_up(dev);
850 if (err) 844 if (err)
851 return err; 845 return err;
852 else 846 enable_irq(dev->irq);
853 netif_device_attach(dev); 847 netif_device_attach(dev);
854 } 848 }
855 } 849 }
856 return 0; 850 return 0;