diff options
author | Greg Rose <gregory.v.rose@intel.com> | 2013-01-17 04:03:06 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2013-01-18 07:55:16 -0500 |
commit | fa44f2f185f7f9da19d331929bb1b56c1ccd1d93 (patch) | |
tree | 836c53e105232f90ca7cfd5ebbdfa3278573c878 /drivers/net/ethernet/intel/igb/igb_main.c | |
parent | b67e191307a3f330525265af3e2877a74d557cbf (diff) |
igb: Enable SR-IOV configuration via PCI sysfs interface
Implement callback in the driver for the new PCI bus driver
interface that allows the user to enable/disable SR-IOV
virtual functions in a device via the sysfs interface.
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@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 | 320 |
1 files changed, 219 insertions, 101 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index a0a31b55a073..342bbd661d3b 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -193,6 +193,7 @@ static const struct dev_pm_ops igb_pm_ops = { | |||
193 | }; | 193 | }; |
194 | #endif | 194 | #endif |
195 | static void igb_shutdown(struct pci_dev *); | 195 | static void igb_shutdown(struct pci_dev *); |
196 | static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs); | ||
196 | #ifdef CONFIG_IGB_DCA | 197 | #ifdef CONFIG_IGB_DCA |
197 | static int igb_notify_dca(struct notifier_block *, unsigned long, void *); | 198 | static int igb_notify_dca(struct notifier_block *, unsigned long, void *); |
198 | static struct notifier_block dca_notifier = { | 199 | static struct notifier_block dca_notifier = { |
@@ -234,6 +235,7 @@ static struct pci_driver igb_driver = { | |||
234 | .driver.pm = &igb_pm_ops, | 235 | .driver.pm = &igb_pm_ops, |
235 | #endif | 236 | #endif |
236 | .shutdown = igb_shutdown, | 237 | .shutdown = igb_shutdown, |
238 | .sriov_configure = igb_pci_sriov_configure, | ||
237 | .err_handler = &igb_err_handler | 239 | .err_handler = &igb_err_handler |
238 | }; | 240 | }; |
239 | 241 | ||
@@ -2195,6 +2197,99 @@ err_dma: | |||
2195 | return err; | 2197 | return err; |
2196 | } | 2198 | } |
2197 | 2199 | ||
2200 | #ifdef CONFIG_PCI_IOV | ||
2201 | static int igb_disable_sriov(struct pci_dev *pdev) | ||
2202 | { | ||
2203 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
2204 | struct igb_adapter *adapter = netdev_priv(netdev); | ||
2205 | struct e1000_hw *hw = &adapter->hw; | ||
2206 | |||
2207 | /* reclaim resources allocated to VFs */ | ||
2208 | if (adapter->vf_data) { | ||
2209 | /* disable iov and allow time for transactions to clear */ | ||
2210 | if (igb_vfs_are_assigned(adapter)) { | ||
2211 | dev_warn(&pdev->dev, | ||
2212 | "Cannot deallocate SR-IOV virtual functions while they are assigned - VFs will not be deallocated\n"); | ||
2213 | return -EPERM; | ||
2214 | } else { | ||
2215 | pci_disable_sriov(pdev); | ||
2216 | msleep(500); | ||
2217 | } | ||
2218 | |||
2219 | kfree(adapter->vf_data); | ||
2220 | adapter->vf_data = NULL; | ||
2221 | adapter->vfs_allocated_count = 0; | ||
2222 | wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); | ||
2223 | wrfl(); | ||
2224 | msleep(100); | ||
2225 | dev_info(&pdev->dev, "IOV Disabled\n"); | ||
2226 | |||
2227 | /* Re-enable DMA Coalescing flag since IOV is turned off */ | ||
2228 | adapter->flags |= IGB_FLAG_DMAC; | ||
2229 | } | ||
2230 | |||
2231 | return 0; | ||
2232 | } | ||
2233 | |||
2234 | static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) | ||
2235 | { | ||
2236 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
2237 | struct igb_adapter *adapter = netdev_priv(netdev); | ||
2238 | int old_vfs = pci_num_vf(pdev); | ||
2239 | int err = 0; | ||
2240 | int i; | ||
2241 | |||
2242 | if (!num_vfs) | ||
2243 | goto out; | ||
2244 | else if (old_vfs && old_vfs == num_vfs) | ||
2245 | goto out; | ||
2246 | else if (old_vfs && old_vfs != num_vfs) | ||
2247 | err = igb_disable_sriov(pdev); | ||
2248 | |||
2249 | if (err) | ||
2250 | goto out; | ||
2251 | |||
2252 | if (num_vfs > 7) { | ||
2253 | err = -EPERM; | ||
2254 | goto out; | ||
2255 | } | ||
2256 | |||
2257 | adapter->vfs_allocated_count = num_vfs; | ||
2258 | |||
2259 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, | ||
2260 | sizeof(struct vf_data_storage), GFP_KERNEL); | ||
2261 | |||
2262 | /* if allocation failed then we do not support SR-IOV */ | ||
2263 | if (!adapter->vf_data) { | ||
2264 | adapter->vfs_allocated_count = 0; | ||
2265 | dev_err(&pdev->dev, | ||
2266 | "Unable to allocate memory for VF Data Storage\n"); | ||
2267 | err = -ENOMEM; | ||
2268 | goto out; | ||
2269 | } | ||
2270 | |||
2271 | err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); | ||
2272 | if (err) | ||
2273 | goto err_out; | ||
2274 | |||
2275 | dev_info(&pdev->dev, "%d VFs allocated\n", | ||
2276 | adapter->vfs_allocated_count); | ||
2277 | for (i = 0; i < adapter->vfs_allocated_count; i++) | ||
2278 | igb_vf_configure(adapter, i); | ||
2279 | |||
2280 | /* DMA Coalescing is not supported in IOV mode. */ | ||
2281 | adapter->flags &= ~IGB_FLAG_DMAC; | ||
2282 | goto out; | ||
2283 | |||
2284 | err_out: | ||
2285 | kfree(adapter->vf_data); | ||
2286 | adapter->vf_data = NULL; | ||
2287 | adapter->vfs_allocated_count = 0; | ||
2288 | out: | ||
2289 | return err; | ||
2290 | } | ||
2291 | |||
2292 | #endif | ||
2198 | /** | 2293 | /** |
2199 | * igb_remove - Device Removal Routine | 2294 | * igb_remove - Device Removal Routine |
2200 | * @pdev: PCI device information struct | 2295 | * @pdev: PCI device information struct |
@@ -2242,23 +2337,7 @@ static void igb_remove(struct pci_dev *pdev) | |||
2242 | igb_clear_interrupt_scheme(adapter); | 2337 | igb_clear_interrupt_scheme(adapter); |
2243 | 2338 | ||
2244 | #ifdef CONFIG_PCI_IOV | 2339 | #ifdef CONFIG_PCI_IOV |
2245 | /* reclaim resources allocated to VFs */ | 2340 | igb_disable_sriov(pdev); |
2246 | if (adapter->vf_data) { | ||
2247 | /* disable iov and allow time for transactions to clear */ | ||
2248 | if (igb_vfs_are_assigned(adapter)) { | ||
2249 | dev_info(&pdev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n"); | ||
2250 | } else { | ||
2251 | pci_disable_sriov(pdev); | ||
2252 | msleep(500); | ||
2253 | } | ||
2254 | |||
2255 | kfree(adapter->vf_data); | ||
2256 | adapter->vf_data = NULL; | ||
2257 | wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); | ||
2258 | wrfl(); | ||
2259 | msleep(100); | ||
2260 | dev_info(&pdev->dev, "IOV Disabled\n"); | ||
2261 | } | ||
2262 | #endif | 2341 | #endif |
2263 | 2342 | ||
2264 | iounmap(hw->hw_addr); | 2343 | iounmap(hw->hw_addr); |
@@ -2289,103 +2368,22 @@ static void igb_probe_vfs(struct igb_adapter *adapter) | |||
2289 | #ifdef CONFIG_PCI_IOV | 2368 | #ifdef CONFIG_PCI_IOV |
2290 | struct pci_dev *pdev = adapter->pdev; | 2369 | struct pci_dev *pdev = adapter->pdev; |
2291 | struct e1000_hw *hw = &adapter->hw; | 2370 | struct e1000_hw *hw = &adapter->hw; |
2292 | int old_vfs = pci_num_vf(adapter->pdev); | ||
2293 | int i; | ||
2294 | 2371 | ||
2295 | /* Virtualization features not supported on i210 family. */ | 2372 | /* Virtualization features not supported on i210 family. */ |
2296 | if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) | 2373 | if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) |
2297 | return; | 2374 | return; |
2298 | 2375 | ||
2299 | if (old_vfs) { | 2376 | igb_enable_sriov(pdev, max_vfs); |
2300 | dev_info(&pdev->dev, "%d pre-allocated VFs found - override " | 2377 | pci_sriov_set_totalvfs(pdev, 7); |
2301 | "max_vfs setting of %d\n", old_vfs, max_vfs); | ||
2302 | adapter->vfs_allocated_count = old_vfs; | ||
2303 | } | ||
2304 | |||
2305 | if (!adapter->vfs_allocated_count) | ||
2306 | return; | ||
2307 | |||
2308 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, | ||
2309 | sizeof(struct vf_data_storage), GFP_KERNEL); | ||
2310 | |||
2311 | /* if allocation failed then we do not support SR-IOV */ | ||
2312 | if (!adapter->vf_data) { | ||
2313 | adapter->vfs_allocated_count = 0; | ||
2314 | dev_err(&pdev->dev, "Unable to allocate memory for VF " | ||
2315 | "Data Storage\n"); | ||
2316 | goto out; | ||
2317 | } | ||
2318 | 2378 | ||
2319 | if (!old_vfs) { | ||
2320 | if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) | ||
2321 | goto err_out; | ||
2322 | } | ||
2323 | dev_info(&pdev->dev, "%d VFs allocated\n", | ||
2324 | adapter->vfs_allocated_count); | ||
2325 | for (i = 0; i < adapter->vfs_allocated_count; i++) | ||
2326 | igb_vf_configure(adapter, i); | ||
2327 | |||
2328 | /* DMA Coalescing is not supported in IOV mode. */ | ||
2329 | adapter->flags &= ~IGB_FLAG_DMAC; | ||
2330 | goto out; | ||
2331 | err_out: | ||
2332 | kfree(adapter->vf_data); | ||
2333 | adapter->vf_data = NULL; | ||
2334 | adapter->vfs_allocated_count = 0; | ||
2335 | out: | ||
2336 | return; | ||
2337 | #endif /* CONFIG_PCI_IOV */ | 2379 | #endif /* CONFIG_PCI_IOV */ |
2338 | } | 2380 | } |
2339 | 2381 | ||
2340 | /** | 2382 | static void igb_init_queue_configuration(struct igb_adapter *adapter) |
2341 | * igb_sw_init - Initialize general software structures (struct igb_adapter) | ||
2342 | * @adapter: board private structure to initialize | ||
2343 | * | ||
2344 | * igb_sw_init initializes the Adapter private data structure. | ||
2345 | * Fields are initialized based on PCI device information and | ||
2346 | * OS network device settings (MTU size). | ||
2347 | **/ | ||
2348 | static int igb_sw_init(struct igb_adapter *adapter) | ||
2349 | { | 2383 | { |
2350 | struct e1000_hw *hw = &adapter->hw; | 2384 | struct e1000_hw *hw = &adapter->hw; |
2351 | struct net_device *netdev = adapter->netdev; | ||
2352 | struct pci_dev *pdev = adapter->pdev; | ||
2353 | u32 max_rss_queues; | 2385 | u32 max_rss_queues; |
2354 | 2386 | ||
2355 | pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); | ||
2356 | |||
2357 | /* set default ring sizes */ | ||
2358 | adapter->tx_ring_count = IGB_DEFAULT_TXD; | ||
2359 | adapter->rx_ring_count = IGB_DEFAULT_RXD; | ||
2360 | |||
2361 | /* set default ITR values */ | ||
2362 | adapter->rx_itr_setting = IGB_DEFAULT_ITR; | ||
2363 | adapter->tx_itr_setting = IGB_DEFAULT_ITR; | ||
2364 | |||
2365 | /* set default work limits */ | ||
2366 | adapter->tx_work_limit = IGB_DEFAULT_TX_WORK; | ||
2367 | |||
2368 | adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + | ||
2369 | VLAN_HLEN; | ||
2370 | adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; | ||
2371 | |||
2372 | spin_lock_init(&adapter->stats64_lock); | ||
2373 | #ifdef CONFIG_PCI_IOV | ||
2374 | switch (hw->mac.type) { | ||
2375 | case e1000_82576: | ||
2376 | case e1000_i350: | ||
2377 | if (max_vfs > 7) { | ||
2378 | dev_warn(&pdev->dev, | ||
2379 | "Maximum of 7 VFs per PF, using max\n"); | ||
2380 | adapter->vfs_allocated_count = 7; | ||
2381 | } else | ||
2382 | adapter->vfs_allocated_count = max_vfs; | ||
2383 | break; | ||
2384 | default: | ||
2385 | break; | ||
2386 | } | ||
2387 | #endif /* CONFIG_PCI_IOV */ | ||
2388 | |||
2389 | /* Determine the maximum number of RSS queues supported. */ | 2387 | /* Determine the maximum number of RSS queues supported. */ |
2390 | switch (hw->mac.type) { | 2388 | switch (hw->mac.type) { |
2391 | case e1000_i211: | 2389 | case e1000_i211: |
@@ -2444,6 +2442,60 @@ static int igb_sw_init(struct igb_adapter *adapter) | |||
2444 | adapter->flags |= IGB_FLAG_QUEUE_PAIRS; | 2442 | adapter->flags |= IGB_FLAG_QUEUE_PAIRS; |
2445 | break; | 2443 | break; |
2446 | } | 2444 | } |
2445 | } | ||
2446 | |||
2447 | /** | ||
2448 | * igb_sw_init - Initialize general software structures (struct igb_adapter) | ||
2449 | * @adapter: board private structure to initialize | ||
2450 | * | ||
2451 | * igb_sw_init initializes the Adapter private data structure. | ||
2452 | * Fields are initialized based on PCI device information and | ||
2453 | * OS network device settings (MTU size). | ||
2454 | **/ | ||
2455 | static int igb_sw_init(struct igb_adapter *adapter) | ||
2456 | { | ||
2457 | struct e1000_hw *hw = &adapter->hw; | ||
2458 | struct net_device *netdev = adapter->netdev; | ||
2459 | struct pci_dev *pdev = adapter->pdev; | ||
2460 | |||
2461 | pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); | ||
2462 | |||
2463 | /* set default ring sizes */ | ||
2464 | adapter->tx_ring_count = IGB_DEFAULT_TXD; | ||
2465 | adapter->rx_ring_count = IGB_DEFAULT_RXD; | ||
2466 | |||
2467 | /* set default ITR values */ | ||
2468 | adapter->rx_itr_setting = IGB_DEFAULT_ITR; | ||
2469 | adapter->tx_itr_setting = IGB_DEFAULT_ITR; | ||
2470 | |||
2471 | /* set default work limits */ | ||
2472 | adapter->tx_work_limit = IGB_DEFAULT_TX_WORK; | ||
2473 | |||
2474 | adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + | ||
2475 | VLAN_HLEN; | ||
2476 | adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; | ||
2477 | |||
2478 | spin_lock_init(&adapter->stats64_lock); | ||
2479 | #ifdef CONFIG_PCI_IOV | ||
2480 | switch (hw->mac.type) { | ||
2481 | case e1000_82576: | ||
2482 | case e1000_i350: | ||
2483 | if (max_vfs > 7) { | ||
2484 | dev_warn(&pdev->dev, | ||
2485 | "Maximum of 7 VFs per PF, using max\n"); | ||
2486 | adapter->vfs_allocated_count = 7; | ||
2487 | } else | ||
2488 | adapter->vfs_allocated_count = max_vfs; | ||
2489 | if (adapter->vfs_allocated_count) | ||
2490 | dev_warn(&pdev->dev, | ||
2491 | "Enabling SR-IOV VFs using the module parameter is deprecated - please use the pci sysfs interface.\n"); | ||
2492 | break; | ||
2493 | default: | ||
2494 | break; | ||
2495 | } | ||
2496 | #endif /* CONFIG_PCI_IOV */ | ||
2497 | |||
2498 | igb_init_queue_configuration(adapter); | ||
2447 | 2499 | ||
2448 | /* Setup and initialize a copy of the hw vlan table array */ | 2500 | /* Setup and initialize a copy of the hw vlan table array */ |
2449 | adapter->shadow_vfta = kzalloc(sizeof(u32) * | 2501 | adapter->shadow_vfta = kzalloc(sizeof(u32) * |
@@ -6902,6 +6954,72 @@ static void igb_shutdown(struct pci_dev *pdev) | |||
6902 | } | 6954 | } |
6903 | } | 6955 | } |
6904 | 6956 | ||
6957 | #ifdef CONFIG_PCI_IOV | ||
6958 | static int igb_sriov_reinit(struct pci_dev *dev) | ||
6959 | { | ||
6960 | struct net_device *netdev = pci_get_drvdata(dev); | ||
6961 | struct igb_adapter *adapter = netdev_priv(netdev); | ||
6962 | struct pci_dev *pdev = adapter->pdev; | ||
6963 | |||
6964 | rtnl_lock(); | ||
6965 | |||
6966 | if (netif_running(netdev)) | ||
6967 | igb_close(netdev); | ||
6968 | |||
6969 | igb_clear_interrupt_scheme(adapter); | ||
6970 | |||
6971 | igb_init_queue_configuration(adapter); | ||
6972 | |||
6973 | if (igb_init_interrupt_scheme(adapter, true)) { | ||
6974 | dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); | ||
6975 | return -ENOMEM; | ||
6976 | } | ||
6977 | |||
6978 | if (netif_running(netdev)) | ||
6979 | igb_open(netdev); | ||
6980 | |||
6981 | rtnl_unlock(); | ||
6982 | |||
6983 | return 0; | ||
6984 | } | ||
6985 | |||
6986 | static int igb_pci_disable_sriov(struct pci_dev *dev) | ||
6987 | { | ||
6988 | int err = igb_disable_sriov(dev); | ||
6989 | |||
6990 | if (!err) | ||
6991 | err = igb_sriov_reinit(dev); | ||
6992 | |||
6993 | return err; | ||
6994 | } | ||
6995 | |||
6996 | static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs) | ||
6997 | { | ||
6998 | int err = igb_enable_sriov(dev, num_vfs); | ||
6999 | |||
7000 | if (err) | ||
7001 | goto out; | ||
7002 | |||
7003 | err = igb_sriov_reinit(dev); | ||
7004 | if (!err) | ||
7005 | return num_vfs; | ||
7006 | |||
7007 | out: | ||
7008 | return err; | ||
7009 | } | ||
7010 | |||
7011 | #endif | ||
7012 | static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs) | ||
7013 | { | ||
7014 | #ifdef CONFIG_PCI_IOV | ||
7015 | if (num_vfs == 0) | ||
7016 | return igb_pci_disable_sriov(dev); | ||
7017 | else | ||
7018 | return igb_pci_enable_sriov(dev, num_vfs); | ||
7019 | #endif | ||
7020 | return 0; | ||
7021 | } | ||
7022 | |||
6905 | #ifdef CONFIG_NET_POLL_CONTROLLER | 7023 | #ifdef CONFIG_NET_POLL_CONTROLLER |
6906 | /* | 7024 | /* |
6907 | * Polling 'interrupt' - used by things like netconsole to send skbs | 7025 | * Polling 'interrupt' - used by things like netconsole to send skbs |