From a7475906bc496456ded9e4b062f94067fb93057a Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Wed, 17 Oct 2007 21:52:33 +0200 Subject: forcedeth msi bugfix pci_enable_msi() replaces the INTx irq number in pci_dev->irq with the new MSI irq number. The forcedeth driver did not update the copy in netdevice->irq and parts of the driver used the stale copy. See bugzilla.kernel.org, bug 9047. The patch - updates netdevice->irq - replaces all accesses to netdevice->irq with pci_dev->irq. The patch is against 2.6.23.1. IMHO suitable for both 2.6.23 and 2.6.24 Signed-Off-By: Manfred Spraul Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index d0bff8a87666..70ddf1acfd88 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -992,7 +992,7 @@ static void nv_enable_irq(struct net_device *dev) if (np->msi_flags & NV_MSI_X_ENABLED) enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else - enable_irq(dev->irq); + enable_irq(np->pci_dev->irq); } else { enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); @@ -1008,7 +1008,7 @@ static void nv_disable_irq(struct net_device *dev) if (np->msi_flags & NV_MSI_X_ENABLED) disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else - disable_irq(dev->irq); + disable_irq(np->pci_dev->irq); } else { disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); @@ -1607,7 +1607,7 @@ static void nv_do_rx_refill(unsigned long data) if (np->msi_flags & NV_MSI_X_ENABLED) disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else - disable_irq(dev->irq); + disable_irq(np->pci_dev->irq); } else { disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } @@ -1625,7 +1625,7 @@ static void nv_do_rx_refill(unsigned long data) if (np->msi_flags & NV_MSI_X_ENABLED) enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else - enable_irq(dev->irq); + enable_irq(np->pci_dev->irq); } else { enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } @@ -3560,10 +3560,12 @@ static int nv_request_irq(struct net_device *dev, int intr_test) if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { if ((ret = pci_enable_msi(np->pci_dev)) == 0) { np->msi_flags |= NV_MSI_ENABLED; + dev->irq = np->pci_dev->irq; if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) { printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); pci_disable_msi(np->pci_dev); np->msi_flags &= ~NV_MSI_ENABLED; + dev->irq = np->pci_dev->irq; goto out_err; } @@ -3626,7 +3628,7 @@ static void nv_do_nic_poll(unsigned long data) if (np->msi_flags & NV_MSI_X_ENABLED) disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else - disable_irq_lockdep(dev->irq); + disable_irq_lockdep(np->pci_dev->irq); mask = np->irqmask; } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { @@ -3644,6 +3646,8 @@ static void nv_do_nic_poll(unsigned long data) } np->nic_poll_irq = 0; + /* disable_irq() contains synchronize_irq, thus no irq handler can run now */ + if (np->recover_error) { np->recover_error = 0; printk(KERN_INFO "forcedeth: MAC in recoverable error state\n"); @@ -3680,7 +3684,6 @@ static void nv_do_nic_poll(unsigned long data) } } - /* FIXME: Do we need synchronize_irq(dev->irq) here? */ writel(mask, base + NvRegIrqMask); pci_push(base); @@ -3693,7 +3696,7 @@ static void nv_do_nic_poll(unsigned long data) if (np->msi_flags & NV_MSI_X_ENABLED) enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else - enable_irq_lockdep(dev->irq); + enable_irq_lockdep(np->pci_dev->irq); } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { nv_nic_irq_rx(0, dev); @@ -4950,7 +4953,7 @@ static int nv_close(struct net_device *dev) #ifdef CONFIG_FORCEDETH_NAPI napi_disable(&np->napi); #endif - synchronize_irq(dev->irq); + synchronize_irq(np->pci_dev->irq); del_timer_sync(&np->oom_kick); del_timer_sync(&np->nic_poll); -- cgit v1.2.2