From bd62e271401c5ebf33a0dd24d89baf706f213251 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Nov 2005 12:28:53 +0900 Subject: [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 Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/pci/hotplug/shpchp_hpc.c') 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) return; } +static inline int shpc_wait_cmd(struct controller *ctrl) +{ + int retval = 0; + unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; + unsigned long timeout = msecs_to_jiffies(timeout_msec); + int rc = wait_event_interruptible_timeout(ctrl->queue, + !ctrl->cmd_busy, timeout); + if (!rc) { + retval = -EIO; + err("Command not completed in %d msec\n", timeout_msec); + } else if (rc < 0) { + retval = -EINTR; + info("Command was interrupted by a signal\n"); + } + ctrl->cmd_busy = 0; + + return retval; +} + static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) { 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) /* To make sure the Controller Busy bit is 0 before we send out the * command. */ + slot->ctrl->cmd_busy = 1; writew(temp_word, php_ctlr->creg + CMD); + /* + * Wait for command completion. + */ + retval = shpc_wait_cmd(slot->ctrl); + DBG_LEAVE_ROUTINE return retval; } @@ -1064,6 +1089,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); temp_dword &= 0xfffdffff; writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } -- cgit v1.2.3