aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2009-06-15 22:01:25 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-16 17:30:11 -0400
commitc825bc94c8c1908750ab20413eb639c6be029e2d (patch)
tree6e5800fe52e0f94f42fdcd4c327b8cfaf803978a
parent498a8faf2c7eb974f70b7c5a60a31f0d48c35d44 (diff)
PCI hotplug: create symlink to hotplug driver module
Create symbolic link to hotplug driver module in the PCI slot directory (/sys/bus/pci/slots/<SLOT#>). In the past, we need to load hotplug drivers one by one to identify the hotplug driver that handles the slot, and it was very inconvenient especially for trouble shooting. With this change, we can easily identify the hotplug driver. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Reviewed-by: Alex Chiang <achiang@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--Documentation/ABI/testing/sysfs-bus-pci7
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c23
-rw-r--r--drivers/pci/slot.c39
-rw-r--r--include/linux/pci.h5
-rw-r--r--include/linux/pci_hotplug.h15
5 files changed, 80 insertions, 9 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 97ad190e13af..6bf68053e4b8 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -122,3 +122,10 @@ Description:
122 This symbolic link appears when a device is a Virtual Function. 122 This symbolic link appears when a device is a Virtual Function.
123 The symbolic link points to the PCI device sysfs entry of the 123 The symbolic link points to the PCI device sysfs entry of the
124 Physical Function this device associates with. 124 Physical Function this device associates with.
125
126What: /sys/bus/pci/slots/.../module
127Date: June 2009
128Contact: linux-pci@vger.kernel.org
129Description:
130 This symbolic link points to the PCI hotplug controller driver
131 module that manages the hotplug slot.
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index ff32c6b4ae13..844580489d4d 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -424,6 +424,9 @@ static int fs_add_slot(struct pci_slot *slot)
424{ 424{
425 int retval = 0; 425 int retval = 0;
426 426
427 /* Create symbolic link to the hotplug driver module */
428 pci_hp_create_module_link(slot);
429
427 if (has_power_file(slot)) { 430 if (has_power_file(slot)) {
428 retval = sysfs_create_file(&slot->kobj, 431 retval = sysfs_create_file(&slot->kobj,
429 &hotplug_slot_attr_power.attr); 432 &hotplug_slot_attr_power.attr);
@@ -498,6 +501,7 @@ exit_attention:
498 if (has_power_file(slot)) 501 if (has_power_file(slot))
499 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr); 502 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
500exit_power: 503exit_power:
504 pci_hp_remove_module_link(slot);
501exit: 505exit:
502 return retval; 506 return retval;
503} 507}
@@ -528,6 +532,8 @@ static void fs_remove_slot(struct pci_slot *slot)
528 532
529 if (has_test_file(slot)) 533 if (has_test_file(slot))
530 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); 534 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
535
536 pci_hp_remove_module_link(slot);
531} 537}
532 538
533static struct hotplug_slot *get_slot_from_name (const char *name) 539static struct hotplug_slot *get_slot_from_name (const char *name)
@@ -544,10 +550,10 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
544} 550}
545 551
546/** 552/**
547 * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem 553 * __pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
548 * @bus: bus this slot is on 554 * @bus: bus this slot is on
549 * @slot: pointer to the &struct hotplug_slot to register 555 * @slot: pointer to the &struct hotplug_slot to register
550 * @slot_nr: slot number 556 * @devnr: device number
551 * @name: name registered with kobject core 557 * @name: name registered with kobject core
552 * 558 *
553 * Registers a hotplug slot with the pci hotplug subsystem, which will allow 559 * Registers a hotplug slot with the pci hotplug subsystem, which will allow
@@ -555,8 +561,9 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
555 * 561 *
556 * Returns 0 if successful, anything else for an error. 562 * Returns 0 if successful, anything else for an error.
557 */ 563 */
558int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr, 564int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus,
559 const char *name) 565 int devnr, const char *name,
566 struct module *owner, const char *mod_name)
560{ 567{
561 int result; 568 int result;
562 struct pci_slot *pci_slot; 569 struct pci_slot *pci_slot;
@@ -571,14 +578,16 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr,
571 return -EINVAL; 578 return -EINVAL;
572 } 579 }
573 580
574 mutex_lock(&pci_hp_mutex); 581 slot->ops->owner = owner;
582 slot->ops->mod_name = mod_name;
575 583
584 mutex_lock(&pci_hp_mutex);
576 /* 585 /*
577 * No problems if we call this interface from both ACPI_PCI_SLOT 586 * No problems if we call this interface from both ACPI_PCI_SLOT
578 * driver and call it here again. If we've already created the 587 * driver and call it here again. If we've already created the
579 * pci_slot, the interface will simply bump the refcount. 588 * pci_slot, the interface will simply bump the refcount.
580 */ 589 */
581 pci_slot = pci_create_slot(bus, slot_nr, name, slot); 590 pci_slot = pci_create_slot(bus, devnr, name, slot);
582 if (IS_ERR(pci_slot)) { 591 if (IS_ERR(pci_slot)) {
583 result = PTR_ERR(pci_slot); 592 result = PTR_ERR(pci_slot);
584 goto out; 593 goto out;
@@ -688,6 +697,6 @@ MODULE_LICENSE("GPL");
688module_param(debug, bool, 0644); 697module_param(debug, bool, 0644);
689MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); 698MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
690 699
691EXPORT_SYMBOL_GPL(pci_hp_register); 700EXPORT_SYMBOL_GPL(__pci_hp_register);
692EXPORT_SYMBOL_GPL(pci_hp_deregister); 701EXPORT_SYMBOL_GPL(pci_hp_deregister);
693EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); 702EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index fe95ce20bcbd..eddb0748b0ea 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -307,6 +307,45 @@ void pci_destroy_slot(struct pci_slot *slot)
307} 307}
308EXPORT_SYMBOL_GPL(pci_destroy_slot); 308EXPORT_SYMBOL_GPL(pci_destroy_slot);
309 309
310#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
311#include <linux/pci_hotplug.h>
312/**
313 * pci_hp_create_link - create symbolic link to the hotplug driver module.
314 * @slot: struct pci_slot
315 *
316 * Helper function for pci_hotplug_core.c to create symbolic link to
317 * the hotplug driver module.
318 */
319void pci_hp_create_module_link(struct pci_slot *pci_slot)
320{
321 struct hotplug_slot *slot = pci_slot->hotplug;
322 struct kobject *kobj = NULL;
323 int no_warn;
324
325 if (!slot || !slot->ops)
326 return;
327 kobj = kset_find_obj(module_kset, slot->ops->mod_name);
328 if (!kobj)
329 return;
330 no_warn = sysfs_create_link(&pci_slot->kobj, kobj, "module");
331 kobject_put(kobj);
332}
333EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
334
335/**
336 * pci_hp_remove_link - remove symbolic link to the hotplug driver module.
337 * @slot: struct pci_slot
338 *
339 * Helper function for pci_hotplug_core.c to remove symbolic link to
340 * the hotplug driver module.
341 */
342void pci_hp_remove_module_link(struct pci_slot *pci_slot)
343{
344 sysfs_remove_link(&pci_slot->kobj, "module");
345}
346EXPORT_SYMBOL_GPL(pci_hp_remove_module_link);
347#endif
348
310static int pci_slot_init(void) 349static int pci_slot_init(void)
311{ 350{
312 struct kset *pci_bus_kset; 351 struct kset *pci_bus_kset;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ea2a153a9126..6a1800ecd95d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1261,5 +1261,10 @@ static inline irqreturn_t pci_sriov_migration(struct pci_dev *dev)
1261} 1261}
1262#endif 1262#endif
1263 1263
1264#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
1265extern void pci_hp_create_module_link(struct pci_slot *pci_slot);
1266extern void pci_hp_remove_module_link(struct pci_slot *pci_slot);
1267#endif
1268
1264#endif /* __KERNEL__ */ 1269#endif /* __KERNEL__ */
1265#endif /* LINUX_PCI_H */ 1270#endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index 11936fd0b56d..b3646cd7fd5a 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -69,6 +69,7 @@ enum pcie_link_speed {
69/** 69/**
70 * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use 70 * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
71 * @owner: The module owner of this structure 71 * @owner: The module owner of this structure
72 * @mod_name: The module name (KBUILD_MODNAME) of this structure
72 * @enable_slot: Called when the user wants to enable a specific pci slot 73 * @enable_slot: Called when the user wants to enable a specific pci slot
73 * @disable_slot: Called when the user wants to disable a specific pci slot 74 * @disable_slot: Called when the user wants to disable a specific pci slot
74 * @set_attention_status: Called to set the specific slot's attention LED to 75 * @set_attention_status: Called to set the specific slot's attention LED to
@@ -101,6 +102,7 @@ enum pcie_link_speed {
101 */ 102 */
102struct hotplug_slot_ops { 103struct hotplug_slot_ops {
103 struct module *owner; 104 struct module *owner;
105 const char *mod_name;
104 int (*enable_slot) (struct hotplug_slot *slot); 106 int (*enable_slot) (struct hotplug_slot *slot);
105 int (*disable_slot) (struct hotplug_slot *slot); 107 int (*disable_slot) (struct hotplug_slot *slot);
106 int (*set_attention_status) (struct hotplug_slot *slot, u8 value); 108 int (*set_attention_status) (struct hotplug_slot *slot, u8 value);
@@ -159,12 +161,21 @@ static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
159 return pci_slot_name(slot->pci_slot); 161 return pci_slot_name(slot->pci_slot);
160} 162}
161 163
162extern int pci_hp_register(struct hotplug_slot *, struct pci_bus *, int nr, 164extern int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus,
163 const char *name); 165 int nr, const char *name,
166 struct module *owner, const char *mod_name);
164extern int pci_hp_deregister(struct hotplug_slot *slot); 167extern int pci_hp_deregister(struct hotplug_slot *slot);
165extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, 168extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,
166 struct hotplug_slot_info *info); 169 struct hotplug_slot_info *info);
167 170
171static inline int pci_hp_register(struct hotplug_slot *slot,
172 struct pci_bus *pbus,
173 int devnr, const char *name)
174{
175 return __pci_hp_register(slot, pbus, devnr, name,
176 THIS_MODULE, KBUILD_MODNAME);
177}
178
168/* PCI Setting Record (Type 0) */ 179/* PCI Setting Record (Type 0) */
169struct hpp_type0 { 180struct hpp_type0 {
170 u32 revision; 181 u32 revision;