From patchwork Wed Jan 23 21:39:53 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [3.5.y.z, extended, stable] Patch "igb: release already assigned MSI-X interrupts if setup" has been added to staging queue Date: Wed, 23 Jan 2013 11:39:53 -0000 From: Herton Ronaldo Krzesinski X-Patchwork-Id: 215047 Message-Id: <1358977193-24152-1-git-send-email-herton.krzesinski@canonical.com> To: Stefan Assmann Cc: kernel-team@lists.ubuntu.com, Jeff Kirsher This is a note to let you know that I have just added a patch titled igb: release already assigned MSI-X interrupts if setup to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree which can be found at: http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.5.y-queue If you, or anyone else, feels it should not be added to this tree, please reply to this email. For more information about the 3.5.y.z tree, see https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable Thanks. -Herton ------ >From fb8dae6836fd81fecb3a3b53584ba8d2a697ba3e Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Tue, 4 Dec 2012 06:00:17 +0000 Subject: [PATCH] igb: release already assigned MSI-X interrupts if setup fails commit 52285b762b3681669215bf1d17ca6143448ab7d3 upstream. During MSI-X setup the system might run out of vectors. If this happens the already assigned vectors for this NIC should be freed before trying the disable MSI-X. Failing to do so results in the following oops. kernel BUG at drivers/pci/msi.c:341! [...] Call Trace: [] pci_disable_msix+0x3d/0x60 [] igb_reset_interrupt_capability+0x27/0x5c [igb] [] igb_clear_interrupt_scheme+0x26/0x2d [igb] [] igb_request_irq+0x73/0x297 [igb] [] __igb_open+0xc8/0x223 [igb] [] igb_open+0x13/0x15 [igb] [] __dev_open+0xbf/0x120 [] __dev_change_flags+0xa1/0x180 [] dev_change_flags+0x28/0x70 [] devinet_ioctl+0x5b7/0x620 [] inet_ioctl+0x88/0xa0 [] sock_do_ioctl+0x30/0x70 [] sock_ioctl+0x72/0x270 [] do_vfs_ioctl+0x8c/0x340 [] sys_ioctl+0xa1/0xb0 [] system_call_fastpath+0x16/0x1b Code: 48 89 df e8 1f 40 ed ff 4d 39 e6 49 8b 45 10 75 b6 48 83 c4 18 5b 41 5c 41 5d 41 5e 41 5f c9 c3 48 8b 7b 20 e8 3e 91 db ff eb ae <0f> 0b eb fe 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00 RIP [] free_msi_irqs+0x124/0x130 RSP Signed-off-by: Stefan Assmann Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Herton Ronaldo Krzesinski --- drivers/net/ethernet/intel/igb/igb_main.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) -- 1.7.9.5 diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index dd3bfe8..64a0f74 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -937,17 +937,18 @@ static int igb_request_msix(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; - int i, err = 0, vector = 0; + int i, err = 0, vector = 0, free_vector = 0; err = request_irq(adapter->msix_entries[vector].vector, igb_msix_other, 0, netdev->name, adapter); if (err) - goto out; - vector++; + goto err_out; for (i = 0; i < adapter->num_q_vectors; i++) { struct igb_q_vector *q_vector = adapter->q_vector[i]; + vector++; + q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); if (q_vector->rx.ring && q_vector->tx.ring) @@ -966,13 +967,22 @@ static int igb_request_msix(struct igb_adapter *adapter) igb_msix_ring, 0, q_vector->name, q_vector); if (err) - goto out; - vector++; + goto err_free; } igb_configure_msix(adapter); return 0; -out: + +err_free: + /* free already assigned IRQs */ + free_irq(adapter->msix_entries[free_vector++].vector, adapter); + + vector--; + for (i = 0; i < vector; i++) { + free_irq(adapter->msix_entries[free_vector++].vector, + adapter->q_vector[i]); + } +err_out: return err; }