aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2008-06-19 23:07:08 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-06-27 16:00:43 -0400
commitc4635eb06af700820d658a163f06aff12e17cfb2 (patch)
tree97bae8af21e7dc26374de8d9ed45e9f112b7de5a /drivers
parente4ec7a00ed30429030112e5591cf3138645727c2 (diff)
pciehp: fix interrupt initialization
Current pciehp driver's intialization sequence is as follows: (1) initialize controller data structure (2) install interrupt handler (3) enable software notification (4) initialize controller specific slot data structure (5) initialize generic slot data structure and register it to pci hotplug core The interrupt handler of pciehp assumes that controller specific slot data structure is already initialized. However, it is installed at (2) before initializing controller specific slot data structure at (4). Because of this, pciehp driver cannot handle the following cases properly. - If devices that shares IRQ with pciehp raise interrupts between (2) and (4). - If hotplug events (e.g. MRL open) happen between (3) and (4). We already have a workaround for this problem ("pciehp: fix NULL dereference in interrupt handler: dbd79aed1aea2bece0bf43cc2ff3b2f9baf48a08). But we still need fundamental fix. This patch fix the problem by changing the initilization sequence as follows: (1) initialize controller data structure (2) initialize controller specific slot data structure (3) install interrupt handler (4) enable software notification (5) initialize generic slot data structure and register it to pci hotplug core Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Acked-by: Alex Chiang <achiang@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/hotplug/pciehp.h5
-rw-r--r--drivers/pci/hotplug/pciehp_core.c80
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c179
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;
43extern int pciehp_poll_time; 43extern int pciehp_poll_time;
44extern int pciehp_debug; 44extern int pciehp_debug;
45extern int pciehp_force; 45extern int pciehp_force;
46extern int pciehp_slot_with_bus;
46extern struct workqueue_struct *pciehp_wq; 47extern 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);
156extern int pciehp_configure_device(struct slot *p_slot); 157extern int pciehp_configure_device(struct slot *p_slot);
157extern int pciehp_unconfigure_device(struct slot *p_slot); 158extern int pciehp_unconfigure_device(struct slot *p_slot);
158extern void pciehp_queue_pushbutton_work(struct work_struct *work); 159extern void pciehp_queue_pushbutton_work(struct work_struct *work);
159int pcie_init(struct controller *ctrl, struct pcie_device *dev); 160struct controller *pcie_init(struct pcie_device *dev);
160int pciehp_enable_slot(struct slot *p_slot); 161int pciehp_enable_slot(struct slot *p_slot);
161int pciehp_disable_slot(struct slot *p_slot); 162int pciehp_disable_slot(struct slot *p_slot);
162int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev); 163int pcie_enable_notification(struct controller *ctrl);
163 164
164static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) 165static 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;
41int pciehp_poll_mode; 41int pciehp_poll_mode;
42int pciehp_poll_time; 42int pciehp_poll_time;
43int pciehp_force; 43int pciehp_force;
44static int pciehp_slot_with_bus; 44int pciehp_slot_with_bus;
45struct workqueue_struct *pciehp_wq; 45struct 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 */
184static void release_slot(struct hotplug_slot *hotplug_slot) 184static 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
195static 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
205static int init_slots(struct controller *ctrl) 192static 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);
281error_hpslot: 249error_hpslot:
282 kfree(hotplug_slot); 250 kfree(hotplug_slot);
283error_slot:
284 kfree(slot);
285error: 251error:
286 return retval; 252 return retval;
287} 253}
288 254
289static void cleanup_slots(struct controller *ctrl) 255static 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);
493err_out_release_ctlr: 440err_out_release_ctlr:
494 ctrl->hpc_ops->release_ctlr(ctrl); 441 ctrl->hpc_ops->release_ctlr(ctrl);
495err_out_free_ctrl:
496 kfree(ctrl);
497err_out_none: 442err_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
612static 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
629static int hpc_power_on_slot(struct slot * slot) 612static 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
961static void pcie_release_ctrl(struct controller *ctrl);
990static struct hpc_ops pciehp_hpc_ops = { 962static 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
1015static int pcie_init_hardware_part1(struct controller *ctrl, 987int 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
1032int 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
1011static 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
1020static 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
1031static void pcie_shutdown_notification(struct controller *ctrl)
1032{
1033 pcie_disable_notification(ctrl);
1034 pciehp_free_irq(ctrl);
1035}
1036
1037static 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
1046static 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
1067static 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
1057static inline void dbg_ctrl(struct controller *ctrl) 1078static 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
1096int pcie_init(struct controller *ctrl, struct pcie_device *dev) 1117struct 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
1157abort_free_irq: 1187 return ctrl;
1158 pciehp_free_irq(ctrl); 1188
1189abort_slot:
1190 pcie_cleanup_slot(ctrl);
1191abort_ctrl:
1192 kfree(ctrl);
1159abort: 1193abort:
1160 return -1; 1194 return NULL;
1195}
1196
1197void 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}