Commit d985e2be authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/reset'

- Add sysfs 'reset_subordinate' to reset hierarchy below bridge (Keith
  Busch)

- Warn if we reset a running device where driver didn't register
  pci_error_handlers notification callbacks (Keith Busch)

* pci/reset:
  PCI: Warn if a running device is unaware of reset
  PCI: Add 'reset_subordinate' to reset hierarchy below bridge
parents ce1deca9 a3151e6d
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -163,6 +163,17 @@ Description:
		will be present in sysfs.  Writing 1 to this file
		will perform reset.

What:		/sys/bus/pci/devices/.../reset_subordinate
Date:		October 2024
Contact:	linux-pci@vger.kernel.org
Description:
		This is visible only for bridge devices. If you want to reset
		all devices attached through the subordinate bus of a specific
		bridge device, writing 1 to this will try to do it.  This will
		affect all devices attached to the system through this bridge
		similiar to writing 1 to their individual "reset" file, so use
		with caution.

What:		/sys/bus/pci/devices/.../vpd
Date:		February 2008
Contact:	Ben Hutchings <bwh@kernel.org>
+26 −0
Original line number Diff line number Diff line
@@ -521,6 +521,31 @@ static ssize_t bus_rescan_store(struct device *dev,
static struct device_attribute dev_attr_bus_rescan = __ATTR(rescan, 0200, NULL,
							    bus_rescan_store);

static ssize_t reset_subordinate_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct pci_bus *bus = pdev->subordinate;
	unsigned long val;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (kstrtoul(buf, 0, &val) < 0)
		return -EINVAL;

	if (val) {
		int ret = __pci_reset_bus(bus);

		if (ret)
			return ret;
	}

	return count;
}
static DEVICE_ATTR_WO(reset_subordinate);

#if defined(CONFIG_PM) && defined(CONFIG_ACPI)
static ssize_t d3cold_allowed_store(struct device *dev,
				    struct device_attribute *attr,
@@ -625,6 +650,7 @@ static struct attribute *pci_dev_attrs[] = {
static struct attribute *pci_bridge_attrs[] = {
	&dev_attr_subordinate_bus_number.attr,
	&dev_attr_secondary_bus_number.attr,
	&dev_attr_reset_subordinate.attr,
	NULL,
};

+5 −1
Original line number Diff line number Diff line
@@ -5158,6 +5158,8 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
	 */
	if (err_handler && err_handler->reset_prepare)
		err_handler->reset_prepare(dev);
	else if (dev->driver)
		pci_warn(dev, "resetting");

	/*
	 * Wake-up device prior to save.  PM registers default to D0 after
@@ -5191,6 +5193,8 @@ static void pci_dev_restore(struct pci_dev *dev)
	 */
	if (err_handler && err_handler->reset_done)
		err_handler->reset_done(dev);
	else if (dev->driver)
		pci_warn(dev, "reset done");
}

/* dev->reset_methods[] is a 0-terminated list of indices into this array */
@@ -5880,7 +5884,7 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_bus);
 *
 * Same as above except return -EAGAIN if the bus cannot be locked
 */
static int __pci_reset_bus(struct pci_bus *bus)
int __pci_reset_bus(struct pci_bus *bus)
{
	int rc;

+1 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ bool pci_reset_supported(struct pci_dev *dev);
void pci_init_reset_methods(struct pci_dev *dev);
int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
int pci_bus_error_reset(struct pci_dev *dev);
int __pci_reset_bus(struct pci_bus *bus);

struct pci_cap_saved_data {
	u16		cap_nr;