diff options
author | Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | 2005-11-24 22:28:53 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-09 15:13:17 -0500 |
commit | bd62e271401c5ebf33a0dd24d89baf706f213251 (patch) | |
tree | 77b8e2cd249df83b0d256f8126047a037a1fc542 | |
parent | f467f6187fc60c954a9509b3a3e17ef89a4f6f22 (diff) |
[PATCH] shpchp: fix improper wait for command completion
Current SHPCHP driver uses msleep_interruptible() function to wait for
a command completion event. But I think this would cause an unnecessary
long wait until timeout, if command completion interrupt came before
task state was changed to TASK_INTERRUPTIBLE. This patch fixes this
issue. With this patch, command completion becomes faster as follows:
o Without this patch
# time echo 1 > power
real 0m4.708s
user 0m0.000s
sys 0m0.524s
o With this patch
# time echo 1 > power
real 0m2.221s
user 0m0.000s
sys 0m0.532s
Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/pci/hotplug/shpchp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 37 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 26 |
3 files changed, 27 insertions, 37 deletions
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 55b0cd15f348..ce0e9b6ce833 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -101,6 +101,7 @@ struct controller { | |||
101 | u32 cap_offset; | 101 | u32 cap_offset; |
102 | unsigned long mmio_base; | 102 | unsigned long mmio_base; |
103 | unsigned long mmio_size; | 103 | unsigned long mmio_size; |
104 | volatile int cmd_busy; | ||
104 | }; | 105 | }; |
105 | 106 | ||
106 | struct hotplug_params { | 107 | struct hotplug_params { |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 58619359ad08..25ccb0e47593 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -248,7 +248,6 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, | |||
248 | up(&ctrl->crit_sect); | 248 | up(&ctrl->crit_sect); |
249 | return WRONG_BUS_FREQUENCY; | 249 | return WRONG_BUS_FREQUENCY; |
250 | } | 250 | } |
251 | wait_for_ctrl_irq (ctrl); | ||
252 | 251 | ||
253 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 252 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
254 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | 253 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", |
@@ -330,9 +329,6 @@ static int board_added(struct slot *p_slot) | |||
330 | up(&ctrl->crit_sect); | 329 | up(&ctrl->crit_sect); |
331 | return -1; | 330 | return -1; |
332 | } | 331 | } |
333 | |||
334 | /* Wait for the command to complete */ | ||
335 | wait_for_ctrl_irq (ctrl); | ||
336 | 332 | ||
337 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | 333 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); |
338 | if (rc) { | 334 | if (rc) { |
@@ -352,7 +348,6 @@ static int board_added(struct slot *p_slot) | |||
352 | up(&ctrl->crit_sect); | 348 | up(&ctrl->crit_sect); |
353 | return WRONG_BUS_FREQUENCY; | 349 | return WRONG_BUS_FREQUENCY; |
354 | } | 350 | } |
355 | wait_for_ctrl_irq (ctrl); | ||
356 | 351 | ||
357 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 352 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
358 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", | 353 | err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", |
@@ -367,7 +362,6 @@ static int board_added(struct slot *p_slot) | |||
367 | up(&ctrl->crit_sect); | 362 | up(&ctrl->crit_sect); |
368 | return rc; | 363 | return rc; |
369 | } | 364 | } |
370 | wait_for_ctrl_irq (ctrl); | ||
371 | 365 | ||
372 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 366 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
373 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | 367 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); |
@@ -494,7 +488,6 @@ static int board_added(struct slot *p_slot) | |||
494 | up(&ctrl->crit_sect); | 488 | up(&ctrl->crit_sect); |
495 | return rc; | 489 | return rc; |
496 | } | 490 | } |
497 | wait_for_ctrl_irq (ctrl); | ||
498 | 491 | ||
499 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { | 492 | if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { |
500 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); | 493 | err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); |
@@ -532,9 +525,6 @@ static int board_added(struct slot *p_slot) | |||
532 | 525 | ||
533 | p_slot->hpc_ops->green_led_on(p_slot); | 526 | p_slot->hpc_ops->green_led_on(p_slot); |
534 | 527 | ||
535 | /* Wait for the command to complete */ | ||
536 | wait_for_ctrl_irq (ctrl); | ||
537 | |||
538 | /* Done with exclusive hardware access */ | 528 | /* Done with exclusive hardware access */ |
539 | up(&ctrl->crit_sect); | 529 | up(&ctrl->crit_sect); |
540 | 530 | ||
@@ -552,8 +542,6 @@ err_exit: | |||
552 | up(&ctrl->crit_sect); | 542 | up(&ctrl->crit_sect); |
553 | return rc; | 543 | return rc; |
554 | } | 544 | } |
555 | /* Wait for the command to complete */ | ||
556 | wait_for_ctrl_irq (ctrl); | ||
557 | 545 | ||
558 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | 546 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); |
559 | if (rc) { | 547 | if (rc) { |
@@ -603,8 +591,6 @@ static int remove_board(struct slot *p_slot) | |||
603 | up(&ctrl->crit_sect); | 591 | up(&ctrl->crit_sect); |
604 | return rc; | 592 | return rc; |
605 | } | 593 | } |
606 | /* Wait for the command to complete */ | ||
607 | wait_for_ctrl_irq (ctrl); | ||
608 | 594 | ||
609 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); | 595 | rc = p_slot->hpc_ops->check_cmd_status(ctrl); |
610 | if (rc) { | 596 | if (rc) { |
@@ -621,8 +607,6 @@ static int remove_board(struct slot *p_slot) | |||
621 | up(&ctrl->crit_sect); | 607 | up(&ctrl->crit_sect); |
622 | return rc; | 608 | return rc; |
623 | } | 609 | } |
624 | /* Wait for the command to complete */ | ||
625 | wait_for_ctrl_irq (ctrl); | ||
626 | 610 | ||
627 | /* Done with exclusive hardware access */ | 611 | /* Done with exclusive hardware access */ |
628 | up(&ctrl->crit_sect); | 612 | up(&ctrl->crit_sect); |
@@ -676,9 +660,6 @@ static void shpchp_pushbutton_thread (unsigned long slot) | |||
676 | 660 | ||
677 | p_slot->hpc_ops->green_led_off(p_slot); | 661 | p_slot->hpc_ops->green_led_off(p_slot); |
678 | 662 | ||
679 | /* Wait for the command to complete */ | ||
680 | wait_for_ctrl_irq (p_slot->ctrl); | ||
681 | |||
682 | /* Done with exclusive hardware access */ | 663 | /* Done with exclusive hardware access */ |
683 | up(&p_slot->ctrl->crit_sect); | 664 | up(&p_slot->ctrl->crit_sect); |
684 | } | 665 | } |
@@ -790,14 +771,9 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
790 | down(&ctrl->crit_sect); | 771 | down(&ctrl->crit_sect); |
791 | 772 | ||
792 | p_slot->hpc_ops->green_led_on(p_slot); | 773 | p_slot->hpc_ops->green_led_on(p_slot); |
793 | /* Wait for the command to complete */ | ||
794 | wait_for_ctrl_irq (ctrl); | ||
795 | 774 | ||
796 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 775 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
797 | 776 | ||
798 | /* Wait for the command to complete */ | ||
799 | wait_for_ctrl_irq (ctrl); | ||
800 | |||
801 | /* Done with exclusive hardware access */ | 777 | /* Done with exclusive hardware access */ |
802 | up(&ctrl->crit_sect); | 778 | up(&ctrl->crit_sect); |
803 | break; | 779 | break; |
@@ -806,12 +782,8 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
806 | down(&ctrl->crit_sect); | 782 | down(&ctrl->crit_sect); |
807 | 783 | ||
808 | p_slot->hpc_ops->green_led_off(p_slot); | 784 | p_slot->hpc_ops->green_led_off(p_slot); |
809 | /* Wait for the command to complete */ | ||
810 | wait_for_ctrl_irq (ctrl); | ||
811 | 785 | ||
812 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 786 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
813 | /* Wait for the command to complete */ | ||
814 | wait_for_ctrl_irq (ctrl); | ||
815 | 787 | ||
816 | /* Done with exclusive hardware access */ | 788 | /* Done with exclusive hardware access */ |
817 | up(&ctrl->crit_sect); | 789 | up(&ctrl->crit_sect); |
@@ -845,14 +817,9 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
845 | 817 | ||
846 | /* blink green LED and turn off amber */ | 818 | /* blink green LED and turn off amber */ |
847 | p_slot->hpc_ops->green_led_blink(p_slot); | 819 | p_slot->hpc_ops->green_led_blink(p_slot); |
848 | /* Wait for the command to complete */ | ||
849 | wait_for_ctrl_irq (ctrl); | ||
850 | 820 | ||
851 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 821 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
852 | 822 | ||
853 | /* Wait for the command to complete */ | ||
854 | wait_for_ctrl_irq (ctrl); | ||
855 | |||
856 | /* Done with exclusive hardware access */ | 823 | /* Done with exclusive hardware access */ |
857 | up(&ctrl->crit_sect); | 824 | up(&ctrl->crit_sect); |
858 | 825 | ||
@@ -870,12 +837,8 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
870 | down(&ctrl->crit_sect); | 837 | down(&ctrl->crit_sect); |
871 | 838 | ||
872 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 839 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
873 | /* Wait for the command to complete */ | ||
874 | wait_for_ctrl_irq (ctrl); | ||
875 | 840 | ||
876 | p_slot->hpc_ops->green_led_off(p_slot); | 841 | p_slot->hpc_ops->green_led_off(p_slot); |
877 | /* Wait for the command to complete */ | ||
878 | wait_for_ctrl_irq (ctrl); | ||
879 | 842 | ||
880 | /* Done with exclusive hardware access */ | 843 | /* Done with exclusive hardware access */ |
881 | up(&ctrl->crit_sect); | 844 | up(&ctrl->crit_sect); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index f25e11645071..b4226ff3a854 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -275,6 +275,25 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) | |||
275 | return; | 275 | return; |
276 | } | 276 | } |
277 | 277 | ||
278 | static inline int shpc_wait_cmd(struct controller *ctrl) | ||
279 | { | ||
280 | int retval = 0; | ||
281 | unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; | ||
282 | unsigned long timeout = msecs_to_jiffies(timeout_msec); | ||
283 | int rc = wait_event_interruptible_timeout(ctrl->queue, | ||
284 | !ctrl->cmd_busy, timeout); | ||
285 | if (!rc) { | ||
286 | retval = -EIO; | ||
287 | err("Command not completed in %d msec\n", timeout_msec); | ||
288 | } else if (rc < 0) { | ||
289 | retval = -EINTR; | ||
290 | info("Command was interrupted by a signal\n"); | ||
291 | } | ||
292 | ctrl->cmd_busy = 0; | ||
293 | |||
294 | return retval; | ||
295 | } | ||
296 | |||
278 | static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | 297 | static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) |
279 | { | 298 | { |
280 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 299 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; |
@@ -314,8 +333,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
314 | /* To make sure the Controller Busy bit is 0 before we send out the | 333 | /* To make sure the Controller Busy bit is 0 before we send out the |
315 | * command. | 334 | * command. |
316 | */ | 335 | */ |
336 | slot->ctrl->cmd_busy = 1; | ||
317 | writew(temp_word, php_ctlr->creg + CMD); | 337 | writew(temp_word, php_ctlr->creg + CMD); |
318 | 338 | ||
339 | /* | ||
340 | * Wait for command completion. | ||
341 | */ | ||
342 | retval = shpc_wait_cmd(slot->ctrl); | ||
343 | |||
319 | DBG_LEAVE_ROUTINE | 344 | DBG_LEAVE_ROUTINE |
320 | return retval; | 345 | return retval; |
321 | } | 346 | } |
@@ -1064,6 +1089,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
1064 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); | 1089 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); |
1065 | temp_dword &= 0xfffdffff; | 1090 | temp_dword &= 0xfffdffff; |
1066 | writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); | 1091 | writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); |
1092 | ctrl->cmd_busy = 0; | ||
1067 | wake_up_interruptible(&ctrl->queue); | 1093 | wake_up_interruptible(&ctrl->queue); |
1068 | } | 1094 | } |
1069 | 1095 | ||