Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

authored by

Yinghai Lu and committed by
Jesse Barnes
b9d320fc da7822e5

+37
+9
Documentation/ABI/testing/sysfs-bus-pci
··· 74 74 hot-remove the PCI device and any of its children. 75 75 Depends on CONFIG_HOTPLUG. 76 76 77 + What: /sys/bus/pci/devices/.../pci_bus/.../rescan 78 + Date: May 2011 79 + Contact: Linux PCI developers <linux-pci@vger.kernel.org> 80 + Description: 81 + Writing a non-zero value to this attribute will 82 + force a rescan of the bus and all child buses, 83 + and re-discover devices removed earlier from this 84 + part of the device tree. Depends on CONFIG_HOTPLUG. 85 + 77 86 What: /sys/bus/pci/devices/.../rescan 78 87 Date: January 2009 79 88 Contact: Linux PCI developers <linux-pci@vger.kernel.org>
+26
drivers/pci/pci-sysfs.c
··· 318 318 count = ret; 319 319 return count; 320 320 } 321 + 322 + static ssize_t 323 + dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, 324 + const char *buf, size_t count) 325 + { 326 + unsigned long val; 327 + struct pci_bus *bus = to_pci_bus(dev); 328 + 329 + if (strict_strtoul(buf, 0, &val) < 0) 330 + return -EINVAL; 331 + 332 + if (val) { 333 + mutex_lock(&pci_remove_rescan_mutex); 334 + pci_rescan_bus(bus); 335 + mutex_unlock(&pci_remove_rescan_mutex); 336 + } 337 + return count; 338 + } 339 + 321 340 #endif 322 341 323 342 struct device_attribute pci_dev_attrs[] = { ··· 362 343 #ifdef CONFIG_HOTPLUG 363 344 __ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store), 364 345 __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store), 346 + #endif 347 + __ATTR_NULL, 348 + }; 349 + 350 + struct device_attribute pcibus_dev_attrs[] = { 351 + #ifdef CONFIG_HOTPLUG 352 + __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store), 365 353 #endif 366 354 __ATTR_NULL, 367 355 };
+1
drivers/pci/pci.h
··· 156 156 157 157 } 158 158 extern struct device_attribute pci_dev_attrs[]; 159 + extern struct device_attribute pcibus_dev_attrs[]; 159 160 extern struct device_attribute dev_attr_cpuaffinity; 160 161 extern struct device_attribute dev_attr_cpulistaffinity; 161 162 #ifdef CONFIG_HOTPLUG
+1
drivers/pci/probe.c
··· 95 95 static struct class pcibus_class = { 96 96 .name = "pci_bus", 97 97 .dev_release = &release_pcibus_dev, 98 + .dev_attrs = pcibus_dev_attrs, 98 99 }; 99 100 100 101 static int __init pcibus_class_init(void)