ixgbe: do not use adapter->num_vfs when setting VFs via module parameter

Avoid setting adapter->num_vfs early in the init code path when
using the max_vfs module parameter by passing it to ixgbe_enable_sriov()
as a function parameter.

This fixes an issue where if we failed to allocate vfinfo in
__ixgbe_enable_sriov() the driver will crash with NULL pointer in
ixgbe_disable_sriov() when attempting to free the vfinfo struct based
on adapter->num_vfs. Also it cleans up the assignment of adapter->num_vfs
since now it will only be set in __ixgbe_enable_sriov() and cleared in
ixgbe_disable_sriov().

Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Emil Tantilov 2017-01-20 14:11:56 -08:00 committed by Jeff Kirsher
parent da614d042a
commit 5c11f00dda
3 changed files with 28 additions and 30 deletions

View File

@ -5955,10 +5955,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
/* assign number of SR-IOV VFs */ /* assign number of SR-IOV VFs */
if (hw->mac.type != ixgbe_mac_82598EB) { if (hw->mac.type != ixgbe_mac_82598EB) {
if (max_vfs > IXGBE_MAX_VFS_DRV_LIMIT) { if (max_vfs > IXGBE_MAX_VFS_DRV_LIMIT) {
adapter->num_vfs = 0; max_vfs = 0;
e_dev_warn("max_vfs parameter out of range. Not assigning any SR-IOV VFs\n"); e_dev_warn("max_vfs parameter out of range. Not assigning any SR-IOV VFs\n");
} else {
adapter->num_vfs = max_vfs;
} }
} }
#endif /* CONFIG_PCI_IOV */ #endif /* CONFIG_PCI_IOV */
@ -9821,7 +9819,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ixgbe_init_mbx_params_pf(hw); ixgbe_init_mbx_params_pf(hw);
hw->mbx.ops = ii->mbx_ops; hw->mbx.ops = ii->mbx_ops;
pci_sriov_set_totalvfs(pdev, IXGBE_MAX_VFS_DRV_LIMIT); pci_sriov_set_totalvfs(pdev, IXGBE_MAX_VFS_DRV_LIMIT);
ixgbe_enable_sriov(adapter); ixgbe_enable_sriov(adapter, max_vfs);
skip_sriov: skip_sriov:
#endif #endif

View File

@ -46,14 +46,15 @@
#include "ixgbe_sriov.h" #include "ixgbe_sriov.h"
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
static inline void ixgbe_alloc_vf_macvlans(struct ixgbe_adapter *adapter) static inline void ixgbe_alloc_vf_macvlans(struct ixgbe_adapter *adapter,
unsigned int num_vfs)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
struct vf_macvlans *mv_list; struct vf_macvlans *mv_list;
int num_vf_macvlans, i; int num_vf_macvlans, i;
num_vf_macvlans = hw->mac.num_rar_entries - num_vf_macvlans = hw->mac.num_rar_entries -
(IXGBE_MAX_PF_MACVLANS + 1 + adapter->num_vfs); (IXGBE_MAX_PF_MACVLANS + 1 + num_vfs);
if (!num_vf_macvlans) if (!num_vf_macvlans)
return; return;
@ -71,7 +72,8 @@ static inline void ixgbe_alloc_vf_macvlans(struct ixgbe_adapter *adapter)
} }
} }
static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter) static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
unsigned int num_vfs)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
int i; int i;
@ -82,28 +84,27 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
adapter->flags |= IXGBE_FLAG_VMDQ_ENABLED; adapter->flags |= IXGBE_FLAG_VMDQ_ENABLED;
if (!adapter->ring_feature[RING_F_VMDQ].limit) if (!adapter->ring_feature[RING_F_VMDQ].limit)
adapter->ring_feature[RING_F_VMDQ].limit = 1; adapter->ring_feature[RING_F_VMDQ].limit = 1;
adapter->ring_feature[RING_F_VMDQ].offset = adapter->num_vfs;
/* If call to enable VFs succeeded then allocate memory /* Allocate memory for per VF control structures */
* for per VF control structures. adapter->vfinfo = kcalloc(num_vfs, sizeof(struct vf_data_storage),
*/ GFP_KERNEL);
adapter->vfinfo = kcalloc(adapter->num_vfs,
sizeof(struct vf_data_storage), GFP_KERNEL);
if (!adapter->vfinfo) if (!adapter->vfinfo)
return -ENOMEM; return -ENOMEM;
ixgbe_alloc_vf_macvlans(adapter); adapter->num_vfs = num_vfs;
ixgbe_alloc_vf_macvlans(adapter, num_vfs);
adapter->ring_feature[RING_F_VMDQ].offset = num_vfs;
/* Initialize default switching mode VEB */ /* Initialize default switching mode VEB */
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
adapter->bridge_mode = BRIDGE_MODE_VEB; adapter->bridge_mode = BRIDGE_MODE_VEB;
/* limit trafffic classes based on VFs enabled */ /* limit trafffic classes based on VFs enabled */
if ((adapter->hw.mac.type == ixgbe_mac_82599EB) && if ((adapter->hw.mac.type == ixgbe_mac_82599EB) && (num_vfs < 16)) {
(adapter->num_vfs < 16)) {
adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS; adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS;
adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS; adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS;
} else if (adapter->num_vfs < 32) { } else if (num_vfs < 32) {
adapter->dcb_cfg.num_tcs.pg_tcs = 4; adapter->dcb_cfg.num_tcs.pg_tcs = 4;
adapter->dcb_cfg.num_tcs.pfc_tcs = 4; adapter->dcb_cfg.num_tcs.pfc_tcs = 4;
} else { } else {
@ -115,7 +116,7 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE | adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
IXGBE_FLAG2_RSC_ENABLED); IXGBE_FLAG2_RSC_ENABLED);
for (i = 0; i < adapter->num_vfs; i++) { for (i = 0; i < num_vfs; i++) {
/* enable spoof checking for all VFs */ /* enable spoof checking for all VFs */
adapter->vfinfo[i].spoofchk_enabled = true; adapter->vfinfo[i].spoofchk_enabled = true;
@ -133,7 +134,7 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
adapter->vfinfo[i].xcast_mode = IXGBEVF_XCAST_MODE_NONE; adapter->vfinfo[i].xcast_mode = IXGBEVF_XCAST_MODE_NONE;
} }
e_info(probe, "SR-IOV enabled with %d VFs\n", adapter->num_vfs); e_info(probe, "SR-IOV enabled with %d VFs\n", num_vfs);
return 0; return 0;
} }
@ -172,12 +173,13 @@ static void ixgbe_get_vfs(struct ixgbe_adapter *adapter)
/* Note this function is called when the user wants to enable SR-IOV /* Note this function is called when the user wants to enable SR-IOV
* VFs using the now deprecated module parameter * VFs using the now deprecated module parameter
*/ */
void ixgbe_enable_sriov(struct ixgbe_adapter *adapter) void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, unsigned int max_vfs)
{ {
int pre_existing_vfs = 0; int pre_existing_vfs = 0;
unsigned int num_vfs;
pre_existing_vfs = pci_num_vf(adapter->pdev); pre_existing_vfs = pci_num_vf(adapter->pdev);
if (!pre_existing_vfs && !adapter->num_vfs) if (!pre_existing_vfs && !max_vfs)
return; return;
/* If there are pre-existing VFs then we have to force /* If there are pre-existing VFs then we have to force
@ -187,7 +189,7 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
* have been created via the new PCI SR-IOV sysfs interface. * have been created via the new PCI SR-IOV sysfs interface.
*/ */
if (pre_existing_vfs) { if (pre_existing_vfs) {
adapter->num_vfs = pre_existing_vfs; num_vfs = pre_existing_vfs;
dev_warn(&adapter->pdev->dev, dev_warn(&adapter->pdev->dev,
"Virtual Functions already enabled for this device - Please reload all VF drivers to avoid spoofed packet errors\n"); "Virtual Functions already enabled for this device - Please reload all VF drivers to avoid spoofed packet errors\n");
} else { } else {
@ -199,17 +201,16 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
* physical function. If the user requests greater than * physical function. If the user requests greater than
* 63 VFs then it is an error - reset to default of zero. * 63 VFs then it is an error - reset to default of zero.
*/ */
adapter->num_vfs = min_t(unsigned int, adapter->num_vfs, IXGBE_MAX_VFS_DRV_LIMIT); num_vfs = min_t(unsigned int, max_vfs, IXGBE_MAX_VFS_DRV_LIMIT);
err = pci_enable_sriov(adapter->pdev, adapter->num_vfs); err = pci_enable_sriov(adapter->pdev, num_vfs);
if (err) { if (err) {
e_err(probe, "Failed to enable PCI sriov: %d\n", err); e_err(probe, "Failed to enable PCI sriov: %d\n", err);
adapter->num_vfs = 0;
return; return;
} }
} }
if (!__ixgbe_enable_sriov(adapter)) { if (!__ixgbe_enable_sriov(adapter, num_vfs)) {
ixgbe_get_vfs(adapter); ixgbe_get_vfs(adapter);
return; return;
} }
@ -347,13 +348,12 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
return -EPERM; return -EPERM;
} }
} }
adapter->num_vfs = num_vfs;
err = __ixgbe_enable_sriov(adapter); err = __ixgbe_enable_sriov(adapter, num_vfs);
if (err) if (err)
return err; return err;
for (i = 0; i < adapter->num_vfs; i++) for (i = 0; i < num_vfs; i++)
ixgbe_vf_configuration(dev, (i | 0x10000000)); ixgbe_vf_configuration(dev, (i | 0x10000000));
/* reset before enabling SRIOV to avoid mailbox issues */ /* reset before enabling SRIOV to avoid mailbox issues */

View File

@ -59,7 +59,7 @@ int ixgbe_ndo_get_vf_config(struct net_device *netdev,
void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter); void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
int ixgbe_disable_sriov(struct ixgbe_adapter *adapter); int ixgbe_disable_sriov(struct ixgbe_adapter *adapter);
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
void ixgbe_enable_sriov(struct ixgbe_adapter *adapter); void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, unsigned int max_vfs);
#endif #endif
int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs); int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs);