aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGreg Rose <gregory.v.rose@intel.com>2012-12-11 03:26:43 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-01-23 17:34:07 -0500
commitda36b64736cf2552e7fb5109c0255d4af804f5e7 (patch)
tree2a0b5b5693ab96737625349a02646ec556ec56e2 /drivers
parent66dcfd756919ef9d8f564a0696a451574012852c (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.h3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c31
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c91
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h3
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,
778extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); 778extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
779extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter); 779extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
780extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr); 780extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
781#ifdef CONFIG_PCI_IOV
782void 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
6840void 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
6839void ixgbe_do_reset(struct net_device *netdev) 6859void 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 */
210void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) 210int 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
273static 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
316out:
317 return num_vfs;
318
319err_out:
320 return err;
321#endif
322 return 0;
323}
324
325static 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
345int 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
268static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, 353static 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);
41int ixgbe_ndo_get_vf_config(struct net_device *netdev, 41int 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);
43void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter); 43void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
44void ixgbe_disable_sriov(struct ixgbe_adapter *adapter); 44int ixgbe_disable_sriov(struct ixgbe_adapter *adapter);
45#ifdef CONFIG_PCI_IOV 45#ifdef CONFIG_PCI_IOV
46void ixgbe_enable_sriov(struct ixgbe_adapter *adapter); 46void ixgbe_enable_sriov(struct ixgbe_adapter *adapter);
47#endif 47#endif
48int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
48 49
49static inline void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, 50static inline void ixgbe_set_vmvir(struct ixgbe_adapter *adapter,
50 u16 vid, u16 qos, u32 vf) 51 u16 vid, u16 qos, u32 vf)