Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ceb09cc authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/virtualization' into next

* pci/virtualization:
  PCI: Document reset method return values
  PCI: Detach driver before procfs & sysfs teardown on device remove
  PCI: Apply Cavium ThunderX ACS quirk to more Root Ports
  PCI: Set Cavium ACS capability quirk flags to assert RR/CR/SV/UF
  PCI: Restore ARI Capable Hierarchy before setting numVFs
  PCI: Create SR-IOV virtfn/physfn links before attaching driver
  PCI: Expose SR-IOV offset, stride, and VF device ID via sysfs
  PCI: Cache the VF device ID in the SR-IOV structure
  PCI: Add Kconfig PCI_IOV dependency for PCI_REALLOC_ENABLE_AUTO
  PCI: Remove unused function __pci_reset_function()
  PCI: Remove reset argument from pci_iov_{add,remove}_virtfn()
parents 9af21ac5 832c418a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -441,7 +441,7 @@ static void *eeh_add_virt_device(void *data, void *userdata)
	}

#ifdef CONFIG_PPC_POWERNV
	pci_iov_add_virtfn(edev->physfn, pdn->vf_index, 0);
	pci_iov_add_virtfn(edev->physfn, pdn->vf_index);
#endif
	return NULL;
}
@@ -499,7 +499,7 @@ static void *eeh_rmv_device(void *data, void *userdata)
#ifdef CONFIG_PPC_POWERNV
		struct pci_dn *pdn = eeh_dev_to_pdn(edev);

		pci_iov_remove_virtfn(edev->physfn, pdn->vf_index, 0);
		pci_iov_remove_virtfn(edev->physfn, pdn->vf_index);
		edev->pdev = NULL;

		/*
+4 −4
Original line number Diff line number Diff line
@@ -51,13 +51,13 @@ config PCI_DEBUG
config PCI_REALLOC_ENABLE_AUTO
	bool "Enable PCI resource re-allocation detection"
	depends on PCI
	depends on PCI_IOV
	help
	  Say Y here if you want the PCI core to detect if PCI resource
	  re-allocation needs to be enabled. You can always use pci=realloc=on
          or pci=realloc=off to override it.  Note this feature is a no-op
          unless PCI_IOV support is also enabled; in that case it will
          automatically re-allocate PCI resources if SR-IOV BARs have not
          been allocated by the BIOS.
	  or pci=realloc=off to override it.  It will automatically
	  re-allocate PCI resources if SR-IOV BARs have not been allocated by
	  the BIOS.

	  When in doubt, say N.

+18 −16
Original line number Diff line number Diff line
@@ -113,7 +113,7 @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
	return dev->sriov->barsz[resno - PCI_IOV_RESOURCES];
}

int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
int pci_iov_add_virtfn(struct pci_dev *dev, int id)
{
	int i;
	int rc = -ENOMEM;
@@ -134,7 +134,7 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)

	virtfn->devfn = pci_iov_virtfn_devfn(dev, id);
	virtfn->vendor = dev->vendor;
	pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device);
	virtfn->device = iov->vf_device;
	rc = pci_setup_device(virtfn);
	if (rc)
		goto failed0;
@@ -157,12 +157,8 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
		BUG_ON(rc);
	}

	if (reset)
		__pci_reset_function(virtfn);

	pci_device_add(virtfn, virtfn->bus);

	pci_bus_add_device(virtfn);
	sprintf(buf, "virtfn%u", id);
	rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
	if (rc)
@@ -173,6 +169,8 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)

	kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);

	pci_bus_add_device(virtfn);

	return 0;

failed2:
@@ -187,7 +185,7 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
	return rc;
}

void pci_iov_remove_virtfn(struct pci_dev *dev, int id, int reset)
void pci_iov_remove_virtfn(struct pci_dev *dev, int id)
{
	char buf[VIRTFN_ID_LEN];
	struct pci_dev *virtfn;
@@ -198,11 +196,6 @@ void pci_iov_remove_virtfn(struct pci_dev *dev, int id, int reset)
	if (!virtfn)
		return;

	if (reset) {
		device_release_driver(&virtfn->dev);
		__pci_reset_function(virtfn);
	}

	sprintf(buf, "virtfn%u", id);
	sysfs_remove_link(&dev->dev.kobj, buf);
	/*
@@ -317,7 +310,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
	pci_cfg_access_unlock(dev);

	for (i = 0; i < initial; i++) {
		rc = pci_iov_add_virtfn(dev, i, 0);
		rc = pci_iov_add_virtfn(dev, i);
		if (rc)
			goto failed;
	}
@@ -329,7 +322,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)

failed:
	while (i--)
		pci_iov_remove_virtfn(dev, i, 0);
		pci_iov_remove_virtfn(dev, i);

err_pcibios:
	iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
@@ -356,7 +349,7 @@ static void sriov_disable(struct pci_dev *dev)
		return;

	for (i = 0; i < iov->num_VFs; i++)
		pci_iov_remove_virtfn(dev, i, 0);
		pci_iov_remove_virtfn(dev, i);

	iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
	pci_cfg_access_lock(dev);
@@ -449,6 +442,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
	iov->nres = nres;
	iov->ctrl = ctrl;
	iov->total_VFs = total;
	pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &iov->vf_device);
	iov->pgsz = pgsz;
	iov->self = dev;
	iov->drivers_autoprobe = true;
@@ -504,6 +498,14 @@ static void sriov_restore_state(struct pci_dev *dev)
	if (ctrl & PCI_SRIOV_CTRL_VFE)
		return;

	/*
	 * Restore PCI_SRIOV_CTRL_ARI before pci_iov_set_numvfs() because
	 * it reads offset & stride, which depend on PCI_SRIOV_CTRL_ARI.
	 */
	ctrl &= ~PCI_SRIOV_CTRL_ARI;
	ctrl |= iov->ctrl & PCI_SRIOV_CTRL_ARI;
	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, ctrl);

	for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++)
		pci_update_resource(dev, i);

@@ -724,7 +726,7 @@ int pci_vfs_assigned(struct pci_dev *dev)
	 * determine the device ID for the VFs, the vendor ID will be the
	 * same as the PF so there is no need to check for that one
	 */
	pci_read_config_word(dev, dev->sriov->pos + PCI_SRIOV_VF_DID, &dev_id);
	dev_id = dev->sriov->vf_device;

	/* loop through all the VFs to see if we own any that are assigned */
	vfdev = pci_get_device(dev->vendor, dev_id, NULL);
+33 −0
Original line number Diff line number Diff line
@@ -648,6 +648,33 @@ static ssize_t sriov_numvfs_store(struct device *dev,
	return count;
}

static ssize_t sriov_offset_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->offset);
}

static ssize_t sriov_stride_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->stride);
}

static ssize_t sriov_vf_device_show(struct device *dev,
				    struct device_attribute *attr,
				    char *buf)
{
	struct pci_dev *pdev = to_pci_dev(dev);

	return sprintf(buf, "%x\n", pdev->sriov->vf_device);
}

static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
					    struct device_attribute *attr,
					    char *buf)
@@ -676,6 +703,9 @@ 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_offset_attr = __ATTR_RO(sriov_offset);
static struct device_attribute sriov_stride_attr = __ATTR_RO(sriov_stride);
static struct device_attribute sriov_vf_device_attr = __ATTR_RO(sriov_vf_device);
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);
@@ -1748,6 +1778,9 @@ static const struct attribute_group pci_dev_hp_attr_group = {
static struct attribute *sriov_dev_attrs[] = {
	&sriov_totalvfs_attr.attr,
	&sriov_numvfs_attr.attr,
	&sriov_offset_attr.attr,
	&sriov_stride_attr.attr,
	&sriov_vf_device_attr.attr,
	&sriov_drivers_autoprobe_attr.attr,
	NULL,
};
+11 −32
Original line number Diff line number Diff line
@@ -4246,35 +4246,6 @@ static void pci_dev_restore(struct pci_dev *dev)
		err_handler->reset_done(dev);
}

/**
 * __pci_reset_function - reset a PCI device function
 * @dev: PCI device to reset
 *
 * Some devices allow an individual function to be reset without affecting
 * other functions in the same device.  The PCI device must be responsive
 * to PCI config space in order to use this function.
 *
 * The device function is presumed to be unused when this function is called.
 * Resetting the device will make the contents of PCI configuration space
 * random, so any caller of this must be prepared to reinitialise the
 * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
 * etc.
 *
 * Returns 0 if the device function was successfully reset or negative if the
 * device doesn't support resetting a single function.
 */
int __pci_reset_function(struct pci_dev *dev)
{
	int ret;

	pci_dev_lock(dev);
	ret = __pci_reset_function_locked(dev);
	pci_dev_unlock(dev);

	return ret;
}
EXPORT_SYMBOL_GPL(__pci_reset_function);

/**
 * __pci_reset_function_locked - reset a PCI device function while holding
 * the @dev mutex lock.
@@ -4300,6 +4271,14 @@ int __pci_reset_function_locked(struct pci_dev *dev)

	might_sleep();

	/*
	 * A reset method returns -ENOTTY if it doesn't support this device
	 * and we should try the next method.
	 *
	 * If it returns 0 (success), we're finished.  If it returns any
	 * other error, we're also finished: this indicates that further
	 * reset mechanisms might be broken on the device.
	 */
	rc = pci_dev_specific_reset(dev, 0);
	if (rc != -ENOTTY)
		return rc;
@@ -4365,8 +4344,8 @@ int pci_probe_reset_function(struct pci_dev *dev)
 *
 * This function does not just reset the PCI portion of a device, but
 * clears all the state associated with the device.  This function differs
 * from __pci_reset_function in that it saves and restores device state
 * over the reset.
 * from __pci_reset_function_locked() in that it saves and restores device state
 * over the reset and takes the PCI device lock.
 *
 * Returns 0 if the device function was successfully reset or negative if the
 * device doesn't support resetting a single function.
@@ -4401,7 +4380,7 @@ EXPORT_SYMBOL_GPL(pci_reset_function);
 *
 * This function does not just reset the PCI portion of a device, but
 * clears all the state associated with the device.  This function differs
 * from __pci_reset_function() in that it saves and restores device state
 * from __pci_reset_function_locked() in that it saves and restores device state
 * over the reset.  It also differs from pci_reset_function() in that it
 * requires the PCI device lock to be held.
 *
Loading