Skip to content

Commit

Permalink
ixgbe: Save VF info and take references
Browse files Browse the repository at this point in the history
Save VF device pointers and take references to speed accesses used
to monitor the device behavior to avoid slot resets. The saved
information avoids lock contention during the search used to access
each of the VFs.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Darin Miller <darin.j.miller@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Mark Rustad authored and Jeff Kirsher committed Dec 3, 2015
1 parent 48b4461 commit 988d130
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 23 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ enum ixgbe_tx_flags {
#define IXGBE_X540_VF_DEVICE_ID 0x1515

struct vf_data_storage {
struct pci_dev *vfdev;
unsigned char vf_mac_addresses[ETH_ALEN];
u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES];
u16 num_vf_mc_hashes;
Expand Down
31 changes: 10 additions & 21 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6666,10 +6666,8 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
struct pci_dev *vfdev;
unsigned int vf;
u32 gpc;
int pos;
unsigned short vf_id;

if (!(netif_carrier_ok(adapter->netdev)))
return;
Expand All @@ -6686,26 +6684,17 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
if (!pdev)
return;

pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
if (!pos)
return;

/* get the device ID for the VF */
pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id);

/* check status reg for all VFs owned by this PF */
vfdev = pci_get_device(pdev->vendor, vf_id, NULL);
while (vfdev) {
if (vfdev->is_virtfn && (vfdev->physfn == pdev)) {
u16 status_reg;

pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
if (status_reg & PCI_STATUS_REC_MASTER_ABORT)
/* issue VFLR */
ixgbe_issue_vf_flr(adapter, vfdev);
}
for (vf = 0; vf < adapter->num_vfs; ++vf) {
struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev;
u16 status_reg;

vfdev = pci_get_device(pdev->vendor, vf_id, vfdev);
if (!vfdev)
continue;
pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
if (status_reg != IXGBE_FAILED_READ_CFG_WORD &&
status_reg & PCI_STATUS_REC_MASTER_ABORT)
ixgbe_issue_vf_flr(adapter, vfdev);
}
}

Expand Down
50 changes: 48 additions & 2 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2014 Intel Corporation.
Copyright(c) 1999 - 2015 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
Expand Down Expand Up @@ -130,6 +130,38 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
return -ENOMEM;
}

/**
* ixgbe_get_vfs - Find and take references to all vf devices
* @adapter: Pointer to adapter struct
*/
static void ixgbe_get_vfs(struct ixgbe_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
u16 vendor = pdev->vendor;
struct pci_dev *vfdev;
int vf = 0;
u16 vf_id;
int pos;

pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
if (!pos)
return;
pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id);

vfdev = pci_get_device(vendor, vf_id, NULL);
for (; vfdev; vfdev = pci_get_device(vendor, vf_id, vfdev)) {
if (!vfdev->is_virtfn)
continue;
if (vfdev->physfn != pdev)
continue;
if (vf >= adapter->num_vfs)
continue;
pci_dev_get(vfdev);
adapter->vfinfo[vf].vfdev = vfdev;
++vf;
}
}

/* Note this function is called when the user wants to enable SR-IOV
* VFs using the now deprecated module parameter
*/
Expand Down Expand Up @@ -170,8 +202,10 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
}
}

if (!__ixgbe_enable_sriov(adapter))
if (!__ixgbe_enable_sriov(adapter)) {
ixgbe_get_vfs(adapter);
return;
}

/* If we have gotten to this point then there is no memory available
* to manage the VF devices - print message and bail.
Expand All @@ -184,6 +218,7 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
#endif /* #ifdef CONFIG_PCI_IOV */
int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
{
unsigned int num_vfs = adapter->num_vfs, vf;
struct ixgbe_hw *hw = &adapter->hw;
u32 gpie;
u32 vmdctl;
Expand All @@ -192,6 +227,16 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
/* set num VFs to 0 to prevent access to vfinfo */
adapter->num_vfs = 0;

/* put the reference to all of the vf devices */
for (vf = 0; vf < num_vfs; ++vf) {
struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev;

if (!vfdev)
continue;
adapter->vfinfo[vf].vfdev = NULL;
pci_dev_put(vfdev);
}

/* free VF control structures */
kfree(adapter->vfinfo);
adapter->vfinfo = NULL;
Expand Down Expand Up @@ -289,6 +334,7 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
e_dev_warn("Failed to enable PCI sriov: %d\n", err);
return err;
}
ixgbe_get_vfs(adapter);
ixgbe_sriov_reinit(adapter);

return num_vfs;
Expand Down

0 comments on commit 988d130

Please sign in to comment.