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 39 int shpchp_debug; 40 40 int shpchp_poll_mode; 41 41 int shpchp_poll_time; 42 - static int shpchp_slot_with_bus; 43 42 struct workqueue_struct *shpchp_wq; 44 43 45 44 #define DRIVER_VERSION "0.4" ··· 52 53 module_param(shpchp_debug, bool, 0644); 53 54 module_param(shpchp_poll_mode, bool, 0644); 54 55 module_param(shpchp_poll_time, int, 0644); 55 - module_param(shpchp_slot_with_bus, bool, 0644); 56 56 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); 57 57 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); 58 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 59 61 60 #define SHPC_MODULE_NAME "shpchp" 62 61 ··· 96 99 kfree(slot); 97 100 } 98 101 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 102 static int init_slots(struct controller *ctrl) 110 103 { 111 104 struct slot *slot; 112 105 struct hotplug_slot *hotplug_slot; 113 106 struct hotplug_slot_info *info; 114 107 int retval = -ENOMEM; 115 - int i; 108 + int i, len, dup = 1; 116 109 117 110 for (i = 0; i < ctrl->num_slots; i++) { 118 111 slot = kzalloc(sizeof(*slot), GFP_KERNEL); ··· 133 146 /* register this slot with the hotplug pci core */ 134 147 hotplug_slot->private = slot; 135 148 hotplug_slot->release = &release_slot; 136 - make_slot_name(slot); 149 + snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); 137 150 hotplug_slot->ops = &shpchp_hotplug_slot_ops; 138 151 139 152 get_power_status(hotplug_slot, &info->power_status); ··· 144 157 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 145 158 "slot_device_offset=%x\n", slot->bus, slot->device, 146 159 slot->hp_slot, slot->number, ctrl->slot_device_offset); 160 + duplicate_name: 147 161 retval = pci_hp_register(slot->hotplug_slot, 148 162 ctrl->pci_dev->subordinate, slot->device); 149 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 + } 150 176 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 177 goto error_info; 156 178 } 157 179