[PATCH] PCI Express Hotplug: clear sticky power-fault bit
authorRajesh Shah <rajesh.shah@intel.com>
Wed, 23 Nov 2005 23:44:54 +0000 (15:44 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 24 Nov 2005 07:04:27 +0000 (23:04 -0800)
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>
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c

index c42b68d3aa2410d27741e51c01585603c58c10b8..6a61b9f286e14a320e59815dfcaf53832bea93e3 100644 (file)
@@ -59,7 +59,6 @@ struct slot {
        struct slot *next;
        u8 bus;
        u8 device;
-       u16 status;
        u32 number;
        u8 state;
        struct timer_list task_event;
index 5e582eca21d8df27f2a1bf83314781e22047c3ab..83c4b865718a15239361b9f314391b9f31d32de4 100644 (file)
@@ -207,7 +207,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
                 * power fault Cleared
                 */
                info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
-               p_slot->status = 0x00;
                taskInfo->event_type = INT_POWER_FAULT_CLEAR;
        } else {
                /*
@@ -215,8 +214,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
                 */
                info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
                taskInfo->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)
@@ -317,13 +314,10 @@ static int board_added(struct slot *p_slot)
                return rc;
        }
 
-       dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
-
        /* Check for a power fault */
-       if (p_slot->status == 0xFF) {
-               /* power fault occurred, but it was benign */
+       if (p_slot->hpc_ops->query_power_fault(p_slot)) {
+               dbg("%s: power fault detected\n", __FUNCTION__);
                rc = POWER_FAILURE;
-               p_slot->status = 0;
                goto err_exit;
        }
 
@@ -334,8 +328,6 @@ static int board_added(struct slot *p_slot)
                goto err_exit;
        }
 
-       p_slot->status = 0;
-
        /*
         * Some PCI Express root ports require fixup after hot-plug operation.
         */
@@ -382,9 +374,6 @@ static int remove_board(struct slot *p_slot)
 
        dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
 
-       /* Change status to shutdown */
-       p_slot->status = 0x01;
-
        /* Wait for exclusive access to hardware */
        down(&ctrl->crit_sect);
 
index 2387e75da0feee0ab93e4491fc3b1ee0ad0d0f62..0b8b26beb1636ca5875d24e6891504ac81f33899 100644 (file)
@@ -750,7 +750,7 @@ static int hpc_power_on_slot(struct slot * slot)
 {
        struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd;
-       u16 slot_ctrl;
+       u16 slot_ctrl, slot_status;
 
        int retval = 0;
 
@@ -767,6 +767,14 @@ static int hpc_power_on_slot(struct slot * slot)
                return -1;
        }
 
+       /* Clear sticky power-fault bit from previous power failures */
+       hp_register_read_word(php_ctlr->pci_dev,
+                       SLOT_STATUS(slot->ctrl->cap_base), slot_status);
+       slot_status &= PWR_FAULT_DETECTED;
+       if (slot_status)
+               hp_register_write_word(php_ctlr->pci_dev,
+                       SLOT_STATUS(slot->ctrl->cap_base), slot_status);
+
        retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {