diff options
| author | Alex Chiang <achiang@hp.com> | 2008-08-21 17:13:29 -0400 |
|---|---|---|
| committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-08-21 18:15:10 -0400 |
| commit | 167e782e301188c7c7e31e486bbeea5f918324c1 (patch) | |
| tree | c226d2a2de10ff6d437505ac05ea55ae897a83cc | |
| parent | 6a55617ed5d1aa62b850de2cf66f5ede2eef4825 (diff) | |
PCI: pciehp: Rename duplicate slot name N as N-1, N-2, N-M...
Commit 3800345f723fd130d50434d4717b99d4a9f383c8 (pciehp: fix slot name)
introduces the pciehp_slot_with_bus module parameter, which was intended
to help work around broken firmware that assigns the same name to multiple
slots.
Commit 9e4f2e8d4ddb04ad16a3828cd9a369a5a5287009 (pciehp: add message about
pciehp_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: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Acked-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
| -rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 21 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 11 |
3 files changed, 15 insertions, 18 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e3a1e7e7dba2..9e6cec67e1cc 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -43,7 +43,6 @@ extern int pciehp_poll_mode; | |||
| 43 | extern int pciehp_poll_time; | 43 | extern int pciehp_poll_time; |
| 44 | extern int pciehp_debug; | 44 | extern int pciehp_debug; |
| 45 | extern int pciehp_force; | 45 | extern int pciehp_force; |
| 46 | extern int pciehp_slot_with_bus; | ||
| 47 | extern struct workqueue_struct *pciehp_wq; | 46 | extern struct workqueue_struct *pciehp_wq; |
| 48 | 47 | ||
| 49 | #define dbg(format, arg...) \ | 48 | #define dbg(format, arg...) \ |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 3677495c4f91..4fd5355bc3b5 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -41,7 +41,6 @@ int pciehp_debug; | |||
| 41 | int pciehp_poll_mode; | 41 | int pciehp_poll_mode; |
| 42 | int pciehp_poll_time; | 42 | int pciehp_poll_time; |
| 43 | int pciehp_force; | 43 | int pciehp_force; |
| 44 | int pciehp_slot_with_bus; | ||
| 45 | struct workqueue_struct *pciehp_wq; | 44 | struct workqueue_struct *pciehp_wq; |
| 46 | 45 | ||
| 47 | #define DRIVER_VERSION "0.4" | 46 | #define DRIVER_VERSION "0.4" |
| @@ -56,12 +55,10 @@ module_param(pciehp_debug, bool, 0644); | |||
| 56 | module_param(pciehp_poll_mode, bool, 0644); | 55 | module_param(pciehp_poll_mode, bool, 0644); |
| 57 | module_param(pciehp_poll_time, int, 0644); | 56 | module_param(pciehp_poll_time, int, 0644); |
| 58 | module_param(pciehp_force, bool, 0644); | 57 | module_param(pciehp_force, bool, 0644); |
| 59 | module_param(pciehp_slot_with_bus, bool, 0644); | ||
| 60 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); | 58 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); |
| 61 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); | 59 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); |
| 62 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); | 60 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); |
| 63 | MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); | 61 | MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); |
| 64 | MODULE_PARM_DESC(pciehp_slot_with_bus, "Use bus number in the slot name"); | ||
| 65 | 62 | ||
| 66 | #define PCIE_MODULE_NAME "pciehp" | 63 | #define PCIE_MODULE_NAME "pciehp" |
| 67 | 64 | ||
| @@ -194,6 +191,7 @@ static int init_slots(struct controller *ctrl) | |||
| 194 | struct slot *slot; | 191 | struct slot *slot; |
| 195 | struct hotplug_slot *hotplug_slot; | 192 | struct hotplug_slot *hotplug_slot; |
| 196 | struct hotplug_slot_info *info; | 193 | struct hotplug_slot_info *info; |
| 194 | int len, dup = 1; | ||
| 197 | int retval = -ENOMEM; | 195 | int retval = -ENOMEM; |
| 198 | 196 | ||
| 199 | list_for_each_entry(slot, &ctrl->slot_list, slot_list) { | 197 | list_for_each_entry(slot, &ctrl->slot_list, slot_list) { |
| @@ -220,15 +218,24 @@ static int init_slots(struct controller *ctrl) | |||
| 220 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " | 218 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " |
| 221 | "slot_device_offset=%x\n", slot->bus, slot->device, | 219 | "slot_device_offset=%x\n", slot->bus, slot->device, |
| 222 | slot->hp_slot, slot->number, ctrl->slot_device_offset); | 220 | slot->hp_slot, slot->number, ctrl->slot_device_offset); |
| 221 | duplicate_name: | ||
| 223 | retval = pci_hp_register(hotplug_slot, | 222 | retval = pci_hp_register(hotplug_slot, |
| 224 | ctrl->pci_dev->subordinate, | 223 | ctrl->pci_dev->subordinate, |
| 225 | slot->device); | 224 | slot->device); |
| 226 | if (retval) { | 225 | if (retval) { |
| 226 | /* | ||
| 227 | * If slot N already exists, we'll try to create | ||
| 228 | * slot N-1, N-2 ... N-M, until we overflow. | ||
| 229 | */ | ||
| 230 | if (retval == -EEXIST) { | ||
| 231 | len = snprintf(slot->name, SLOT_NAME_SIZE, | ||
| 232 | "%d-%d", slot->number, dup++); | ||
| 233 | if (len < SLOT_NAME_SIZE) | ||
| 234 | goto duplicate_name; | ||
| 235 | else | ||
| 236 | err("duplicate slot name overflow\n"); | ||
| 237 | } | ||
| 227 | err("pci_hp_register failed with error %d\n", retval); | 238 | err("pci_hp_register failed with error %d\n", retval); |
| 228 | if (retval == -EEXIST) | ||
| 229 | err("Failed to register slot because of name " | ||
| 230 | "collision. Try \'pciehp_slot_with_bus\' " | ||
| 231 | "module option.\n"); | ||
| 232 | goto error_info; | 239 | goto error_info; |
| 233 | } | 240 | } |
| 234 | /* create additional sysfs entries */ | 241 | /* create additional sysfs entries */ |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index ad27e9e225a6..ab31f5ba665d 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -1030,15 +1030,6 @@ static void pcie_shutdown_notification(struct controller *ctrl) | |||
| 1030 | pciehp_free_irq(ctrl); | 1030 | pciehp_free_irq(ctrl); |
| 1031 | } | 1031 | } |
| 1032 | 1032 | ||
| 1033 | static void make_slot_name(struct slot *slot) | ||
| 1034 | { | ||
| 1035 | if (pciehp_slot_with_bus) | ||
| 1036 | snprintf(slot->name, SLOT_NAME_SIZE, "%04d_%04d", | ||
| 1037 | slot->bus, slot->number); | ||
| 1038 | else | ||
| 1039 | snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | static int pcie_init_slot(struct controller *ctrl) | 1033 | static int pcie_init_slot(struct controller *ctrl) |
| 1043 | { | 1034 | { |
| 1044 | struct slot *slot; | 1035 | struct slot *slot; |
| @@ -1053,7 +1044,7 @@ static int pcie_init_slot(struct controller *ctrl) | |||
| 1053 | slot->device = ctrl->slot_device_offset + slot->hp_slot; | 1044 | slot->device = ctrl->slot_device_offset + slot->hp_slot; |
| 1054 | slot->hpc_ops = ctrl->hpc_ops; | 1045 | slot->hpc_ops = ctrl->hpc_ops; |
| 1055 | slot->number = ctrl->first_slot; | 1046 | slot->number = ctrl->first_slot; |
| 1056 | make_slot_name(slot); | 1047 | snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); |
| 1057 | mutex_init(&slot->lock); | 1048 | mutex_init(&slot->lock); |
| 1058 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); | 1049 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); |
| 1059 | list_add(&slot->slot_list, &ctrl->slot_list); | 1050 | list_add(&slot->slot_list, &ctrl->slot_list); |
