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

Commit b9d320fc authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes
Browse files

PCI: add rescan to /sys/.../pci_bus/.../



After remove the device from /sys, we have to rescan all or
find out the bridge and access /sys../device/rescan there.

this patch add /sys/.../pci_bus/.../rescan. So user can rescan more easy.
that is more clean and easy to understand.

like after remove 0000:c4:00.0, you can rescan 0000:c4 directly.

-v2: According to Jesse, use function instead of exposing attr, so could hide
	#ifdef in header file.
     also add code to remove rescan file in remove path.
-v3: GregKH pointed out that we should use dev_attrs to avoid racing.
     So add pcibus_attrs and make it to be member of pcibus_attrs.
-v4: Change name to pcibus_dev_attrs according to GregKH

Acked-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent da7822e5
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -74,6 +74,15 @@ Description:
		hot-remove the PCI device and any of its children.
		Depends on CONFIG_HOTPLUG.

What:		/sys/bus/pci/devices/.../pci_bus/.../rescan
Date:		May 2011
Contact:	Linux PCI developers <linux-pci@vger.kernel.org>
Description:
		Writing a non-zero value to this attribute will
		force a rescan of the bus and all child buses,
		and re-discover devices removed earlier from this
		part of the device tree.  Depends on CONFIG_HOTPLUG.

What:		/sys/bus/pci/devices/.../rescan
Date:		January 2009
Contact:	Linux PCI developers <linux-pci@vger.kernel.org>
+26 −0
Original line number Diff line number Diff line
@@ -318,6 +318,25 @@ remove_store(struct device *dev, struct device_attribute *dummy,
		count = ret;
	return count;
}

static ssize_t
dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
		 const char *buf, size_t count)
{
	unsigned long val;
	struct pci_bus *bus = to_pci_bus(dev);

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

	if (val) {
		mutex_lock(&pci_remove_rescan_mutex);
		pci_rescan_bus(bus);
		mutex_unlock(&pci_remove_rescan_mutex);
	}
	return count;
}

#endif

struct device_attribute pci_dev_attrs[] = {
@@ -347,6 +366,13 @@ struct device_attribute pci_dev_attrs[] = {
	__ATTR_NULL,
};

struct device_attribute pcibus_dev_attrs[] = {
#ifdef CONFIG_HOTPLUG
	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store),
#endif
	__ATTR_NULL,
};

static ssize_t
boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
{
+1 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)

}
extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute pcibus_dev_attrs[];
extern struct device_attribute dev_attr_cpuaffinity;
extern struct device_attribute dev_attr_cpulistaffinity;
#ifdef CONFIG_HOTPLUG
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ static void release_pcibus_dev(struct device *dev)
static struct class pcibus_class = {
	.name		= "pci_bus",
	.dev_release	= &release_pcibus_dev,
	.dev_attrs	= pcibus_dev_attrs,
};

static int __init pcibus_class_init(void)