diff mbox

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

Message ID CAE9FiQXkgLw6y2GmVvRStOAuqqOY=kTypLKY6YcvOhD2zOhdsw@mail.gmail.com
State Changes Requested
Headers show

Commit Message

Yinghai Lu Dec. 18, 2013, 6:50 a.m. UTC
On Tue, Dec 17, 2013 at 10:17 PM, Rajat Jain <rajatjain@juniper.net> 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
diff mbox

Patch

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

To see if there is some link state change.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 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");