mirror of
https://github.com/adulau/aha.git
synced 2025-01-04 07:03:38 +00:00
[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>
This commit is contained in:
parent
f467f6187f
commit
bd62e27140
3 changed files with 27 additions and 37 deletions
|
@ -101,6 +101,7 @@ struct controller {
|
||||||
u32 cap_offset;
|
u32 cap_offset;
|
||||||
unsigned long mmio_base;
|
unsigned long mmio_base;
|
||||||
unsigned long mmio_size;
|
unsigned long mmio_size;
|
||||||
|
volatile int cmd_busy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hotplug_params {
|
struct hotplug_params {
|
||||||
|
|
|
@ -248,7 +248,6 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return WRONG_BUS_FREQUENCY;
|
return WRONG_BUS_FREQUENCY;
|
||||||
}
|
}
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
||||||
err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
|
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)
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
|
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -352,7 +348,6 @@ static int board_added(struct slot *p_slot)
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return WRONG_BUS_FREQUENCY;
|
return WRONG_BUS_FREQUENCY;
|
||||||
}
|
}
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
||||||
err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
|
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)
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
||||||
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
|
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
|
||||||
|
@ -494,7 +488,6 @@ static int board_added(struct slot *p_slot)
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
|
||||||
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
|
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
|
||||||
|
@ -532,9 +525,6 @@ static int board_added(struct slot *p_slot)
|
||||||
|
|
||||||
p_slot->hpc_ops->green_led_on(p_slot);
|
p_slot->hpc_ops->green_led_on(p_slot);
|
||||||
|
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
/* Done with exclusive hardware access */
|
/* Done with exclusive hardware access */
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
|
|
||||||
|
@ -552,8 +542,6 @@ err_exit:
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
|
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -603,8 +591,6 @@ static int remove_board(struct slot *p_slot)
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
|
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -621,8 +607,6 @@ static int remove_board(struct slot *p_slot)
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
/* Done with exclusive hardware access */
|
/* Done with exclusive hardware access */
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
|
@ -676,9 +660,6 @@ static void shpchp_pushbutton_thread (unsigned long slot)
|
||||||
|
|
||||||
p_slot->hpc_ops->green_led_off(p_slot);
|
p_slot->hpc_ops->green_led_off(p_slot);
|
||||||
|
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (p_slot->ctrl);
|
|
||||||
|
|
||||||
/* Done with exclusive hardware access */
|
/* Done with exclusive hardware access */
|
||||||
up(&p_slot->ctrl->crit_sect);
|
up(&p_slot->ctrl->crit_sect);
|
||||||
}
|
}
|
||||||
|
@ -790,14 +771,9 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||||
down(&ctrl->crit_sect);
|
down(&ctrl->crit_sect);
|
||||||
|
|
||||||
p_slot->hpc_ops->green_led_on(p_slot);
|
p_slot->hpc_ops->green_led_on(p_slot);
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||||
|
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
/* Done with exclusive hardware access */
|
/* Done with exclusive hardware access */
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
break;
|
break;
|
||||||
|
@ -806,12 +782,8 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||||
down(&ctrl->crit_sect);
|
down(&ctrl->crit_sect);
|
||||||
|
|
||||||
p_slot->hpc_ops->green_led_off(p_slot);
|
p_slot->hpc_ops->green_led_off(p_slot);
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
/* Done with exclusive hardware access */
|
/* Done with exclusive hardware access */
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
|
@ -845,14 +817,9 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||||
|
|
||||||
/* blink green LED and turn off amber */
|
/* blink green LED and turn off amber */
|
||||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||||
|
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
/* Done with exclusive hardware access */
|
/* Done with exclusive hardware access */
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
|
|
||||||
|
@ -870,12 +837,8 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||||
down(&ctrl->crit_sect);
|
down(&ctrl->crit_sect);
|
||||||
|
|
||||||
p_slot->hpc_ops->set_attention_status(p_slot, 1);
|
p_slot->hpc_ops->set_attention_status(p_slot, 1);
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
p_slot->hpc_ops->green_led_off(p_slot);
|
p_slot->hpc_ops->green_led_off(p_slot);
|
||||||
/* Wait for the command to complete */
|
|
||||||
wait_for_ctrl_irq (ctrl);
|
|
||||||
|
|
||||||
/* Done with exclusive hardware access */
|
/* Done with exclusive hardware access */
|
||||||
up(&ctrl->crit_sect);
|
up(&ctrl->crit_sect);
|
||||||
|
|
|
@ -275,6 +275,25 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
|
||||||
return;
|
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)
|
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;
|
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
|
/* To make sure the Controller Busy bit is 0 before we send out the
|
||||||
* command.
|
* command.
|
||||||
*/
|
*/
|
||||||
|
slot->ctrl->cmd_busy = 1;
|
||||||
writew(temp_word, php_ctlr->creg + CMD);
|
writew(temp_word, php_ctlr->creg + CMD);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for command completion.
|
||||||
|
*/
|
||||||
|
retval = shpc_wait_cmd(slot->ctrl);
|
||||||
|
|
||||||
DBG_LEAVE_ROUTINE
|
DBG_LEAVE_ROUTINE
|
||||||
return retval;
|
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 = readl(php_ctlr->creg + SERR_INTR_ENABLE);
|
||||||
temp_dword &= 0xfffdffff;
|
temp_dword &= 0xfffdffff;
|
||||||
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
|
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
|
||||||
|
ctrl->cmd_busy = 0;
|
||||||
wake_up_interruptible(&ctrl->queue);
|
wake_up_interruptible(&ctrl->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue