diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 18 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 14 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 205 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 38 |
4 files changed, 82 insertions, 193 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e4524cf02427..17167d594472 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -173,24 +173,6 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) | |||
173 | return NULL; | 173 | return NULL; |
174 | } | 174 | } |
175 | 175 | ||
176 | static inline int wait_for_ctrl_irq(struct controller *ctrl) | ||
177 | { | ||
178 | DECLARE_WAITQUEUE(wait, current); | ||
179 | |||
180 | add_wait_queue(&ctrl->queue, &wait); | ||
181 | if (!pciehp_poll_mode) | ||
182 | /* Sleep for up to 1 second */ | ||
183 | msleep_interruptible(1000); | ||
184 | else | ||
185 | msleep_interruptible(2500); | ||
186 | |||
187 | remove_wait_queue(&ctrl->queue, &wait); | ||
188 | if (signal_pending(current)) | ||
189 | return -EINTR; | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | struct hpc_ops { | 176 | struct hpc_ops { |
195 | int (*power_on_slot)(struct slot *slot); | 177 | int (*power_on_slot)(struct slot *slot); |
196 | int (*power_off_slot)(struct slot *slot); | 178 | int (*power_off_slot)(struct slot *slot); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index e2d45662bdbf..f7b8e0504fec 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -374,25 +374,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
374 | pciehp_ctrl_list = ctrl; | 374 | pciehp_ctrl_list = ctrl; |
375 | } | 375 | } |
376 | 376 | ||
377 | /* Wait for exclusive access to hardware */ | ||
378 | mutex_lock(&ctrl->ctrl_lock); | ||
379 | |||
380 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 377 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
381 | |||
382 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { | 378 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { |
383 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 379 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
384 | if (rc) { | 380 | if (rc) |
385 | /* Done with exclusive hardware access */ | ||
386 | mutex_unlock(&ctrl->ctrl_lock); | ||
387 | goto err_out_free_ctrl_slot; | 381 | goto err_out_free_ctrl_slot; |
388 | } else | ||
389 | /* Wait for the command to complete */ | ||
390 | wait_for_ctrl_irq (ctrl); | ||
391 | } | 382 | } |
392 | 383 | ||
393 | /* Done with exclusive hardware access */ | ||
394 | mutex_unlock(&ctrl->ctrl_lock); | ||
395 | |||
396 | return 0; | 384 | return 0; |
397 | 385 | ||
398 | err_out_free_ctrl_slot: | 386 | err_out_free_ctrl_slot: |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 072befa345a7..4283ef56dbd9 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -229,35 +229,25 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) | |||
229 | 229 | ||
230 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) | 230 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) |
231 | { | 231 | { |
232 | /* Wait for exclusive access to hardware */ | ||
233 | mutex_lock(&ctrl->ctrl_lock); | ||
234 | |||
235 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ | 232 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ |
236 | if (POWER_CTRL(ctrl->ctrlcap)) { | 233 | if (POWER_CTRL(ctrl->ctrlcap)) { |
237 | if (pslot->hpc_ops->power_off_slot(pslot)) { | 234 | if (pslot->hpc_ops->power_off_slot(pslot)) { |
238 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); | 235 | err("%s: Issue of Slot Power Off command failed\n", |
239 | mutex_unlock(&ctrl->ctrl_lock); | 236 | __FUNCTION__); |
240 | return; | 237 | return; |
241 | } | 238 | } |
242 | wait_for_ctrl_irq (ctrl); | ||
243 | } | 239 | } |
244 | 240 | ||
245 | if (PWR_LED(ctrl->ctrlcap)) { | 241 | if (PWR_LED(ctrl->ctrlcap)) |
246 | pslot->hpc_ops->green_led_off(pslot); | 242 | pslot->hpc_ops->green_led_off(pslot); |
247 | wait_for_ctrl_irq (ctrl); | ||
248 | } | ||
249 | 243 | ||
250 | if (ATTN_LED(ctrl->ctrlcap)) { | 244 | if (ATTN_LED(ctrl->ctrlcap)) { |
251 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { | 245 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { |
252 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); | 246 | err("%s: Issue of Set Attention Led command failed\n", |
253 | mutex_unlock(&ctrl->ctrl_lock); | 247 | __FUNCTION__); |
254 | return; | 248 | return; |
255 | } | 249 | } |
256 | wait_for_ctrl_irq (ctrl); | ||
257 | } | 250 | } |
258 | |||
259 | /* Done with exclusive hardware access */ | ||
260 | mutex_unlock(&ctrl->ctrl_lock); | ||
261 | } | 251 | } |
262 | 252 | ||
263 | /** | 253 | /** |
@@ -270,7 +260,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
270 | static int board_added(struct slot *p_slot) | 260 | static int board_added(struct slot *p_slot) |
271 | { | 261 | { |
272 | u8 hp_slot; | 262 | u8 hp_slot; |
273 | int rc = 0; | 263 | int retval = 0; |
274 | struct controller *ctrl = p_slot->ctrl; | 264 | struct controller *ctrl = p_slot->ctrl; |
275 | 265 | ||
276 | hp_slot = p_slot->device - ctrl->slot_device_offset; | 266 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
@@ -279,53 +269,38 @@ static int board_added(struct slot *p_slot) | |||
279 | __FUNCTION__, p_slot->device, | 269 | __FUNCTION__, p_slot->device, |
280 | ctrl->slot_device_offset, hp_slot); | 270 | ctrl->slot_device_offset, hp_slot); |
281 | 271 | ||
282 | /* Wait for exclusive access to hardware */ | ||
283 | mutex_lock(&ctrl->ctrl_lock); | ||
284 | |||
285 | if (POWER_CTRL(ctrl->ctrlcap)) { | 272 | if (POWER_CTRL(ctrl->ctrlcap)) { |
286 | /* Power on slot */ | 273 | /* Power on slot */ |
287 | rc = p_slot->hpc_ops->power_on_slot(p_slot); | 274 | retval = p_slot->hpc_ops->power_on_slot(p_slot); |
288 | if (rc) { | 275 | if (retval) |
289 | mutex_unlock(&ctrl->ctrl_lock); | 276 | return retval; |
290 | return -1; | ||
291 | } | ||
292 | |||
293 | /* Wait for the command to complete */ | ||
294 | wait_for_ctrl_irq (ctrl); | ||
295 | } | 277 | } |
296 | 278 | ||
297 | if (PWR_LED(ctrl->ctrlcap)) { | 279 | if (PWR_LED(ctrl->ctrlcap)) |
298 | p_slot->hpc_ops->green_led_blink(p_slot); | 280 | p_slot->hpc_ops->green_led_blink(p_slot); |
299 | |||
300 | /* Wait for the command to complete */ | ||
301 | wait_for_ctrl_irq (ctrl); | ||
302 | } | ||
303 | |||
304 | /* Done with exclusive hardware access */ | ||
305 | mutex_unlock(&ctrl->ctrl_lock); | ||
306 | 281 | ||
307 | /* Wait for ~1 second */ | 282 | /* Wait for ~1 second */ |
308 | wait_for_ctrl_irq (ctrl); | 283 | msleep(1000); |
309 | 284 | ||
310 | /* Check link training status */ | 285 | /* Check link training status */ |
311 | rc = p_slot->hpc_ops->check_lnk_status(ctrl); | 286 | retval = p_slot->hpc_ops->check_lnk_status(ctrl); |
312 | if (rc) { | 287 | if (retval) { |
313 | err("%s: Failed to check link status\n", __FUNCTION__); | 288 | err("%s: Failed to check link status\n", __FUNCTION__); |
314 | set_slot_off(ctrl, p_slot); | 289 | set_slot_off(ctrl, p_slot); |
315 | return rc; | 290 | return retval; |
316 | } | 291 | } |
317 | 292 | ||
318 | /* Check for a power fault */ | 293 | /* Check for a power fault */ |
319 | if (p_slot->hpc_ops->query_power_fault(p_slot)) { | 294 | if (p_slot->hpc_ops->query_power_fault(p_slot)) { |
320 | dbg("%s: power fault detected\n", __FUNCTION__); | 295 | dbg("%s: power fault detected\n", __FUNCTION__); |
321 | rc = POWER_FAILURE; | 296 | retval = POWER_FAILURE; |
322 | goto err_exit; | 297 | goto err_exit; |
323 | } | 298 | } |
324 | 299 | ||
325 | rc = pciehp_configure_device(p_slot); | 300 | retval = pciehp_configure_device(p_slot); |
326 | if (rc) { | 301 | if (retval) { |
327 | err("Cannot add device 0x%x:%x\n", p_slot->bus, | 302 | err("Cannot add device 0x%x:%x\n", p_slot->bus, |
328 | p_slot->device); | 303 | p_slot->device); |
329 | goto err_exit; | 304 | goto err_exit; |
330 | } | 305 | } |
331 | 306 | ||
@@ -334,26 +309,16 @@ static int board_added(struct slot *p_slot) | |||
334 | */ | 309 | */ |
335 | if (pcie_mch_quirk) | 310 | if (pcie_mch_quirk) |
336 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | 311 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); |
337 | if (PWR_LED(ctrl->ctrlcap)) { | 312 | if (PWR_LED(ctrl->ctrlcap)) |
338 | /* Wait for exclusive access to hardware */ | ||
339 | mutex_lock(&ctrl->ctrl_lock); | ||
340 | |||
341 | p_slot->hpc_ops->green_led_on(p_slot); | 313 | p_slot->hpc_ops->green_led_on(p_slot); |
342 | 314 | ||
343 | /* Wait for the command to complete */ | ||
344 | wait_for_ctrl_irq (ctrl); | ||
345 | |||
346 | /* Done with exclusive hardware access */ | ||
347 | mutex_unlock(&ctrl->ctrl_lock); | ||
348 | } | ||
349 | return 0; | 315 | return 0; |
350 | 316 | ||
351 | err_exit: | 317 | err_exit: |
352 | set_slot_off(ctrl, p_slot); | 318 | set_slot_off(ctrl, p_slot); |
353 | return -1; | 319 | return retval; |
354 | } | 320 | } |
355 | 321 | ||
356 | |||
357 | /** | 322 | /** |
358 | * remove_board - Turns off slot and LED's | 323 | * remove_board - Turns off slot and LED's |
359 | * | 324 | * |
@@ -362,44 +327,32 @@ static int remove_board(struct slot *p_slot) | |||
362 | { | 327 | { |
363 | u8 device; | 328 | u8 device; |
364 | u8 hp_slot; | 329 | u8 hp_slot; |
365 | int rc; | 330 | int retval = 0; |
366 | struct controller *ctrl = p_slot->ctrl; | 331 | struct controller *ctrl = p_slot->ctrl; |
367 | 332 | ||
368 | if (pciehp_unconfigure_device(p_slot)) | 333 | retval = pciehp_unconfigure_device(p_slot); |
369 | return 1; | 334 | if (retval) |
335 | return retval; | ||
370 | 336 | ||
371 | device = p_slot->device; | 337 | device = p_slot->device; |
372 | |||
373 | hp_slot = p_slot->device - ctrl->slot_device_offset; | 338 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
374 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 339 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
375 | 340 | ||
376 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 341 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
377 | 342 | ||
378 | /* Wait for exclusive access to hardware */ | ||
379 | mutex_lock(&ctrl->ctrl_lock); | ||
380 | |||
381 | if (POWER_CTRL(ctrl->ctrlcap)) { | 343 | if (POWER_CTRL(ctrl->ctrlcap)) { |
382 | /* power off slot */ | 344 | /* power off slot */ |
383 | rc = p_slot->hpc_ops->power_off_slot(p_slot); | 345 | retval = p_slot->hpc_ops->power_off_slot(p_slot); |
384 | if (rc) { | 346 | if (retval) { |
385 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 347 | err("%s: Issue of Slot Disable command failed\n", |
386 | mutex_unlock(&ctrl->ctrl_lock); | 348 | __FUNCTION__); |
387 | return rc; | 349 | return retval; |
388 | } | 350 | } |
389 | /* Wait for the command to complete */ | ||
390 | wait_for_ctrl_irq (ctrl); | ||
391 | } | 351 | } |
392 | 352 | ||
393 | if (PWR_LED(ctrl->ctrlcap)) { | 353 | if (PWR_LED(ctrl->ctrlcap)) |
394 | /* turn off Green LED */ | 354 | /* turn off Green LED */ |
395 | p_slot->hpc_ops->green_led_off(p_slot); | 355 | p_slot->hpc_ops->green_led_off(p_slot); |
396 | |||
397 | /* Wait for the command to complete */ | ||
398 | wait_for_ctrl_irq (ctrl); | ||
399 | } | ||
400 | |||
401 | /* Done with exclusive hardware access */ | ||
402 | mutex_unlock(&ctrl->ctrl_lock); | ||
403 | 356 | ||
404 | return 0; | 357 | return 0; |
405 | } | 358 | } |
@@ -444,18 +397,10 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
444 | dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, | 397 | dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, |
445 | p_slot->bus, p_slot->device); | 398 | p_slot->bus, p_slot->device); |
446 | 399 | ||
447 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 400 | if (pciehp_enable_slot(p_slot) && |
448 | /* Wait for exclusive access to hardware */ | 401 | PWR_LED(p_slot->ctrl->ctrlcap)) |
449 | mutex_lock(&p_slot->ctrl->ctrl_lock); | ||
450 | |||
451 | p_slot->hpc_ops->green_led_off(p_slot); | 402 | p_slot->hpc_ops->green_led_off(p_slot); |
452 | 403 | ||
453 | /* Wait for the command to complete */ | ||
454 | wait_for_ctrl_irq (p_slot->ctrl); | ||
455 | |||
456 | /* Done with exclusive hardware access */ | ||
457 | mutex_unlock(&p_slot->ctrl->ctrl_lock); | ||
458 | } | ||
459 | p_slot->state = STATIC_STATE; | 404 | p_slot->state = STATIC_STATE; |
460 | } | 405 | } |
461 | 406 | ||
@@ -494,18 +439,10 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
494 | dbg("%s: adding bus:device(%x:%x)\n", | 439 | dbg("%s: adding bus:device(%x:%x)\n", |
495 | __FUNCTION__, p_slot->bus, p_slot->device); | 440 | __FUNCTION__, p_slot->bus, p_slot->device); |
496 | 441 | ||
497 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 442 | if (pciehp_enable_slot(p_slot) && |
498 | /* Wait for exclusive access to hardware */ | 443 | PWR_LED(p_slot->ctrl->ctrlcap)) |
499 | mutex_lock(&p_slot->ctrl->ctrl_lock); | ||
500 | |||
501 | p_slot->hpc_ops->green_led_off(p_slot); | 444 | p_slot->hpc_ops->green_led_off(p_slot); |
502 | 445 | ||
503 | /* Wait for the command to complete */ | ||
504 | wait_for_ctrl_irq (p_slot->ctrl); | ||
505 | |||
506 | /* Done with exclusive hardware access */ | ||
507 | mutex_unlock(&p_slot->ctrl->ctrl_lock); | ||
508 | } | ||
509 | p_slot->state = STATIC_STATE; | 446 | p_slot->state = STATIC_STATE; |
510 | } | 447 | } |
511 | 448 | ||
@@ -616,40 +553,18 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
616 | 553 | ||
617 | switch (p_slot->state) { | 554 | switch (p_slot->state) { |
618 | case BLINKINGOFF_STATE: | 555 | case BLINKINGOFF_STATE: |
619 | /* Wait for exclusive access to hardware */ | 556 | if (PWR_LED(ctrl->ctrlcap)) |
620 | mutex_lock(&ctrl->ctrl_lock); | ||
621 | |||
622 | if (PWR_LED(ctrl->ctrlcap)) { | ||
623 | p_slot->hpc_ops->green_led_on(p_slot); | 557 | p_slot->hpc_ops->green_led_on(p_slot); |
624 | /* Wait for the command to complete */ | ||
625 | wait_for_ctrl_irq (ctrl); | ||
626 | } | ||
627 | if (ATTN_LED(ctrl->ctrlcap)) { | ||
628 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
629 | 558 | ||
630 | /* Wait for the command to complete */ | 559 | if (ATTN_LED(ctrl->ctrlcap)) |
631 | wait_for_ctrl_irq (ctrl); | 560 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
632 | } | ||
633 | /* Done with exclusive hardware access */ | ||
634 | mutex_unlock(&ctrl->ctrl_lock); | ||
635 | break; | 561 | break; |
636 | case BLINKINGON_STATE: | 562 | case BLINKINGON_STATE: |
637 | /* Wait for exclusive access to hardware */ | 563 | if (PWR_LED(ctrl->ctrlcap)) |
638 | mutex_lock(&ctrl->ctrl_lock); | ||
639 | |||
640 | if (PWR_LED(ctrl->ctrlcap)) { | ||
641 | p_slot->hpc_ops->green_led_off(p_slot); | 564 | p_slot->hpc_ops->green_led_off(p_slot); |
642 | /* Wait for the command to complete */ | ||
643 | wait_for_ctrl_irq (ctrl); | ||
644 | } | ||
645 | if (ATTN_LED(ctrl->ctrlcap)){ | ||
646 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
647 | /* Wait for the command to complete */ | ||
648 | wait_for_ctrl_irq (ctrl); | ||
649 | } | ||
650 | /* Done with exclusive hardware access */ | ||
651 | mutex_unlock(&ctrl->ctrl_lock); | ||
652 | 565 | ||
566 | if (ATTN_LED(ctrl->ctrlcap)) | ||
567 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
653 | break; | 568 | break; |
654 | default: | 569 | default: |
655 | warn("Not a valid state\n"); | 570 | warn("Not a valid state\n"); |
@@ -676,26 +591,13 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
676 | info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); | 591 | info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); |
677 | } | 592 | } |
678 | 593 | ||
679 | /* Wait for exclusive access to hardware */ | ||
680 | mutex_lock(&ctrl->ctrl_lock); | ||
681 | |||
682 | /* blink green LED and turn off amber */ | 594 | /* blink green LED and turn off amber */ |
683 | if (PWR_LED(ctrl->ctrlcap)) { | 595 | if (PWR_LED(ctrl->ctrlcap)) |
684 | p_slot->hpc_ops->green_led_blink(p_slot); | 596 | p_slot->hpc_ops->green_led_blink(p_slot); |
685 | /* Wait for the command to complete */ | ||
686 | wait_for_ctrl_irq (ctrl); | ||
687 | } | ||
688 | 597 | ||
689 | if (ATTN_LED(ctrl->ctrlcap)) { | 598 | if (ATTN_LED(ctrl->ctrlcap)) |
690 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 599 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
691 | 600 | ||
692 | /* Wait for the command to complete */ | ||
693 | wait_for_ctrl_irq (ctrl); | ||
694 | } | ||
695 | |||
696 | /* Done with exclusive hardware access */ | ||
697 | mutex_unlock(&ctrl->ctrl_lock); | ||
698 | |||
699 | init_timer(&p_slot->task_event); | 601 | init_timer(&p_slot->task_event); |
700 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | 602 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ |
701 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | 603 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; |
@@ -708,21 +610,11 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
708 | else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { | 610 | else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { |
709 | if (POWER_CTRL(ctrl->ctrlcap)) { | 611 | if (POWER_CTRL(ctrl->ctrlcap)) { |
710 | dbg("power fault\n"); | 612 | dbg("power fault\n"); |
711 | /* Wait for exclusive access to hardware */ | 613 | if (ATTN_LED(ctrl->ctrlcap)) |
712 | mutex_lock(&ctrl->ctrl_lock); | ||
713 | |||
714 | if (ATTN_LED(ctrl->ctrlcap)) { | ||
715 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 614 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
716 | wait_for_ctrl_irq (ctrl); | ||
717 | } | ||
718 | 615 | ||
719 | if (PWR_LED(ctrl->ctrlcap)) { | 616 | if (PWR_LED(ctrl->ctrlcap)) |
720 | p_slot->hpc_ops->green_led_off(p_slot); | 617 | p_slot->hpc_ops->green_led_off(p_slot); |
721 | wait_for_ctrl_irq (ctrl); | ||
722 | } | ||
723 | |||
724 | /* Done with exclusive hardware access */ | ||
725 | mutex_unlock(&ctrl->ctrl_lock); | ||
726 | } | 618 | } |
727 | } | 619 | } |
728 | /***********SURPRISE REMOVAL********************/ | 620 | /***********SURPRISE REMOVAL********************/ |
@@ -750,7 +642,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
750 | } | 642 | } |
751 | } | 643 | } |
752 | 644 | ||
753 | |||
754 | int pciehp_enable_slot(struct slot *p_slot) | 645 | int pciehp_enable_slot(struct slot *p_slot) |
755 | { | 646 | { |
756 | u8 getstatus = 0; | 647 | u8 getstatus = 0; |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index d8f4f1241b56..9fbd9b9f9824 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -249,6 +249,24 @@ static void start_int_poll_timer(struct controller *ctrl, int sec) | |||
249 | add_timer(&ctrl->poll_timer); | 249 | add_timer(&ctrl->poll_timer); |
250 | } | 250 | } |
251 | 251 | ||
252 | static inline int pcie_wait_cmd(struct controller *ctrl) | ||
253 | { | ||
254 | DECLARE_WAITQUEUE(wait, current); | ||
255 | |||
256 | add_wait_queue(&ctrl->queue, &wait); | ||
257 | if (!pciehp_poll_mode) | ||
258 | /* Sleep for up to 1 second */ | ||
259 | msleep_interruptible(1000); | ||
260 | else | ||
261 | msleep_interruptible(2500); | ||
262 | |||
263 | remove_wait_queue(&ctrl->queue, &wait); | ||
264 | if (signal_pending(current)) | ||
265 | return -EINTR; | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
252 | static int pcie_write_cmd(struct slot *slot, u16 cmd) | 270 | static int pcie_write_cmd(struct slot *slot, u16 cmd) |
253 | { | 271 | { |
254 | struct controller *ctrl = slot->ctrl; | 272 | struct controller *ctrl = slot->ctrl; |
@@ -257,24 +275,34 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
257 | 275 | ||
258 | DBG_ENTER_ROUTINE | 276 | DBG_ENTER_ROUTINE |
259 | 277 | ||
278 | mutex_lock(&ctrl->ctrl_lock); | ||
279 | |||
260 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 280 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
261 | if (retval) { | 281 | if (retval) { |
262 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); | 282 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
263 | return retval; | 283 | goto out; |
264 | } | 284 | } |
265 | 285 | ||
266 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { | 286 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { |
267 | /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue | 287 | /* After 1 sec and CMD_COMPLETED still not set, just |
268 | the next command according to spec. Just print out the error message */ | 288 | proceed forward to issue the next command according |
269 | dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); | 289 | to spec. Just print out the error message */ |
290 | dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", | ||
291 | __FUNCTION__); | ||
270 | } | 292 | } |
271 | 293 | ||
272 | retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); | 294 | retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); |
273 | if (retval) { | 295 | if (retval) { |
274 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); | 296 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); |
275 | return retval; | 297 | goto out; |
276 | } | 298 | } |
277 | 299 | ||
300 | /* | ||
301 | * Wait for command completion. | ||
302 | */ | ||
303 | retval = pcie_wait_cmd(ctrl); | ||
304 | out: | ||
305 | mutex_unlock(&ctrl->ctrl_lock); | ||
278 | DBG_LEAVE_ROUTINE | 306 | DBG_LEAVE_ROUTINE |
279 | return retval; | 307 | return retval; |
280 | } | 308 | } |