diff options
author | Greg Rose <gregory.v.rose@intel.com> | 2011-10-13 22:57:14 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-10-17 08:08:13 -0400 |
commit | 0224d663063d542b3d829706f3fcbd0f640f19b3 (patch) | |
tree | ffdcb4a4f95e499424ad01d9436b993720bfeb48 /drivers/net/ethernet/intel | |
parent | 4d2d55ac94f52ea8787270ec29579ced83f5f96b (diff) |
igb: Check if subordinate VFs are assigned to virtual machines
Kvm and the Xen pci-back driver will set a flag in the virtual function
pci device dev_flags when the VF is assigned to a guest VM. Before
destroying subordinate VFs check to see if the flag is set and if so
skip the call to pci_disable_sriov() to avoid system crashes.
Copy the maintainer for the Xen pci-back driver. Also CC'ing
maintainers of all drivers found to call pci_disable_sriov().
V2 - Fix uninitialized variable warning
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Christian Benvenuti <benve@cisco.com>
Cc: Sathya Perla <sathya.perla@emulex.com>
Cc: Dimitris Michailidis <dm@chelsio.com>
Cc: Jon Mason <jdmason@kudzu.us>
Cc: James Smart <james.smart@emulex.com>
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 177 |
2 files changed, 150 insertions, 30 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 4c500a76972e..559443015cc5 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h | |||
@@ -72,6 +72,8 @@ struct igb_adapter; | |||
72 | #define IGB_MAX_VF_MC_ENTRIES 30 | 72 | #define IGB_MAX_VF_MC_ENTRIES 30 |
73 | #define IGB_MAX_VF_FUNCTIONS 8 | 73 | #define IGB_MAX_VF_FUNCTIONS 8 |
74 | #define IGB_MAX_VFTA_ENTRIES 128 | 74 | #define IGB_MAX_VFTA_ENTRIES 128 |
75 | #define IGB_82576_VF_DEV_ID 0x10CA | ||
76 | #define IGB_I350_VF_DEV_ID 0x1520 | ||
75 | 77 | ||
76 | struct vf_data_storage { | 78 | struct vf_data_storage { |
77 | unsigned char vf_mac_addresses[ETH_ALEN]; | 79 | unsigned char vf_mac_addresses[ETH_ALEN]; |
@@ -83,6 +85,7 @@ struct vf_data_storage { | |||
83 | u16 pf_vlan; /* When set, guest VLAN config not allowed. */ | 85 | u16 pf_vlan; /* When set, guest VLAN config not allowed. */ |
84 | u16 pf_qos; | 86 | u16 pf_qos; |
85 | u16 tx_rate; | 87 | u16 tx_rate; |
88 | struct pci_dev *vfdev; | ||
86 | }; | 89 | }; |
87 | 90 | ||
88 | #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ | 91 | #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index c10cc716fdec..837adbbce772 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -162,6 +162,9 @@ static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); | |||
162 | static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, | 162 | static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, |
163 | struct ifla_vf_info *ivi); | 163 | struct ifla_vf_info *ivi); |
164 | static void igb_check_vf_rate_limit(struct igb_adapter *); | 164 | static void igb_check_vf_rate_limit(struct igb_adapter *); |
165 | static int igb_vf_configure(struct igb_adapter *adapter, int vf); | ||
166 | static int igb_find_enabled_vfs(struct igb_adapter *adapter); | ||
167 | static int igb_check_vf_assignment(struct igb_adapter *adapter); | ||
165 | 168 | ||
166 | #ifdef CONFIG_PM | 169 | #ifdef CONFIG_PM |
167 | static int igb_suspend(struct pci_dev *, pm_message_t); | 170 | static int igb_suspend(struct pci_dev *, pm_message_t); |
@@ -2232,8 +2235,12 @@ static void __devexit igb_remove(struct pci_dev *pdev) | |||
2232 | /* reclaim resources allocated to VFs */ | 2235 | /* reclaim resources allocated to VFs */ |
2233 | if (adapter->vf_data) { | 2236 | if (adapter->vf_data) { |
2234 | /* disable iov and allow time for transactions to clear */ | 2237 | /* disable iov and allow time for transactions to clear */ |
2235 | pci_disable_sriov(pdev); | 2238 | if (!igb_check_vf_assignment(adapter)) { |
2236 | msleep(500); | 2239 | pci_disable_sriov(pdev); |
2240 | msleep(500); | ||
2241 | } else { | ||
2242 | dev_info(&pdev->dev, "VF(s) assigned to guests!\n"); | ||
2243 | } | ||
2237 | 2244 | ||
2238 | kfree(adapter->vf_data); | 2245 | kfree(adapter->vf_data); |
2239 | adapter->vf_data = NULL; | 2246 | adapter->vf_data = NULL; |
@@ -2270,42 +2277,49 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) | |||
2270 | { | 2277 | { |
2271 | #ifdef CONFIG_PCI_IOV | 2278 | #ifdef CONFIG_PCI_IOV |
2272 | struct pci_dev *pdev = adapter->pdev; | 2279 | struct pci_dev *pdev = adapter->pdev; |
2280 | int old_vfs = igb_find_enabled_vfs(adapter); | ||
2281 | int i; | ||
2273 | 2282 | ||
2274 | if (adapter->vfs_allocated_count) { | 2283 | if (old_vfs) { |
2275 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, | 2284 | dev_info(&pdev->dev, "%d pre-allocated VFs found - override " |
2276 | sizeof(struct vf_data_storage), | 2285 | "max_vfs setting of %d\n", old_vfs, max_vfs); |
2277 | GFP_KERNEL); | 2286 | adapter->vfs_allocated_count = old_vfs; |
2278 | /* if allocation failed then we do not support SR-IOV */ | ||
2279 | if (!adapter->vf_data) { | ||
2280 | adapter->vfs_allocated_count = 0; | ||
2281 | dev_err(&pdev->dev, "Unable to allocate memory for VF " | ||
2282 | "Data Storage\n"); | ||
2283 | } | ||
2284 | } | 2287 | } |
2285 | 2288 | ||
2286 | if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) { | 2289 | if (!adapter->vfs_allocated_count) |
2287 | kfree(adapter->vf_data); | 2290 | return; |
2288 | adapter->vf_data = NULL; | 2291 | |
2289 | #endif /* CONFIG_PCI_IOV */ | 2292 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, |
2293 | sizeof(struct vf_data_storage), GFP_KERNEL); | ||
2294 | /* if allocation failed then we do not support SR-IOV */ | ||
2295 | if (!adapter->vf_data) { | ||
2290 | adapter->vfs_allocated_count = 0; | 2296 | adapter->vfs_allocated_count = 0; |
2291 | #ifdef CONFIG_PCI_IOV | 2297 | dev_err(&pdev->dev, "Unable to allocate memory for VF " |
2292 | } else { | 2298 | "Data Storage\n"); |
2293 | unsigned char mac_addr[ETH_ALEN]; | 2299 | goto out; |
2294 | int i; | ||
2295 | dev_info(&pdev->dev, "%d vfs allocated\n", | ||
2296 | adapter->vfs_allocated_count); | ||
2297 | for (i = 0; i < adapter->vfs_allocated_count; i++) { | ||
2298 | random_ether_addr(mac_addr); | ||
2299 | igb_set_vf_mac(adapter, i, mac_addr); | ||
2300 | } | ||
2301 | /* DMA Coalescing is not supported in IOV mode. */ | ||
2302 | if (adapter->flags & IGB_FLAG_DMAC) | ||
2303 | adapter->flags &= ~IGB_FLAG_DMAC; | ||
2304 | } | 2300 | } |
2301 | |||
2302 | if (!old_vfs) { | ||
2303 | if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) | ||
2304 | goto err_out; | ||
2305 | } | ||
2306 | dev_info(&pdev->dev, "%d VFs allocated\n", | ||
2307 | adapter->vfs_allocated_count); | ||
2308 | for (i = 0; i < adapter->vfs_allocated_count; i++) | ||
2309 | igb_vf_configure(adapter, i); | ||
2310 | |||
2311 | /* DMA Coalescing is not supported in IOV mode. */ | ||
2312 | adapter->flags &= ~IGB_FLAG_DMAC; | ||
2313 | goto out; | ||
2314 | err_out: | ||
2315 | kfree(adapter->vf_data); | ||
2316 | adapter->vf_data = NULL; | ||
2317 | adapter->vfs_allocated_count = 0; | ||
2318 | out: | ||
2319 | return; | ||
2305 | #endif /* CONFIG_PCI_IOV */ | 2320 | #endif /* CONFIG_PCI_IOV */ |
2306 | } | 2321 | } |
2307 | 2322 | ||
2308 | |||
2309 | /** | 2323 | /** |
2310 | * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp | 2324 | * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp |
2311 | * @adapter: board private structure to initialize | 2325 | * @adapter: board private structure to initialize |
@@ -4917,6 +4931,109 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event, | |||
4917 | } | 4931 | } |
4918 | #endif /* CONFIG_IGB_DCA */ | 4932 | #endif /* CONFIG_IGB_DCA */ |
4919 | 4933 | ||
4934 | #ifdef CONFIG_PCI_IOV | ||
4935 | static int igb_vf_configure(struct igb_adapter *adapter, int vf) | ||
4936 | { | ||
4937 | unsigned char mac_addr[ETH_ALEN]; | ||
4938 | struct pci_dev *pdev = adapter->pdev; | ||
4939 | struct e1000_hw *hw = &adapter->hw; | ||
4940 | struct pci_dev *pvfdev; | ||
4941 | unsigned int device_id; | ||
4942 | u16 thisvf_devfn; | ||
4943 | |||
4944 | random_ether_addr(mac_addr); | ||
4945 | igb_set_vf_mac(adapter, vf, mac_addr); | ||
4946 | |||
4947 | switch (adapter->hw.mac.type) { | ||
4948 | case e1000_82576: | ||
4949 | device_id = IGB_82576_VF_DEV_ID; | ||
4950 | /* VF Stride for 82576 is 2 */ | ||
4951 | thisvf_devfn = (pdev->devfn + 0x80 + (vf << 1)) | | ||
4952 | (pdev->devfn & 1); | ||
4953 | break; | ||
4954 | case e1000_i350: | ||
4955 | device_id = IGB_I350_VF_DEV_ID; | ||
4956 | /* VF Stride for I350 is 4 */ | ||
4957 | thisvf_devfn = (pdev->devfn + 0x80 + (vf << 2)) | | ||
4958 | (pdev->devfn & 3); | ||
4959 | break; | ||
4960 | default: | ||
4961 | device_id = 0; | ||
4962 | thisvf_devfn = 0; | ||
4963 | break; | ||
4964 | } | ||
4965 | |||
4966 | pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); | ||
4967 | while (pvfdev) { | ||
4968 | if (pvfdev->devfn == thisvf_devfn) | ||
4969 | break; | ||
4970 | pvfdev = pci_get_device(hw->vendor_id, | ||
4971 | device_id, pvfdev); | ||
4972 | } | ||
4973 | |||
4974 | if (pvfdev) | ||
4975 | adapter->vf_data[vf].vfdev = pvfdev; | ||
4976 | else | ||
4977 | dev_err(&pdev->dev, | ||
4978 | "Couldn't find pci dev ptr for VF %4.4x\n", | ||
4979 | thisvf_devfn); | ||
4980 | return pvfdev != NULL; | ||
4981 | } | ||
4982 | |||
4983 | static int igb_find_enabled_vfs(struct igb_adapter *adapter) | ||
4984 | { | ||
4985 | struct e1000_hw *hw = &adapter->hw; | ||
4986 | struct pci_dev *pdev = adapter->pdev; | ||
4987 | struct pci_dev *pvfdev; | ||
4988 | u16 vf_devfn = 0; | ||
4989 | u16 vf_stride; | ||
4990 | unsigned int device_id; | ||
4991 | int vfs_found = 0; | ||
4992 | |||
4993 | switch (adapter->hw.mac.type) { | ||
4994 | case e1000_82576: | ||
4995 | device_id = IGB_82576_VF_DEV_ID; | ||
4996 | /* VF Stride for 82576 is 2 */ | ||
4997 | vf_stride = 2; | ||
4998 | break; | ||
4999 | case e1000_i350: | ||
5000 | device_id = IGB_I350_VF_DEV_ID; | ||
5001 | /* VF Stride for I350 is 4 */ | ||
5002 | vf_stride = 4; | ||
5003 | break; | ||
5004 | default: | ||
5005 | device_id = 0; | ||
5006 | vf_stride = 0; | ||
5007 | break; | ||
5008 | } | ||
5009 | |||
5010 | vf_devfn = pdev->devfn + 0x80; | ||
5011 | pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); | ||
5012 | while (pvfdev) { | ||
5013 | if (pvfdev->devfn == vf_devfn) | ||
5014 | vfs_found++; | ||
5015 | vf_devfn += vf_stride; | ||
5016 | pvfdev = pci_get_device(hw->vendor_id, | ||
5017 | device_id, pvfdev); | ||
5018 | } | ||
5019 | |||
5020 | return vfs_found; | ||
5021 | } | ||
5022 | |||
5023 | static int igb_check_vf_assignment(struct igb_adapter *adapter) | ||
5024 | { | ||
5025 | int i; | ||
5026 | for (i = 0; i < adapter->vfs_allocated_count; i++) { | ||
5027 | if (adapter->vf_data[i].vfdev) { | ||
5028 | if (adapter->vf_data[i].vfdev->dev_flags & | ||
5029 | PCI_DEV_FLAGS_ASSIGNED) | ||
5030 | return true; | ||
5031 | } | ||
5032 | } | ||
5033 | return false; | ||
5034 | } | ||
5035 | |||
5036 | #endif | ||
4920 | static void igb_ping_all_vfs(struct igb_adapter *adapter) | 5037 | static void igb_ping_all_vfs(struct igb_adapter *adapter) |
4921 | { | 5038 | { |
4922 | struct e1000_hw *hw = &adapter->hw; | 5039 | struct e1000_hw *hw = &adapter->hw; |