diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 80 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 179 |
3 files changed, 128 insertions, 136 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 8492fab800cc..d17233ae06f5 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -43,6 +43,7 @@ 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; | ||
46 | extern struct workqueue_struct *pciehp_wq; | 47 | extern struct workqueue_struct *pciehp_wq; |
47 | 48 | ||
48 | #define dbg(format, arg...) \ | 49 | #define dbg(format, arg...) \ |
@@ -156,10 +157,10 @@ extern u8 pciehp_handle_power_fault(struct slot *p_slot); | |||
156 | extern int pciehp_configure_device(struct slot *p_slot); | 157 | extern int pciehp_configure_device(struct slot *p_slot); |
157 | extern int pciehp_unconfigure_device(struct slot *p_slot); | 158 | extern int pciehp_unconfigure_device(struct slot *p_slot); |
158 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); | 159 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); |
159 | int pcie_init(struct controller *ctrl, struct pcie_device *dev); | 160 | struct controller *pcie_init(struct pcie_device *dev); |
160 | int pciehp_enable_slot(struct slot *p_slot); | 161 | int pciehp_enable_slot(struct slot *p_slot); |
161 | int pciehp_disable_slot(struct slot *p_slot); | 162 | int pciehp_disable_slot(struct slot *p_slot); |
162 | int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev); | 163 | int pcie_enable_notification(struct controller *ctrl); |
163 | 164 | ||
164 | static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) | 165 | static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) |
165 | { | 166 | { |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 7b21c86e4bff..d0fb56936911 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -41,7 +41,7 @@ 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 | static int pciehp_slot_with_bus; | 44 | int pciehp_slot_with_bus; |
45 | struct workqueue_struct *pciehp_wq; | 45 | struct workqueue_struct *pciehp_wq; |
46 | 46 | ||
47 | #define DRIVER_VERSION "0.4" | 47 | #define DRIVER_VERSION "0.4" |
@@ -183,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = { | |||
183 | */ | 183 | */ |
184 | static void release_slot(struct hotplug_slot *hotplug_slot) | 184 | static void release_slot(struct hotplug_slot *hotplug_slot) |
185 | { | 185 | { |
186 | struct slot *slot = hotplug_slot->private; | ||
187 | |||
188 | dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); | 186 | dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); |
189 | 187 | ||
190 | kfree(slot->hotplug_slot->info); | 188 | kfree(hotplug_slot->info); |
191 | kfree(slot->hotplug_slot); | 189 | kfree(hotplug_slot); |
192 | kfree(slot); | ||
193 | } | ||
194 | |||
195 | static void make_slot_name(struct slot *slot) | ||
196 | { | ||
197 | if (pciehp_slot_with_bus) | ||
198 | snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", | ||
199 | slot->bus, slot->number); | ||
200 | else | ||
201 | snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", | ||
202 | slot->number); | ||
203 | } | 190 | } |
204 | 191 | ||
205 | static int init_slots(struct controller *ctrl) | 192 | static int init_slots(struct controller *ctrl) |
@@ -208,44 +195,27 @@ static int init_slots(struct controller *ctrl) | |||
208 | struct hotplug_slot *hotplug_slot; | 195 | struct hotplug_slot *hotplug_slot; |
209 | struct hotplug_slot_info *info; | 196 | struct hotplug_slot_info *info; |
210 | int retval = -ENOMEM; | 197 | int retval = -ENOMEM; |
211 | int i; | ||
212 | |||
213 | for (i = 0; i < ctrl->num_slots; i++) { | ||
214 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | ||
215 | if (!slot) | ||
216 | goto error; | ||
217 | 198 | ||
199 | list_for_each_entry(slot, &ctrl->slot_list, slot_list) { | ||
218 | hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); | 200 | hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); |
219 | if (!hotplug_slot) | 201 | if (!hotplug_slot) |
220 | goto error_slot; | 202 | goto error; |
221 | slot->hotplug_slot = hotplug_slot; | ||
222 | 203 | ||
223 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 204 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
224 | if (!info) | 205 | if (!info) |
225 | goto error_hpslot; | 206 | goto error_hpslot; |
226 | hotplug_slot->info = info; | ||
227 | |||
228 | hotplug_slot->name = slot->name; | ||
229 | |||
230 | slot->hp_slot = i; | ||
231 | slot->ctrl = ctrl; | ||
232 | slot->bus = ctrl->pci_dev->subordinate->number; | ||
233 | slot->device = ctrl->slot_device_offset + i; | ||
234 | slot->hpc_ops = ctrl->hpc_ops; | ||
235 | slot->number = ctrl->first_slot; | ||
236 | mutex_init(&slot->lock); | ||
237 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); | ||
238 | 207 | ||
239 | /* register this slot with the hotplug pci core */ | 208 | /* register this slot with the hotplug pci core */ |
209 | hotplug_slot->info = info; | ||
210 | hotplug_slot->name = slot->name; | ||
240 | hotplug_slot->private = slot; | 211 | hotplug_slot->private = slot; |
241 | hotplug_slot->release = &release_slot; | 212 | hotplug_slot->release = &release_slot; |
242 | make_slot_name(slot); | ||
243 | hotplug_slot->ops = &pciehp_hotplug_slot_ops; | 213 | hotplug_slot->ops = &pciehp_hotplug_slot_ops; |
244 | |||
245 | get_power_status(hotplug_slot, &info->power_status); | 214 | get_power_status(hotplug_slot, &info->power_status); |
246 | get_attention_status(hotplug_slot, &info->attention_status); | 215 | get_attention_status(hotplug_slot, &info->attention_status); |
247 | get_latch_status(hotplug_slot, &info->latch_status); | 216 | get_latch_status(hotplug_slot, &info->latch_status); |
248 | get_adapter_status(hotplug_slot, &info->adapter_status); | 217 | get_adapter_status(hotplug_slot, &info->adapter_status); |
218 | slot->hotplug_slot = hotplug_slot; | ||
249 | 219 | ||
250 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " | 220 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " |
251 | "slot_device_offset=%x\n", slot->bus, slot->device, | 221 | "slot_device_offset=%x\n", slot->bus, slot->device, |
@@ -271,8 +241,6 @@ static int init_slots(struct controller *ctrl) | |||
271 | goto error_info; | 241 | goto error_info; |
272 | } | 242 | } |
273 | } | 243 | } |
274 | |||
275 | list_add(&slot->slot_list, &ctrl->slot_list); | ||
276 | } | 244 | } |
277 | 245 | ||
278 | return 0; | 246 | return 0; |
@@ -280,27 +248,18 @@ error_info: | |||
280 | kfree(info); | 248 | kfree(info); |
281 | error_hpslot: | 249 | error_hpslot: |
282 | kfree(hotplug_slot); | 250 | kfree(hotplug_slot); |
283 | error_slot: | ||
284 | kfree(slot); | ||
285 | error: | 251 | error: |
286 | return retval; | 252 | return retval; |
287 | } | 253 | } |
288 | 254 | ||
289 | static void cleanup_slots(struct controller *ctrl) | 255 | static void cleanup_slots(struct controller *ctrl) |
290 | { | 256 | { |
291 | struct list_head *tmp; | ||
292 | struct list_head *next; | ||
293 | struct slot *slot; | 257 | struct slot *slot; |
294 | 258 | ||
295 | list_for_each_safe(tmp, next, &ctrl->slot_list) { | 259 | list_for_each_entry(slot, &ctrl->slot_list, slot_list) { |
296 | slot = list_entry(tmp, struct slot, slot_list); | ||
297 | list_del(&slot->slot_list); | ||
298 | if (EMI(ctrl)) | 260 | if (EMI(ctrl)) |
299 | sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj, | 261 | sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj, |
300 | &hotplug_slot_attr_lock.attr); | 262 | &hotplug_slot_attr_lock.attr); |
301 | cancel_delayed_work(&slot->work); | ||
302 | flush_scheduled_work(); | ||
303 | flush_workqueue(pciehp_wq); | ||
304 | pci_hp_deregister(slot->hotplug_slot); | 263 | pci_hp_deregister(slot->hotplug_slot); |
305 | } | 264 | } |
306 | } | 265 | } |
@@ -441,25 +400,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
441 | else if (pciehp_get_hp_hw_control_from_firmware(pdev)) | 400 | else if (pciehp_get_hp_hw_control_from_firmware(pdev)) |
442 | goto err_out_none; | 401 | goto err_out_none; |
443 | 402 | ||
444 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | 403 | ctrl = pcie_init(dev); |
445 | if (!ctrl) { | 404 | if (!ctrl) { |
446 | err("%s : out of memory\n", __func__); | ||
447 | goto err_out_none; | ||
448 | } | ||
449 | INIT_LIST_HEAD(&ctrl->slot_list); | ||
450 | |||
451 | rc = pcie_init(ctrl, dev); | ||
452 | if (rc) { | ||
453 | dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); | 405 | dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); |
454 | goto err_out_free_ctrl; | 406 | goto err_out_none; |
455 | } | 407 | } |
456 | |||
457 | pci_set_drvdata(pdev, ctrl); | 408 | pci_set_drvdata(pdev, ctrl); |
458 | 409 | ||
459 | dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", | ||
460 | __func__, pdev->bus->number, PCI_SLOT(pdev->devfn), | ||
461 | PCI_FUNC(pdev->devfn), pdev->irq); | ||
462 | |||
463 | /* Setup the slot information structures */ | 410 | /* Setup the slot information structures */ |
464 | rc = init_slots(ctrl); | 411 | rc = init_slots(ctrl); |
465 | if (rc) { | 412 | if (rc) { |
@@ -492,8 +439,6 @@ err_out_free_ctrl_slot: | |||
492 | cleanup_slots(ctrl); | 439 | cleanup_slots(ctrl); |
493 | err_out_release_ctlr: | 440 | err_out_release_ctlr: |
494 | ctrl->hpc_ops->release_ctlr(ctrl); | 441 | ctrl->hpc_ops->release_ctlr(ctrl); |
495 | err_out_free_ctrl: | ||
496 | kfree(ctrl); | ||
497 | err_out_none: | 442 | err_out_none: |
498 | return -ENODEV; | 443 | return -ENODEV; |
499 | } | 444 | } |
@@ -505,7 +450,6 @@ static void pciehp_remove (struct pcie_device *dev) | |||
505 | 450 | ||
506 | cleanup_slots(ctrl); | 451 | cleanup_slots(ctrl); |
507 | ctrl->hpc_ops->release_ctlr(ctrl); | 452 | ctrl->hpc_ops->release_ctlr(ctrl); |
508 | kfree(ctrl); | ||
509 | } | 453 | } |
510 | 454 | ||
511 | #ifdef CONFIG_PM | 455 | #ifdef CONFIG_PM |
@@ -525,7 +469,7 @@ static int pciehp_resume (struct pcie_device *dev) | |||
525 | u8 status; | 469 | u8 status; |
526 | 470 | ||
527 | /* reinitialize the chipset's event detection logic */ | 471 | /* reinitialize the chipset's event detection logic */ |
528 | pcie_init_hardware_part2(ctrl, dev); | 472 | pcie_enable_notification(ctrl); |
529 | 473 | ||
530 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 474 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
531 | 475 | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 59c28093d291..1ce52437e1ed 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -609,23 +609,6 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
609 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 609 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); |
610 | } | 610 | } |
611 | 611 | ||
612 | static void hpc_release_ctlr(struct controller *ctrl) | ||
613 | { | ||
614 | /* Mask Hot-plug Interrupt Enable */ | ||
615 | if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) | ||
616 | err("%s: Cannot mask hotplug interrupt enable\n", __func__); | ||
617 | |||
618 | /* Free interrupt handler or interrupt polling timer */ | ||
619 | pciehp_free_irq(ctrl); | ||
620 | |||
621 | /* | ||
622 | * If this is the last controller to be released, destroy the | ||
623 | * pciehp work queue | ||
624 | */ | ||
625 | if (atomic_dec_and_test(&pciehp_num_controllers)) | ||
626 | destroy_workqueue(pciehp_wq); | ||
627 | } | ||
628 | |||
629 | static int hpc_power_on_slot(struct slot * slot) | 612 | static int hpc_power_on_slot(struct slot * slot) |
630 | { | 613 | { |
631 | struct controller *ctrl = slot->ctrl; | 614 | struct controller *ctrl = slot->ctrl; |
@@ -798,19 +781,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
798 | if (!(intr_loc & ~CMD_COMPLETED)) | 781 | if (!(intr_loc & ~CMD_COMPLETED)) |
799 | return IRQ_HANDLED; | 782 | return IRQ_HANDLED; |
800 | 783 | ||
801 | /* | ||
802 | * Return without handling events if this handler routine is | ||
803 | * called before controller initialization is done. This may | ||
804 | * happen if hotplug event or another interrupt that shares | ||
805 | * the IRQ with pciehp arrives before slot initialization is | ||
806 | * done after interrupt handler is registered. | ||
807 | * | ||
808 | * FIXME - Need more structural fixes. We need to be ready to | ||
809 | * handle the event before installing interrupt handler. | ||
810 | */ | ||
811 | p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 784 | p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
812 | if (!p_slot || !p_slot->hpc_ops) | ||
813 | return IRQ_HANDLED; | ||
814 | 785 | ||
815 | /* Check MRL Sensor Changed */ | 786 | /* Check MRL Sensor Changed */ |
816 | if (intr_loc & MRL_SENS_CHANGED) | 787 | if (intr_loc & MRL_SENS_CHANGED) |
@@ -987,6 +958,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot, | |||
987 | return retval; | 958 | return retval; |
988 | } | 959 | } |
989 | 960 | ||
961 | static void pcie_release_ctrl(struct controller *ctrl); | ||
990 | static struct hpc_ops pciehp_hpc_ops = { | 962 | static struct hpc_ops pciehp_hpc_ops = { |
991 | .power_on_slot = hpc_power_on_slot, | 963 | .power_on_slot = hpc_power_on_slot, |
992 | .power_off_slot = hpc_power_off_slot, | 964 | .power_off_slot = hpc_power_off_slot, |
@@ -1008,28 +980,11 @@ static struct hpc_ops pciehp_hpc_ops = { | |||
1008 | .green_led_off = hpc_set_green_led_off, | 980 | .green_led_off = hpc_set_green_led_off, |
1009 | .green_led_blink = hpc_set_green_led_blink, | 981 | .green_led_blink = hpc_set_green_led_blink, |
1010 | 982 | ||
1011 | .release_ctlr = hpc_release_ctlr, | 983 | .release_ctlr = pcie_release_ctrl, |
1012 | .check_lnk_status = hpc_check_lnk_status, | 984 | .check_lnk_status = hpc_check_lnk_status, |
1013 | }; | 985 | }; |
1014 | 986 | ||
1015 | static int pcie_init_hardware_part1(struct controller *ctrl, | 987 | int pcie_enable_notification(struct controller *ctrl) |
1016 | struct pcie_device *dev) | ||
1017 | { | ||
1018 | /* Clear all remaining event bits in Slot Status register */ | ||
1019 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { | ||
1020 | err("%s: Cannot write to SLOTSTATUS register\n", __func__); | ||
1021 | return -1; | ||
1022 | } | ||
1023 | |||
1024 | /* Mask Hot-plug Interrupt Enable */ | ||
1025 | if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) { | ||
1026 | err("%s: Cannot mask hotplug interrupt enable\n", __func__); | ||
1027 | return -1; | ||
1028 | } | ||
1029 | return 0; | ||
1030 | } | ||
1031 | |||
1032 | int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) | ||
1033 | { | 988 | { |
1034 | u16 cmd, mask; | 989 | u16 cmd, mask; |
1035 | 990 | ||
@@ -1050,10 +1005,76 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) | |||
1050 | err("%s: Cannot enable software notification\n", __func__); | 1005 | err("%s: Cannot enable software notification\n", __func__); |
1051 | return -1; | 1006 | return -1; |
1052 | } | 1007 | } |
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | static void pcie_disable_notification(struct controller *ctrl) | ||
1012 | { | ||
1013 | u16 mask; | ||
1014 | mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE | | ||
1015 | PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE; | ||
1016 | if (pcie_write_cmd(ctrl, 0, mask)) | ||
1017 | warn("%s: Cannot disable software notification\n", __func__); | ||
1018 | } | ||
1019 | |||
1020 | static int pcie_init_notification(struct controller *ctrl) | ||
1021 | { | ||
1022 | if (pciehp_request_irq(ctrl)) | ||
1023 | return -1; | ||
1024 | if (pcie_enable_notification(ctrl)) { | ||
1025 | pciehp_free_irq(ctrl); | ||
1026 | return -1; | ||
1027 | } | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | static void pcie_shutdown_notification(struct controller *ctrl) | ||
1032 | { | ||
1033 | pcie_disable_notification(ctrl); | ||
1034 | pciehp_free_irq(ctrl); | ||
1035 | } | ||
1036 | |||
1037 | static void make_slot_name(struct slot *slot) | ||
1038 | { | ||
1039 | if (pciehp_slot_with_bus) | ||
1040 | snprintf(slot->name, SLOT_NAME_SIZE, "%04d_%04d", | ||
1041 | slot->bus, slot->number); | ||
1042 | else | ||
1043 | snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); | ||
1044 | } | ||
1053 | 1045 | ||
1046 | static int pcie_init_slot(struct controller *ctrl) | ||
1047 | { | ||
1048 | struct slot *slot; | ||
1049 | |||
1050 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | ||
1051 | if (!slot) | ||
1052 | return -ENOMEM; | ||
1053 | |||
1054 | slot->hp_slot = 0; | ||
1055 | slot->ctrl = ctrl; | ||
1056 | slot->bus = ctrl->pci_dev->subordinate->number; | ||
1057 | slot->device = ctrl->slot_device_offset + slot->hp_slot; | ||
1058 | slot->hpc_ops = ctrl->hpc_ops; | ||
1059 | slot->number = ctrl->first_slot; | ||
1060 | make_slot_name(slot); | ||
1061 | mutex_init(&slot->lock); | ||
1062 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); | ||
1063 | list_add(&slot->slot_list, &ctrl->slot_list); | ||
1054 | return 0; | 1064 | return 0; |
1055 | } | 1065 | } |
1056 | 1066 | ||
1067 | static void pcie_cleanup_slot(struct controller *ctrl) | ||
1068 | { | ||
1069 | struct slot *slot; | ||
1070 | slot = list_first_entry(&ctrl->slot_list, struct slot, slot_list); | ||
1071 | list_del(&slot->slot_list); | ||
1072 | cancel_delayed_work(&slot->work); | ||
1073 | flush_scheduled_work(); | ||
1074 | flush_workqueue(pciehp_wq); | ||
1075 | kfree(slot); | ||
1076 | } | ||
1077 | |||
1057 | static inline void dbg_ctrl(struct controller *ctrl) | 1078 | static inline void dbg_ctrl(struct controller *ctrl) |
1058 | { | 1079 | { |
1059 | int i; | 1080 | int i; |
@@ -1093,11 +1114,19 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
1093 | dbg("Slot Control : 0x%04x\n", reg16); | 1114 | dbg("Slot Control : 0x%04x\n", reg16); |
1094 | } | 1115 | } |
1095 | 1116 | ||
1096 | int pcie_init(struct controller *ctrl, struct pcie_device *dev) | 1117 | struct controller *pcie_init(struct pcie_device *dev) |
1097 | { | 1118 | { |
1119 | struct controller *ctrl; | ||
1098 | u32 slot_cap; | 1120 | u32 slot_cap; |
1099 | struct pci_dev *pdev = dev->port; | 1121 | struct pci_dev *pdev = dev->port; |
1100 | 1122 | ||
1123 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | ||
1124 | if (!ctrl) { | ||
1125 | err("%s : out of memory\n", __func__); | ||
1126 | goto abort; | ||
1127 | } | ||
1128 | INIT_LIST_HEAD(&ctrl->slot_list); | ||
1129 | |||
1101 | ctrl->pci_dev = pdev; | 1130 | ctrl->pci_dev = pdev; |
1102 | ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 1131 | ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); |
1103 | if (!ctrl->cap_base) { | 1132 | if (!ctrl->cap_base) { |
@@ -1128,15 +1157,12 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev) | |||
1128 | !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) | 1157 | !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) |
1129 | ctrl->no_cmd_complete = 1; | 1158 | ctrl->no_cmd_complete = 1; |
1130 | 1159 | ||
1131 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", | 1160 | /* Clear all remaining event bits in Slot Status register */ |
1132 | pdev->vendor, pdev->device, | 1161 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) |
1133 | pdev->subsystem_vendor, pdev->subsystem_device); | 1162 | goto abort_ctrl; |
1134 | 1163 | ||
1135 | if (pcie_init_hardware_part1(ctrl, dev)) | 1164 | /* Disable sotfware notification */ |
1136 | goto abort; | 1165 | pcie_disable_notification(ctrl); |
1137 | |||
1138 | if (pciehp_request_irq(ctrl)) | ||
1139 | goto abort; | ||
1140 | 1166 | ||
1141 | /* | 1167 | /* |
1142 | * If this is the first controller to be initialized, | 1168 | * If this is the first controller to be initialized, |
@@ -1144,18 +1170,39 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev) | |||
1144 | */ | 1170 | */ |
1145 | if (atomic_add_return(1, &pciehp_num_controllers) == 1) { | 1171 | if (atomic_add_return(1, &pciehp_num_controllers) == 1) { |
1146 | pciehp_wq = create_singlethread_workqueue("pciehpd"); | 1172 | pciehp_wq = create_singlethread_workqueue("pciehpd"); |
1147 | if (!pciehp_wq) { | 1173 | if (!pciehp_wq) |
1148 | goto abort_free_irq; | 1174 | goto abort_ctrl; |
1149 | } | ||
1150 | } | 1175 | } |
1151 | 1176 | ||
1152 | if (pcie_init_hardware_part2(ctrl, dev)) | 1177 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", |
1153 | goto abort_free_irq; | 1178 | pdev->vendor, pdev->device, |
1179 | pdev->subsystem_vendor, pdev->subsystem_device); | ||
1180 | |||
1181 | if (pcie_init_slot(ctrl)) | ||
1182 | goto abort_ctrl; | ||
1154 | 1183 | ||
1155 | return 0; | 1184 | if (pcie_init_notification(ctrl)) |
1185 | goto abort_slot; | ||
1156 | 1186 | ||
1157 | abort_free_irq: | 1187 | return ctrl; |
1158 | pciehp_free_irq(ctrl); | 1188 | |
1189 | abort_slot: | ||
1190 | pcie_cleanup_slot(ctrl); | ||
1191 | abort_ctrl: | ||
1192 | kfree(ctrl); | ||
1159 | abort: | 1193 | abort: |
1160 | return -1; | 1194 | return NULL; |
1195 | } | ||
1196 | |||
1197 | void pcie_release_ctrl(struct controller *ctrl) | ||
1198 | { | ||
1199 | pcie_shutdown_notification(ctrl); | ||
1200 | pcie_cleanup_slot(ctrl); | ||
1201 | /* | ||
1202 | * If this is the last controller to be released, destroy the | ||
1203 | * pciehp work queue | ||
1204 | */ | ||
1205 | if (atomic_dec_and_test(&pciehp_num_controllers)) | ||
1206 | destroy_workqueue(pciehp_wq); | ||
1207 | kfree(ctrl); | ||
1161 | } | 1208 | } |