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:
@@ -450,6 +450,7 @@ found:
|
||||
iov->total_VFs = total;
|
||||
iov->pgsz = pgsz;
|
||||
iov->self = dev;
|
||||
iov->drivers_autoprobe = true;
|
||||
pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
|
||||
pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
|
||||
if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)
|
||||
|
@@ -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)
|
||||
{
|
||||
int error;
|
||||
@@ -405,10 +417,12 @@ static int pci_device_probe(struct device *dev)
|
||||
return error;
|
||||
|
||||
pci_dev_get(pci_dev);
|
||||
error = __pci_device_probe(drv, pci_dev);
|
||||
if (error) {
|
||||
pcibios_free_irq(pci_dev);
|
||||
pci_dev_put(pci_dev);
|
||||
if (pci_device_can_probe(pci_dev)) {
|
||||
error = __pci_device_probe(drv, pci_dev);
|
||||
if (error) {
|
||||
pcibios_free_irq(pci_dev);
|
||||
pci_dev_put(pci_dev);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
|
@@ -526,10 +526,37 @@ exit:
|
||||
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_numvfs_attr =
|
||||
__ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
|
||||
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 */
|
||||
|
||||
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[] = {
|
||||
&sriov_totalvfs_attr.attr,
|
||||
&sriov_numvfs_attr.attr,
|
||||
&sriov_drivers_autoprobe_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@@ -3860,24 +3860,41 @@ static void pci_flr_wait(struct pci_dev *dev)
|
||||
(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;
|
||||
|
||||
if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
|
||||
return false;
|
||||
|
||||
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
|
||||
if (!(cap & PCI_EXP_DEVCAP_FLR))
|
||||
return -ENOTTY;
|
||||
|
||||
if (probe)
|
||||
return 0;
|
||||
return cap & PCI_EXP_DEVCAP_FLR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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))
|
||||
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);
|
||||
pci_flr_wait(dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcie_flr);
|
||||
|
||||
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)
|
||||
return -ENOTTY;
|
||||
|
||||
if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
|
||||
return -ENOTTY;
|
||||
|
||||
pci_read_config_byte(dev, pos + PCI_AF_CAP, &cap);
|
||||
if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
|
||||
return -ENOTTY;
|
||||
@@ -4058,9 +4078,12 @@ static int __pci_dev_reset(struct pci_dev *dev, int probe)
|
||||
if (rc != -ENOTTY)
|
||||
goto done;
|
||||
|
||||
rc = pcie_flr(dev, probe);
|
||||
if (rc != -ENOTTY)
|
||||
if (pcie_has_flr(dev)) {
|
||||
if (!probe)
|
||||
pcie_flr(dev);
|
||||
rc = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = pci_af_flr(dev, probe);
|
||||
if (rc != -ENOTTY)
|
||||
|
@@ -272,6 +272,7 @@ struct pci_sriov {
|
||||
struct pci_dev *self; /* this PF */
|
||||
struct mutex lock; /* lock for setting sriov_numvfs in sysfs */
|
||||
resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
|
||||
bool drivers_autoprobe; /* auto probing of VFs by driver */
|
||||
};
|
||||
|
||||
/* pci_dev priv_flags */
|
||||
|
@@ -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
|
||||
* 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)
|
||||
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);
|
||||
|
||||
if (!probe)
|
||||
pcie_flr(dev);
|
||||
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_MASKALL);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
pcie_flr(dev);
|
||||
|
||||
/*
|
||||
* 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, 0x2032, 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);
|
||||
|
Reference in New Issue
Block a user