diff options
-rw-r--r-- | drivers/pci/hotplug/shpchp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 120 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 25 |
3 files changed, 23 insertions, 123 deletions
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index f6d606dde691..b1e2a7705835 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -80,6 +80,7 @@ struct event_info { | |||
80 | struct controller { | 80 | struct controller { |
81 | struct list_head ctrl_list; | 81 | struct list_head ctrl_list; |
82 | struct mutex crit_sect; /* critical section mutex */ | 82 | struct mutex crit_sect; /* critical section mutex */ |
83 | struct mutex cmd_lock; /* command lock */ | ||
83 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ | 84 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ |
84 | int num_slots; /* Number of slots on ctlr */ | 85 | int num_slots; /* Number of slots on ctlr */ |
85 | int slot_num_inc; /* 1 or -1 */ | 86 | int slot_num_inc; /* 1 or -1 */ |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 3a8e733aead5..802c4c48d186 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -242,21 +242,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, | |||
242 | int rc = 0; | 242 | int rc = 0; |
243 | 243 | ||
244 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); | 244 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); |
245 | mutex_lock(&ctrl->crit_sect); | ||
246 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { | 245 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { |
247 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); | 246 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); |
248 | mutex_unlock(&ctrl->crit_sect); | ||
249 | return WRONG_BUS_FREQUENCY; | ||
250 | } | ||
251 | |||
252 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
253 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | ||
254 | __FUNCTION__); | ||
255 | err("%s: Error code (%d)\n", __FUNCTION__, rc); | ||
256 | mutex_unlock(&ctrl->crit_sect); | ||
257 | return WRONG_BUS_FREQUENCY; | 247 | return WRONG_BUS_FREQUENCY; |
258 | } | 248 | } |
259 | mutex_unlock(&ctrl->crit_sect); | ||
260 | return rc; | 249 | return rc; |
261 | } | 250 | } |
262 | 251 | ||
@@ -330,15 +319,6 @@ static int board_added(struct slot *p_slot) | |||
330 | return -1; | 319 | return -1; |
331 | } | 320 | } |
332 | 321 | ||
333 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | ||
334 | if (rc) { | ||
335 | err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); | ||
336 | /* Done with exclusive hardware access */ | ||
337 | mutex_unlock(&ctrl->crit_sect); | ||
338 | return -1; | ||
339 | } | ||
340 | |||
341 | |||
342 | if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { | 322 | if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { |
343 | if (slots_not_empty) | 323 | if (slots_not_empty) |
344 | return WRONG_BUS_FREQUENCY; | 324 | return WRONG_BUS_FREQUENCY; |
@@ -349,25 +329,12 @@ static int board_added(struct slot *p_slot) | |||
349 | return WRONG_BUS_FREQUENCY; | 329 | return WRONG_BUS_FREQUENCY; |
350 | } | 330 | } |
351 | 331 | ||
352 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
353 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | ||
354 | __FUNCTION__); | ||
355 | err("%s: Error code (%d)\n", __FUNCTION__, rc); | ||
356 | mutex_unlock(&ctrl->crit_sect); | ||
357 | return WRONG_BUS_FREQUENCY; | ||
358 | } | ||
359 | /* turn on board, blink green LED, turn off Amber LED */ | 332 | /* turn on board, blink green LED, turn off Amber LED */ |
360 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { | 333 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { |
361 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); | 334 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); |
362 | mutex_unlock(&ctrl->crit_sect); | 335 | mutex_unlock(&ctrl->crit_sect); |
363 | return rc; | 336 | return rc; |
364 | } | 337 | } |
365 | |||
366 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
367 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | ||
368 | mutex_unlock(&ctrl->crit_sect); | ||
369 | return rc; | ||
370 | } | ||
371 | } | 338 | } |
372 | 339 | ||
373 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); | 340 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); |
@@ -481,22 +448,12 @@ static int board_added(struct slot *p_slot) | |||
481 | return rc; | 448 | return rc; |
482 | } | 449 | } |
483 | 450 | ||
484 | mutex_lock(&ctrl->crit_sect); | ||
485 | /* turn on board, blink green LED, turn off Amber LED */ | 451 | /* turn on board, blink green LED, turn off Amber LED */ |
486 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { | 452 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { |
487 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); | 453 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); |
488 | mutex_unlock(&ctrl->crit_sect); | ||
489 | return rc; | 454 | return rc; |
490 | } | 455 | } |
491 | 456 | ||
492 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | ||
493 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | ||
494 | mutex_unlock(&ctrl->crit_sect); | ||
495 | return rc; | ||
496 | } | ||
497 | |||
498 | mutex_unlock(&ctrl->crit_sect); | ||
499 | |||
500 | /* Wait for ~1 second */ | 457 | /* Wait for ~1 second */ |
501 | wait_for_ctrl_irq (ctrl); | 458 | wait_for_ctrl_irq (ctrl); |
502 | 459 | ||
@@ -520,40 +477,18 @@ static int board_added(struct slot *p_slot) | |||
520 | p_slot->is_a_board = 0x01; | 477 | p_slot->is_a_board = 0x01; |
521 | p_slot->pwr_save = 1; | 478 | p_slot->pwr_save = 1; |
522 | 479 | ||
523 | /* Wait for exclusive access to hardware */ | ||
524 | mutex_lock(&ctrl->crit_sect); | ||
525 | |||
526 | p_slot->hpc_ops->green_led_on(p_slot); | 480 | p_slot->hpc_ops->green_led_on(p_slot); |
527 | 481 | ||
528 | /* Done with exclusive hardware access */ | ||
529 | mutex_unlock(&ctrl->crit_sect); | ||
530 | |||
531 | return 0; | 482 | return 0; |
532 | 483 | ||
533 | err_exit: | 484 | err_exit: |
534 | /* Wait for exclusive access to hardware */ | ||
535 | mutex_lock(&ctrl->crit_sect); | ||
536 | |||
537 | /* turn off slot, turn on Amber LED, turn off Green LED */ | 485 | /* turn off slot, turn on Amber LED, turn off Green LED */ |
538 | rc = p_slot->hpc_ops->slot_disable(p_slot); | 486 | rc = p_slot->hpc_ops->slot_disable(p_slot); |
539 | if (rc) { | 487 | if (rc) { |
540 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 488 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
541 | /* Done with exclusive hardware access */ | ||
542 | mutex_unlock(&ctrl->crit_sect); | ||
543 | return rc; | 489 | return rc; |
544 | } | 490 | } |
545 | 491 | ||
546 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | ||
547 | if (rc) { | ||
548 | err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); | ||
549 | /* Done with exclusive hardware access */ | ||
550 | mutex_unlock(&ctrl->crit_sect); | ||
551 | return rc; | ||
552 | } | ||
553 | |||
554 | /* Done with exclusive hardware access */ | ||
555 | mutex_unlock(&ctrl->crit_sect); | ||
556 | |||
557 | return(rc); | 492 | return(rc); |
558 | } | 493 | } |
559 | 494 | ||
@@ -580,37 +515,19 @@ static int remove_board(struct slot *p_slot) | |||
580 | if (p_slot->is_a_board) | 515 | if (p_slot->is_a_board) |
581 | p_slot->status = 0x01; | 516 | p_slot->status = 0x01; |
582 | 517 | ||
583 | /* Wait for exclusive access to hardware */ | ||
584 | mutex_lock(&ctrl->crit_sect); | ||
585 | |||
586 | /* turn off slot, turn on Amber LED, turn off Green LED */ | 518 | /* turn off slot, turn on Amber LED, turn off Green LED */ |
587 | rc = p_slot->hpc_ops->slot_disable(p_slot); | 519 | rc = p_slot->hpc_ops->slot_disable(p_slot); |
588 | if (rc) { | 520 | if (rc) { |
589 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 521 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
590 | /* Done with exclusive hardware access */ | ||
591 | mutex_unlock(&ctrl->crit_sect); | ||
592 | return rc; | 522 | return rc; |
593 | } | 523 | } |
594 | |||
595 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | ||
596 | if (rc) { | ||
597 | err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); | ||
598 | /* Done with exclusive hardware access */ | ||
599 | mutex_unlock(&ctrl->crit_sect); | ||
600 | return rc; | ||
601 | } | ||
602 | 524 | ||
603 | rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); | 525 | rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); |
604 | if (rc) { | 526 | if (rc) { |
605 | err("%s: Issue of Set Attention command failed\n", __FUNCTION__); | 527 | err("%s: Issue of Set Attention command failed\n", __FUNCTION__); |
606 | /* Done with exclusive hardware access */ | ||
607 | mutex_unlock(&ctrl->crit_sect); | ||
608 | return rc; | 528 | return rc; |
609 | } | 529 | } |
610 | 530 | ||
611 | /* Done with exclusive hardware access */ | ||
612 | mutex_unlock(&ctrl->crit_sect); | ||
613 | |||
614 | p_slot->pwr_save = 0; | 531 | p_slot->pwr_save = 0; |
615 | p_slot->is_a_board = 0; | 532 | p_slot->is_a_board = 0; |
616 | 533 | ||
@@ -654,15 +571,9 @@ static void shpchp_pushbutton_thread (unsigned long slot) | |||
654 | } else { | 571 | } else { |
655 | p_slot->state = POWERON_STATE; | 572 | p_slot->state = POWERON_STATE; |
656 | 573 | ||
657 | if (shpchp_enable_slot(p_slot)) { | 574 | if (shpchp_enable_slot(p_slot)) |
658 | /* Wait for exclusive access to hardware */ | ||
659 | mutex_lock(&p_slot->ctrl->crit_sect); | ||
660 | |||
661 | p_slot->hpc_ops->green_led_off(p_slot); | 575 | p_slot->hpc_ops->green_led_off(p_slot); |
662 | 576 | ||
663 | /* Done with exclusive hardware access */ | ||
664 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
665 | } | ||
666 | p_slot->state = STATIC_STATE; | 577 | p_slot->state = STATIC_STATE; |
667 | } | 578 | } |
668 | 579 | ||
@@ -767,27 +678,12 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
767 | 678 | ||
768 | switch (p_slot->state) { | 679 | switch (p_slot->state) { |
769 | case BLINKINGOFF_STATE: | 680 | case BLINKINGOFF_STATE: |
770 | /* Wait for exclusive access to hardware */ | ||
771 | mutex_lock(&ctrl->crit_sect); | ||
772 | |||
773 | p_slot->hpc_ops->green_led_on(p_slot); | 681 | p_slot->hpc_ops->green_led_on(p_slot); |
774 | |||
775 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 682 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
776 | |||
777 | /* Done with exclusive hardware access */ | ||
778 | mutex_unlock(&ctrl->crit_sect); | ||
779 | break; | 683 | break; |
780 | case BLINKINGON_STATE: | 684 | case BLINKINGON_STATE: |
781 | /* Wait for exclusive access to hardware */ | ||
782 | mutex_lock(&ctrl->crit_sect); | ||
783 | |||
784 | p_slot->hpc_ops->green_led_off(p_slot); | 685 | p_slot->hpc_ops->green_led_off(p_slot); |
785 | |||
786 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 686 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
787 | |||
788 | /* Done with exclusive hardware access */ | ||
789 | mutex_unlock(&ctrl->crit_sect); | ||
790 | |||
791 | break; | 687 | break; |
792 | default: | 688 | default: |
793 | warn("Not a valid state\n"); | 689 | warn("Not a valid state\n"); |
@@ -812,17 +708,10 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
812 | info(msg_button_on, p_slot->number); | 708 | info(msg_button_on, p_slot->number); |
813 | } | 709 | } |
814 | 710 | ||
815 | /* Wait for exclusive access to hardware */ | ||
816 | mutex_lock(&ctrl->crit_sect); | ||
817 | |||
818 | /* blink green LED and turn off amber */ | 711 | /* blink green LED and turn off amber */ |
819 | p_slot->hpc_ops->green_led_blink(p_slot); | 712 | p_slot->hpc_ops->green_led_blink(p_slot); |
820 | |||
821 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 713 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
822 | 714 | ||
823 | /* Done with exclusive hardware access */ | ||
824 | mutex_unlock(&ctrl->crit_sect); | ||
825 | |||
826 | init_timer(&p_slot->task_event); | 715 | init_timer(&p_slot->task_event); |
827 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | 716 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ |
828 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | 717 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; |
@@ -833,15 +722,8 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
833 | } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { | 722 | } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { |
834 | /***********POWER FAULT********************/ | 723 | /***********POWER FAULT********************/ |
835 | dbg("%s: power fault\n", __FUNCTION__); | 724 | dbg("%s: power fault\n", __FUNCTION__); |
836 | /* Wait for exclusive access to hardware */ | ||
837 | mutex_lock(&ctrl->crit_sect); | ||
838 | |||
839 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 725 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
840 | |||
841 | p_slot->hpc_ops->green_led_off(p_slot); | 726 | p_slot->hpc_ops->green_led_off(p_slot); |
842 | |||
843 | /* Done with exclusive hardware access */ | ||
844 | mutex_unlock(&ctrl->crit_sect); | ||
845 | } else { | 727 | } else { |
846 | /* refresh notification */ | 728 | /* refresh notification */ |
847 | if (p_slot) | 729 | if (p_slot) |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index ae81427e42b1..c32a1b16704f 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -231,6 +231,7 @@ static spinlock_t list_lock; | |||
231 | static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); | 231 | static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); |
232 | 232 | ||
233 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); | 233 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); |
234 | static int hpc_check_cmd_status(struct controller *ctrl); | ||
234 | 235 | ||
235 | /* This is the interrupt polling timeout function. */ | 236 | /* This is the interrupt polling timeout function. */ |
236 | static void int_poll_timeout(unsigned long lphp_ctlr) | 237 | static void int_poll_timeout(unsigned long lphp_ctlr) |
@@ -303,10 +304,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
303 | int i; | 304 | int i; |
304 | 305 | ||
305 | DBG_ENTER_ROUTINE | 306 | DBG_ENTER_ROUTINE |
306 | 307 | ||
308 | mutex_lock(&slot->ctrl->cmd_lock); | ||
309 | |||
307 | if (!php_ctlr) { | 310 | if (!php_ctlr) { |
308 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 311 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
309 | return -1; | 312 | retval = -EINVAL; |
313 | goto out; | ||
310 | } | 314 | } |
311 | 315 | ||
312 | for (i = 0; i < 10; i++) { | 316 | for (i = 0; i < 10; i++) { |
@@ -323,7 +327,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
323 | if (cmd_status & 0x1) { | 327 | if (cmd_status & 0x1) { |
324 | /* After 1 sec and and the controller is still busy */ | 328 | /* After 1 sec and and the controller is still busy */ |
325 | err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); | 329 | err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); |
326 | return -1; | 330 | retval = -EBUSY; |
331 | goto out; | ||
327 | } | 332 | } |
328 | 333 | ||
329 | ++t_slot; | 334 | ++t_slot; |
@@ -340,6 +345,17 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
340 | * Wait for command completion. | 345 | * Wait for command completion. |
341 | */ | 346 | */ |
342 | retval = shpc_wait_cmd(slot->ctrl); | 347 | retval = shpc_wait_cmd(slot->ctrl); |
348 | if (retval) | ||
349 | goto out; | ||
350 | |||
351 | cmd_status = hpc_check_cmd_status(slot->ctrl); | ||
352 | if (cmd_status) { | ||
353 | err("%s: Failed to issued command 0x%x (error code = %d)\n", | ||
354 | __FUNCTION__, cmd, cmd_status); | ||
355 | retval = -EIO; | ||
356 | } | ||
357 | out: | ||
358 | mutex_unlock(&slot->ctrl->cmd_lock); | ||
343 | 359 | ||
344 | DBG_LEAVE_ROUTINE | 360 | DBG_LEAVE_ROUTINE |
345 | return retval; | 361 | return retval; |
@@ -1343,7 +1359,6 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
1343 | .green_led_blink = hpc_set_green_led_blink, | 1359 | .green_led_blink = hpc_set_green_led_blink, |
1344 | 1360 | ||
1345 | .release_ctlr = hpc_release_ctlr, | 1361 | .release_ctlr = hpc_release_ctlr, |
1346 | .check_cmd_status = hpc_check_cmd_status, | ||
1347 | }; | 1362 | }; |
1348 | 1363 | ||
1349 | inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, | 1364 | inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, |
@@ -1455,6 +1470,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1455 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); | 1470 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); |
1456 | 1471 | ||
1457 | mutex_init(&ctrl->crit_sect); | 1472 | mutex_init(&ctrl->crit_sect); |
1473 | mutex_init(&ctrl->cmd_lock); | ||
1474 | |||
1458 | /* Setup wait queue */ | 1475 | /* Setup wait queue */ |
1459 | init_waitqueue_head(&ctrl->queue); | 1476 | init_waitqueue_head(&ctrl->queue); |
1460 | 1477 | ||