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>

authored by

Anton Vorontsov and committed by
David S. Miller
704cc92e a43912ab

+3 -9
+3 -9
drivers/net/3c59x.c
··· 813 if (netif_running(dev)) { 814 netif_device_detach(dev); 815 vortex_down(dev, 1); 816 } 817 pci_save_state(pdev); 818 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); 819 - free_irq(dev->irq, dev); 820 pci_disable_device(pdev); 821 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 822 } ··· 839 return err; 840 } 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)) { 849 err = vortex_up(dev); 850 if (err) 851 return err; 852 - else 853 - netif_device_attach(dev); 854 } 855 } 856 return 0;
··· 813 if (netif_running(dev)) { 814 netif_device_detach(dev); 815 vortex_down(dev, 1); 816 + disable_irq(dev->irq); 817 } 818 pci_save_state(pdev); 819 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); 820 pci_disable_device(pdev); 821 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 822 } ··· 839 return err; 840 } 841 pci_set_master(pdev); 842 if (netif_running(dev)) { 843 err = vortex_up(dev); 844 if (err) 845 return err; 846 + enable_irq(dev->irq); 847 + netif_device_attach(dev); 848 } 849 } 850 return 0;