Merge branch 'pci/virtualization' into next

* pci/virtualization:
  ixgbe: Use pcie_flr() instead of duplicating it
  IB/hfi1: Use pcie_flr() instead of duplicating it
  PCI: Call pcie_flr() from reset_chelsio_generic_dev()
  PCI: Call pcie_flr() from reset_intel_82599_sfp_virtfn()
  PCI: Export pcie_flr()
  PCI: Add sysfs sriov_drivers_autoprobe to control VF driver binding
  PCI: Avoid FLR for Intel 82579 NICs

Conflicts:
	include/linux/pci.h
This commit is contained in:
Bjorn Helgaas 2017-04-28 10:36:12 -05:00
commit ef1b5dad5a
13 changed files with 134 additions and 86 deletions

View File

@ -301,3 +301,25 @@ Contact: Emil Velikov <emil.l.velikov@gmail.com>
Description: Description:
This file contains the revision field of the the PCI device. This file contains the revision field of the the PCI device.
The value comes from device config space. The file is read only. The value comes from device config space. The file is read only.
What: /sys/bus/pci/devices/.../sriov_drivers_autoprobe
Date: April 2017
Contact: Bodong Wang<bodong@mellanox.com>
Description:
This file is associated with the PF of a device that
supports SR-IOV. It determines whether newly-enabled VFs
are immediately bound to a driver. It initially contains
1, which means the kernel automatically binds VFs to a
compatible driver immediately after they are enabled. If
an application writes 0 to the file before enabling VFs,
the kernel will not bind VFs to a driver.
A typical use case is to write 0 to this file, then enable
VFs, then assign the newly-created VFs to virtual machines.
Note that changing this file does not affect already-
enabled VFs. In this scenario, the user must first disable
the VFs, write 0 to sriov_drivers_autoprobe, then re-enable
the VFs.
This is similar to /sys/bus/pci/drivers_autoprobe, but
affects only the VFs associated with a specific PF.

View File

@ -68,6 +68,18 @@ To disable SR-IOV capability:
echo 0 > \ echo 0 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
To enable auto probing VFs by a compatible driver on the host, run
command below before enabling SR-IOV capabilities. This is the
default behavior.
echo 1 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
To disable auto probing VFs by a compatible driver on the host, run
command below before enabling SR-IOV capabilities. Updating this
entry will not affect VFs which are already probed.
echo 0 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
3.2 Usage example 3.2 Usage example
Following piece of code illustrates the usage of the SR-IOV API. Following piece of code illustrates the usage of the SR-IOV API.

View File

@ -13610,14 +13610,14 @@ static void init_chip(struct hfi1_devdata *dd)
dd_dev_info(dd, "Resetting CSRs with FLR\n"); dd_dev_info(dd, "Resetting CSRs with FLR\n");
/* do the FLR, the DC reset will remain */ /* do the FLR, the DC reset will remain */
hfi1_pcie_flr(dd); pcie_flr(dd->pcidev);
/* restore command and BARs */ /* restore command and BARs */
restore_pci_variables(dd); restore_pci_variables(dd);
if (is_ax(dd)) { if (is_ax(dd)) {
dd_dev_info(dd, "Resetting CSRs with FLR\n"); dd_dev_info(dd, "Resetting CSRs with FLR\n");
hfi1_pcie_flr(dd); pcie_flr(dd->pcidev);
restore_pci_variables(dd); restore_pci_variables(dd);
} }
} else { } else {

View File

@ -1764,7 +1764,6 @@ int hfi1_pcie_init(struct pci_dev *, const struct pci_device_id *);
void hfi1_pcie_cleanup(struct pci_dev *); void hfi1_pcie_cleanup(struct pci_dev *);
int hfi1_pcie_ddinit(struct hfi1_devdata *, struct pci_dev *); int hfi1_pcie_ddinit(struct hfi1_devdata *, struct pci_dev *);
void hfi1_pcie_ddcleanup(struct hfi1_devdata *); void hfi1_pcie_ddcleanup(struct hfi1_devdata *);
void hfi1_pcie_flr(struct hfi1_devdata *);
int pcie_speeds(struct hfi1_devdata *); int pcie_speeds(struct hfi1_devdata *);
void request_msix(struct hfi1_devdata *, u32 *, struct hfi1_msix_entry *); void request_msix(struct hfi1_devdata *, u32 *, struct hfi1_msix_entry *);
void hfi1_enable_intx(struct pci_dev *); void hfi1_enable_intx(struct pci_dev *);

View File

@ -240,36 +240,6 @@ void hfi1_pcie_ddcleanup(struct hfi1_devdata *dd)
iounmap(dd->piobase); iounmap(dd->piobase);
} }
/*
* Do a Function Level Reset (FLR) on the device.
* Based on static function drivers/pci/pci.c:pcie_flr().
*/
void hfi1_pcie_flr(struct hfi1_devdata *dd)
{
int i;
u16 status;
/* no need to check for the capability - we know the device has it */
/* wait for Transaction Pending bit to clear, at most a few ms */
for (i = 0; i < 4; i++) {
if (i)
msleep((1 << (i - 1)) * 100);
pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVSTA, &status);
if (!(status & PCI_EXP_DEVSTA_TRPND))
goto clear;
}
dd_dev_err(dd, "Transaction Pending bit is not clearing, proceeding with reset anyway\n");
clear:
pcie_capability_set_word(dd->pcidev, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_BCR_FLR);
/* PCIe spec requires the function to be back within 100ms */
msleep(100);
}
static void msix_setup(struct hfi1_devdata *dd, int pos, u32 *msixcnt, static void msix_setup(struct hfi1_devdata *dd, int pos, u32 *msixcnt,
struct hfi1_msix_entry *hfi1_msix_entry) struct hfi1_msix_entry *hfi1_msix_entry)
{ {

View File

@ -7112,18 +7112,6 @@ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter)
} }
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
static inline void ixgbe_issue_vf_flr(struct ixgbe_adapter *adapter,
struct pci_dev *vfdev)
{
if (!pci_wait_for_pending_transaction(vfdev))
e_dev_warn("Issuing VFLR with pending transactions\n");
e_dev_err("Issuing VFLR for VF %s\n", pci_name(vfdev));
pcie_capability_set_word(vfdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
msleep(100);
}
static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter) static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
@ -7156,7 +7144,7 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
pci_read_config_word(vfdev, PCI_STATUS, &status_reg); pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
if (status_reg != IXGBE_FAILED_READ_CFG_WORD && if (status_reg != IXGBE_FAILED_READ_CFG_WORD &&
status_reg & PCI_STATUS_REC_MASTER_ABORT) status_reg & PCI_STATUS_REC_MASTER_ABORT)
ixgbe_issue_vf_flr(adapter, vfdev); pcie_flr(vfdev);
} }
} }
@ -10244,7 +10232,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
* VFLR. Just clean up the AER in that case. * VFLR. Just clean up the AER in that case.
*/ */
if (vfdev) { if (vfdev) {
ixgbe_issue_vf_flr(adapter, vfdev); pcie_flr(vfdev);
/* Free device reference count */ /* Free device reference count */
pci_dev_put(vfdev); pci_dev_put(vfdev);
} }

View File

@ -450,6 +450,7 @@ found:
iov->total_VFs = total; iov->total_VFs = total;
iov->pgsz = pgsz; iov->pgsz = pgsz;
iov->self = dev; iov->self = dev;
iov->drivers_autoprobe = true;
pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)

View File

@ -394,6 +394,18 @@ void __weak pcibios_free_irq(struct pci_dev *dev)
{ {
} }
#ifdef CONFIG_PCI_IOV
static inline bool pci_device_can_probe(struct pci_dev *pdev)
{
return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe);
}
#else
static inline bool pci_device_can_probe(struct pci_dev *pdev)
{
return true;
}
#endif
static int pci_device_probe(struct device *dev) static int pci_device_probe(struct device *dev)
{ {
int error; int error;
@ -405,10 +417,12 @@ static int pci_device_probe(struct device *dev)
return error; return error;
pci_dev_get(pci_dev); pci_dev_get(pci_dev);
error = __pci_device_probe(drv, pci_dev); if (pci_device_can_probe(pci_dev)) {
if (error) { error = __pci_device_probe(drv, pci_dev);
pcibios_free_irq(pci_dev); if (error) {
pci_dev_put(pci_dev); pcibios_free_irq(pci_dev);
pci_dev_put(pci_dev);
}
} }
return error; return error;

View File

@ -526,10 +526,37 @@ exit:
return count; return count;
} }
static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe);
}
static ssize_t sriov_drivers_autoprobe_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
bool drivers_autoprobe;
if (kstrtobool(buf, &drivers_autoprobe) < 0)
return -EINVAL;
pdev->sriov->drivers_autoprobe = drivers_autoprobe;
return count;
}
static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs); static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
static struct device_attribute sriov_numvfs_attr = static struct device_attribute sriov_numvfs_attr =
__ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP), __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
sriov_numvfs_show, sriov_numvfs_store); sriov_numvfs_show, sriov_numvfs_store);
static struct device_attribute sriov_drivers_autoprobe_attr =
__ATTR(sriov_drivers_autoprobe, (S_IRUGO|S_IWUSR|S_IWGRP),
sriov_drivers_autoprobe_show, sriov_drivers_autoprobe_store);
#endif /* CONFIG_PCI_IOV */ #endif /* CONFIG_PCI_IOV */
static ssize_t driver_override_store(struct device *dev, static ssize_t driver_override_store(struct device *dev,
@ -1539,6 +1566,7 @@ static struct attribute_group pci_dev_hp_attr_group = {
static struct attribute *sriov_dev_attrs[] = { static struct attribute *sriov_dev_attrs[] = {
&sriov_totalvfs_attr.attr, &sriov_totalvfs_attr.attr,
&sriov_numvfs_attr.attr, &sriov_numvfs_attr.attr,
&sriov_drivers_autoprobe_attr.attr,
NULL, NULL,
}; };

View File

@ -3860,24 +3860,41 @@ static void pci_flr_wait(struct pci_dev *dev)
(i - 1) * 100); (i - 1) * 100);
} }
static int pcie_flr(struct pci_dev *dev, int probe) /**
* pcie_has_flr - check if a device supports function level resets
* @dev: device to check
*
* Returns true if the device advertises support for PCIe function level
* resets.
*/
static bool pcie_has_flr(struct pci_dev *dev)
{ {
u32 cap; u32 cap;
if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
return false;
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
if (!(cap & PCI_EXP_DEVCAP_FLR)) return cap & PCI_EXP_DEVCAP_FLR;
return -ENOTTY; }
if (probe)
return 0;
/**
* pcie_flr - initiate a PCIe function level reset
* @dev: device to reset
*
* Initiate a function level reset on @dev. The caller should ensure the
* device supports FLR before calling this function, e.g. by using the
* pcie_has_flr() helper.
*/
void pcie_flr(struct pci_dev *dev)
{
if (!pci_wait_for_pending_transaction(dev)) if (!pci_wait_for_pending_transaction(dev))
dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n"); dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
pci_flr_wait(dev); pci_flr_wait(dev);
return 0;
} }
EXPORT_SYMBOL_GPL(pcie_flr);
static int pci_af_flr(struct pci_dev *dev, int probe) static int pci_af_flr(struct pci_dev *dev, int probe)
{ {
@ -3888,6 +3905,9 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
if (!pos) if (!pos)
return -ENOTTY; return -ENOTTY;
if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
return -ENOTTY;
pci_read_config_byte(dev, pos + PCI_AF_CAP, &cap); pci_read_config_byte(dev, pos + PCI_AF_CAP, &cap);
if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR)) if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
return -ENOTTY; return -ENOTTY;
@ -4058,9 +4078,12 @@ static int __pci_dev_reset(struct pci_dev *dev, int probe)
if (rc != -ENOTTY) if (rc != -ENOTTY)
goto done; goto done;
rc = pcie_flr(dev, probe); if (pcie_has_flr(dev)) {
if (rc != -ENOTTY) if (!probe)
pcie_flr(dev);
rc = 0;
goto done; goto done;
}
rc = pci_af_flr(dev, probe); rc = pci_af_flr(dev, probe);
if (rc != -ENOTTY) if (rc != -ENOTTY)

View File

@ -272,6 +272,7 @@ struct pci_sriov {
struct pci_dev *self; /* this PF */ struct pci_dev *self; /* this PF */
struct mutex lock; /* lock for setting sriov_numvfs in sysfs */ struct mutex lock; /* lock for setting sriov_numvfs in sysfs */
resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */ resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
bool drivers_autoprobe; /* auto probing of VFs by driver */
}; };
/* pci_dev priv_flags */ /* pci_dev priv_flags */

View File

@ -3666,19 +3666,11 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
* *
* The 82599 supports FLR on VFs, but FLR support is reported only * The 82599 supports FLR on VFs, but FLR support is reported only
* in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5). * in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5).
* Therefore, we can't use pcie_flr(), which checks the VF DEVCAP. * Thus we must call pcie_flr() directly without first checking if it is
* supported.
*/ */
if (!probe)
if (probe) pcie_flr(dev);
return 0;
if (!pci_wait_for_pending_transaction(dev))
dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
msleep(100);
return 0; return 0;
} }
@ -3783,20 +3775,7 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_ENABLE |
PCI_MSIX_FLAGS_MASKALL); PCI_MSIX_FLAGS_MASKALL);
/* pcie_flr(dev);
* Start of pcie_flr() code sequence. This reset code is a copy of
* the guts of pcie_flr() because that's not an exported function.
*/
if (!pci_wait_for_pending_transaction(dev))
dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
msleep(100);
/*
* End of pcie_flr() code sequence.
*/
/* /*
* Restore the configuration information (BAR values, etc.) including * Restore the configuration information (BAR values, etc.) including
@ -4677,3 +4656,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid);
/* FLR may cause some 82579 devices to hang. */
static void quirk_intel_no_flr(struct pci_dev *dev)
{
dev->dev_flags |= PCI_DEV_FLAGS_NO_FLR_RESET;
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_intel_no_flr);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_intel_no_flr);

View File

@ -181,6 +181,8 @@ enum pci_dev_flags {
PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8), PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
/* a non-root bridge where translation occurs, stop alias search here */ /* a non-root bridge where translation occurs, stop alias search here */
PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9), PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9),
/* Do not use FLR even if device advertises PCI_AF_CAP */
PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10),
}; };
enum pci_irq_reroute_variant { enum pci_irq_reroute_variant {
@ -1037,6 +1039,7 @@ int pcie_get_mps(struct pci_dev *dev);
int pcie_set_mps(struct pci_dev *dev, int mps); int pcie_set_mps(struct pci_dev *dev, int mps);
int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed, int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
enum pcie_link_width *width); enum pcie_link_width *width);
void pcie_flr(struct pci_dev *dev);
int __pci_reset_function(struct pci_dev *dev); int __pci_reset_function(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev); int __pci_reset_function_locked(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev);