aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_ctrl.c
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2006-09-22 10:17:29 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2006-10-18 11:36:10 -0700
commitdd5619cb4407e830a8921a93c949be37c81105b5 (patch)
treef726db26b6019e6f741dfb146e3d37eca9198cf4 /drivers/pci/hotplug/pciehp_ctrl.c
parent49ed2b4963cd00993eab518b820a6700f94f222d (diff)
downloadkernel_samsung_smdk4412-dd5619cb4407e830a8921a93c949be37c81105b5.zip
kernel_samsung_smdk4412-dd5619cb4407e830a8921a93c949be37c81105b5.tar.gz
kernel_samsung_smdk4412-dd5619cb4407e830a8921a93c949be37c81105b5.tar.bz2
pciehp - add missing locking
This patch fixes the problem that system will panic if multiple power on/off operations are issued to the same slot in parallel. This problem can be easily reproduced by commands below. # while true; do echo 1 > power; echo 0 > power; done & # while true; do echo 1 > power; echo 0 > power; done & The cause is lack of locking for enable/disable operations. This patch fixes this problem. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/pciehp_ctrl.c')
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c54
1 files changed, 27 insertions, 27 deletions
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index f602b04..c206a3d 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -234,13 +234,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
static void set_slot_off(struct controller *ctrl, struct slot * pslot)
{
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
if (POWER_CTRL(ctrl->ctrlcap)) {
if (pslot->hpc_ops->power_off_slot(pslot)) {
err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
return;
}
wait_for_ctrl_irq (ctrl);
@@ -254,14 +254,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
if (ATTN_LED(ctrl->ctrlcap)) {
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
return;
}
wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
}
/**
@@ -284,13 +284,13 @@ static int board_added(struct slot *p_slot)
ctrl->slot_device_offset, hp_slot);
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
if (POWER_CTRL(ctrl->ctrlcap)) {
/* Power on slot */
rc = p_slot->hpc_ops->power_on_slot(p_slot);
if (rc) {
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
return -1;
}
@@ -306,7 +306,7 @@ static int board_added(struct slot *p_slot)
}
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
/* Wait for ~1 second */
wait_for_ctrl_irq (ctrl);
@@ -340,7 +340,7 @@ static int board_added(struct slot *p_slot)
pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
if (PWR_LED(ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
p_slot->hpc_ops->green_led_on(p_slot);
@@ -348,7 +348,7 @@ static int board_added(struct slot *p_slot)
wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
}
return 0;
@@ -380,14 +380,14 @@ static int remove_board(struct slot *p_slot)
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
if (POWER_CTRL(ctrl->ctrlcap)) {
/* power off slot */
rc = p_slot->hpc_ops->power_off_slot(p_slot);
if (rc) {
err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
return rc;
}
/* Wait for the command to complete */
@@ -403,7 +403,7 @@ static int remove_board(struct slot *p_slot)
}
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
return 0;
}
@@ -450,7 +450,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */
- mutex_lock(&p_slot->ctrl->crit_sect);
+ mutex_lock(&p_slot->ctrl->ctrl_lock);
p_slot->hpc_ops->green_led_off(p_slot);
@@ -458,7 +458,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
wait_for_ctrl_irq (p_slot->ctrl);
/* Done with exclusive hardware access */
- mutex_unlock(&p_slot->ctrl->crit_sect);
+ mutex_unlock(&p_slot->ctrl->ctrl_lock);
}
p_slot->state = STATIC_STATE;
}
@@ -500,7 +500,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */
- mutex_lock(&p_slot->ctrl->crit_sect);
+ mutex_lock(&p_slot->ctrl->ctrl_lock);
p_slot->hpc_ops->green_led_off(p_slot);
@@ -508,7 +508,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
wait_for_ctrl_irq (p_slot->ctrl);
/* Done with exclusive hardware access */
- mutex_unlock(&p_slot->ctrl->crit_sect);
+ mutex_unlock(&p_slot->ctrl->ctrl_lock);
}
p_slot->state = STATIC_STATE;
}
@@ -621,7 +621,7 @@ static void interrupt_event_handler(struct controller *ctrl)
switch (p_slot->state) {
case BLINKINGOFF_STATE:
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
if (PWR_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->green_led_on(p_slot);
@@ -635,11 +635,11 @@ static void interrupt_event_handler(struct controller *ctrl)
wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
break;
case BLINKINGON_STATE:
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
if (PWR_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->green_led_off(p_slot);
@@ -652,7 +652,7 @@ static void interrupt_event_handler(struct controller *ctrl)
wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
break;
default:
@@ -681,7 +681,7 @@ static void interrupt_event_handler(struct controller *ctrl)
}
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
/* blink green LED and turn off amber */
if (PWR_LED(ctrl->ctrlcap)) {
@@ -698,7 +698,7 @@ static void interrupt_event_handler(struct controller *ctrl)
}
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
init_timer(&p_slot->task_event);
p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
@@ -713,7 +713,7 @@ static void interrupt_event_handler(struct controller *ctrl)
if (POWER_CTRL(ctrl->ctrlcap)) {
dbg("power fault\n");
/* Wait for exclusive access to hardware */
- mutex_lock(&ctrl->crit_sect);
+ mutex_lock(&ctrl->ctrl_lock);
if (ATTN_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->set_attention_status(p_slot, 1);
@@ -726,7 +726,7 @@ static void interrupt_event_handler(struct controller *ctrl)
}
/* Done with exclusive hardware access */
- mutex_unlock(&ctrl->crit_sect);
+ mutex_unlock(&ctrl->ctrl_lock);
}
}
/***********SURPRISE REMOVAL********************/
@@ -789,7 +789,6 @@ int pciehp_enable_slot(struct slot *p_slot)
return -EINVAL;
}
}
- mutex_unlock(&p_slot->ctrl->crit_sect);
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
@@ -801,6 +800,7 @@ int pciehp_enable_slot(struct slot *p_slot)
if (p_slot)
update_slot_info(p_slot);
+ mutex_unlock(&p_slot->ctrl->crit_sect);
return rc;
}
@@ -846,10 +846,10 @@ int pciehp_disable_slot(struct slot *p_slot)
}
}
- mutex_unlock(&p_slot->ctrl->crit_sect);
-
ret = remove_board(p_slot);
update_slot_info(p_slot);
+
+ mutex_unlock(&p_slot->ctrl->crit_sect);
return ret;
}