Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f1050a35cd99d6cfded7ce1273757dca84e92f9b
Commit:     f1050a35cd99d6cfded7ce1273757dca84e92f9b
Parent:     8bb7c7af1ff2a9e9e0936dbdd15901c80329c7af
Author:     Kenji Kaneshige <[EMAIL PROTECTED]>
AuthorDate: Thu Dec 20 19:45:09 2007 +0900
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Feb 1 15:04:28 2008 -0800

    pciehp: workaround against Bad DLLP during power off
    
    Set Bad DLLP Mask bit in Correctable Error Mask Register during
    turning power off the slot.
    
    This is the workaround against Bad DLLP error that sometimes happen
    during turning power off on the slot which conforms to PCI Express
    1.0a spec. The cause of this error seems that PCI Express 1.0a spec
    doesn't have the following consideration that was added to PCI Express
    1.1 spec.
    
        "If the port is associated with a hot-pluggable slot (Hot-Plug
        Capable bit in the Slot Capabilities register set to 1b), and
        Power Controller Control bit in Slot Control register is 1b(Off),
        then any transition to DL Inactive must not be considered an
        error."
    
    Signed-off-by: Kenji Kaneshige <[EMAIL PROTECTED]>
    Signed-off-by: Kristen Carlson Accardi <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/pci/hotplug/pciehp_hpc.c |   45 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index b2cde04..6eba9b2 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot)
        return retval;
 }
 
+static inline int pcie_mask_bad_dllp(struct controller *ctrl)
+{
+       struct pci_dev *dev = ctrl->pci_dev;
+       int pos;
+       u32 reg;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return 0;
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+       if (reg & PCI_ERR_COR_BAD_DLLP)
+               return 0;
+       reg |= PCI_ERR_COR_BAD_DLLP;
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+       return 1;
+}
+
+static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
+{
+       struct pci_dev *dev = ctrl->pci_dev;
+       u32 reg;
+       int pos;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return;
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+       if (!(reg & PCI_ERR_COR_BAD_DLLP))
+               return;
+       reg &= ~PCI_ERR_COR_BAD_DLLP;
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+}
+
 static int hpc_power_off_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
        u16 cmd_mask;
        int retval = 0;
+       int changed;
 
        dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
 
+       /*
+        * Set Bad DLLP Mask bit in Correctable Error Mask
+        * Register. This is the workaround against Bad DLLP error
+        * that sometimes happens during turning power off the slot
+        * which conforms to PCI Express 1.0a spec.
+        */
+       changed = pcie_mask_bad_dllp(ctrl);
+
        slot_cmd = POWER_OFF;
        cmd_mask = PWR_CTRL;
        /*
@@ -681,6 +723,9 @@ static int hpc_power_off_slot(struct slot * slot)
         */
        msleep(1000);
 
+       if (changed)
+               pcie_unmask_bad_dllp(ctrl);
+
        return retval;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to