diff options
author | Stefan Assmann <sassmann@kpanic.de> | 2013-09-24 01:18:39 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2013-10-24 08:53:46 -0400 |
commit | 781798a11e2820ee35fa9142869bb8cec117dedc (patch) | |
tree | 7938d5fb27c67d12af63042072fde0d636365291 /drivers/net/ethernet/intel/igb/igb_main.c | |
parent | d1c17d806b6a52ff020322bec457717a91ea50a9 (diff) |
igb: fix driver reload with VF assigned to guest
commit fa44f2f185f7f9da19d331929bb1b56c1ccd1d93 broke reloading of igb, when
VFs are assigned to a guest, in several ways.
1. on module load adapter->vf_data does not get properly allocated,
resulting in a null pointer exception when accessing adapter->vf_data in
igb_reset() on module reload.
modprobe -r igb ; modprobe igb max_vfs=7
[ 215.215837] igb 0000:01:00.1: removed PHC on eth1
[ 216.932072] igb 0000:01:00.1: IOV Disabled
[ 216.937038] igb 0000:01:00.0: removed PHC on eth0
[ 217.127032] igb 0000:01:00.0: Cannot deallocate SR-IOV virtual functions while they are assigned - VFs will not be deallocated
[ 217.146178] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.0.5-k
[ 217.154050] igb: Copyright (c) 2007-2013 Intel Corporation.
[ 217.160688] igb 0000:01:00.0: Enabling SR-IOV VFs using the module parameter is deprecated - please use the pci sysfs interface.
[ 217.173703] igb 0000:01:00.0: irq 103 for MSI/MSI-X
[ 217.179227] igb 0000:01:00.0: irq 104 for MSI/MSI-X
[ 217.184735] igb 0000:01:00.0: irq 105 for MSI/MSI-X
[ 217.220082] BUG: unable to handle kernel NULL pointer dereference at 0000000000000048
[ 217.228846] IP: [<ffffffffa007c5e5>] igb_reset+0xc5/0x4b0 [igb]
[ 217.235472] PGD 3607ec067 PUD 36170b067 PMD 0
[ 217.240461] Oops: 0002 [#1] SMP
[ 217.244085] Modules linked in: igb(+) igbvf mptsas mptscsih mptbase scsi_transport_sas [last unloaded: igb]
[ 217.255040] CPU: 4 PID: 4833 Comm: modprobe Not tainted 3.11.0+ #46
[...]
[ 217.390007] [<ffffffffa007fab2>] igb_probe+0x892/0xfd0 [igb]
[ 217.396422] [<ffffffff81470b3e>] local_pci_probe+0x1e/0x40
[ 217.402641] [<ffffffff81472029>] pci_device_probe+0xf9/0x110
[...]
2. A follow up issue, pci_enable_sriov() should only be called if no VFs were
still allocated on module unload. Otherwise pci_enable_sriov() gets called
multiple times in a row rendering the NIC unusable until reset.
3. simply calling igb_enable_sriov() in igb_probe_vfs() is not enough as the
interrupts need to be re-setup. Switching that to igb_pci_enable_sriov().
Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Tested-by: Sibai Li <Sibai.li@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igb/igb_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 37 |
1 files changed, 16 insertions, 21 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index a505d3bad09a..ebe6370c4b18 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -182,6 +182,7 @@ static void igb_check_vf_rate_limit(struct igb_adapter *); | |||
182 | 182 | ||
183 | #ifdef CONFIG_PCI_IOV | 183 | #ifdef CONFIG_PCI_IOV |
184 | static int igb_vf_configure(struct igb_adapter *adapter, int vf); | 184 | static int igb_vf_configure(struct igb_adapter *adapter, int vf); |
185 | static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs); | ||
185 | #endif | 186 | #endif |
186 | 187 | ||
187 | #ifdef CONFIG_PM | 188 | #ifdef CONFIG_PM |
@@ -2429,7 +2430,7 @@ err_dma: | |||
2429 | } | 2430 | } |
2430 | 2431 | ||
2431 | #ifdef CONFIG_PCI_IOV | 2432 | #ifdef CONFIG_PCI_IOV |
2432 | static int igb_disable_sriov(struct pci_dev *pdev) | 2433 | static int igb_disable_sriov(struct pci_dev *pdev) |
2433 | { | 2434 | { |
2434 | struct net_device *netdev = pci_get_drvdata(pdev); | 2435 | struct net_device *netdev = pci_get_drvdata(pdev); |
2435 | struct igb_adapter *adapter = netdev_priv(netdev); | 2436 | struct igb_adapter *adapter = netdev_priv(netdev); |
@@ -2470,27 +2471,19 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) | |||
2470 | int err = 0; | 2471 | int err = 0; |
2471 | int i; | 2472 | int i; |
2472 | 2473 | ||
2473 | if (!adapter->msix_entries) { | 2474 | if (!adapter->msix_entries || num_vfs > 7) { |
2474 | err = -EPERM; | 2475 | err = -EPERM; |
2475 | goto out; | 2476 | goto out; |
2476 | } | 2477 | } |
2477 | |||
2478 | if (!num_vfs) | 2478 | if (!num_vfs) |
2479 | goto out; | 2479 | goto out; |
2480 | else if (old_vfs && old_vfs == num_vfs) | ||
2481 | goto out; | ||
2482 | else if (old_vfs && old_vfs != num_vfs) | ||
2483 | err = igb_disable_sriov(pdev); | ||
2484 | |||
2485 | if (err) | ||
2486 | goto out; | ||
2487 | 2480 | ||
2488 | if (num_vfs > 7) { | 2481 | if (old_vfs) { |
2489 | err = -EPERM; | 2482 | dev_info(&pdev->dev, "%d pre-allocated VFs found - override max_vfs setting of %d\n", |
2490 | goto out; | 2483 | old_vfs, max_vfs); |
2491 | } | 2484 | adapter->vfs_allocated_count = old_vfs; |
2492 | 2485 | } else | |
2493 | adapter->vfs_allocated_count = num_vfs; | 2486 | adapter->vfs_allocated_count = num_vfs; |
2494 | 2487 | ||
2495 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, | 2488 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, |
2496 | sizeof(struct vf_data_storage), GFP_KERNEL); | 2489 | sizeof(struct vf_data_storage), GFP_KERNEL); |
@@ -2504,10 +2497,12 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) | |||
2504 | goto out; | 2497 | goto out; |
2505 | } | 2498 | } |
2506 | 2499 | ||
2507 | err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); | 2500 | /* only call pci_enable_sriov() if no VFs are allocated already */ |
2508 | if (err) | 2501 | if (!old_vfs) { |
2509 | goto err_out; | 2502 | err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); |
2510 | 2503 | if (err) | |
2504 | goto err_out; | ||
2505 | } | ||
2511 | dev_info(&pdev->dev, "%d VFs allocated\n", | 2506 | dev_info(&pdev->dev, "%d VFs allocated\n", |
2512 | adapter->vfs_allocated_count); | 2507 | adapter->vfs_allocated_count); |
2513 | for (i = 0; i < adapter->vfs_allocated_count; i++) | 2508 | for (i = 0; i < adapter->vfs_allocated_count; i++) |
@@ -2623,7 +2618,7 @@ static void igb_probe_vfs(struct igb_adapter *adapter) | |||
2623 | return; | 2618 | return; |
2624 | 2619 | ||
2625 | pci_sriov_set_totalvfs(pdev, 7); | 2620 | pci_sriov_set_totalvfs(pdev, 7); |
2626 | igb_enable_sriov(pdev, max_vfs); | 2621 | igb_pci_enable_sriov(pdev, max_vfs); |
2627 | 2622 | ||
2628 | #endif /* CONFIG_PCI_IOV */ | 2623 | #endif /* CONFIG_PCI_IOV */ |
2629 | } | 2624 | } |