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

Commit ef0ff95f136f0f2d035667af5d18b824609de320 (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 b3bd307c628af2f0a581c42d5d7e4bcdbbf64b6a (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: 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>

authored by Alex Chiang and committed by Jesse Barnes d6a9e9b4 167e782e

+15 -19
+15 -19
drivers/pci/hotplug/shpchp_core.c
··· 39 int shpchp_debug; 40 int shpchp_poll_mode; 41 int shpchp_poll_time; 42 - static int shpchp_slot_with_bus; 43 struct workqueue_struct *shpchp_wq; 44 45 #define DRIVER_VERSION "0.4" ··· 52 module_param(shpchp_debug, bool, 0644); 53 module_param(shpchp_poll_mode, bool, 0644); 54 module_param(shpchp_poll_time, int, 0644); 55 - module_param(shpchp_slot_with_bus, bool, 0644); 56 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); 57 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); 58 MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); 59 - MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name"); 60 61 #define SHPC_MODULE_NAME "shpchp" 62 ··· 96 kfree(slot); 97 } 98 99 - static void make_slot_name(struct slot *slot) 100 - { 101 - if (shpchp_slot_with_bus) 102 - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", 103 - slot->bus, slot->number); 104 - else 105 - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", 106 - slot->number); 107 - } 108 - 109 static int init_slots(struct controller *ctrl) 110 { 111 struct slot *slot; 112 struct hotplug_slot *hotplug_slot; 113 struct hotplug_slot_info *info; 114 int retval = -ENOMEM; 115 - int i; 116 117 for (i = 0; i < ctrl->num_slots; i++) { 118 slot = kzalloc(sizeof(*slot), GFP_KERNEL); ··· 133 /* register this slot with the hotplug pci core */ 134 hotplug_slot->private = slot; 135 hotplug_slot->release = &release_slot; 136 - make_slot_name(slot); 137 hotplug_slot->ops = &shpchp_hotplug_slot_ops; 138 139 get_power_status(hotplug_slot, &info->power_status); ··· 144 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 145 "slot_device_offset=%x\n", slot->bus, slot->device, 146 slot->hp_slot, slot->number, ctrl->slot_device_offset); 147 retval = pci_hp_register(slot->hotplug_slot, 148 ctrl->pci_dev->subordinate, slot->device); 149 if (retval) { 150 err("pci_hp_register failed with error %d\n", retval); 151 - if (retval == -EEXIST) 152 - err("Failed to register slot because of name " 153 - "collision. Try \'shpchp_slot_with_bus\' " 154 - "module option.\n"); 155 goto error_info; 156 } 157
··· 39 int shpchp_debug; 40 int shpchp_poll_mode; 41 int shpchp_poll_time; 42 struct workqueue_struct *shpchp_wq; 43 44 #define DRIVER_VERSION "0.4" ··· 53 module_param(shpchp_debug, bool, 0644); 54 module_param(shpchp_poll_mode, bool, 0644); 55 module_param(shpchp_poll_time, int, 0644); 56 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); 57 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); 58 MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); 59 60 #define SHPC_MODULE_NAME "shpchp" 61 ··· 99 kfree(slot); 100 } 101 102 static int init_slots(struct controller *ctrl) 103 { 104 struct slot *slot; 105 struct hotplug_slot *hotplug_slot; 106 struct hotplug_slot_info *info; 107 int retval = -ENOMEM; 108 + int i, len, dup = 1; 109 110 for (i = 0; i < ctrl->num_slots; i++) { 111 slot = kzalloc(sizeof(*slot), GFP_KERNEL); ··· 146 /* register this slot with the hotplug pci core */ 147 hotplug_slot->private = slot; 148 hotplug_slot->release = &release_slot; 149 + snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); 150 hotplug_slot->ops = &shpchp_hotplug_slot_ops; 151 152 get_power_status(hotplug_slot, &info->power_status); ··· 157 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 158 "slot_device_offset=%x\n", slot->bus, slot->device, 159 slot->hp_slot, slot->number, ctrl->slot_device_offset); 160 + duplicate_name: 161 retval = pci_hp_register(slot->hotplug_slot, 162 ctrl->pci_dev->subordinate, slot->device); 163 if (retval) { 164 + /* 165 + * If slot N already exists, we'll try to create 166 + * slot N-1, N-2 ... N-M, until we overflow. 167 + */ 168 + if (retval == -EEXIST) { 169 + len = snprintf(slot->name, SLOT_NAME_SIZE, 170 + "%d-%d", slot->number, dup++); 171 + if (len < SLOT_NAME_SIZE) 172 + goto duplicate_name; 173 + else 174 + err("duplicate slot name overflow\n"); 175 + } 176 err("pci_hp_register failed with error %d\n", retval); 177 goto error_info; 178 } 179