diff options
author | Greg Rose <gregory.v.rose@intel.com> | 2012-12-11 03:26:43 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2013-01-23 17:34:07 -0500 |
commit | da36b64736cf2552e7fb5109c0255d4af804f5e7 (patch) | |
tree | 2a0b5b5693ab96737625349a02646ec556ec56e2 /drivers | |
parent | 66dcfd756919ef9d8f564a0696a451574012852c (diff) |
ixgbe: Implement PCI SR-IOV sysfs callback operation
Implement callbacks in the driver for the new PCI bus driver
interface that allows the user to enable/disable SR-IOV VFs
in a device via the sysfs interface.
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
CC: Don Dutile <ddutile@redhat.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 91 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h | 3 |
4 files changed, 122 insertions, 6 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index cd4c83b1a977..8371ae4265fe 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h | |||
@@ -778,5 +778,8 @@ extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, | |||
778 | extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); | 778 | extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); |
779 | extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter); | 779 | extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter); |
780 | extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr); | 780 | extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr); |
781 | #ifdef CONFIG_PCI_IOV | ||
782 | void ixgbe_sriov_reinit(struct ixgbe_adapter *adapter); | ||
783 | #endif | ||
781 | 784 | ||
782 | #endif /* _IXGBE_H_ */ | 785 | #endif /* _IXGBE_H_ */ |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 2472dc85db0d..5e3ed33215f7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -6836,6 +6836,26 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) | |||
6836 | } | 6836 | } |
6837 | 6837 | ||
6838 | #endif /* CONFIG_IXGBE_DCB */ | 6838 | #endif /* CONFIG_IXGBE_DCB */ |
6839 | #ifdef CONFIG_PCI_IOV | ||
6840 | void ixgbe_sriov_reinit(struct ixgbe_adapter *adapter) | ||
6841 | { | ||
6842 | struct net_device *netdev = adapter->netdev; | ||
6843 | |||
6844 | rtnl_lock(); | ||
6845 | #ifdef CONFIG_IXGBE_DCB | ||
6846 | ixgbe_setup_tc(netdev, netdev_get_num_tc(netdev)); | ||
6847 | #else | ||
6848 | if (netif_running(netdev)) | ||
6849 | ixgbe_close(netdev); | ||
6850 | ixgbe_clear_interrupt_scheme(adapter); | ||
6851 | ixgbe_init_interrupt_scheme(adapter); | ||
6852 | if (netif_running(netdev)) | ||
6853 | ixgbe_open(netdev); | ||
6854 | #endif | ||
6855 | rtnl_unlock(); | ||
6856 | } | ||
6857 | |||
6858 | #endif | ||
6839 | void ixgbe_do_reset(struct net_device *netdev) | 6859 | void ixgbe_do_reset(struct net_device *netdev) |
6840 | { | 6860 | { |
6841 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 6861 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
@@ -7625,8 +7645,14 @@ static void ixgbe_remove(struct pci_dev *pdev) | |||
7625 | if (netdev->reg_state == NETREG_REGISTERED) | 7645 | if (netdev->reg_state == NETREG_REGISTERED) |
7626 | unregister_netdev(netdev); | 7646 | unregister_netdev(netdev); |
7627 | 7647 | ||
7628 | ixgbe_disable_sriov(adapter); | 7648 | #ifdef CONFIG_PCI_IOV |
7629 | 7649 | /* | |
7650 | * Only disable SR-IOV on unload if the user specified the now | ||
7651 | * deprecated max_vfs module parameter. | ||
7652 | */ | ||
7653 | if (max_vfs) | ||
7654 | ixgbe_disable_sriov(adapter); | ||
7655 | #endif | ||
7630 | ixgbe_clear_interrupt_scheme(adapter); | 7656 | ixgbe_clear_interrupt_scheme(adapter); |
7631 | 7657 | ||
7632 | ixgbe_release_hw_control(adapter); | 7658 | ixgbe_release_hw_control(adapter); |
@@ -7840,6 +7866,7 @@ static struct pci_driver ixgbe_driver = { | |||
7840 | .resume = ixgbe_resume, | 7866 | .resume = ixgbe_resume, |
7841 | #endif | 7867 | #endif |
7842 | .shutdown = ixgbe_shutdown, | 7868 | .shutdown = ixgbe_shutdown, |
7869 | .sriov_configure = ixgbe_pci_sriov_configure, | ||
7843 | .err_handler = &ixgbe_err_handler | 7870 | .err_handler = &ixgbe_err_handler |
7844 | }; | 7871 | }; |
7845 | 7872 | ||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 8a284ac4b400..ee3507f0ea53 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | |||
@@ -207,11 +207,12 @@ static bool ixgbe_vfs_are_assigned(struct ixgbe_adapter *adapter) | |||
207 | } | 207 | } |
208 | 208 | ||
209 | #endif /* #ifdef CONFIG_PCI_IOV */ | 209 | #endif /* #ifdef CONFIG_PCI_IOV */ |
210 | void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) | 210 | int ixgbe_disable_sriov(struct ixgbe_adapter *adapter) |
211 | { | 211 | { |
212 | struct ixgbe_hw *hw = &adapter->hw; | 212 | struct ixgbe_hw *hw = &adapter->hw; |
213 | u32 gpie; | 213 | u32 gpie; |
214 | u32 vmdctl; | 214 | u32 vmdctl; |
215 | int rss; | ||
215 | 216 | ||
216 | /* set num VFs to 0 to prevent access to vfinfo */ | 217 | /* set num VFs to 0 to prevent access to vfinfo */ |
217 | adapter->num_vfs = 0; | 218 | adapter->num_vfs = 0; |
@@ -226,7 +227,7 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) | |||
226 | 227 | ||
227 | /* if SR-IOV is already disabled then there is nothing to do */ | 228 | /* if SR-IOV is already disabled then there is nothing to do */ |
228 | if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) | 229 | if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) |
229 | return; | 230 | return 0; |
230 | 231 | ||
231 | #ifdef CONFIG_PCI_IOV | 232 | #ifdef CONFIG_PCI_IOV |
232 | /* | 233 | /* |
@@ -236,7 +237,7 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) | |||
236 | */ | 237 | */ |
237 | if (ixgbe_vfs_are_assigned(adapter)) { | 238 | if (ixgbe_vfs_are_assigned(adapter)) { |
238 | e_dev_warn("Unloading driver while VFs are assigned - VFs will not be deallocated\n"); | 239 | e_dev_warn("Unloading driver while VFs are assigned - VFs will not be deallocated\n"); |
239 | return; | 240 | return -EPERM; |
240 | } | 241 | } |
241 | /* disable iov and allow time for transactions to clear */ | 242 | /* disable iov and allow time for transactions to clear */ |
242 | pci_disable_sriov(adapter->pdev); | 243 | pci_disable_sriov(adapter->pdev); |
@@ -259,10 +260,94 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) | |||
259 | adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED; | 260 | adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED; |
260 | adapter->ring_feature[RING_F_VMDQ].offset = 0; | 261 | adapter->ring_feature[RING_F_VMDQ].offset = 0; |
261 | 262 | ||
263 | rss = min_t(int, IXGBE_MAX_RSS_INDICES, num_online_cpus()); | ||
264 | adapter->ring_feature[RING_F_RSS].limit = rss; | ||
265 | |||
262 | /* take a breather then clean up driver data */ | 266 | /* take a breather then clean up driver data */ |
263 | msleep(100); | 267 | msleep(100); |
264 | 268 | ||
265 | adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; | 269 | adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; |
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs) | ||
274 | { | ||
275 | #ifdef CONFIG_PCI_IOV | ||
276 | struct ixgbe_adapter *adapter = pci_get_drvdata(dev); | ||
277 | int err = 0; | ||
278 | int i; | ||
279 | int pre_existing_vfs = pci_num_vf(dev); | ||
280 | |||
281 | if (pre_existing_vfs && pre_existing_vfs != num_vfs) | ||
282 | err = ixgbe_disable_sriov(adapter); | ||
283 | else if (pre_existing_vfs && pre_existing_vfs == num_vfs) | ||
284 | goto out; | ||
285 | |||
286 | if (err) | ||
287 | goto err_out; | ||
288 | |||
289 | /* While the SR-IOV capability structure reports total VFs to be | ||
290 | * 64 we limit the actual number that can be allocated to 63 so | ||
291 | * that some transmit/receive resources can be reserved to the | ||
292 | * PF. The PCI bus driver already checks for other values out of | ||
293 | * range. | ||
294 | */ | ||
295 | if (num_vfs > 63) { | ||
296 | err = -EPERM; | ||
297 | goto err_out; | ||
298 | } | ||
299 | |||
300 | adapter->num_vfs = num_vfs; | ||
301 | |||
302 | err = __ixgbe_enable_sriov(adapter); | ||
303 | if (err) | ||
304 | goto err_out; | ||
305 | |||
306 | for (i = 0; i < adapter->num_vfs; i++) | ||
307 | ixgbe_vf_configuration(dev, (i | 0x10000000)); | ||
308 | |||
309 | err = pci_enable_sriov(dev, num_vfs); | ||
310 | if (err) { | ||
311 | e_dev_warn("Failed to enable PCI sriov: %d\n", err); | ||
312 | goto err_out; | ||
313 | } | ||
314 | ixgbe_sriov_reinit(adapter); | ||
315 | |||
316 | out: | ||
317 | return num_vfs; | ||
318 | |||
319 | err_out: | ||
320 | return err; | ||
321 | #endif | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int ixgbe_pci_sriov_disable(struct pci_dev *dev) | ||
326 | { | ||
327 | struct ixgbe_adapter *adapter = pci_get_drvdata(dev); | ||
328 | int err; | ||
329 | u32 current_flags = adapter->flags; | ||
330 | |||
331 | err = ixgbe_disable_sriov(adapter); | ||
332 | |||
333 | /* Only reinit if no error and state changed */ | ||
334 | if (!err && current_flags != adapter->flags) { | ||
335 | /* ixgbe_disable_sriov() doesn't clear VMDQ flag */ | ||
336 | adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED; | ||
337 | #ifdef CONFIG_PCI_IOV | ||
338 | ixgbe_sriov_reinit(adapter); | ||
339 | #endif | ||
340 | } | ||
341 | |||
342 | return err; | ||
343 | } | ||
344 | |||
345 | int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs) | ||
346 | { | ||
347 | if (num_vfs == 0) | ||
348 | return ixgbe_pci_sriov_disable(dev); | ||
349 | else | ||
350 | return ixgbe_pci_sriov_enable(dev, num_vfs); | ||
266 | } | 351 | } |
267 | 352 | ||
268 | static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, | 353 | static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h index f693469b81ef..008f9cea68d1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h | |||
@@ -41,10 +41,11 @@ int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); | |||
41 | int ixgbe_ndo_get_vf_config(struct net_device *netdev, | 41 | int ixgbe_ndo_get_vf_config(struct net_device *netdev, |
42 | int vf, struct ifla_vf_info *ivi); | 42 | int vf, struct ifla_vf_info *ivi); |
43 | void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter); | 43 | void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter); |
44 | void ixgbe_disable_sriov(struct ixgbe_adapter *adapter); | 44 | int ixgbe_disable_sriov(struct ixgbe_adapter *adapter); |
45 | #ifdef CONFIG_PCI_IOV | 45 | #ifdef CONFIG_PCI_IOV |
46 | void ixgbe_enable_sriov(struct ixgbe_adapter *adapter); | 46 | void ixgbe_enable_sriov(struct ixgbe_adapter *adapter); |
47 | #endif | 47 | #endif |
48 | int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs); | ||
48 | 49 | ||
49 | static inline void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, | 50 | static inline void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, |
50 | u16 vid, u16 qos, u32 vf) | 51 | u16 vid, u16 qos, u32 vf) |