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

Commit 705b1aaa authored by Alex Chiang's avatar Alex Chiang Committed by Jesse Barnes
Browse files

PCI: Introduce /sys/bus/pci/rescan



This interface allows the user to force a rescan of all PCI buses
in system, and rediscover devices that have been removed earlier.

pci_bus_attrs implementation from Trent Piepho.

Thanks to Vegard Nossum for discovering locking issues with the
sysfs interface.

Cc: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 3ed4fd96
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -57,6 +57,15 @@ Description:
		match the driver to the device.  For example:
		# echo "8086 10f5" > /sys/bus/pci/drivers/foo/remove_id

What:		/sys/bus/pci/rescan
Date:		January 2009
Contact:	Linux PCI developers <linux-pci@vger.kernel.org>
Description:
		Writing a non-zero value to this attribute will
		force a rescan of all PCI buses in the system, and
		re-discover previously removed devices.
		Depends on CONFIG_HOTPLUG.

What:		/sys/bus/pci/devices/.../vpd
Date:		February 2008
Contact:	Ben Hutchings <bhutchings@solarflare.com>
+1 −0
Original line number Diff line number Diff line
@@ -1049,6 +1049,7 @@ struct bus_type pci_bus_type = {
	.remove		= pci_device_remove,
	.shutdown	= pci_device_shutdown,
	.dev_attrs	= pci_dev_attrs,
	.bus_attrs	= pci_bus_attrs,
	.pm		= PCI_PM_OPS_PTR,
};

+26 −0
Original line number Diff line number Diff line
@@ -219,6 +219,32 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
	return count;
}

#ifdef CONFIG_HOTPLUG
static DEFINE_MUTEX(pci_remove_rescan_mutex);
static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
				size_t count)
{
	unsigned long val;
	struct pci_bus *b = NULL;

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

	if (val) {
		mutex_lock(&pci_remove_rescan_mutex);
		while ((b = pci_find_next_bus(b)) != NULL)
			pci_rescan_bus(b);
		mutex_unlock(&pci_remove_rescan_mutex);
	}
	return count;
}

struct bus_attribute pci_bus_attrs[] = {
	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store),
	__ATTR_NULL
};
#endif

struct device_attribute pci_dev_attrs[] = {
	__ATTR_RO(resource),
	__ATTR_RO(vendor),
+6 −0
Original line number Diff line number Diff line
@@ -138,6 +138,12 @@ extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute dev_attr_cpuaffinity;
extern struct device_attribute dev_attr_cpulistaffinity;
#ifdef CONFIG_HOTPLUG
extern struct bus_attribute pci_bus_attrs[];
#else
#define pci_bus_attrs	NULL
#endif


/**
 * pci_match_one_device - Tell if a PCI device structure has a matching
+2 −2
Original line number Diff line number Diff line
@@ -1228,13 +1228,13 @@ unsigned int __devinit pci_rescan_bus(struct pci_bus *bus)

	max = pci_scan_child_bus(bus);

	up_read(&pci_bus_sem);
	down_read(&pci_bus_sem);
	list_for_each_entry(dev, &bus->devices, bus_list)
		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
			if (dev->subordinate)
				pci_bus_size_bridges(dev->subordinate);
	down_read(&pci_bus_sem);
	up_read(&pci_bus_sem);

	pci_bus_assign_resources(bus);
	pci_enable_bridges(bus);