| From stable-bounces@linux.kernel.org Fri Dec 8 09:03:45 2006 |
| Date: Fri, 8 Dec 2006 11:58:15 -0500 (EST) |
| From: Daniel Barkalow <barkalow@iabervon.org> |
| To: stable@kernel.org |
| Message-ID: <Pine.LNX.4.64.0612081147290.20138@iabervon.org> |
| Cc: Linus Torvalds <torvalds@osdl.org>, Greg KH <gregkh@suse.de>, Jeff Garzik <jeff@garzik.org> |
| Subject: forcedeth: Disable INTx when enabling MSI in forcedeth |
| |
| At least some nforce cards continue to send legacy interrupts when MSI |
| is enabled, and these interrupts are treated as unhandled by the |
| kernel. This patch disables legacy interrupts explicitly when enabling |
| MSI mode. |
| |
| The correct fix is to change the MSI infrastructure to disable legacy |
| interrupts when enabling MSI, but this is potentially risky if the |
| device isn't PCI-2.3 or is quirky, so the correct fix is going into |
| mainline, while patches like this one go into -stable. |
| |
| Legend has it that it is most correct to disable legacy interrupts |
| before enabling MSI, but the mainline patch does it in the other |
| order, and this patch is "obviously" the same as mainline. |
| |
| Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> |
| Cc: Jeff Garzik <jeff@garzik.org> |
| Cc: Greg KH <gregkh@suse.de> |
| Signed-off-by: Chris Wright <chrisw@sous-sol.org> |
| --- |
| |
| The general patch got into mainline last night, and this patch is clearly |
| the same as that one, limited to the case of forcedeth (the pci_intx() |
| calls are lifted from {enable,disable}_msi_mode to all of the indirect |
| callers in forcedeth). |
| |
| drivers/net/forcedeth.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- linux-2.6.19.orig/drivers/net/forcedeth.c |
| +++ linux-2.6.19/drivers/net/forcedeth.c |
| @@ -2815,11 +2815,13 @@ static int nv_request_irq(struct net_dev |
| } |
| if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { |
| if ((ret = pci_enable_msi(np->pci_dev)) == 0) { |
| + pci_intx(np->pci_dev, 0); |
| np->msi_flags |= NV_MSI_ENABLED; |
| if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, IRQF_SHARED, dev->name, dev) != 0) || |
| (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, IRQF_SHARED, dev->name, dev) != 0)) { |
| printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); |
| pci_disable_msi(np->pci_dev); |
| + pci_intx(np->pci_dev, 1); |
| np->msi_flags &= ~NV_MSI_ENABLED; |
| goto out_err; |
| } |
| @@ -2862,6 +2864,7 @@ static void nv_free_irq(struct net_devic |
| free_irq(np->pci_dev->irq, dev); |
| if (np->msi_flags & NV_MSI_ENABLED) { |
| pci_disable_msi(np->pci_dev); |
| + pci_intx(np->pci_dev, 1); |
| np->msi_flags &= ~NV_MSI_ENABLED; |
| } |
| } |