diff options
author | Rajesh Shah <rajesh.shah@intel.com> | 2005-11-23 18:44:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-24 02:04:27 -0500 |
commit | 5a49f2036ad14092c11d09f186da86fd5ae49a05 (patch) | |
tree | 75817c2524974df325db97786469e806c4ee546a /drivers/pci/hotplug | |
parent | dcb890749bbe63af96163c499e9c86b441fb6c83 (diff) |
[PATCH] PCI Express Hotplug: clear sticky power-fault bit
Per the PCI Express spec, the power-fault-detected bit in the
slot status register can be set anytime hardware detects a power
fault, regardless of whether the slot has a device populated in
it or not. This bit is sticky and must be explicitly cleared.
This patch is needed to allow hot-add after such a power fault
has been detected.
Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 15 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 10 |
3 files changed, 11 insertions, 15 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index c42b68d3aa24..6a61b9f286e1 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -59,7 +59,6 @@ struct slot { | |||
59 | struct slot *next; | 59 | struct slot *next; |
60 | u8 bus; | 60 | u8 bus; |
61 | u8 device; | 61 | u8 device; |
62 | u16 status; | ||
63 | u32 number; | 62 | u32 number; |
64 | u8 state; | 63 | u8 state; |
65 | struct timer_list task_event; | 64 | struct timer_list task_event; |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 5e582eca21d8..83c4b865718a 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -207,7 +207,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
207 | * power fault Cleared | 207 | * power fault Cleared |
208 | */ | 208 | */ |
209 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 209 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); |
210 | p_slot->status = 0x00; | ||
211 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 210 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; |
212 | } else { | 211 | } else { |
213 | /* | 212 | /* |
@@ -215,8 +214,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
215 | */ | 214 | */ |
216 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 215 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); |
217 | taskInfo->event_type = INT_POWER_FAULT; | 216 | taskInfo->event_type = INT_POWER_FAULT; |
218 | /* set power fault status for this board */ | ||
219 | p_slot->status = 0xFF; | ||
220 | info("power fault bit %x set\n", hp_slot); | 217 | info("power fault bit %x set\n", hp_slot); |
221 | } | 218 | } |
222 | if (rc) | 219 | if (rc) |
@@ -317,13 +314,10 @@ static int board_added(struct slot *p_slot) | |||
317 | return rc; | 314 | return rc; |
318 | } | 315 | } |
319 | 316 | ||
320 | dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); | ||
321 | |||
322 | /* Check for a power fault */ | 317 | /* Check for a power fault */ |
323 | if (p_slot->status == 0xFF) { | 318 | if (p_slot->hpc_ops->query_power_fault(p_slot)) { |
324 | /* power fault occurred, but it was benign */ | 319 | dbg("%s: power fault detected\n", __FUNCTION__); |
325 | rc = POWER_FAILURE; | 320 | rc = POWER_FAILURE; |
326 | p_slot->status = 0; | ||
327 | goto err_exit; | 321 | goto err_exit; |
328 | } | 322 | } |
329 | 323 | ||
@@ -334,8 +328,6 @@ static int board_added(struct slot *p_slot) | |||
334 | goto err_exit; | 328 | goto err_exit; |
335 | } | 329 | } |
336 | 330 | ||
337 | p_slot->status = 0; | ||
338 | |||
339 | /* | 331 | /* |
340 | * Some PCI Express root ports require fixup after hot-plug operation. | 332 | * Some PCI Express root ports require fixup after hot-plug operation. |
341 | */ | 333 | */ |
@@ -382,9 +374,6 @@ static int remove_board(struct slot *p_slot) | |||
382 | 374 | ||
383 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 375 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
384 | 376 | ||
385 | /* Change status to shutdown */ | ||
386 | p_slot->status = 0x01; | ||
387 | |||
388 | /* Wait for exclusive access to hardware */ | 377 | /* Wait for exclusive access to hardware */ |
389 | down(&ctrl->crit_sect); | 378 | down(&ctrl->crit_sect); |
390 | 379 | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 2387e75da0fe..0b8b26beb163 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -750,7 +750,7 @@ static int hpc_power_on_slot(struct slot * slot) | |||
750 | { | 750 | { |
751 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 751 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; |
752 | u16 slot_cmd; | 752 | u16 slot_cmd; |
753 | u16 slot_ctrl; | 753 | u16 slot_ctrl, slot_status; |
754 | 754 | ||
755 | int retval = 0; | 755 | int retval = 0; |
756 | 756 | ||
@@ -767,6 +767,14 @@ static int hpc_power_on_slot(struct slot * slot) | |||
767 | return -1; | 767 | return -1; |
768 | } | 768 | } |
769 | 769 | ||
770 | /* Clear sticky power-fault bit from previous power failures */ | ||
771 | hp_register_read_word(php_ctlr->pci_dev, | ||
772 | SLOT_STATUS(slot->ctrl->cap_base), slot_status); | ||
773 | slot_status &= PWR_FAULT_DETECTED; | ||
774 | if (slot_status) | ||
775 | hp_register_write_word(php_ctlr->pci_dev, | ||
776 | SLOT_STATUS(slot->ctrl->cap_base), slot_status); | ||
777 | |||
770 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | 778 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
771 | 779 | ||
772 | if (retval) { | 780 | if (retval) { |