PCI, ACPI: Physical PCI slot objects
Subsystems (8)
v12 cover PCI, ACPI: Physical PCI slot objects
Hi Greg,
This is v12 of the physical pci_slot series.
I had to do one last respin because I misspelled Kenji-san's name in the changelog. I've also added his Acked-by.
There are no code changes between v11 and v12.
Sorry for the noise.
Thanks.
/ac
PATCH v12 1/4 Construct one fakephp slot per pci slot
Register one slot per slot, rather than one slot per function. Change the name of the slot to fake%d instead of the pci address.
--- drivers/pci/hotplug/fakephp.c | 85 ++++++++++++++-------------------------- 1 files changed, 30 insertions(+), 55 deletions(-)
drivers/pci/hotplug/fakephp.c +30 -55
@@ -66,6 +66,7 @@ struct dummy_slot {struct pci_dev *dev;struct work_struct remove_work;unsigned long removed; +char name[8 ]; };static int debug;
@@ -100,6 +101,7 @@ static int add_slot(struct pci_dev *dev)struct dummy_slot *dslot;struct hotplug_slot *slot;int retval = -ENOMEM ; +static int count =1 ; slot =kzalloc (sizeof (struct hotplug_slot ),GFP_KERNEL );if (!slot)
@@ -113,13 +115,14 @@ static int add_slot(struct pci_dev *dev) slot->info->max_bus_speed =PCI_SPEED_UNKNOWN ; slot->info->cur_bus_speed =PCI_SPEED_UNKNOWN ; - slot->name = &dev->dev.bus_id[0 ]; -dbg ("slot->name = %s\n" , slot->name); - dslot =kzalloc (sizeof (struct dummy_slot ),GFP_KERNEL );if (!dslot) goto error_info; + slot->name = dslot->name; +snprintf (slot->name,sizeof (dslot->name),"fake%d" , count++); +dbg ("slot->name = %s\n" , slot->name); + slot->ops = &dummy_hotplug_slot_ops; slot->release = &dummy_release; slot->private = dslot;
@@ -148,17 +151,17 @@ error:static int __init pci_scan_buses (void ) {struct pci_dev *dev =NULL ; -int retval =0 ; +int lastslot =0 ;while ((dev =pci_get_device (PCI_ANY_ID ,PCI_ANY_ID , dev)) !=NULL ) { - retval =add_slot (dev); -if (retval) { -pci_dev_put (dev); -break ; - } +if (PCI_FUNC (dev->devfn) >0 && + lastslot ==PCI_SLOT (dev->devfn)) +continue ; + lastslot =PCI_SLOT (dev->devfn); +add_slot (dev); } -return retval; +return 0 ; }static void remove_slot (struct dummy_slot *dslot)
@@ -296,23 +299,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)return -ENODEV ; } -/* find the hotplug_slot for the pci_dev */ -static struct hotplug_slot *get_slot_from_dev (struct pci_dev *dev) -{ -struct dummy_slot *dslot; - -list_for_each_entry (dslot, &slot_list, node) { -if (dslot->dev == dev) -return dslot->slot; - } -return NULL ; -} - -static int disable_slot (struct hotplug_slot *slot) {struct dummy_slot *dslot; -struct hotplug_slot *hslot;struct pci_dev *dev;int func;
@@ -322,41 +311,27 @@ static int disable_slot(struct hotplug_slot *slot)dbg ("%s - physical_slot = %s\n" , __FUNCTION__, slot->name); -/* don't disable bridged devices just yet, we can't handle them easily... */ -if (dslot->dev->subordinate) { -err ("Can't remove PCI devices with other PCI devices behind it yet.\n" ); -return -ENODEV ; - } -if (test_and_set_bit (0 , &dslot->removed)) { -dbg ("Slot already scheduled for removal\n" ); -return -ENODEV ; - } -/* search for subfunctions and disable them first */ -if (!(dslot->dev->devfn &7 )) { -for (func =1 ; func <8 ; func++) { - dev =pci_get_slot (dslot->dev->bus, - dslot->dev->devfn + func); -if (dev) { - hslot =get_slot_from_dev (dev); -if (hslot) -disable_slot (hslot); -else { -err ("Hotplug slot not found for subfunction of PCI device\n" ); -return -ENODEV ; - } -pci_dev_put (dev); - }else -dbg ("No device in slot found\n" ); +for (func =7 ; func >=0 ; func--) { + dev =pci_get_slot (dslot->dev->bus, dslot->dev->devfn + func); +if (!dev) +continue ; + +if (test_and_set_bit (0 , &dslot->removed)) { +dbg ("Slot already scheduled for removal\n" ); +return -ENODEV ; } - } -/* remove the device from the pci core */ -pci_remove_bus_device (dslot->dev); +/* queue work item to blow away this sysfs entry and other +* parts. +*/ +INIT_WORK (&dslot->remove_work, remove_slot_worker); +queue_work (dummyphp_wq, &dslot->remove_work); -/* queue work item to blow away this sysfs entry and other parts. */ -INIT_WORK (&dslot->remove_work, remove_slot_worker); -queue_work (dummyphp_wq, &dslot->remove_work); +/* blow away this sysfs entry and other parts. */ +remove_slot (dslot); +pci_dev_put (dev); + }return 0 ; }
Signature · 1 line
1.5.3.1.g1e61
PATCH v12 1/4 Construct one fakephp slot per pci slot
In reply to Alex ChiangRegister one slot per slot, rather than one slot per function. Change the name of the slot to fake%d instead of the pci address.
--- drivers/pci/hotplug/fakephp.c | 85 ++++++++++++++-------------------------- 1 files changed, 30 insertions(+), 55 deletions(-)
drivers/pci/hotplug/fakephp.c +30 -55
@@ -66,6 +66,7 @@ struct dummy_slot {struct pci_dev *dev;struct work_struct remove_work;unsigned long removed; +char name[8 ]; };static int debug;
@@ -100,6 +101,7 @@ static int add_slot(struct pci_dev *dev)struct dummy_slot *dslot;struct hotplug_slot *slot;int retval = -ENOMEM ; +static int count =1 ; slot =kzalloc (sizeof (struct hotplug_slot ),GFP_KERNEL );if (!slot)
@@ -113,13 +115,14 @@ static int add_slot(struct pci_dev *dev) slot->info->max_bus_speed =PCI_SPEED_UNKNOWN ; slot->info->cur_bus_speed =PCI_SPEED_UNKNOWN ; - slot->name = &dev->dev.bus_id[0 ]; -dbg ("slot->name = %s\n" , slot->name); - dslot =kzalloc (sizeof (struct dummy_slot ),GFP_KERNEL );if (!dslot) goto error_info; + slot->name = dslot->name; +snprintf (slot->name,sizeof (dslot->name),"fake%d" , count++); +dbg ("slot->name = %s\n" , slot->name); + slot->ops = &dummy_hotplug_slot_ops; slot->release = &dummy_release; slot->private = dslot;
@@ -148,17 +151,17 @@ error:static int __init pci_scan_buses (void ) {struct pci_dev *dev =NULL ; -int retval =0 ; +int lastslot =0 ;while ((dev =pci_get_device (PCI_ANY_ID ,PCI_ANY_ID , dev)) !=NULL ) { - retval =add_slot (dev); -if (retval) { -pci_dev_put (dev); -break ; - } +if (PCI_FUNC (dev->devfn) >0 && + lastslot ==PCI_SLOT (dev->devfn)) +continue ; + lastslot =PCI_SLOT (dev->devfn); +add_slot (dev); } -return retval; +return 0 ; }static void remove_slot (struct dummy_slot *dslot)
@@ -296,23 +299,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)return -ENODEV ; } -/* find the hotplug_slot for the pci_dev */ -static struct hotplug_slot *get_slot_from_dev (struct pci_dev *dev) -{ -struct dummy_slot *dslot; - -list_for_each_entry (dslot, &slot_list, node) { -if (dslot->dev == dev) -return dslot->slot; - } -return NULL ; -} - -static int disable_slot (struct hotplug_slot *slot) {struct dummy_slot *dslot; -struct hotplug_slot *hslot;struct pci_dev *dev;int func;
@@ -322,41 +311,27 @@ static int disable_slot(struct hotplug_slot *slot)dbg ("%s - physical_slot = %s\n" , __FUNCTION__, slot->name); -/* don't disable bridged devices just yet, we can't handle them easily... */ -if (dslot->dev->subordinate) { -err ("Can't remove PCI devices with other PCI devices behind it yet.\n" ); -return -ENODEV ; - } -if (test_and_set_bit (0 , &dslot->removed)) { -dbg ("Slot already scheduled for removal\n" ); -return -ENODEV ; - } -/* search for subfunctions and disable them first */ -if (!(dslot->dev->devfn &7 )) { -for (func =1 ; func <8 ; func++) { - dev =pci_get_slot (dslot->dev->bus, - dslot->dev->devfn + func); -if (dev) { - hslot =get_slot_from_dev (dev); -if (hslot) -disable_slot (hslot); -else { -err ("Hotplug slot not found for subfunction of PCI device\n" ); -return -ENODEV ; - } -pci_dev_put (dev); - }else -dbg ("No device in slot found\n" ); +for (func =7 ; func >=0 ; func--) { + dev =pci_get_slot (dslot->dev->bus, dslot->dev->devfn + func); +if (!dev) +continue ; + +if (test_and_set_bit (0 , &dslot->removed)) { +dbg ("Slot already scheduled for removal\n" ); +return -ENODEV ; } - } -/* remove the device from the pci core */ -pci_remove_bus_device (dslot->dev); +/* queue work item to blow away this sysfs entry and other +* parts. +*/ +INIT_WORK (&dslot->remove_work, remove_slot_worker); +queue_work (dummyphp_wq, &dslot->remove_work); -/* queue work item to blow away this sysfs entry and other parts. */ -INIT_WORK (&dslot->remove_work, remove_slot_worker); -queue_work (dummyphp_wq, &dslot->remove_work); +/* blow away this sysfs entry and other parts. */ +remove_slot (dslot); +pci_dev_put (dev); + }return 0 ; }
Signature · 1 line
1.5.3.1.g1e61
PATCH v12 2/4 Export kobject_rename for pci_hotplug_core
In reply to Alex ChiangExport kobject_rename() to fix the following link error. This happens when pci_hotplug_core driver is compiled as a kernel module.
ERROR: "kobject_rename" [drivers/pci/hotplug/pci_hotplug.ko] undefined! make[1]: *** [__modpost] Error 1
make: *** [modules] Error 2
make: *** Waiting for unfinished jobs....
--- lib/kobject.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
lib/kobject.c +1 -0
@@ -456,6 +456,7 @@ out:return error; } +EXPORT_SYMBOL_GPL (kobject_rename);/** * kobject_move - move object to another parent
Signature · 1 line
1.5.3.1.g1e61
PATCH v12 2/4 Export kobject_rename for pci_hotplug_core
In reply to Alex ChiangExport kobject_rename() to fix the following link error. This happens when pci_hotplug_core driver is compiled as a kernel module.
ERROR: "kobject_rename" [drivers/pci/hotplug/pci_hotplug.ko] undefined! make[1]: *** [__modpost] Error 1
make: *** [modules] Error 2
make: *** Waiting for unfinished jobs....
--- lib/kobject.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
lib/kobject.c +1 -0
@@ -456,6 +456,7 @@ out:return error; } +EXPORT_SYMBOL_GPL (kobject_rename);/** * kobject_move - move object to another parent
Signature · 1 line
1.5.3.1.g1e61
PATCH v12 3/4 Introduce pci_slot
In reply to Alex ChiangCurrently, /sys/bus/pci/slots/ only exposes hotplug attributes when a hotplug driver is loaded, but PCI slots have attributes such as address, speed, width, etc. that are not related to hotplug at all.
Introduce pci_slot as the primary data structure and kobject model. Hotplug attributes described in hotplug_slot become a secondary structure associated with the pci_slot.
This patch only creates the infrastructure that allows the separation of PCI slot attributes and hotplug attributes. In this patch, the PCI hotplug core remains the only user of this infrastructure, and thus, /sys/bus/pci/slots/ will still only become populated when a hotplug driver is loaded.
A later patch in this series will add a second user of this new infrastructure and demonstrate splitting the task of exposing pci_slot attributes from hotplug_slot attributes.
- Make pci_slot the primary sysfs entity. hotplug_slot becomes a subsidiary structure.
o pci_create_slot() creates and registers a slot with the PCI core
o pci_slot_add_hotplug() gives it hotplug capability
- Change the prototype of pci_hp_register() to take the bus and slot number (on parent bus) as parameters.
- Remove all the ->get_address methods since this functionality is now handled by pci_slot directly.
v10 -> v12:
Thanks to Kenji Kaneshige for the following updates
- Add missing semaphore for slot release
- Use list_head for pci slot list
- Replace dbg with pr_debug
- Remove useless release handler
- Use .default_attrs for address file
- Fix return value of pci_create_slot()
- Change return value of pci_destroy_slot()
- Trivial cleanups for slot.c
- add missing lock for hotplug slot list
v9 -> v10:
No change
v8 -> v9:
Fixed printk output, changed to American spelling of "initialization"
v7 -> v8:
Removed externs from C files.
Taught sn_hp_destroy and sn_hotplug_slot_register about struct pci_slot.
v6 -> v7:
Refresh to new kobject model.
v5 -> v6:
Add debugging information.
v4 -> v5:
Add refcounting for pci_slot objects.
Return -EBUSY if an hp driver attempts to register a slot that is already registered to another driver. Do not consider that to be an error condition in acpiphp and pciehp.
v3 -> v4:
Fixed bug with pciehp and rpaphp registering slots
v2 -> v3:
Separated slot creation and slot hotplug ability into two interfaces. Fixed bugs in pci_destroy_slot(), and now properly calling from pci_hp_deregister.
v1 -> v2:
No change
--- drivers/pci/Makefile | 2 +- drivers/pci/hotplug/acpiphp.h | 1 - drivers/pci/hotplug/acpiphp_core.c | 25 +--- drivers/pci/hotplug/acpiphp_glue.c | 23 +-- drivers/pci/hotplug/acpiphp_ibm.c | 6 +- drivers/pci/hotplug/cpci_hotplug_core.c | 2 +- drivers/pci/hotplug/cpqphp_core.c | 4 +- drivers/pci/hotplug/fakephp.c | 2 +- drivers/pci/hotplug/ibmphp_ebda.c | 3 +- drivers/pci/hotplug/pci_hotplug_core.c | 257 ++++++++++++------------------- drivers/pci/hotplug/pciehp_core.c | 31 ++-- drivers/pci/hotplug/rpadlpar_sysfs.c | 5 +- drivers/pci/hotplug/rpaphp_slot.c | 3 +- drivers/pci/hotplug/sgi_hotplug.c | 10 +- drivers/pci/hotplug/shpchp_core.c | 17 +-- drivers/pci/pci.h | 13 ++ drivers/pci/probe.c | 1 + drivers/pci/slot.c | 147 ++++++++++++++++++ include/linux/pci.h | 14 ++ include/linux/pci_hotplug.h | 12 +- 20 files changed, 325 insertions(+), 253 deletions(-) create mode 100644 drivers/pci/slot.c
drivers/pci/Makefile +1 -1
@@ -2,7 +2,7 @@ # Makefile for the PCI bus specific drivers. # -obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ +obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o obj-$(CONFIG_PROC_FS) += proc.o
drivers/pci/hotplug/acpiphp.h +0 -1
@@ -215,7 +215,6 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); -extern u32 acpiphp_get_address (struct acpiphp_slot *slot);/* variables */ extern int acpiphp_debug;
drivers/pci/hotplug/acpiphp_core.c +5 -20
@@ -70,7 +70,6 @@ static int disable_slot (struct hotplug_slot *slot);static int set_attention_status (struct hotplug_slot *slot,u8 value);static int get_power_status (struct hotplug_slot *slot,u8 *value);static int get_attention_status (struct hotplug_slot *slot,u8 *value); -static int get_address (struct hotplug_slot *slot,u32 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value);
@@ -83,7 +82,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_address = get_address, };
@@ -274,23 +272,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } - -/** -* get_address - get pci address of a slot -* @hotplug_slot: slot to get status -* @value: pointer to struct pci_busdev (seg, bus, dev) -*/ -static int get_address (struct hotplug_slot *hotplug_slot,u32 *value) -{ -struct slot *slot = hotplug_slot->private; - -dbg ("%s - physical_slot = %s\n" , __FUNCTION__, hotplug_slot->name); - - *value =acpiphp_get_address (slot->acpi_slot); - -return 0 ; -} -static int __init init_acpi (void ) {int retval;
@@ -357,7 +338,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) acpiphp_slot->slot = slot;snprintf (slot->name,sizeof (slot->name),"%u" , slot->acpi_slot->sun); - retval =pci_hp_register (slot->hotplug_slot); + retval =pci_hp_register (slot->hotplug_slot, + acpiphp_slot->bridge->pci_bus, + acpiphp_slot->device); +if (retval == -EBUSY ) + goto error_hpslot;if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_hpslot;
drivers/pci/hotplug/acpiphp_glue.c +6 -17
@@ -258,7 +258,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) bridge->pci_bus->number, slot->device); retval =acpiphp_register_hotplug_slot (slot);if (retval) { -warn ("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n" , retval); +if (retval == -EBUSY ) +warn ("Slot %d already registered by another " +"hotplug driver\n" , slot->sun); +else +warn ("acpiphp_register_hotplug_slot failed " +"(err code = 0x%x)\n" , retval); goto err_exit; } }
@@ -1867,19 +1872,3 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)return (sta ==0 ) ?0 :1 ; } - - -/* -* pci address (seg/bus/dev) -*/ -u32 acpiphp_get_address (struct acpiphp_slot *slot) -{ -u32 address; -struct pci_bus *pci_bus = slot->bridge->pci_bus; - - address = (pci_domain_nr (pci_bus) <<16 ) | - (pci_bus->number <<8 ) | - slot->device; - -return address; -}
drivers/pci/hotplug/acpiphp_ibm.c +4 -2
@@ -33,8 +33,10 @@#include <linux/kobject.h> #include <asm/uaccess.h> #include <linux/moduleparam.h> +#include <linux/pci.h> #include "acpiphp.h" +#include "../pci.h" #define DRIVER_VERSION "1.0.1"#define DRIVER_AUTHOR "Irene Zubarev <[email protected]>, Vernon Mauery <[email protected]>"
@@ -430,7 +432,7 @@ static int __init ibm_acpiphp_init(void)int retval =0 ;acpi_status status;struct acpi_device *device; -struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; +struct kobject *sysdir = &pci_slots_kset->kobj;dbg ("%s\n" , __FUNCTION__);
@@ -477,7 +479,7 @@ init_return: static void __exit ibm_acpiphp_exit(void) {acpi_status status; -struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; +struct kobject *sysdir = &pci_slots_kset->kobj;dbg ("%s\n" , __FUNCTION__);
drivers/pci/hotplug/cpci_hotplug_core.c +1 -1
@@ -285,7 +285,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) info->attention_status =cpci_get_attention_status (slot);dbg ("registering slot %s" , slot->hotplug_slot->name); - status =pci_hp_register (slot->hotplug_slot); + status =pci_hp_register (slot->hotplug_slot, bus, i);if (status) {err ("pci_hp_register failed with error %d" , status); goto error_name;
drivers/pci/hotplug/cpqphp_core.c +3 -1
@@ -434,7 +434,9 @@ static int ctrl_slot_setup(struct controller *ctrl, slot->bus, slot->device, slot->number, ctrl->slot_device_offset, slot_number); - result =pci_hp_register (hotplug_slot); + result =pci_hp_register (hotplug_slot, + ctrl->pci_dev->subordinate, + slot->device);if (result) {err ("pci_hp_register failed with error %d\n" , result); goto error_name;
drivers/pci/hotplug/fakephp.c +1 -1
@@ -127,7 +127,7 @@ static int add_slot(struct pci_dev *dev) slot->release = &dummy_release; slot->private = dslot; - retval =pci_hp_register (slot); + retval =pci_hp_register (slot, dev->bus,PCI_SLOT (dev->devfn));if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_dslot;
drivers/pci/hotplug/ibmphp_ebda.c +2 -1
@@ -1001,7 +1001,8 @@ static int __init ebda_rsrc_controller (void) tmp_slot = list_entry (list, struct slot, ibm_slot_list);snprintf (tmp_slot->hotplug_slot->name,30 ,"%s" ,create_file_name (tmp_slot)); -pci_hp_register (tmp_slot->hotplug_slot); +pci_hp_register (tmp_slot->hotplug_slot, +pci_find_bus (0 , tmp_slot->bus), tmp_slot->device); }print_ebda_hpc ();
drivers/pci/hotplug/pci_hotplug_core.c +97 -160
555 lines not on this page · raw message
drivers/pci/hotplug/pciehp_core.c +13 -18
@@ -69,7 +69,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);static int get_attention_status (struct hotplug_slot *slot,u8 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value); -static int get_address (struct hotplug_slot *slot,u32 *value);static int get_max_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);static int get_cur_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);
@@ -82,7 +81,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, };
@@ -245,14 +243,18 @@ static int init_slots(struct controller *ctrl)dbg ("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n" , slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval =pci_hp_register (hotplug_slot); + retval =pci_hp_register (hotplug_slot, + ctrl->pci_dev->subordinate, + slot->device); +if (retval == -EBUSY ) + goto error_info;if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_info; }/* create additional sysfs entries */ if (EMI (ctrl->ctrlcap)) { - retval =sysfs_create_file (&hotplug_slot->kobj, + retval =sysfs_create_file (&hotplug_slot->pci_slot->kobj, &hotplug_slot_attr_lock.attr);if (retval) {pci_hp_deregister (hotplug_slot);
@@ -285,7 +287,7 @@ static void cleanup_slots(struct controller *ctrl) slot = list_entry(tmp, struct slot, slot_list);list_del (&slot->slot_list);if (EMI (ctrl->ctrlcap)) -sysfs_remove_file (&slot->hotplug_slot->kobj, +sysfs_remove_file (&slot->hotplug_slot->pci_slot->kobj, &hotplug_slot_attr_lock.attr);cancel_delayed_work (&slot->work);flush_scheduled_work ();
@@ -387,18 +389,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } -static int get_address (struct hotplug_slot *hotplug_slot,u32 *value) -{ -struct slot *slot = hotplug_slot->private; -struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; - -dbg ("%s - physical_slot = %s\n" , __FUNCTION__, hotplug_slot->name); - - *value = (pci_domain_nr (bus) <<16 ) | (slot->bus <<8 ) | slot->device; - -return 0 ; -} -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot,enum pci_bus_speed *value) {struct slot *slot = hotplug_slot->private;
@@ -460,7 +450,12 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_/* Setup the slot information structures */ rc =init_slots (ctrl);if (rc) { -err ("%s: slot initialization failed\n" ,PCIE_MODULE_NAME ); +if (rc == -EBUSY ) +warn ("%s: slot already registered by another " +"hotplug driver\n" ,PCIE_MODULE_NAME ); +else +err ("%s: slot initialization failed\n" , +PCIE_MODULE_NAME ); goto err_out_release_ctlr; }
drivers/pci/hotplug/rpadlpar_sysfs.c +3 -2
@@ -14,8 +14,10 @@*/ #include <linux/kobject.h> #include <linux/string.h> +#include <linux/pci.h> #include <linux/pci_hotplug.h> #include "rpadlpar.h" +#include "../pcih." #define DLPAR_KOBJ_NAME "control"#define ADD_SLOT_ATTR_NAME "add_slot"
@@ -23,7 +25,6 @@#define MAX_DRC_NAME_LEN 64 -static ssize_t add_slot_store (struct kobject *kobj,struct kobj_attribute *attr,const char *buf,size_t nbytes) {
@@ -108,7 +109,7 @@ int dlpar_sysfs_init(void)int error; dlpar_kobj =kobject_create_and_add (DLPAR_KOBJ_NAME , - &pci_hotplug_slots_kset->kobj); + &pci_slots_kset->kobj);if (!dlpar_kobj)return -EINVAL ;
drivers/pci/hotplug/rpaphp_slot.c +2 -1
@@ -162,7 +162,8 @@ int rpaphp_register_slot(struct slot *slot)return -EAGAIN ; } - retval =pci_hp_register (php_slot); + retval =pci_hp_register (php_slot, slot->bus, +PCI_SLOT (PCI_DN (slot->dn->child)->devfn));if (retval) {err ("pci_hp_register failed with error %d\n" , retval);return retval;
drivers/pci/hotplug/sgi_hotplug.c +7 -3
@@ -197,13 +197,15 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,static struct hotplug_slot *sn_hp_destroy (void ) {struct slot *slot; +struct pci_slot *pci_slot;struct hotplug_slot *bss_hotplug_slot =NULL ;list_for_each_entry (slot, &sn_hp_list, hp_list) { bss_hotplug_slot = slot->hotplug_slot; + pci_slot = bss_hotplug_slot->pci_slot;list_del (&((struct slot *)bss_hotplug_slot->private)-> hp_list); -sysfs_remove_file (&bss_hotplug_slot->kobj, +sysfs_remove_file (&pci_slot->kobj, &sn_slot_path_attr.attr);break ; }
@@ -614,6 +616,7 @@ static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)static int sn_hotplug_slot_register (struct pci_bus *pci_bus) {int device; +struct pci_slot *pci_slot;struct hotplug_slot *bss_hotplug_slot;int rc =0 ;
@@ -650,11 +653,12 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) bss_hotplug_slot->ops = &sn_hotplug_slot_ops; bss_hotplug_slot->release = &sn_release_slot; - rc =pci_hp_register (bss_hotplug_slot); + rc =pci_hp_register (bss_hotplug_slot, pci_bus, device);if (rc) goto register_err; - rc =sysfs_create_file (&bss_hotplug_slot->kobj, + pci_slot = bss_hotplug_slot->pci_slot; + rc =sysfs_create_file (&pci_slot->kobj, &sn_slot_path_attr.attr);if (rc) goto register_err;
drivers/pci/hotplug/shpchp_core.c +2 -15
@@ -65,7 +65,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);static int get_attention_status (struct hotplug_slot *slot,u8 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value); -static int get_address (struct hotplug_slot *slot,u32 *value);static int get_max_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);static int get_cur_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);
@@ -78,7 +77,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, };
@@ -152,7 +150,8 @@ static int init_slots(struct controller *ctrl)dbg ("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n" , slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval =pci_hp_register (slot->hotplug_slot); + retval =pci_hp_register (slot->hotplug_slot, + ctrl->pci_dev->subordinate, slot->device);if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_info;
@@ -277,18 +276,6 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } -static int get_address (struct hotplug_slot *hotplug_slot,u32 *value) -{ -struct slot *slot =get_slot (hotplug_slot); -struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; - -dbg ("%s - physical_slot = %s\n" , __FUNCTION__, hotplug_slot->name); - - *value = (pci_domain_nr (bus) <<16 ) | (slot->bus <<8 ) | slot->device; - -return 0 ; -} -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot,enum pci_bus_speed *value) {struct slot *slot =get_slot (hotplug_slot);
drivers/pci/pci.h +13 -0
@@ -87,3 +87,16 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) }struct pci_dev *pci_find_upstream_pcie_bridge (struct pci_dev *pdev); + +/* PCI slot sysfs helper code */ +#define to_pci_slot (s) container_of(s, struct pci_slot, kobj) + +extern struct kset *pci_slots_kset; + +struct pci_slot_attribute { +struct attribute attr; +ssize_t (*show)(struct pci_slot *,char *); +ssize_t (*store)(struct pci_slot *,const char *,size_t ); +}; +#define to_pci_slot_attr (s) container_of(s, struct pci_slot_attribute, attr) +
drivers/pci/probe.c +1 -0
@@ -384,6 +384,7 @@ static struct pci_bus * pci_alloc_bus(void)INIT_LIST_HEAD (&b->node);INIT_LIST_HEAD (&b->children);INIT_LIST_HEAD (&b->devices); +INIT_LIST_HEAD (&b->slots); }return b; }
drivers/pci/slot.c new file +147 -0
147 lines not on this page · raw message
include/linux/pci.h +14 -0
@@ -128,6 +128,15 @@ struct pci_cap_saved_state {u32 data[0 ]; }; +/* pci_slot represents a physical slot */ +struct pci_slot { +struct pci_bus *bus;/* The bus this slot is on */ +struct list_head list;/* node in list of slots on this bus */ +struct hotplug_slot *hotplug;/* Hotplug info (migrate over time) */ +unsigned char number;/* PCI_SLOT(pci_dev->devfn) */ +struct kobject kobj; +}; +/* * The pci_dev structure is used to describe PCI devices. */
@@ -139,6 +148,7 @@ struct pci_dev {void *sysdata;/* hook for sys-specific extension */ struct proc_dir_entry *procent;/* device entry in /proc/bus/pci */ +struct pci_slot *slot;/* Physical slot this device is in */ unsigned int devfn;/* encoded device & function index */ unsigned short vendor;
@@ -258,6 +268,7 @@ struct pci_bus {struct list_head children;/* list of child buses */ struct list_head devices;/* list of devices on this bus */ struct pci_dev *self;/* bridge device as seen by parent */ +struct list_head slots;/* list of slots on this bus */ struct resource *resource[PCI_BUS_NUM_RESOURCES ];/* address space routed to this bus */
@@ -481,6 +492,9 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);struct pci_bus *pci_add_new_bus (struct pci_bus *parent,struct pci_dev *dev,int busnr); +struct pci_slot *pci_create_slot (struct pci_bus *parent,int slot_nr, +const char *name); +void pci_destroy_slot (struct pci_slot *slot);int pci_scan_slot (struct pci_bus *bus,int devfn);struct pci_dev *pci_scan_single_device (struct pci_bus *bus,int devfn);void pci_device_add (struct pci_dev *dev,struct pci_bus *bus);
include/linux/pci_hotplug.h +3 -9
@@ -95,9 +95,6 @@ struct hotplug_slot_attribute {* @get_adapter_status: Called to get see if an adapter is present in the slot or not. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. -* @get_address: Called to get pci address of a slot. -* If this field is NULL, the value passed in the struct hotplug_slot_info -* will be used when this value is requested by a user. * @get_max_bus_speed: Called to get the max bus speed for a slot. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user.
@@ -120,7 +117,6 @@ struct hotplug_slot_ops {int (*get_attention_status) (struct hotplug_slot *slot,u8 *value);int (*get_latch_status) (struct hotplug_slot *slot,u8 *value);int (*get_adapter_status) (struct hotplug_slot *slot,u8 *value); -int (*get_address) (struct hotplug_slot *slot,u32 *value);int (*get_max_bus_speed) (struct hotplug_slot *slot,enum pci_bus_speed *value);int (*get_cur_bus_speed) (struct hotplug_slot *slot,enum pci_bus_speed *value); };
@@ -140,7 +136,6 @@ struct hotplug_slot_info {u8 attention_status;u8 latch_status;u8 adapter_status; -u32 address;enum pci_bus_speed max_bus_speed;enum pci_bus_speed cur_bus_speed; };
@@ -166,15 +161,14 @@ struct hotplug_slot {/* Variables below this are for use only by the hotplug pci core. */ struct list_head slot_list; -struct kobject kobj; +struct pci_slot *pci_slot; };#define to_hotplug_slot (n) container_of(n, struct hotplug_slot, kobj) -extern int pci_hp_register (struct hotplug_slot *slot); -extern int pci_hp_deregister (struct hotplug_slot *slot); +extern int pci_hp_register (struct hotplug_slot *,struct pci_bus *,int nr); +extern int pci_hp_deregister (struct hotplug_slot *slot);extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,struct hotplug_slot_info *info); -extern struct kset *pci_hotplug_slots_kset;/* PCI Setting Record (Type 0) */ struct hpp_type0 {
Signature · 1 line
1.5.3.1.g1e61
PATCH v12 3/4 Introduce pci_slot
In reply to Alex ChiangCurrently, /sys/bus/pci/slots/ only exposes hotplug attributes when a hotplug driver is loaded, but PCI slots have attributes such as address, speed, width, etc. that are not related to hotplug at all.
Introduce pci_slot as the primary data structure and kobject model. Hotplug attributes described in hotplug_slot become a secondary structure associated with the pci_slot.
This patch only creates the infrastructure that allows the separation of PCI slot attributes and hotplug attributes. In this patch, the PCI hotplug core remains the only user of this infrastructure, and thus, /sys/bus/pci/slots/ will still only become populated when a hotplug driver is loaded.
A later patch in this series will add a second user of this new infrastructure and demonstrate splitting the task of exposing pci_slot attributes from hotplug_slot attributes.
- Make pci_slot the primary sysfs entity. hotplug_slot becomes a subsidiary structure.
o pci_create_slot() creates and registers a slot with the PCI core
o pci_slot_add_hotplug() gives it hotplug capability
- Change the prototype of pci_hp_register() to take the bus and slot number (on parent bus) as parameters.
- Remove all the ->get_address methods since this functionality is now handled by pci_slot directly.
v10 -> v12:
Thanks to Kenji Kaneshige for the following updates
- Add missing semaphore for slot release
- Use list_head for pci slot list
- Replace dbg with pr_debug
- Remove useless release handler
- Use .default_attrs for address file
- Fix return value of pci_create_slot()
- Change return value of pci_destroy_slot()
- Trivial cleanups for slot.c
- add missing lock for hotplug slot list
v9 -> v10:
No change
v8 -> v9:
Fixed printk output, changed to American spelling of "initialization"
v7 -> v8:
Removed externs from C files.
Taught sn_hp_destroy and sn_hotplug_slot_register about struct pci_slot.
v6 -> v7:
Refresh to new kobject model.
v5 -> v6:
Add debugging information.
v4 -> v5:
Add refcounting for pci_slot objects.
Return -EBUSY if an hp driver attempts to register a slot that is already registered to another driver. Do not consider that to be an error condition in acpiphp and pciehp.
v3 -> v4:
Fixed bug with pciehp and rpaphp registering slots
v2 -> v3:
Separated slot creation and slot hotplug ability into two interfaces. Fixed bugs in pci_destroy_slot(), and now properly calling from pci_hp_deregister.
v1 -> v2:
No change
--- drivers/pci/Makefile | 2 +- drivers/pci/hotplug/acpiphp.h | 1 - drivers/pci/hotplug/acpiphp_core.c | 25 +--- drivers/pci/hotplug/acpiphp_glue.c | 23 +-- drivers/pci/hotplug/acpiphp_ibm.c | 6 +- drivers/pci/hotplug/cpci_hotplug_core.c | 2 +- drivers/pci/hotplug/cpqphp_core.c | 4 +- drivers/pci/hotplug/fakephp.c | 2 +- drivers/pci/hotplug/ibmphp_ebda.c | 3 +- drivers/pci/hotplug/pci_hotplug_core.c | 257 ++++++++++++------------------- drivers/pci/hotplug/pciehp_core.c | 31 ++-- drivers/pci/hotplug/rpadlpar_sysfs.c | 5 +- drivers/pci/hotplug/rpaphp_slot.c | 3 +- drivers/pci/hotplug/sgi_hotplug.c | 10 +- drivers/pci/hotplug/shpchp_core.c | 17 +-- drivers/pci/pci.h | 13 ++ drivers/pci/probe.c | 1 + drivers/pci/slot.c | 147 ++++++++++++++++++ include/linux/pci.h | 14 ++ include/linux/pci_hotplug.h | 12 +- 20 files changed, 325 insertions(+), 253 deletions(-) create mode 100644 drivers/pci/slot.c
drivers/pci/Makefile +1 -1
@@ -2,7 +2,7 @@ # Makefile for the PCI bus specific drivers. # -obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ +obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o obj-$(CONFIG_PROC_FS) += proc.o
drivers/pci/hotplug/acpiphp.h +0 -1
@@ -215,7 +215,6 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); -extern u32 acpiphp_get_address (struct acpiphp_slot *slot);/* variables */ extern int acpiphp_debug;
drivers/pci/hotplug/acpiphp_core.c +5 -20
@@ -70,7 +70,6 @@ static int disable_slot (struct hotplug_slot *slot);static int set_attention_status (struct hotplug_slot *slot,u8 value);static int get_power_status (struct hotplug_slot *slot,u8 *value);static int get_attention_status (struct hotplug_slot *slot,u8 *value); -static int get_address (struct hotplug_slot *slot,u32 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value);
@@ -83,7 +82,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_address = get_address, };
@@ -274,23 +272,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } - -/** -* get_address - get pci address of a slot -* @hotplug_slot: slot to get status -* @value: pointer to struct pci_busdev (seg, bus, dev) -*/ -static int get_address (struct hotplug_slot *hotplug_slot,u32 *value) -{ -struct slot *slot = hotplug_slot->private; - -dbg ("%s - physical_slot = %s\n" , __FUNCTION__, hotplug_slot->name); - - *value =acpiphp_get_address (slot->acpi_slot); - -return 0 ; -} -static int __init init_acpi (void ) {int retval;
@@ -357,7 +338,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) acpiphp_slot->slot = slot;snprintf (slot->name,sizeof (slot->name),"%u" , slot->acpi_slot->sun); - retval =pci_hp_register (slot->hotplug_slot); + retval =pci_hp_register (slot->hotplug_slot, + acpiphp_slot->bridge->pci_bus, + acpiphp_slot->device); +if (retval == -EBUSY ) + goto error_hpslot;if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_hpslot;
drivers/pci/hotplug/acpiphp_glue.c +6 -17
@@ -258,7 +258,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) bridge->pci_bus->number, slot->device); retval =acpiphp_register_hotplug_slot (slot);if (retval) { -warn ("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n" , retval); +if (retval == -EBUSY ) +warn ("Slot %d already registered by another " +"hotplug driver\n" , slot->sun); +else +warn ("acpiphp_register_hotplug_slot failed " +"(err code = 0x%x)\n" , retval); goto err_exit; } }
@@ -1867,19 +1872,3 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)return (sta ==0 ) ?0 :1 ; } - - -/* -* pci address (seg/bus/dev) -*/ -u32 acpiphp_get_address (struct acpiphp_slot *slot) -{ -u32 address; -struct pci_bus *pci_bus = slot->bridge->pci_bus; - - address = (pci_domain_nr (pci_bus) <<16 ) | - (pci_bus->number <<8 ) | - slot->device; - -return address; -}
drivers/pci/hotplug/acpiphp_ibm.c +4 -2
@@ -33,8 +33,10 @@#include <linux/kobject.h> #include <asm/uaccess.h> #include <linux/moduleparam.h> +#include <linux/pci.h> #include "acpiphp.h" +#include "../pci.h" #define DRIVER_VERSION "1.0.1"#define DRIVER_AUTHOR "Irene Zubarev <[email protected]>, Vernon Mauery <[email protected]>"
@@ -430,7 +432,7 @@ static int __init ibm_acpiphp_init(void)int retval =0 ;acpi_status status;struct acpi_device *device; -struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; +struct kobject *sysdir = &pci_slots_kset->kobj;dbg ("%s\n" , __FUNCTION__);
@@ -477,7 +479,7 @@ init_return: static void __exit ibm_acpiphp_exit(void) {acpi_status status; -struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; +struct kobject *sysdir = &pci_slots_kset->kobj;dbg ("%s\n" , __FUNCTION__);
drivers/pci/hotplug/cpci_hotplug_core.c +1 -1
@@ -285,7 +285,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) info->attention_status =cpci_get_attention_status (slot);dbg ("registering slot %s" , slot->hotplug_slot->name); - status =pci_hp_register (slot->hotplug_slot); + status =pci_hp_register (slot->hotplug_slot, bus, i);if (status) {err ("pci_hp_register failed with error %d" , status); goto error_name;
drivers/pci/hotplug/cpqphp_core.c +3 -1
@@ -434,7 +434,9 @@ static int ctrl_slot_setup(struct controller *ctrl, slot->bus, slot->device, slot->number, ctrl->slot_device_offset, slot_number); - result =pci_hp_register (hotplug_slot); + result =pci_hp_register (hotplug_slot, + ctrl->pci_dev->subordinate, + slot->device);if (result) {err ("pci_hp_register failed with error %d\n" , result); goto error_name;
drivers/pci/hotplug/fakephp.c +1 -1
@@ -127,7 +127,7 @@ static int add_slot(struct pci_dev *dev) slot->release = &dummy_release; slot->private = dslot; - retval =pci_hp_register (slot); + retval =pci_hp_register (slot, dev->bus,PCI_SLOT (dev->devfn));if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_dslot;
drivers/pci/hotplug/ibmphp_ebda.c +2 -1
@@ -1001,7 +1001,8 @@ static int __init ebda_rsrc_controller (void) tmp_slot = list_entry (list, struct slot, ibm_slot_list);snprintf (tmp_slot->hotplug_slot->name,30 ,"%s" ,create_file_name (tmp_slot)); -pci_hp_register (tmp_slot->hotplug_slot); +pci_hp_register (tmp_slot->hotplug_slot, +pci_find_bus (0 , tmp_slot->bus), tmp_slot->device); }print_ebda_hpc ();
drivers/pci/hotplug/pci_hotplug_core.c +97 -160
555 lines not on this page · raw message
drivers/pci/hotplug/pciehp_core.c +13 -18
@@ -69,7 +69,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);static int get_attention_status (struct hotplug_slot *slot,u8 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value); -static int get_address (struct hotplug_slot *slot,u32 *value);static int get_max_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);static int get_cur_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);
@@ -82,7 +81,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, };
@@ -245,14 +243,18 @@ static int init_slots(struct controller *ctrl)dbg ("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n" , slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval =pci_hp_register (hotplug_slot); + retval =pci_hp_register (hotplug_slot, + ctrl->pci_dev->subordinate, + slot->device); +if (retval == -EBUSY ) + goto error_info;if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_info; }/* create additional sysfs entries */ if (EMI (ctrl->ctrlcap)) { - retval =sysfs_create_file (&hotplug_slot->kobj, + retval =sysfs_create_file (&hotplug_slot->pci_slot->kobj, &hotplug_slot_attr_lock.attr);if (retval) {pci_hp_deregister (hotplug_slot);
@@ -285,7 +287,7 @@ static void cleanup_slots(struct controller *ctrl) slot = list_entry(tmp, struct slot, slot_list);list_del (&slot->slot_list);if (EMI (ctrl->ctrlcap)) -sysfs_remove_file (&slot->hotplug_slot->kobj, +sysfs_remove_file (&slot->hotplug_slot->pci_slot->kobj, &hotplug_slot_attr_lock.attr);cancel_delayed_work (&slot->work);flush_scheduled_work ();
@@ -387,18 +389,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } -static int get_address (struct hotplug_slot *hotplug_slot,u32 *value) -{ -struct slot *slot = hotplug_slot->private; -struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; - -dbg ("%s - physical_slot = %s\n" , __FUNCTION__, hotplug_slot->name); - - *value = (pci_domain_nr (bus) <<16 ) | (slot->bus <<8 ) | slot->device; - -return 0 ; -} -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot,enum pci_bus_speed *value) {struct slot *slot = hotplug_slot->private;
@@ -460,7 +450,12 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_/* Setup the slot information structures */ rc =init_slots (ctrl);if (rc) { -err ("%s: slot initialization failed\n" ,PCIE_MODULE_NAME ); +if (rc == -EBUSY ) +warn ("%s: slot already registered by another " +"hotplug driver\n" ,PCIE_MODULE_NAME ); +else +err ("%s: slot initialization failed\n" , +PCIE_MODULE_NAME ); goto err_out_release_ctlr; }
drivers/pci/hotplug/rpadlpar_sysfs.c +3 -2
@@ -14,8 +14,10 @@*/ #include <linux/kobject.h> #include <linux/string.h> +#include <linux/pci.h> #include <linux/pci_hotplug.h> #include "rpadlpar.h" +#include "../pcih." #define DLPAR_KOBJ_NAME "control"#define ADD_SLOT_ATTR_NAME "add_slot"
@@ -23,7 +25,6 @@#define MAX_DRC_NAME_LEN 64 -static ssize_t add_slot_store (struct kobject *kobj,struct kobj_attribute *attr,const char *buf,size_t nbytes) {
@@ -108,7 +109,7 @@ int dlpar_sysfs_init(void)int error; dlpar_kobj =kobject_create_and_add (DLPAR_KOBJ_NAME , - &pci_hotplug_slots_kset->kobj); + &pci_slots_kset->kobj);if (!dlpar_kobj)return -EINVAL ;
drivers/pci/hotplug/rpaphp_slot.c +2 -1
@@ -162,7 +162,8 @@ int rpaphp_register_slot(struct slot *slot)return -EAGAIN ; } - retval =pci_hp_register (php_slot); + retval =pci_hp_register (php_slot, slot->bus, +PCI_SLOT (PCI_DN (slot->dn->child)->devfn));if (retval) {err ("pci_hp_register failed with error %d\n" , retval);return retval;
drivers/pci/hotplug/sgi_hotplug.c +7 -3
@@ -197,13 +197,15 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,static struct hotplug_slot *sn_hp_destroy (void ) {struct slot *slot; +struct pci_slot *pci_slot;struct hotplug_slot *bss_hotplug_slot =NULL ;list_for_each_entry (slot, &sn_hp_list, hp_list) { bss_hotplug_slot = slot->hotplug_slot; + pci_slot = bss_hotplug_slot->pci_slot;list_del (&((struct slot *)bss_hotplug_slot->private)-> hp_list); -sysfs_remove_file (&bss_hotplug_slot->kobj, +sysfs_remove_file (&pci_slot->kobj, &sn_slot_path_attr.attr);break ; }
@@ -614,6 +616,7 @@ static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)static int sn_hotplug_slot_register (struct pci_bus *pci_bus) {int device; +struct pci_slot *pci_slot;struct hotplug_slot *bss_hotplug_slot;int rc =0 ;
@@ -650,11 +653,12 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) bss_hotplug_slot->ops = &sn_hotplug_slot_ops; bss_hotplug_slot->release = &sn_release_slot; - rc =pci_hp_register (bss_hotplug_slot); + rc =pci_hp_register (bss_hotplug_slot, pci_bus, device);if (rc) goto register_err; - rc =sysfs_create_file (&bss_hotplug_slot->kobj, + pci_slot = bss_hotplug_slot->pci_slot; + rc =sysfs_create_file (&pci_slot->kobj, &sn_slot_path_attr.attr);if (rc) goto register_err;
drivers/pci/hotplug/shpchp_core.c +2 -15
@@ -65,7 +65,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);static int get_attention_status (struct hotplug_slot *slot,u8 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value); -static int get_address (struct hotplug_slot *slot,u32 *value);static int get_max_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);static int get_cur_bus_speed (struct hotplug_slot *slot,enum pci_bus_speed *value);
@@ -78,7 +77,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, };
@@ -152,7 +150,8 @@ static int init_slots(struct controller *ctrl)dbg ("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n" , slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval =pci_hp_register (slot->hotplug_slot); + retval =pci_hp_register (slot->hotplug_slot, + ctrl->pci_dev->subordinate, slot->device);if (retval) {err ("pci_hp_register failed with error %d\n" , retval); goto error_info;
@@ -277,18 +276,6 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } -static int get_address (struct hotplug_slot *hotplug_slot,u32 *value) -{ -struct slot *slot =get_slot (hotplug_slot); -struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; - -dbg ("%s - physical_slot = %s\n" , __FUNCTION__, hotplug_slot->name); - - *value = (pci_domain_nr (bus) <<16 ) | (slot->bus <<8 ) | slot->device; - -return 0 ; -} -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot,enum pci_bus_speed *value) {struct slot *slot =get_slot (hotplug_slot);
drivers/pci/pci.h +13 -0
@@ -87,3 +87,16 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) }struct pci_dev *pci_find_upstream_pcie_bridge (struct pci_dev *pdev); + +/* PCI slot sysfs helper code */ +#define to_pci_slot (s) container_of(s, struct pci_slot, kobj) + +extern struct kset *pci_slots_kset; + +struct pci_slot_attribute { +struct attribute attr; +ssize_t (*show)(struct pci_slot *,char *); +ssize_t (*store)(struct pci_slot *,const char *,size_t ); +}; +#define to_pci_slot_attr (s) container_of(s, struct pci_slot_attribute, attr) +
drivers/pci/probe.c +1 -0
@@ -384,6 +384,7 @@ static struct pci_bus * pci_alloc_bus(void)INIT_LIST_HEAD (&b->node);INIT_LIST_HEAD (&b->children);INIT_LIST_HEAD (&b->devices); +INIT_LIST_HEAD (&b->slots); }return b; }
drivers/pci/slot.c new file +147 -0
147 lines not on this page · raw message
include/linux/pci.h +14 -0
@@ -128,6 +128,15 @@ struct pci_cap_saved_state {u32 data[0 ]; }; +/* pci_slot represents a physical slot */ +struct pci_slot { +struct pci_bus *bus;/* The bus this slot is on */ +struct list_head list;/* node in list of slots on this bus */ +struct hotplug_slot *hotplug;/* Hotplug info (migrate over time) */ +unsigned char number;/* PCI_SLOT(pci_dev->devfn) */ +struct kobject kobj; +}; +/* * The pci_dev structure is used to describe PCI devices. */
@@ -139,6 +148,7 @@ struct pci_dev {void *sysdata;/* hook for sys-specific extension */ struct proc_dir_entry *procent;/* device entry in /proc/bus/pci */ +struct pci_slot *slot;/* Physical slot this device is in */ unsigned int devfn;/* encoded device & function index */ unsigned short vendor;
@@ -258,6 +268,7 @@ struct pci_bus {struct list_head children;/* list of child buses */ struct list_head devices;/* list of devices on this bus */ struct pci_dev *self;/* bridge device as seen by parent */ +struct list_head slots;/* list of slots on this bus */ struct resource *resource[PCI_BUS_NUM_RESOURCES ];/* address space routed to this bus */
@@ -481,6 +492,9 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);struct pci_bus *pci_add_new_bus (struct pci_bus *parent,struct pci_dev *dev,int busnr); +struct pci_slot *pci_create_slot (struct pci_bus *parent,int slot_nr, +const char *name); +void pci_destroy_slot (struct pci_slot *slot);int pci_scan_slot (struct pci_bus *bus,int devfn);struct pci_dev *pci_scan_single_device (struct pci_bus *bus,int devfn);void pci_device_add (struct pci_dev *dev,struct pci_bus *bus);
include/linux/pci_hotplug.h +3 -9
@@ -95,9 +95,6 @@ struct hotplug_slot_attribute {* @get_adapter_status: Called to get see if an adapter is present in the slot or not. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. -* @get_address: Called to get pci address of a slot. -* If this field is NULL, the value passed in the struct hotplug_slot_info -* will be used when this value is requested by a user. * @get_max_bus_speed: Called to get the max bus speed for a slot. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user.
@@ -120,7 +117,6 @@ struct hotplug_slot_ops {int (*get_attention_status) (struct hotplug_slot *slot,u8 *value);int (*get_latch_status) (struct hotplug_slot *slot,u8 *value);int (*get_adapter_status) (struct hotplug_slot *slot,u8 *value); -int (*get_address) (struct hotplug_slot *slot,u32 *value);int (*get_max_bus_speed) (struct hotplug_slot *slot,enum pci_bus_speed *value);int (*get_cur_bus_speed) (struct hotplug_slot *slot,enum pci_bus_speed *value); };
@@ -140,7 +136,6 @@ struct hotplug_slot_info {u8 attention_status;u8 latch_status;u8 adapter_status; -u32 address;enum pci_bus_speed max_bus_speed;enum pci_bus_speed cur_bus_speed; };
@@ -166,15 +161,14 @@ struct hotplug_slot {/* Variables below this are for use only by the hotplug pci core. */ struct list_head slot_list; -struct kobject kobj; +struct pci_slot *pci_slot; };#define to_hotplug_slot (n) container_of(n, struct hotplug_slot, kobj) -extern int pci_hp_register (struct hotplug_slot *slot); -extern int pci_hp_deregister (struct hotplug_slot *slot); +extern int pci_hp_register (struct hotplug_slot *,struct pci_bus *,int nr); +extern int pci_hp_deregister (struct hotplug_slot *slot);extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,struct hotplug_slot_info *info); -extern struct kset *pci_hotplug_slots_kset;/* PCI Setting Record (Type 0) */ struct hpp_type0 {
Signature · 1 line
1.5.3.1.g1e61
PATCH v12 4/4 ACPI PCI slot detection driver
In reply to Alex ChiangDetect all physical PCI slots as described by ACPI, and create entries in /sys/bus/pci/slots/.
Not all physical slots are hotpluggable, and the acpiphp module does not detect them. Now we know the physical PCI geography of our system, without caring about hotplug.
v10 -> v12:
Thanks to Kenji Kaneshige for the following updates:
- Fix dmi table for Fujitsu PRIMEQUEST
- Fix _STA evaluation
- Use list_head for pci slot list
- Fix slot removal path
v9 -> v10:
Allow an hp driver to override the pci_slot kobject name.
v8 -> v9:
Add DMI quirk for Fujitsu machines; eval _STA before _SUN
v6 -> v8:
No change
v5 -> v6:
Add debugging information.
v4 -> v5:
Convert to a tristate module.
Remove #ifdef CONFIG_ACPI_PCI_SLOT, as struct pci_slot objects are properly refcounted, and multiple calls to pci_create/destroy_slot work just fine.
Remove prior -EBUSY changes, as they have been folded into the Introduce pci_slot patch.
v3 -> v4:
Always attempt to call pci_create_slot from pcihp_core to cover cases of
a) user did not say Y to Kconfig option ACPI_PCI_SLOT
b) native PCIe hotplug driver registering on a non-ACPI system.
Return -EBUSY if an hp driver attempts to register a slot that is already registered to another driver. Do not consider that to be an error condition in acpiphp and pciehp.
v2 -> v3:
Add Kconfig option to driver, allowing users to [de]config this driver. If configured, take slightly different code paths in pci_hp_register and pci_hp_deregister.
v1 -> v2:
Now recursively discovering p2p bridges and slots underneath them. Hopefully, this will prevent us from trying to register the same slot multiple times.
--- drivers/acpi/Kconfig | 9 + drivers/acpi/Makefile | 1 + drivers/acpi/pci_slot.c | 370 ++++++++++++++++++++++++++++++++ drivers/pci/hotplug/pci_hotplug_core.c | 16 ++ drivers/pci/hotplug/pciehp_core.c | 2 +- drivers/pci/hotplug/sgi_hotplug.c | 2 +- 6 files changed, 398 insertions(+), 2 deletions(-) create mode 100644 drivers/acpi/pci_slot.c
drivers/acpi/Kconfig +9 -0
@@ -335,6 +335,15 @@ config ACPI_EC the battery and thermal drivers. If you are compiling for a mobile system, say Y. +config ACPI_PCI_SLOT + tristate "PCI slot detection driver" + default n + help + This driver will attempt to discover all PCI slots in your system, + and creates entries in /sys/bus/pci/slots/. This feature can + help you correlate PCI bus addresses with the physical geography + of your slots. If you are unsure, say N. + config ACPI_POWER bool default y
drivers/acpi/Makefile +1 -0
@@ -48,6 +48,7 @@ obj-$(CONFIG_ACPI_DOCK) += dock.o obj-$(CONFIG_ACPI_BAY) += bay.o obj-$(CONFIG_ACPI_VIDEO) += video.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_CONTAINER) += container.o
drivers/acpi/pci_slot.c new file +370 -0
370 lines not on this page · raw message
drivers/pci/hotplug/pci_hotplug_core.c +16 -0
@@ -566,6 +566,11 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)return -EINVAL ; } +/* +* No problems if we call this interface from both ACPI_PCI_SLOT +* driver and call it here again. If we've already created the +* pci_slot, the interface will simply bump the refcount. +*/ pci_slot =pci_create_slot (bus, slot_nr, slot->name);if (IS_ERR (pci_slot))return PTR_ERR (pci_slot);
@@ -579,6 +584,17 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr) slot->pci_slot = pci_slot; pci_slot->hotplug = slot; +/* +* Allow pcihp drivers to override the ACPI_PCI_SLOT name. +*/ +if (strcmp (kobject_name (&pci_slot->kobj), slot->name)) { + result =kobject_rename (&pci_slot->kobj, slot->name); +if (result) { +pci_destroy_slot (pci_slot); +return result; + } + } +spin_lock (&pci_hotplug_slot_list_lock);list_add (&slot->slot_list, &pci_hotplug_slot_list);spin_unlock (&pci_hotplug_slot_list_lock);
drivers/pci/hotplug/pciehp_core.c +1 -1
@@ -249,7 +249,7 @@ static int init_slots(struct controller *ctrl)if (retval == -EBUSY ) goto error_info;if (retval) { -err ("pci_hp_register failed with error %d\n" , retval); +err ("pci_hp_register failed with error %d\n" , retval); goto error_info; }/* create additional sysfs entries */
drivers/pci/hotplug/sgi_hotplug.c +1 -1
@@ -668,7 +668,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) register_err:dev_dbg (&pci_bus->self->dev,"bus failed to register with err = %d\n" , - rc); + rc); alloc_err:if (rc == -ENOMEM )
Signature · 1 line
1.5.3.1.g1e61