diff options
author | Stefan Assmann <sassmann@kpanic.de> | 2012-12-04 01:00:17 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-12-07 00:55:00 -0500 |
commit | 52285b762b3681669215bf1d17ca6143448ab7d3 (patch) | |
tree | bd03c87362021874f518580da61c13428ee43153 | |
parent | 53c7d06418bdf2f20fc869b33e3a44bb770aff1e (diff) |
igb: release already assigned MSI-X interrupts if setup fails
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:
[<ffffffff8128f39d>] pci_disable_msix+0x3d/0x60
[<ffffffffa037d1ce>] igb_reset_interrupt_capability+0x27/0x5c [igb]
[<ffffffffa037d229>] igb_clear_interrupt_scheme+0x26/0x2d [igb]
[<ffffffffa0384268>] igb_request_irq+0x73/0x297 [igb]
[<ffffffffa0384554>] __igb_open+0xc8/0x223 [igb]
[<ffffffffa0384815>] igb_open+0x13/0x15 [igb]
[<ffffffff8144592f>] __dev_open+0xbf/0x120
[<ffffffff81443e51>] __dev_change_flags+0xa1/0x180
[<ffffffff81445828>] dev_change_flags+0x28/0x70
[<ffffffff814af537>] devinet_ioctl+0x5b7/0x620
[<ffffffff814b01c8>] inet_ioctl+0x88/0xa0
[<ffffffff8142e8a0>] sock_do_ioctl+0x30/0x70
[<ffffffff8142ecf2>] sock_ioctl+0x72/0x270
[<ffffffff8118062c>] do_vfs_ioctl+0x8c/0x340
[<ffffffff81180981>] sys_ioctl+0xa1/0xb0
[<ffffffff815161a9>] 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 [<ffffffff8128e144>] free_msi_irqs+0x124/0x130
RSP <ffff880037503bd8>
Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 615b68c06505..60a2380e9b8c 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -832,17 +832,18 @@ static int igb_request_msix(struct igb_adapter *adapter) | |||
832 | { | 832 | { |
833 | struct net_device *netdev = adapter->netdev; | 833 | struct net_device *netdev = adapter->netdev; |
834 | struct e1000_hw *hw = &adapter->hw; | 834 | struct e1000_hw *hw = &adapter->hw; |
835 | int i, err = 0, vector = 0; | 835 | int i, err = 0, vector = 0, free_vector = 0; |
836 | 836 | ||
837 | err = request_irq(adapter->msix_entries[vector].vector, | 837 | err = request_irq(adapter->msix_entries[vector].vector, |
838 | igb_msix_other, 0, netdev->name, adapter); | 838 | igb_msix_other, 0, netdev->name, adapter); |
839 | if (err) | 839 | if (err) |
840 | goto out; | 840 | goto err_out; |
841 | vector++; | ||
842 | 841 | ||
843 | for (i = 0; i < adapter->num_q_vectors; i++) { | 842 | for (i = 0; i < adapter->num_q_vectors; i++) { |
844 | struct igb_q_vector *q_vector = adapter->q_vector[i]; | 843 | struct igb_q_vector *q_vector = adapter->q_vector[i]; |
845 | 844 | ||
845 | vector++; | ||
846 | |||
846 | q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); | 847 | q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); |
847 | 848 | ||
848 | if (q_vector->rx.ring && q_vector->tx.ring) | 849 | if (q_vector->rx.ring && q_vector->tx.ring) |
@@ -861,13 +862,22 @@ static int igb_request_msix(struct igb_adapter *adapter) | |||
861 | igb_msix_ring, 0, q_vector->name, | 862 | igb_msix_ring, 0, q_vector->name, |
862 | q_vector); | 863 | q_vector); |
863 | if (err) | 864 | if (err) |
864 | goto out; | 865 | goto err_free; |
865 | vector++; | ||
866 | } | 866 | } |
867 | 867 | ||
868 | igb_configure_msix(adapter); | 868 | igb_configure_msix(adapter); |
869 | return 0; | 869 | return 0; |
870 | out: | 870 | |
871 | err_free: | ||
872 | /* free already assigned IRQs */ | ||
873 | free_irq(adapter->msix_entries[free_vector++].vector, adapter); | ||
874 | |||
875 | vector--; | ||
876 | for (i = 0; i < vector; i++) { | ||
877 | free_irq(adapter->msix_entries[free_vector++].vector, | ||
878 | adapter->q_vector[i]); | ||
879 | } | ||
880 | err_out: | ||
871 | return err; | 881 | return err; |
872 | } | 882 | } |
873 | 883 | ||