diff options
Diffstat (limited to 'drivers/pci/hotplug')
| -rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 38 | ||||
| -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 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 34 |
5 files changed, 56 insertions, 49 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 93e37f0666ab..e17ef54f0efc 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
| @@ -382,7 +382,7 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); | |||
| 382 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | 382 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) |
| 383 | { | 383 | { |
| 384 | acpi_status status; | 384 | acpi_status status; |
| 385 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); | 385 | acpi_handle chandle, handle; |
| 386 | struct pci_dev *pdev = dev; | 386 | struct pci_dev *pdev = dev; |
| 387 | struct pci_bus *parent; | 387 | struct pci_bus *parent; |
| 388 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 388 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
| @@ -399,10 +399,25 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
| 399 | * Per PCI firmware specification, we should run the ACPI _OSC | 399 | * Per PCI firmware specification, we should run the ACPI _OSC |
| 400 | * method to get control of hotplug hardware before using it. If | 400 | * method to get control of hotplug hardware before using it. If |
| 401 | * an _OSC is missing, we look for an OSHP to do the same thing. | 401 | * an _OSC is missing, we look for an OSHP to do the same thing. |
| 402 | * To handle different BIOS behavior, we look for _OSC and OSHP | 402 | * To handle different BIOS behavior, we look for _OSC on a root |
| 403 | * within the scope of the hotplug controller and its parents, | 403 | * bridge preferentially (according to PCI fw spec). Later for |
| 404 | * OSHP within the scope of the hotplug controller and its parents, | ||
| 404 | * upto the host bridge under which this controller exists. | 405 | * upto the host bridge under which this controller exists. |
| 405 | */ | 406 | */ |
| 407 | handle = acpi_find_root_bridge_handle(pdev); | ||
| 408 | if (handle) { | ||
| 409 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
| 410 | dbg("Trying to get hotplug control for %s\n", | ||
| 411 | (char *)string.pointer); | ||
| 412 | status = pci_osc_control_set(handle, flags); | ||
| 413 | if (ACPI_SUCCESS(status)) | ||
| 414 | goto got_one; | ||
| 415 | kfree(string.pointer); | ||
| 416 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 417 | } | ||
| 418 | |||
| 419 | pdev = dev; | ||
| 420 | handle = DEVICE_ACPI_HANDLE(&dev->dev); | ||
| 406 | while (!handle) { | 421 | while (!handle) { |
| 407 | /* | 422 | /* |
| 408 | * This hotplug controller was not listed in the ACPI name | 423 | * This hotplug controller was not listed in the ACPI name |
| @@ -427,15 +442,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
| 427 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 442 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
| 428 | dbg("Trying to get hotplug control for %s \n", | 443 | dbg("Trying to get hotplug control for %s \n", |
| 429 | (char *)string.pointer); | 444 | (char *)string.pointer); |
| 430 | status = pci_osc_control_set(handle, flags); | 445 | status = acpi_run_oshp(handle); |
| 431 | if (status == AE_NOT_FOUND) | 446 | if (ACPI_SUCCESS(status)) |
| 432 | status = acpi_run_oshp(handle); | 447 | goto got_one; |
| 433 | if (ACPI_SUCCESS(status)) { | ||
| 434 | dbg("Gained control for hotplug HW for pci %s (%s)\n", | ||
| 435 | pci_name(dev), (char *)string.pointer); | ||
| 436 | kfree(string.pointer); | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | if (acpi_root_bridge(handle)) | 448 | if (acpi_root_bridge(handle)) |
| 440 | break; | 449 | break; |
| 441 | chandle = handle; | 450 | chandle = handle; |
| @@ -449,6 +458,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
| 449 | 458 | ||
| 450 | kfree(string.pointer); | 459 | kfree(string.pointer); |
| 451 | return -ENODEV; | 460 | return -ENODEV; |
| 461 | got_one: | ||
| 462 | dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), | ||
| 463 | (char *)string.pointer); | ||
| 464 | kfree(string.pointer); | ||
| 465 | return 0; | ||
| 452 | } | 466 | } |
| 453 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); | 467 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); |
| 454 | 468 | ||
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); |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a8cbd039b85b..cc38615395f1 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | int shpchp_debug; | 39 | int shpchp_debug; |
| 40 | int shpchp_poll_mode; | 40 | int shpchp_poll_mode; |
| 41 | int shpchp_poll_time; | 41 | int shpchp_poll_time; |
| 42 | static int shpchp_slot_with_bus; | ||
| 43 | struct workqueue_struct *shpchp_wq; | 42 | struct workqueue_struct *shpchp_wq; |
| 44 | 43 | ||
| 45 | #define DRIVER_VERSION "0.4" | 44 | #define DRIVER_VERSION "0.4" |
| @@ -53,11 +52,9 @@ MODULE_LICENSE("GPL"); | |||
| 53 | module_param(shpchp_debug, bool, 0644); | 52 | module_param(shpchp_debug, bool, 0644); |
| 54 | module_param(shpchp_poll_mode, bool, 0644); | 53 | module_param(shpchp_poll_mode, bool, 0644); |
| 55 | module_param(shpchp_poll_time, int, 0644); | 54 | module_param(shpchp_poll_time, int, 0644); |
| 56 | module_param(shpchp_slot_with_bus, bool, 0644); | ||
| 57 | MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); | 55 | MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); |
| 58 | MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); | 56 | MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); |
| 59 | MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); | 57 | MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); |
| 60 | MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name"); | ||
| 61 | 58 | ||
| 62 | #define SHPC_MODULE_NAME "shpchp" | 59 | #define SHPC_MODULE_NAME "shpchp" |
| 63 | 60 | ||
| @@ -99,23 +96,13 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
| 99 | kfree(slot); | 96 | kfree(slot); |
| 100 | } | 97 | } |
| 101 | 98 | ||
| 102 | static void make_slot_name(struct slot *slot) | ||
| 103 | { | ||
| 104 | if (shpchp_slot_with_bus) | ||
| 105 | snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", | ||
| 106 | slot->bus, slot->number); | ||
| 107 | else | ||
| 108 | snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", | ||
| 109 | slot->number); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int init_slots(struct controller *ctrl) | 99 | static int init_slots(struct controller *ctrl) |
| 113 | { | 100 | { |
| 114 | struct slot *slot; | 101 | struct slot *slot; |
| 115 | struct hotplug_slot *hotplug_slot; | 102 | struct hotplug_slot *hotplug_slot; |
| 116 | struct hotplug_slot_info *info; | 103 | struct hotplug_slot_info *info; |
| 117 | int retval = -ENOMEM; | 104 | int retval = -ENOMEM; |
| 118 | int i; | 105 | int i, len, dup = 1; |
| 119 | 106 | ||
| 120 | for (i = 0; i < ctrl->num_slots; i++) { | 107 | for (i = 0; i < ctrl->num_slots; i++) { |
| 121 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | 108 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
| @@ -146,7 +133,7 @@ static int init_slots(struct controller *ctrl) | |||
| 146 | /* register this slot with the hotplug pci core */ | 133 | /* register this slot with the hotplug pci core */ |
| 147 | hotplug_slot->private = slot; | 134 | hotplug_slot->private = slot; |
| 148 | hotplug_slot->release = &release_slot; | 135 | hotplug_slot->release = &release_slot; |
| 149 | make_slot_name(slot); | 136 | snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); |
| 150 | hotplug_slot->ops = &shpchp_hotplug_slot_ops; | 137 | hotplug_slot->ops = &shpchp_hotplug_slot_ops; |
| 151 | 138 | ||
| 152 | get_power_status(hotplug_slot, &info->power_status); | 139 | get_power_status(hotplug_slot, &info->power_status); |
| @@ -157,14 +144,23 @@ static int init_slots(struct controller *ctrl) | |||
| 157 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " | 144 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " |
| 158 | "slot_device_offset=%x\n", slot->bus, slot->device, | 145 | "slot_device_offset=%x\n", slot->bus, slot->device, |
| 159 | slot->hp_slot, slot->number, ctrl->slot_device_offset); | 146 | slot->hp_slot, slot->number, ctrl->slot_device_offset); |
| 147 | duplicate_name: | ||
| 160 | retval = pci_hp_register(slot->hotplug_slot, | 148 | retval = pci_hp_register(slot->hotplug_slot, |
| 161 | ctrl->pci_dev->subordinate, slot->device); | 149 | ctrl->pci_dev->subordinate, slot->device); |
| 162 | if (retval) { | 150 | if (retval) { |
| 151 | /* | ||
| 152 | * If slot N already exists, we'll try to create | ||
| 153 | * slot N-1, N-2 ... N-M, until we overflow. | ||
| 154 | */ | ||
| 155 | if (retval == -EEXIST) { | ||
| 156 | len = snprintf(slot->name, SLOT_NAME_SIZE, | ||
| 157 | "%d-%d", slot->number, dup++); | ||
| 158 | if (len < SLOT_NAME_SIZE) | ||
| 159 | goto duplicate_name; | ||
| 160 | else | ||
| 161 | err("duplicate slot name overflow\n"); | ||
| 162 | } | ||
| 163 | err("pci_hp_register failed with error %d\n", retval); | 163 | err("pci_hp_register failed with error %d\n", retval); |
| 164 | if (retval == -EEXIST) | ||
| 165 | err("Failed to register slot because of name " | ||
| 166 | "collision. Try \'shpchp_slot_with_bus\' " | ||
| 167 | "module option.\n"); | ||
| 168 | goto error_info; | 164 | goto error_info; |
| 169 | } | 165 | } |
| 170 | 166 | ||
