Commit d6a9e9b4 authored by Alex Chiang's avatar Alex Chiang Committed by Jesse Barnes

PCI: shpchp: Rename duplicate slot name N as N-1, N-2, N-M...

Commit ef0ff95f (shpchp: fix slot name)
introduces the shpchp_slot_with_bus module parameter, which was intended
to help work around broken firmware that assigns the same name to multiple
slots.

Commit b3bd307c (shpchp: add message about
shpchp_slot_with_bus option) tells the user to use the above parameter
in the event of a name collision.

This approach is sub-optimal because it requires too much work from
the user.

Instead, let's rename the slot on behalf of the user. If firmware
assigns the name N to multiple slots, then:

	The first registered slot is assigned N
	The second registered slot is assigned N-1
	The third registered slot is assigned N-2
	The Mth registered slot becomes N-M

In the event we overflow the slot->name parameter, we report an
error to the user.

This is a temporary fix until the entire PCI core can be reworked
such that individual drivers no longer have to manage their own
slot names.
Tested-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Acked-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 167e782e
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
int shpchp_debug; int shpchp_debug;
int shpchp_poll_mode; int shpchp_poll_mode;
int shpchp_poll_time; int shpchp_poll_time;
static int shpchp_slot_with_bus;
struct workqueue_struct *shpchp_wq; struct workqueue_struct *shpchp_wq;
#define DRIVER_VERSION "0.4" #define DRIVER_VERSION "0.4"
...@@ -53,11 +52,9 @@ MODULE_LICENSE("GPL"); ...@@ -53,11 +52,9 @@ MODULE_LICENSE("GPL");
module_param(shpchp_debug, bool, 0644); module_param(shpchp_debug, bool, 0644);
module_param(shpchp_poll_mode, bool, 0644); module_param(shpchp_poll_mode, bool, 0644);
module_param(shpchp_poll_time, int, 0644); module_param(shpchp_poll_time, int, 0644);
module_param(shpchp_slot_with_bus, bool, 0644);
MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name");
#define SHPC_MODULE_NAME "shpchp" #define SHPC_MODULE_NAME "shpchp"
...@@ -99,23 +96,13 @@ static void release_slot(struct hotplug_slot *hotplug_slot) ...@@ -99,23 +96,13 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
kfree(slot); kfree(slot);
} }
static void make_slot_name(struct slot *slot)
{
if (shpchp_slot_with_bus)
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
slot->bus, slot->number);
else
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
slot->number);
}
static int init_slots(struct controller *ctrl) static int init_slots(struct controller *ctrl)
{ {
struct slot *slot; struct slot *slot;
struct hotplug_slot *hotplug_slot; struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info; struct hotplug_slot_info *info;
int retval = -ENOMEM; int retval = -ENOMEM;
int i; int i, len, dup = 1;
for (i = 0; i < ctrl->num_slots; i++) { for (i = 0; i < ctrl->num_slots; i++) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL); slot = kzalloc(sizeof(*slot), GFP_KERNEL);
...@@ -146,7 +133,7 @@ static int init_slots(struct controller *ctrl) ...@@ -146,7 +133,7 @@ static int init_slots(struct controller *ctrl)
/* register this slot with the hotplug pci core */ /* register this slot with the hotplug pci core */
hotplug_slot->private = slot; hotplug_slot->private = slot;
hotplug_slot->release = &release_slot; hotplug_slot->release = &release_slot;
make_slot_name(slot); snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
hotplug_slot->ops = &shpchp_hotplug_slot_ops; hotplug_slot->ops = &shpchp_hotplug_slot_ops;
get_power_status(hotplug_slot, &info->power_status); get_power_status(hotplug_slot, &info->power_status);
...@@ -157,14 +144,23 @@ static int init_slots(struct controller *ctrl) ...@@ -157,14 +144,23 @@ static int init_slots(struct controller *ctrl)
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
"slot_device_offset=%x\n", slot->bus, slot->device, "slot_device_offset=%x\n", slot->bus, slot->device,
slot->hp_slot, slot->number, ctrl->slot_device_offset); slot->hp_slot, slot->number, ctrl->slot_device_offset);
duplicate_name:
retval = pci_hp_register(slot->hotplug_slot, retval = pci_hp_register(slot->hotplug_slot,
ctrl->pci_dev->subordinate, slot->device); ctrl->pci_dev->subordinate, slot->device);
if (retval) { if (retval) {
/*
* If slot N already exists, we'll try to create
* slot N-1, N-2 ... N-M, until we overflow.
*/
if (retval == -EEXIST) {
len = snprintf(slot->name, SLOT_NAME_SIZE,
"%d-%d", slot->number, dup++);
if (len < SLOT_NAME_SIZE)
goto duplicate_name;
else
err("duplicate slot name overflow\n");
}
err("pci_hp_register failed with error %d\n", retval); err("pci_hp_register failed with error %d\n", retval);
if (retval == -EEXIST)
err("Failed to register slot because of name "
"collision. Try \'shpchp_slot_with_bus\' "
"module option.\n");
goto error_info; goto error_info;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment