Re: [PATCH v3 4/8] pciehp: Don't disable the link permanently, during removal

From: Yinghai Lu
Date: Wed Dec 18 2013 - 01:50:28 EST


On Tue, Dec 17, 2013 at 10:17 PM, Rajat Jain <rajatjain@xxxxxxxxxxx> wrote:
> Well, in that case I doubt if the patch will solve the problem. I think
> Most likely the "card present / not present" messages may be replaced
> By "link-up / link-down" messages. But I'd appreciate your testing.

I did have a debug patch at that time to report link status change.
And it did report link up and link down.

Thanks

Yinghai
Subject: [PATCH] PCI, pciehp: Report pcie link state change

To see if there is some link state change.

Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>

---
drivers/pci/hotplug/pciehp_hpc.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)

Index: linux-2.6/drivers/pci/hotplug/pciehp_hpc.c
===================================================================
--- linux-2.6.orig/drivers/pci/hotplug/pciehp_hpc.c
+++ linux-2.6/drivers/pci/hotplug/pciehp_hpc.c
@@ -603,6 +603,25 @@ int pciehp_power_off_slot(struct slot *
return 0;
}

+static u8 pciehp_handle_linkstate_change(struct slot *slot)
+{
+ struct controller *ctrl = slot->ctrl;
+ u16 lnk_status;
+ int retval;
+
+ /* LinkState Change */
+ ctrl_dbg(ctrl, "LinkState change\n");
+
+ retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
+ if (retval) {
+ ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
+ return 1;
+ }
+ ctrl_info(ctrl, "lnk_status = %x\n", lnk_status);
+
+ return 1;
+}
+
static irqreturn_t pcie_isr(int irq, void *dev_id)
{
struct controller *ctrl = (struct controller *)dev_id;
@@ -624,7 +643,7 @@ static irqreturn_t pcie_isr(int irq, voi

detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
- PCI_EXP_SLTSTA_CC);
+ PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
detected &= ~intr_loc;
intr_loc |= detected;
if (!intr_loc)
@@ -648,6 +667,10 @@ static irqreturn_t pcie_isr(int irq, voi
if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
return IRQ_HANDLED;

+ /* Check Link State Changed */
+ if (intr_loc & PCI_EXP_SLTSTA_DLLSC)
+ pciehp_handle_linkstate_change(slot);
+
/* Check MRL Sensor Changed */
if (intr_loc & PCI_EXP_SLTSTA_MRLSC)
pciehp_handle_switch_change(slot);
@@ -689,10 +712,12 @@ int pcie_enable_notification(struct cont
cmd |= PCI_EXP_SLTCTL_MRLSCE;
if (!pciehp_poll_mode)
cmd |= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE;
+ cmd |= PCI_EXP_SLTCTL_DLLSCE;

mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
- PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
+ PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
+ PCI_EXP_SLTCTL_DLLSCE);

if (pcie_write_cmd(ctrl, cmd, mask)) {
ctrl_err(ctrl, "Cannot enable software notification\n");