From 6aa4cdd07139ba4d5b89139b0070d795cc4dea88 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 13 Jan 2006 16:02:15 +0100 Subject: [PATCH] PCI hotplug: convert semaphores to mutex semaphore to mutex conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build tested with allyesconfig. Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 98 +++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 49 deletions(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 643252d9bf3b..65e69252e2f9 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -242,10 +242,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -253,10 +253,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -319,14 +319,14 @@ static int board_added(struct slot *p_slot) ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { err("%s: Failed to power on slot\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -334,7 +334,7 @@ static int board_added(struct slot *p_slot) if (rc) { err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -345,7 +345,7 @@ static int board_added(struct slot *p_slot) if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -353,19 +353,19 @@ static int board_added(struct slot *p_slot) err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } } @@ -380,7 +380,7 @@ static int board_added(struct slot *p_slot) if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -388,7 +388,7 @@ static int board_added(struct slot *p_slot) if (rc || bus_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get bus operation speed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -399,7 +399,7 @@ static int board_added(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); @@ -481,21 +481,21 @@ static int board_added(struct slot *p_slot) return rc; } - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -521,25 +521,25 @@ static int board_added(struct slot *p_slot) p_slot->pwr_save = 1; /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; err_exit: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -547,12 +547,12 @@ err_exit: if (rc) { err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(rc); } @@ -581,14 +581,14 @@ static int remove_board(struct slot *p_slot) p_slot->status = 0x01; /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -596,7 +596,7 @@ static int remove_board(struct slot *p_slot) if (rc) { err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -604,12 +604,12 @@ static int remove_board(struct slot *p_slot) if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); p_slot->pwr_save = 0; p_slot->is_a_board = 0; @@ -656,12 +656,12 @@ static void shpchp_pushbutton_thread (unsigned long slot) if (shpchp_enable_slot(p_slot)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -768,25 +768,25 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; default: @@ -813,7 +813,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); @@ -821,7 +821,7 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ @@ -834,14 +834,14 @@ static void interrupt_event_handler(struct controller *ctrl) /***********POWER FAULT********************/ dbg("%s: power fault\n", __FUNCTION__); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->set_attention_status(p_slot, 1); p_slot->hpc_ops->green_led_off(p_slot); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } else { /* refresh notification */ if (p_slot) @@ -865,26 +865,26 @@ int shpchp_enable_slot (struct slot *p_slot) int rc; /* Check to see if (latch closed, card present, power off) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->is_a_board = 1; @@ -925,27 +925,27 @@ int shpchp_disable_slot (struct slot *p_slot) return -ENODEV; /* Check to see if (latch closed, card present, power on) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); ret = remove_board(p_slot); update_slot_info(p_slot); -- cgit v1.2.3 From a4534560815ffc525bfbe465a290ce048aab4c01 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:58:30 +0900 Subject: [PATCH] shpchp - cleanup controller list This patch changes SHPCHP driver to use list_head structure for managing controller list. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 65e69252e2f9..3a8e733aead5 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -688,7 +688,7 @@ static int event_thread(void* data) if (pushbutton_pending) shpchp_pushbutton_thread(pushbutton_pending); else - for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next) + list_for_each_entry(ctrl, &shpchp_ctrl_list, ctrl_list) interrupt_event_handler(ctrl); } dbg("event_thread signals exit\n"); -- cgit v1.2.3 From d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccf Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:59:24 +0900 Subject: [PATCH] shpchp - cleanup check command status This patch cleanups codes that check the command status. For this, it introduces a new semaphore "cmd_sem" for each controller. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 120 +------------------------------------- 1 file changed, 1 insertion(+), 119 deletions(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 3a8e733aead5..802c4c48d186 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -242,21 +242,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); - mutex_lock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - 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", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - mutex_unlock(&ctrl->crit_sect); return rc; } @@ -330,15 +319,6 @@ static int board_added(struct slot *p_slot) return -1; } - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return -1; - } - - if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { if (slots_not_empty) return WRONG_BUS_FREQUENCY; @@ -349,25 +329,12 @@ static int board_added(struct slot *p_slot) return WRONG_BUS_FREQUENCY; } - 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", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); mutex_unlock(&ctrl->crit_sect); return rc; } - - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return rc; - } } rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); @@ -481,22 +448,12 @@ static int board_added(struct slot *p_slot) return rc; } - mutex_lock(&ctrl->crit_sect); /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return rc; } - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return rc; - } - - mutex_unlock(&ctrl->crit_sect); - /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -520,40 +477,18 @@ static int board_added(struct slot *p_slot) p_slot->is_a_board = 0x01; p_slot->pwr_save = 1; - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_on(p_slot); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return 0; err_exit: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return rc; - } - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return(rc); } @@ -580,37 +515,19 @@ static int remove_board(struct slot *p_slot) if (p_slot->is_a_board) p_slot->status = 0x01; - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return rc; - } rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - p_slot->pwr_save = 0; p_slot->is_a_board = 0; @@ -654,15 +571,9 @@ static void shpchp_pushbutton_thread (unsigned long slot) } else { p_slot->state = POWERON_STATE; - if (shpchp_enable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - mutex_lock(&p_slot->ctrl->crit_sect); - + if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); - /* Done with exclusive hardware access */ - mutex_unlock(&p_slot->ctrl->crit_sect); - } p_slot->state = STATIC_STATE; } @@ -767,27 +678,12 @@ 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); - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - break; default: warn("Not a valid state\n"); @@ -812,17 +708,10 @@ static void interrupt_event_handler(struct controller *ctrl) info(msg_button_on, p_slot->number); } - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; @@ -833,15 +722,8 @@ static void interrupt_event_handler(struct controller *ctrl) } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { /***********POWER FAULT********************/ dbg("%s: power fault\n", __FUNCTION__); - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - p_slot->hpc_ops->green_led_off(p_slot); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); } else { /* refresh notification */ if (p_slot) -- cgit v1.2.3 From ef3be54777901e570185089f21fbe4498453f67e Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:00:33 +0900 Subject: [PATCH] shpchp - bugfix: add missing serialization Current shpchp driver might cause system panic because of lack of serialization. It can be reproduced very easily by the following operation. # cd /sys/bus/pci/slots/ # while true; do echo 0 > power ; echo 1 > power ; done & # while true; do echo 0 > power ; echo 1 > power ; done & This patch fixes this issue by changing shpchp to get appropreate semaphore for hot-plug operation. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 66 ++++++++++++++------------------------- 1 file changed, 24 insertions(+), 42 deletions(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 802c4c48d186..1a7003d4ba96 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -307,15 +307,10 @@ static int board_added(struct slot *p_slot) __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot); - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { err("%s: Failed to power on slot\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return -1; } @@ -325,14 +320,12 @@ static int board_added(struct slot *p_slot) if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return rc; } } @@ -346,16 +339,12 @@ static int board_added(struct slot *p_slot) if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); if (rc || bus_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get bus operation speed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -365,9 +354,6 @@ static int board_added(struct slot *p_slot) max_bus_speed = bus_speed; } - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); pi = 1; @@ -744,29 +730,25 @@ static void interrupt_event_handler(struct controller *ctrl) int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; - int rc; + int rc, retval = -ENODEV; /* Check to see if (latch closed, card present, power off) */ mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->is_a_board = 1; @@ -781,27 +763,29 @@ int shpchp_enable_slot (struct slot *p_slot) && p_slot->ctrl->num_slots == 1) { /* handle amd pogo errata; this must be done before enable */ amd_pogo_errata_save_misc_reg(p_slot); - rc = board_added(p_slot); + retval = board_added(p_slot); /* handle amd pogo errata; this must be done after enable */ amd_pogo_errata_restore_misc_reg(p_slot); } else - rc = board_added(p_slot); + retval = board_added(p_slot); - if (rc) { + if (retval) { p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); } update_slot_info(p_slot); - return rc; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; - int ret = 0; + int rc, retval = -ENODEV; if (!p_slot->ctrl) return -ENODEV; @@ -809,28 +793,26 @@ int shpchp_disable_slot (struct slot *p_slot) /* Check to see if (latch closed, card present, power on) */ mutex_lock(&p_slot->ctrl->crit_sect); - ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); - if (ret || !getstatus) { + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (ret || getstatus) { + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (ret || !getstatus) { + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - mutex_unlock(&p_slot->ctrl->crit_sect); - ret = remove_board(p_slot); + retval = remove_board(p_slot); update_slot_info(p_slot); - return ret; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } -- cgit v1.2.3 From 68c0b671491088d79611fa965bbf94b3bc0024a4 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:42 -0800 Subject: [PATCH] shpchp: Remove unused wait_for_ctrl_irq The wait_for_ctrl_irq() function in SHPCHP driver is no longer needed. This patch removes that. This patch has no functional change. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 1a7003d4ba96..b709328a4145 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -441,7 +441,7 @@ static int board_added(struct slot *p_slot) } /* Wait for ~1 second */ - wait_for_ctrl_irq (ctrl); + msleep(1000); dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); /* Check for a power fault */ -- cgit v1.2.3 From f7391f5325ea744f0632f7ef39a90085162743ac Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:45 -0800 Subject: [PATCH] shpchp: event handling rework The event handler of SHPCHP driver is unnecessarily very complex. In addition, current event handler can only a fixed number of events at the same time, and some of events would be lost if several number of events happened at the same time. This patch simplify the event handler by using 'work queue', and it also fix the above-mentioned issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 313 +++++++++++--------------------------- 1 file changed, 89 insertions(+), 224 deletions(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b709328a4145..2411f3bd08da 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -32,44 +32,46 @@ #include #include #include +#include #include "../pci.h" #include "shpchp.h" -static void interrupt_event_handler(struct controller *ctrl); +static void interrupt_event_handler(void *data); -static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ -static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ -static int event_finished; -static unsigned long pushbutton_pending; /* = 0 */ +static int queue_interrupt_event(struct slot *p_slot, u32 event_type) +{ + struct event_info *info; + + info = kmalloc(sizeof(*info), GFP_ATOMIC); + if (!info) + return -ENOMEM; + + info->event_type = event_type; + info->p_slot = p_slot; + INIT_WORK(&info->work, interrupt_event_handler, info); + + queue_work(shpchp_wq, &info->work); + + return 0; +} u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Attention Button Change */ dbg("shpchp: Attention button interrupt received.\n"); - /* This is the structure that tells the worker thread what to do */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); - p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; /* * Button pressed - See if need to TAKE ACTION!!! */ info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_BUTTON_PRESS; + event_type = INT_BUTTON_PRESS; if ((p_slot->state == BLINKINGON_STATE) || (p_slot->state == BLINKINGOFF_STATE)) { @@ -77,7 +79,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) * attention again before the 5 sec. limit expires to cancel hot-add * or hot-remove */ - taskInfo->event_type = INT_BUTTON_CANCEL; + event_type = INT_BUTTON_CANCEL; info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); } else if ((p_slot->state == POWERON_STATE) || (p_slot->state == POWEROFF_STATE)) { @@ -85,12 +87,11 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) * means that the previous attention button action to hot-add or * hot-remove is undergoing */ - taskInfo->event_type = INT_BUTTON_IGNORE; + event_type = INT_BUTTON_IGNORE; info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); return 0; @@ -100,21 +101,12 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Switch Change */ dbg("shpchp: Switch interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -126,9 +118,9 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch opened */ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_SWITCH_OPEN; + event_type = INT_SWITCH_OPEN; if (p_slot->pwr_save && p_slot->presence_save) { - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; err("Surprise Removal of card\n"); } } else { @@ -136,34 +128,23 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch closed */ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_SWITCH_CLOSE; + event_type = INT_SWITCH_CLOSE; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - /*u8 temp_byte;*/ - struct event_info *taskInfo; + u32 event_type; /* Presence Change */ dbg("shpchp: Presence/Notify input change.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); /* @@ -175,39 +156,29 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) * Card Present */ info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_PRESENCE_ON; + event_type = INT_PRESENCE_ON; } else { /* * Not Present */ info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_PRESENCE_OFF; + event_type = INT_PRESENCE_OFF; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - struct event_info *taskInfo; + u32 event_type; /* Power fault */ dbg("shpchp: Power fault interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { @@ -216,21 +187,21 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) */ info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); p_slot->status = 0x00; - taskInfo->event_type = INT_POWER_FAULT_CLEAR; + event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; info("power fault bit %x set\n", hp_slot); } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ - return rc; + queue_interrupt_event(p_slot, event_type); + + return 1; } /* The following routines constitute the bulk of the @@ -521,14 +492,6 @@ static int remove_board(struct slot *p_slot) } -static void pushbutton_helper_thread (unsigned long data) -{ - pushbutton_pending = data; - - up(&event_semaphore); -} - - /** * shpchp_pushbutton_thread * @@ -536,90 +499,24 @@ static void pushbutton_helper_thread (unsigned long data) * Handles all pending events and exits. * */ -static void shpchp_pushbutton_thread (unsigned long slot) +void shpchp_pushbutton_thread(void *data) { - struct slot *p_slot = (struct slot *) slot; + struct slot *p_slot = data; u8 getstatus; - - pushbutton_pending = 0; - - if (!p_slot) { - dbg("%s: Error! slot NULL\n", __FUNCTION__); - return; - } p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = POWEROFF_STATE; - shpchp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; - if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); - p_slot->state = STATIC_STATE; } - - return; -} - - -/* this is the main worker thread */ -static int event_thread(void* data) -{ - struct controller *ctrl; - lock_kernel(); - daemonize("shpchpd_event"); - unlock_kernel(); - - while (1) { - dbg("!!!!event_thread sleeping\n"); - down_interruptible (&event_semaphore); - dbg("event_thread woken finished = %d\n", event_finished); - if (event_finished || signal_pending(current)) - break; - /* Do stuff here */ - if (pushbutton_pending) - shpchp_pushbutton_thread(pushbutton_pending); - else - list_for_each_entry(ctrl, &shpchp_ctrl_list, ctrl_list) - interrupt_event_handler(ctrl); - } - dbg("event_thread signals exit\n"); - up(&event_exit); - return 0; -} - -int shpchp_event_start_thread (void) -{ - int pid; - - /* initialize our semaphores */ - init_MUTEX_LOCKED(&event_exit); - event_finished=0; - - init_MUTEX_LOCKED(&event_semaphore); - pid = kernel_thread(event_thread, NULL, 0); - - if (pid < 0) { - err ("Can't start up our event thread\n"); - return -1; - } - return 0; -} - - -void shpchp_event_stop_thread (void) -{ - event_finished = 1; - up(&event_semaphore); - down(&event_exit); } - static int update_slot_info (struct slot *slot) { struct hotplug_slot_info *info; @@ -639,91 +536,59 @@ static int update_slot_info (struct slot *slot) return result; } -static void interrupt_event_handler(struct controller *ctrl) +static void interrupt_event_handler(void *data) { - int loop = 0; - int change = 1; - u8 hp_slot; + struct event_info *info = data; + struct slot *p_slot = info->p_slot; u8 getstatus; - struct slot *p_slot; - while (change) { - change = 0; - - for (loop = 0; loop < 10; loop++) { - if (ctrl->event_queue[loop].event_type != 0) { - dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, - ctrl->event_queue[loop].event_type); - hp_slot = ctrl->event_queue[loop].hp_slot; - - p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - - if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { - dbg("%s: button cancel\n", __FUNCTION__); - del_timer(&p_slot->task_event); - - switch (p_slot->state) { - case BLINKINGOFF_STATE: - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - case BLINKINGON_STATE: - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - default: - warn("Not a valid state\n"); - return; - } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { - /* Button Pressed (No action on 1st press...) */ - dbg("%s: Button pressed\n", __FUNCTION__); - - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - /* slot is on */ - dbg("%s: slot is on\n", __FUNCTION__); - p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); - } else { - /* slot is off */ - dbg("%s: slot is off\n", __FUNCTION__); - p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); - } - - /* blink green LED and turn off amber */ - p_slot->hpc_ops->green_led_blink(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - init_timer(&p_slot->task_event); - 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.data = (unsigned long) p_slot; - - dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot); - add_timer(&p_slot->task_event); - } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { - /***********POWER FAULT********************/ - dbg("%s: power fault\n", __FUNCTION__); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - p_slot->hpc_ops->green_led_off(p_slot); - } else { - /* refresh notification */ - if (p_slot) - update_slot_info(p_slot); - } - - ctrl->event_queue[loop].event_type = 0; + switch (info->event_type) { + case INT_BUTTON_CANCEL: + dbg("%s: button cancel\n", __FUNCTION__); + cancel_delayed_work(&p_slot->work); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + p_slot->hpc_ops->green_led_on(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + break; + case BLINKINGON_STATE: + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + break; + default: + warn("Not a valid state\n"); + return; + } + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + break; + case INT_BUTTON_PRESS: + dbg("%s: Button pressed\n", __FUNCTION__); + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + p_slot->state = BLINKINGOFF_STATE; + info(msg_button_off, p_slot->number); + } else { + p_slot->state = BLINKINGON_STATE; + info(msg_button_on, p_slot->number); + } + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); - change = 1; - } - } /* End of FOR loop */ + queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + break; + case INT_POWER_FAULT: + dbg("%s: power fault\n", __FUNCTION__); + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + break; + default: + update_slot_info(p_slot); + break; } - return; + kfree(info); } -- cgit v1.2.3 From a246fa4e9f0f1b5096a1cad0659d22fb10fb3732 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:48 -0800 Subject: [PATCH] shpchp: Fix slot state handling Current SHPCHP driver doesn't care about the confliction between hotplug operation via sysfs and hotplug operation via attention button. So if those ware conflicted, slot could be an unexpected state. This patch changes SHPCHP driver to handle slot state properly. With this patch, slot events are handled according to the current slot state as shown at the Table below. Table. Slot States and Event Handling ========================================================================= Slot State Event and Action ========================================================================= STATIC - Go to POWERON state if user initiates (Slot enabled, insertion request via sysfs Slot disabled) - Go to POWEROFF state if user initiates removal request via sysfs - Go to BLINKINGON state if user presses attention button when the slot is disabled - Go to BLINKINGOFF state if user presses attention button when the slot is enabled --- drivers/pci/hotplug/shpchp_ctrl.c | 227 +++++++++++++++++++++++++++++--------- 1 file changed, 172 insertions(+), 55 deletions(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 2411f3bd08da..10f3257b18a7 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -37,6 +37,8 @@ #include "shpchp.h" static void interrupt_event_handler(void *data); +static int shpchp_enable_slot(struct slot *p_slot); +static int shpchp_disable_slot(struct slot *p_slot); static int queue_interrupt_event(struct slot *p_slot, u32 event_type) { @@ -50,7 +52,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler, info); - queue_work(shpchp_wq, &info->work); + schedule_work(&info->work); return 0; } @@ -73,24 +75,6 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); event_type = INT_BUTTON_PRESS; - if ((p_slot->state == BLINKINGON_STATE) - || (p_slot->state == BLINKINGOFF_STATE)) { - /* Cancel if we are still blinking; this means that we press the - * attention again before the 5 sec. limit expires to cancel hot-add - * or hot-remove - */ - event_type = INT_BUTTON_CANCEL; - info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); - } else if ((p_slot->state == POWERON_STATE) - || (p_slot->state == POWEROFF_STATE)) { - /* Ignore if the slot is on power-on or power-off state; this - * means that the previous attention button action to hot-add or - * hot-remove is undergoing - */ - event_type = INT_BUTTON_IGNORE; - info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); - } - queue_interrupt_event(p_slot, event_type); return 0; @@ -492,6 +476,11 @@ static int remove_board(struct slot *p_slot) } +struct pushbutton_work_info { + struct slot *p_slot; + struct work_struct work; +}; + /** * shpchp_pushbutton_thread * @@ -499,22 +488,61 @@ static int remove_board(struct slot *p_slot) * Handles all pending events and exits. * */ -void shpchp_pushbutton_thread(void *data) +static void shpchp_pushbutton_thread(void *data) { - struct slot *p_slot = data; - u8 getstatus; + struct pushbutton_work_info *info = data; + struct slot *p_slot = info->p_slot; - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - p_slot->state = POWEROFF_STATE; + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case POWEROFF_STATE: + mutex_unlock(&p_slot->lock); shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; - } else { - p_slot->state = POWERON_STATE; + break; + case POWERON_STATE: + mutex_unlock(&p_slot->lock); if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; + break; + default: + break; + } + mutex_unlock(&p_slot->lock); + + kfree(info); +} + +void queue_pushbutton_work(void *data) +{ + struct slot *p_slot = data; + struct pushbutton_work_info *info; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + err("%s: Cannot allocate memory\n", __FUNCTION__); + return; + } + info->p_slot = p_slot; + INIT_WORK(&info->work, shpchp_pushbutton_thread, info); + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + p_slot->state = POWEROFF_STATE; + break; + case BLINKINGON_STATE: + p_slot->state = POWERON_STATE; + break; + default: + goto out; } + queue_work(shpchp_wq, &info->work); + out: + mutex_unlock(&p_slot->lock); } static int update_slot_info (struct slot *slot) @@ -536,34 +564,15 @@ static int update_slot_info (struct slot *slot) return result; } -static void interrupt_event_handler(void *data) +/* + * Note: This function must be called with slot->lock held + */ +static void handle_button_press_event(struct slot *p_slot) { - struct event_info *info = data; - struct slot *p_slot = info->p_slot; u8 getstatus; - switch (info->event_type) { - case INT_BUTTON_CANCEL: - dbg("%s: button cancel\n", __FUNCTION__); - cancel_delayed_work(&p_slot->work); - switch (p_slot->state) { - case BLINKINGOFF_STATE: - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - case BLINKINGON_STATE: - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - default: - warn("Not a valid state\n"); - return; - } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - break; - case INT_BUTTON_PRESS: - dbg("%s: Button pressed\n", __FUNCTION__); + switch (p_slot->state) { + case STATIC_STATE: p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = BLINKINGOFF_STATE; @@ -576,7 +585,51 @@ static void interrupt_event_handler(void *data) p_slot->hpc_ops->green_led_blink(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + schedule_delayed_work(&p_slot->work, 5*HZ); + break; + case BLINKINGOFF_STATE: + case BLINKINGON_STATE: + /* + * Cancel if we are still blinking; this means that we + * press the attention again before the 5 sec. limit + * expires to cancel hot-add or hot-remove + */ + info("Button cancel on Slot(%s)\n", p_slot->name); + dbg("%s: button cancel\n", __FUNCTION__); + cancel_delayed_work(&p_slot->work); + if (p_slot->state == BLINKINGOFF_STATE) + p_slot->hpc_ops->green_led_on(p_slot); + else + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + case POWERON_STATE: + /* + * Ignore if the slot is on power-on or power-off state; + * this means that the previous attention button action + * to hot-add or hot-remove is undergoing + */ + info("Button ignore on Slot(%s)\n", p_slot->name); + update_slot_info(p_slot); + break; + default: + warn("Not a valid state\n"); + break; + } +} + +static void interrupt_event_handler(void *data) +{ + struct event_info *info = data; + struct slot *p_slot = info->p_slot; + + mutex_lock(&p_slot->lock); + switch (info->event_type) { + case INT_BUTTON_PRESS: + handle_button_press_event(p_slot); break; case INT_POWER_FAULT: dbg("%s: power fault\n", __FUNCTION__); @@ -587,12 +640,13 @@ static void interrupt_event_handler(void *data) update_slot_info(p_slot); break; } + mutex_unlock(&p_slot->lock); kfree(info); } -int shpchp_enable_slot (struct slot *p_slot) +static int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; @@ -647,7 +701,7 @@ int shpchp_enable_slot (struct slot *p_slot) } -int shpchp_disable_slot (struct slot *p_slot) +static int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; @@ -681,3 +735,66 @@ int shpchp_disable_slot (struct slot *p_slot) return retval; } +int shpchp_sysfs_enable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGON_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWERON_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_enable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWERON_STATE: + info("Slot %s is already in powering on state\n", + p_slot->name); + break; + case BLINKINGOFF_STATE: + case POWEROFF_STATE: + info("Already enabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} + +int shpchp_sysfs_disable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWEROFF_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + info("Slot %s is already in powering off state\n", + p_slot->name); + break; + case BLINKINGON_STATE: + case POWERON_STATE: + info("Already disabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} -- cgit v1.2.3 From 0afabe906539b4e8b9e895f19ea31aabdf12f30b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 1 Mar 2006 14:55:11 +0900 Subject: [PATCH] shpchp: cleanup bus speed handling The code related to handling bus speed in SHPCHP driver is unnecessarily complex. This patch cleans up and simplify that. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 152 +++++++++----------------------------- 1 file changed, 36 insertions(+), 116 deletions(-) (limited to 'drivers/pci/hotplug/shpchp_ctrl.c') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 10f3257b18a7..4e6381481c55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -198,7 +198,8 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, dbg("%s: change to speed %d\n", __FUNCTION__, speed); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + err("%s: Issue of set bus speed mode command failed\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } return rc; @@ -209,33 +210,26 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, enum pci_bus_speed msp) { int rc = 0; - - if (flag != 0) { /* Other slots on the same bus are occupied */ - if ( asp < bsp ) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp); - return WRONG_BUS_FREQUENCY; + + /* + * If other slots on the same bus are occupied, we cannot + * change the bus speed. + */ + if (flag) { + if (asp < bsp) { + err("%s: speed of bus %x and adapter %x mismatch\n", + __FUNCTION__, bsp, asp); + rc = WRONG_BUS_FREQUENCY; } + return rc; + } + + if (asp < msp) { + if (bsp != asp) + rc = change_bus_speed(ctrl, pslot, asp); } else { - /* Other slots on the same bus are empty */ - if (msp == bsp) { - /* if adapter_speed >= bus_speed, do nothing */ - if (asp < bsp) { - /* - * Try to lower bus speed to accommodate the adapter if other slots - * on the same controller are empty - */ - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } - } else { - if (asp < msp) { - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } else { - if ((rc = change_bus_speed(ctrl, pslot, msp))) - return rc; - } - } + if (bsp != msp) + rc = change_bus_speed(ctrl, pslot, msp); } return rc; } @@ -252,8 +246,7 @@ static int board_added(struct slot *p_slot) u8 hp_slot; u8 slots_not_empty = 0; int rc = 0; - enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; - u8 pi, mode; + enum pci_bus_speed asp, bsp, msp; struct controller *ctrl = p_slot->ctrl; hp_slot = p_slot->device - ctrl->slot_device_offset; @@ -285,109 +278,36 @@ static int board_added(struct slot *p_slot) } } - rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); - /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ - /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ - /* 0xd = PCI-X 133 Mhz 533 */ - /* This encoding is different from the one used in cur_bus_speed & */ - /* max_bus_speed */ - - if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { - err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); + if (rc) { + err("%s: Can't get adapter speed or bus mode mismatch\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); - if (rc || bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); + if (rc) { err("%s: Can't get bus operation speed\n", __FUNCTION__); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); - if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); + if (rc) { err("%s: Can't get max bus operation speed\n", __FUNCTION__); - max_bus_speed = bus_speed; - } - - if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { - err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); - pi = 1; + msp = bsp; } /* Check if there are other slots or devices on the same bus */ if (!list_empty(&ctrl->pci_dev->subordinate->devices)) slots_not_empty = 1; - dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, - slots_not_empty, pi); - dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", - adapter_speed, bus_speed, max_bus_speed); - - if (pi == 2) { - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) { - err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__); - mode = 0; - } + dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, " + "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp, + bsp, msp); - switch (adapter_speed) { - case PCI_SPEED_133MHz_PCIX_533: - case PCI_SPEED_133MHz_PCIX_266: - if ((bus_speed != adapter_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_133MHz_PCIX_ECC: - case PCI_SPEED_133MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x7) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x4) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz_PCIX_ECC: - case PCI_SPEED_66MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x5) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x2) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz: - if ((bus_speed != 0x1) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_33MHz: - if (bus_speed > 0x0) { - if (slots_not_empty == 0) { - if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed))) - return rc; - } else { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } - break; - default: - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } else { - /* If adpater_speed == bus_speed, nothing to do here */ - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((adapter_speed != bus_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } + rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); + if (rc) + return rc; /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { -- cgit v1.2.3