Commit 44ef4cef authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Greg Kroah-Hartman

pciehp: cleanup wait command completion

This patch cleans up the code to wait for command completion.
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarKristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 75e13178
...@@ -173,24 +173,6 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) ...@@ -173,24 +173,6 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
return NULL; return NULL;
} }
static inline int wait_for_ctrl_irq(struct controller *ctrl)
{
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&ctrl->queue, &wait);
if (!pciehp_poll_mode)
/* Sleep for up to 1 second */
msleep_interruptible(1000);
else
msleep_interruptible(2500);
remove_wait_queue(&ctrl->queue, &wait);
if (signal_pending(current))
return -EINTR;
return 0;
}
struct hpc_ops { struct hpc_ops {
int (*power_on_slot)(struct slot *slot); int (*power_on_slot)(struct slot *slot);
int (*power_off_slot)(struct slot *slot); int (*power_off_slot)(struct slot *slot);
......
...@@ -374,25 +374,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ ...@@ -374,25 +374,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
pciehp_ctrl_list = ctrl; pciehp_ctrl_list = ctrl;
} }
/* Wait for exclusive access to hardware */
mutex_lock(&ctrl->ctrl_lock);
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
if (rc) { if (rc)
/* Done with exclusive hardware access */
mutex_unlock(&ctrl->ctrl_lock);
goto err_out_free_ctrl_slot; goto err_out_free_ctrl_slot;
} else
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
} }
/* Done with exclusive hardware access */
mutex_unlock(&ctrl->ctrl_lock);
return 0; return 0;
err_out_free_ctrl_slot: err_out_free_ctrl_slot:
......
...@@ -229,35 +229,25 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) ...@@ -229,35 +229,25 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
static void set_slot_off(struct controller *ctrl, struct slot * pslot) static void set_slot_off(struct controller *ctrl, struct slot * pslot)
{ {
/* Wait for exclusive access to hardware */
mutex_lock(&ctrl->ctrl_lock);
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/ /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
if (POWER_CTRL(ctrl->ctrlcap)) { if (POWER_CTRL(ctrl->ctrlcap)) {
if (pslot->hpc_ops->power_off_slot(pslot)) { if (pslot->hpc_ops->power_off_slot(pslot)) {
err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); err("%s: Issue of Slot Power Off command failed\n",
mutex_unlock(&ctrl->ctrl_lock); __FUNCTION__);
return; return;
} }
wait_for_ctrl_irq (ctrl);
} }
if (PWR_LED(ctrl->ctrlcap)) { if (PWR_LED(ctrl->ctrlcap))
pslot->hpc_ops->green_led_off(pslot); pslot->hpc_ops->green_led_off(pslot);
wait_for_ctrl_irq (ctrl);
}
if (ATTN_LED(ctrl->ctrlcap)) { if (ATTN_LED(ctrl->ctrlcap)) {
if (pslot->hpc_ops->set_attention_status(pslot, 1)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); err("%s: Issue of Set Attention Led command failed\n",
mutex_unlock(&ctrl->ctrl_lock); __FUNCTION__);
return; return;
} }
wait_for_ctrl_irq (ctrl);
} }
/* Done with exclusive hardware access */
mutex_unlock(&ctrl->ctrl_lock);
} }
/** /**
...@@ -270,7 +260,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) ...@@ -270,7 +260,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
static int board_added(struct slot *p_slot) static int board_added(struct slot *p_slot)
{ {
u8 hp_slot; u8 hp_slot;
int rc = 0; int retval = 0;
struct controller *ctrl = p_slot->ctrl; struct controller *ctrl = p_slot->ctrl;
hp_slot = p_slot->device - ctrl->slot_device_offset; hp_slot = p_slot->device - ctrl->slot_device_offset;
...@@ -279,51 +269,36 @@ static int board_added(struct slot *p_slot) ...@@ -279,51 +269,36 @@ static int board_added(struct slot *p_slot)
__FUNCTION__, p_slot->device, __FUNCTION__, p_slot->device,
ctrl->slot_device_offset, hp_slot); ctrl->slot_device_offset, hp_slot);
/* Wait for exclusive access to hardware */
mutex_lock(&ctrl->ctrl_lock);
if (POWER_CTRL(ctrl->ctrlcap)) { if (POWER_CTRL(ctrl->ctrlcap)) {
/* Power on slot */ /* Power on slot */
rc = p_slot->hpc_ops->power_on_slot(p_slot); retval = p_slot->hpc_ops->power_on_slot(p_slot);
if (rc) { if (retval)
mutex_unlock(&ctrl->ctrl_lock); return retval;
return -1;
}
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
} }
if (PWR_LED(ctrl->ctrlcap)) { if (PWR_LED(ctrl->ctrlcap))
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);
}
/* Done with exclusive hardware access */
mutex_unlock(&ctrl->ctrl_lock);
/* Wait for ~1 second */ /* Wait for ~1 second */
wait_for_ctrl_irq (ctrl); msleep(1000);
/* Check link training status */ /* Check link training status */
rc = p_slot->hpc_ops->check_lnk_status(ctrl); retval = p_slot->hpc_ops->check_lnk_status(ctrl);
if (rc) { if (retval) {
err("%s: Failed to check link status\n", __FUNCTION__); err("%s: Failed to check link status\n", __FUNCTION__);
set_slot_off(ctrl, p_slot); set_slot_off(ctrl, p_slot);
return rc; return retval;
} }
/* Check for a power fault */ /* Check for a power fault */
if (p_slot->hpc_ops->query_power_fault(p_slot)) { if (p_slot->hpc_ops->query_power_fault(p_slot)) {
dbg("%s: power fault detected\n", __FUNCTION__); dbg("%s: power fault detected\n", __FUNCTION__);
rc = POWER_FAILURE; retval = POWER_FAILURE;
goto err_exit; goto err_exit;
} }
rc = pciehp_configure_device(p_slot); retval = pciehp_configure_device(p_slot);
if (rc) { if (retval) {
err("Cannot add device 0x%x:%x\n", p_slot->bus, err("Cannot add device 0x%x:%x\n", p_slot->bus,
p_slot->device); p_slot->device);
goto err_exit; goto err_exit;
...@@ -334,26 +309,16 @@ static int board_added(struct slot *p_slot) ...@@ -334,26 +309,16 @@ static int board_added(struct slot *p_slot)
*/ */
if (pcie_mch_quirk) if (pcie_mch_quirk)
pci_fixup_device(pci_fixup_final, ctrl->pci_dev); pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
if (PWR_LED(ctrl->ctrlcap)) { if (PWR_LED(ctrl->ctrlcap))
/* Wait for exclusive access to hardware */
mutex_lock(&ctrl->ctrl_lock);
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 */
mutex_unlock(&ctrl->ctrl_lock);
}
return 0; return 0;
err_exit: err_exit:
set_slot_off(ctrl, p_slot); set_slot_off(ctrl, p_slot);
return -1; return retval;
} }
/** /**
* remove_board - Turns off slot and LED's * remove_board - Turns off slot and LED's
* *
...@@ -362,45 +327,33 @@ static int remove_board(struct slot *p_slot) ...@@ -362,45 +327,33 @@ static int remove_board(struct slot *p_slot)
{ {
u8 device; u8 device;
u8 hp_slot; u8 hp_slot;
int rc; int retval = 0;
struct controller *ctrl = p_slot->ctrl; struct controller *ctrl = p_slot->ctrl;
if (pciehp_unconfigure_device(p_slot)) retval = pciehp_unconfigure_device(p_slot);
return 1; if (retval)
return retval;
device = p_slot->device; device = p_slot->device;
hp_slot = p_slot->device - ctrl->slot_device_offset; hp_slot = p_slot->device - ctrl->slot_device_offset;
p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
/* Wait for exclusive access to hardware */
mutex_lock(&ctrl->ctrl_lock);
if (POWER_CTRL(ctrl->ctrlcap)) { if (POWER_CTRL(ctrl->ctrlcap)) {
/* power off slot */ /* power off slot */
rc = p_slot->hpc_ops->power_off_slot(p_slot); retval = p_slot->hpc_ops->power_off_slot(p_slot);
if (rc) { if (retval) {
err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); err("%s: Issue of Slot Disable command failed\n",
mutex_unlock(&ctrl->ctrl_lock); __FUNCTION__);
return rc; return retval;
} }
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
} }
if (PWR_LED(ctrl->ctrlcap)) { if (PWR_LED(ctrl->ctrlcap))
/* turn off Green LED */ /* turn off Green LED */
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 */
mutex_unlock(&ctrl->ctrl_lock);
return 0; return 0;
} }
...@@ -444,18 +397,10 @@ static void pciehp_pushbutton_thread(unsigned long slot) ...@@ -444,18 +397,10 @@ static void pciehp_pushbutton_thread(unsigned long slot)
dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
p_slot->bus, p_slot->device); p_slot->bus, p_slot->device);
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { if (pciehp_enable_slot(p_slot) &&
/* Wait for exclusive access to hardware */ PWR_LED(p_slot->ctrl->ctrlcap))
mutex_lock(&p_slot->ctrl->ctrl_lock);
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 */
mutex_unlock(&p_slot->ctrl->ctrl_lock);
}
p_slot->state = STATIC_STATE; p_slot->state = STATIC_STATE;
} }
...@@ -494,18 +439,10 @@ static void pciehp_surprise_rm_thread(unsigned long slot) ...@@ -494,18 +439,10 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
dbg("%s: adding bus:device(%x:%x)\n", dbg("%s: adding bus:device(%x:%x)\n",
__FUNCTION__, p_slot->bus, p_slot->device); __FUNCTION__, p_slot->bus, p_slot->device);
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { if (pciehp_enable_slot(p_slot) &&
/* Wait for exclusive access to hardware */ PWR_LED(p_slot->ctrl->ctrlcap))
mutex_lock(&p_slot->ctrl->ctrl_lock);
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 */
mutex_unlock(&p_slot->ctrl->ctrl_lock);
}
p_slot->state = STATIC_STATE; p_slot->state = STATIC_STATE;
} }
...@@ -616,40 +553,18 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -616,40 +553,18 @@ static void interrupt_event_handler(struct controller *ctrl)
switch (p_slot->state) { switch (p_slot->state) {
case BLINKINGOFF_STATE: case BLINKINGOFF_STATE:
/* Wait for exclusive access to hardware */ if (PWR_LED(ctrl->ctrlcap))
mutex_lock(&ctrl->ctrl_lock);
if (PWR_LED(ctrl->ctrlcap)) {
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);
}
if (ATTN_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->set_attention_status(p_slot, 0);
/* Wait for the command to complete */ if (ATTN_LED(ctrl->ctrlcap))
wait_for_ctrl_irq (ctrl); p_slot->hpc_ops->set_attention_status(p_slot, 0);
}
/* Done with exclusive hardware access */
mutex_unlock(&ctrl->ctrl_lock);
break; break;
case BLINKINGON_STATE: case BLINKINGON_STATE:
/* Wait for exclusive access to hardware */ if (PWR_LED(ctrl->ctrlcap))
mutex_lock(&ctrl->ctrl_lock);
if (PWR_LED(ctrl->ctrlcap)) {
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);
}
if (ATTN_LED(ctrl->ctrlcap)){
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 */
mutex_unlock(&ctrl->ctrl_lock);
if (ATTN_LED(ctrl->ctrlcap))
p_slot->hpc_ops->set_attention_status(p_slot, 0);
break; break;
default: default:
warn("Not a valid state\n"); warn("Not a valid state\n");
...@@ -676,26 +591,13 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -676,26 +591,13 @@ static void interrupt_event_handler(struct controller *ctrl)
info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot));
} }
/* Wait for exclusive access to hardware */
mutex_lock(&ctrl->ctrl_lock);
/* blink green LED and turn off amber */ /* blink green LED and turn off amber */
if (PWR_LED(ctrl->ctrlcap)) { if (PWR_LED(ctrl->ctrlcap))
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);
}
if (ATTN_LED(ctrl->ctrlcap)) { if (ATTN_LED(ctrl->ctrlcap))
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 */
mutex_unlock(&ctrl->ctrl_lock);
init_timer(&p_slot->task_event); init_timer(&p_slot->task_event);
p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
...@@ -708,21 +610,11 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -708,21 +610,11 @@ static void interrupt_event_handler(struct controller *ctrl)
else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
if (POWER_CTRL(ctrl->ctrlcap)) { if (POWER_CTRL(ctrl->ctrlcap)) {
dbg("power fault\n"); dbg("power fault\n");
/* Wait for exclusive access to hardware */ if (ATTN_LED(ctrl->ctrlcap))
mutex_lock(&ctrl->ctrl_lock);
if (ATTN_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->set_attention_status(p_slot, 1); p_slot->hpc_ops->set_attention_status(p_slot, 1);
wait_for_ctrl_irq (ctrl);
}
if (PWR_LED(ctrl->ctrlcap)) { if (PWR_LED(ctrl->ctrlcap))
p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->green_led_off(p_slot);
wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */
mutex_unlock(&ctrl->ctrl_lock);
} }
} }
/***********SURPRISE REMOVAL********************/ /***********SURPRISE REMOVAL********************/
...@@ -750,7 +642,6 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -750,7 +642,6 @@ static void interrupt_event_handler(struct controller *ctrl)
} }
} }
int pciehp_enable_slot(struct slot *p_slot) int pciehp_enable_slot(struct slot *p_slot)
{ {
u8 getstatus = 0; u8 getstatus = 0;
......
...@@ -249,6 +249,24 @@ static void start_int_poll_timer(struct controller *ctrl, int sec) ...@@ -249,6 +249,24 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)
add_timer(&ctrl->poll_timer); add_timer(&ctrl->poll_timer);
} }
static inline int pcie_wait_cmd(struct controller *ctrl)
{
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&ctrl->queue, &wait);
if (!pciehp_poll_mode)
/* Sleep for up to 1 second */
msleep_interruptible(1000);
else
msleep_interruptible(2500);
remove_wait_queue(&ctrl->queue, &wait);
if (signal_pending(current))
return -EINTR;
return 0;
}
static int pcie_write_cmd(struct slot *slot, u16 cmd) static int pcie_write_cmd(struct slot *slot, u16 cmd)
{ {
struct controller *ctrl = slot->ctrl; struct controller *ctrl = slot->ctrl;
...@@ -257,24 +275,34 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) ...@@ -257,24 +275,34 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
DBG_ENTER_ROUTINE DBG_ENTER_ROUTINE
mutex_lock(&ctrl->ctrl_lock);
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) { if (retval) {
err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
return retval; goto out;
} }
if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
/* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue /* After 1 sec and CMD_COMPLETED still not set, just
the next command according to spec. Just print out the error message */ proceed forward to issue the next command according
dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); to spec. Just print out the error message */
dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
__FUNCTION__);
} }
retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE));
if (retval) { if (retval) {
err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
return retval; goto out;
} }
/*
* Wait for command completion.
*/
retval = pcie_wait_cmd(ctrl);
out:
mutex_unlock(&ctrl->ctrl_lock);
DBG_LEAVE_ROUTINE DBG_LEAVE_ROUTINE
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment