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 /drivers/pci/hotplug/shpchp_hpc.c | |
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>
Diffstat (limited to 'drivers/pci/hotplug/shpchp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 26 |
1 files changed, 26 insertions, 0 deletions
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 | ||