linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only
@ 2016-08-26  1:47 Ley Foon Tan
  2016-08-26  1:47 ` [PATCH v4 1/2] PCI: altera: Rework configs accessors Ley Foon Tan
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ley Foon Tan @ 2016-08-26  1:47 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-kernel, linux-pci, Ley Foon Tan, Ley Foon Tan

Altera PCIe IP can be configured as rootport or device and they might have
same vendor ID. It will cause the system hang issue if Altera PCIe is in
endpoint mode and work with other PCIe rootport that from other vendors.

This series of patch rework configs accessors and move retrain function
from _FIXUP to altera_pcie_host_init().

History:
v2: change to check PCIe type is PCI_EXP_TYPE_ROOT_PORT
v3: Move retrain function to before pci_scan_root_bus and remove _FIXUP
v4: Split patch to 2 patches

Ley Foon Tan (2):
  PCI: altera: Rework configs accessors
  PCI: altera: Move retrain from _FIXUP to altera_pcie_host_init()

 drivers/pci/host/pcie-altera.c | 215 +++++++++++++++++++++++++----------------
 1 file changed, 132 insertions(+), 83 deletions(-)

-- 
1.8.2.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 1/2] PCI: altera: Rework configs accessors
  2016-08-26  1:47 [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
@ 2016-08-26  1:47 ` Ley Foon Tan
  2016-08-26  1:47 ` [PATCH v4 2/2] PCI: altera: Move retrain from _FIXUP to altera_pcie_host_init() Ley Foon Tan
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ley Foon Tan @ 2016-08-26  1:47 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-kernel, linux-pci, Ley Foon Tan, Ley Foon Tan

Rework configs accessors so a future patch can use them in _probe()
with struct altera_pcie instead of struct pci_bus.

Signed-off-by: Ley Foon Tan <lftan@altera.com>
---
 drivers/pci/host/pcie-altera.c | 64 +++++++++++++++++++++++++++---------------
 1 file changed, 41 insertions(+), 23 deletions(-)

diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c
index 58eef99..34e6258 100644
--- a/drivers/pci/host/pcie-altera.c
+++ b/drivers/pci/host/pcie-altera.c
@@ -330,22 +330,14 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
-				int where, int size, u32 *value)
+static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno,
+				 unsigned int devfn, int where, int size,
+				 u32 *value)
 {
-	struct altera_pcie *pcie = bus->sysdata;
 	int ret;
 	u32 data;
 	u8 byte_en;
 
-	if (altera_pcie_hide_rc_bar(bus, devfn, where))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) {
-		*value = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
 	switch (size) {
 	case 1:
 		byte_en = 1 << (where & 3);
@@ -358,7 +350,7 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
 		break;
 	}
 
-	ret = tlp_cfg_dword_read(pcie, bus->number, devfn,
+	ret = tlp_cfg_dword_read(pcie, busno, devfn,
 				 (where & ~DWORD_MASK), byte_en, &data);
 	if (ret != PCIBIOS_SUCCESSFUL)
 		return ret;
@@ -378,20 +370,14 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
-				 int where, int size, u32 value)
+static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno,
+				  unsigned int devfn, int where, int size,
+				  u32 value)
 {
-	struct altera_pcie *pcie = bus->sysdata;
 	u32 data32;
 	u32 shift = 8 * (where & 3);
 	u8 byte_en;
 
-	if (altera_pcie_hide_rc_bar(bus, devfn, where))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn)))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
 	switch (size) {
 	case 1:
 		data32 = (value & 0xff) << shift;
@@ -407,8 +393,40 @@ static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
 		break;
 	}
 
-	return tlp_cfg_dword_write(pcie, bus->number, devfn,
-		(where & ~DWORD_MASK), byte_en, data32);
+	return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK),
+				   byte_en, data32);
+}
+
+static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 *value)
+{
+	struct altera_pcie *pcie = bus->sysdata;
+
+	if (altera_pcie_hide_rc_bar(bus, devfn, where))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) {
+		*value = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	return _altera_pcie_cfg_read(pcie, bus->number, devfn, where, size,
+				     value);
+}
+
+static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 value)
+{
+	struct altera_pcie *pcie = bus->sysdata;
+
+	if (altera_pcie_hide_rc_bar(bus, devfn, where))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn)))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return _altera_pcie_cfg_write(pcie, bus->number, devfn, where, size,
+				     value);
 }
 
 static struct pci_ops altera_pcie_ops = {
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 2/2] PCI: altera: Move retrain from _FIXUP to altera_pcie_host_init()
  2016-08-26  1:47 [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
  2016-08-26  1:47 ` [PATCH v4 1/2] PCI: altera: Rework configs accessors Ley Foon Tan
@ 2016-08-26  1:47 ` Ley Foon Tan
  2016-09-01  1:17 ` [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
  2016-09-12 21:55 ` Bjorn Helgaas
  3 siblings, 0 replies; 5+ messages in thread
From: Ley Foon Tan @ 2016-08-26  1:47 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-kernel, linux-pci, Ley Foon Tan, Ley Foon Tan

Altera PCIe IP can be configured as rootport or device and they might have
same vendor ID. It will cause the system hang issue if Altera PCIe is in
endpoint mode and work with other PCIe rootport that from other vendors.

Move link retrain function from _FIXUP to altera_pcie_host_init().

Signed-off-by: Ley Foon Tan <lftan@altera.com>
---
 drivers/pci/host/pcie-altera.c | 151 +++++++++++++++++++++++++----------------
 1 file changed, 91 insertions(+), 60 deletions(-)

diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c
index 34e6258..4ca50a2 100644
--- a/drivers/pci/host/pcie-altera.c
+++ b/drivers/pci/host/pcie-altera.c
@@ -43,6 +43,7 @@
 #define RP_LTSSM_MASK			0x1f
 #define LTSSM_L0			0xf
 
+#define PCIE_CAP_OFFSET			0x80
 /* TLP configuration type 0 and 1 */
 #define TLP_FMTTYPE_CFGRD0		0x04	/* Configuration Read Type 0 */
 #define TLP_FMTTYPE_CFGWR0		0x44	/* Configuration Write Type 0 */
@@ -100,66 +101,6 @@ static bool altera_pcie_link_is_up(struct altera_pcie *pcie)
 	return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0);
 }
 
-static void altera_wait_link_retrain(struct pci_dev *dev)
-{
-	u16 reg16;
-	unsigned long start_jiffies;
-	struct altera_pcie *pcie = dev->bus->sysdata;
-
-	/* Wait for link training end. */
-	start_jiffies = jiffies;
-	for (;;) {
-		pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &reg16);
-		if (!(reg16 & PCI_EXP_LNKSTA_LT))
-			break;
-
-		if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) {
-			dev_err(&pcie->pdev->dev, "link retrain timeout\n");
-			break;
-		}
-		udelay(100);
-	}
-
-	/* Wait for link is up */
-	start_jiffies = jiffies;
-	for (;;) {
-		if (altera_pcie_link_is_up(pcie))
-			break;
-
-		if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) {
-			dev_err(&pcie->pdev->dev, "link up timeout\n");
-			break;
-		}
-		udelay(100);
-	}
-}
-
-static void altera_pcie_retrain(struct pci_dev *dev)
-{
-	u16 linkcap, linkstat;
-	struct altera_pcie *pcie = dev->bus->sysdata;
-
-	if (!altera_pcie_link_is_up(pcie))
-		return;
-
-	/*
-	 * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but
-	 * current speed is 2.5 GB/s.
-	 */
-	pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap);
-
-	if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
-		return;
-
-	pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat);
-	if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) {
-		pcie_capability_set_word(dev, PCI_EXP_LNKCTL,
-					 PCI_EXP_LNKCTL_RL);
-		altera_wait_link_retrain(dev);
-	}
-}
-DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain);
-
 /*
  * Altera PCIe port uses BAR0 of RC's configuration space as the translation
  * from PCI bus to native BUS.  Entire DDR region is mapped into PCIe space
@@ -434,6 +375,90 @@ static struct pci_ops altera_pcie_ops = {
 	.write = altera_pcie_cfg_write,
 };
 
+static int altera_read_cap_word(struct altera_pcie *pcie, u8 busno,
+				unsigned int devfn, int offset, u16 *value)
+{
+	u32 data;
+	int ret;
+
+	ret = _altera_pcie_cfg_read(pcie, busno, devfn,
+				    PCIE_CAP_OFFSET + offset, sizeof(*value),
+				    &data);
+	*value = data;
+	return ret;
+}
+
+static int altera_write_cap_word(struct altera_pcie *pcie, u8 busno,
+				 unsigned int devfn, int offset, u16 value)
+{
+	return _altera_pcie_cfg_write(pcie, busno, devfn,
+				      PCIE_CAP_OFFSET + offset, sizeof(value),
+				      value);
+}
+
+static void altera_wait_link_retrain(struct altera_pcie *pcie)
+{
+	u16 reg16;
+	unsigned long start_jiffies;
+
+	/* Wait for link training end. */
+	start_jiffies = jiffies;
+	for (;;) {
+		altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
+				     PCI_EXP_LNKSTA, &reg16);
+		if (!(reg16 & PCI_EXP_LNKSTA_LT))
+			break;
+
+		if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) {
+			dev_err(&pcie->pdev->dev, "link retrain timeout\n");
+			break;
+		}
+		udelay(100);
+	}
+
+	/* Wait for link is up */
+	start_jiffies = jiffies;
+	for (;;) {
+		if (altera_pcie_link_is_up(pcie))
+			break;
+
+		if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) {
+			dev_err(&pcie->pdev->dev, "link up timeout\n");
+			break;
+		}
+		udelay(100);
+	}
+}
+
+static void altera_pcie_retrain(struct altera_pcie *pcie)
+{
+	u16 linkcap, linkstat, linkctl;
+
+	if (!altera_pcie_link_is_up(pcie))
+		return;
+
+	/*
+	 * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but
+	 * current speed is 2.5 GB/s.
+	 */
+	altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKCAP,
+			     &linkcap);
+	if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
+		return;
+
+	altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKSTA,
+			     &linkstat);
+	if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) {
+		altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
+				     PCI_EXP_LNKCTL, &linkctl);
+		linkctl |= PCI_EXP_LNKCTL_RL;
+		altera_write_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
+				      PCI_EXP_LNKCTL, linkctl);
+
+		altera_wait_link_retrain(pcie);
+	}
+}
+
 static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 				irq_hw_number_t hwirq)
 {
@@ -555,6 +580,11 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie)
 	return 0;
 }
 
+static void altera_pcie_host_init(struct altera_pcie *pcie)
+{
+	altera_pcie_retrain(pcie);
+}
+
 static int altera_pcie_probe(struct platform_device *pdev)
 {
 	struct altera_pcie *pcie;
@@ -592,6 +622,7 @@ static int altera_pcie_probe(struct platform_device *pdev)
 	cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS);
 	/* enable all interrupts */
 	cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE);
+	altera_pcie_host_init(pcie);
 
 	bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops,
 				pcie, &pcie->resources);
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only
  2016-08-26  1:47 [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
  2016-08-26  1:47 ` [PATCH v4 1/2] PCI: altera: Rework configs accessors Ley Foon Tan
  2016-08-26  1:47 ` [PATCH v4 2/2] PCI: altera: Move retrain from _FIXUP to altera_pcie_host_init() Ley Foon Tan
@ 2016-09-01  1:17 ` Ley Foon Tan
  2016-09-12 21:55 ` Bjorn Helgaas
  3 siblings, 0 replies; 5+ messages in thread
From: Ley Foon Tan @ 2016-09-01  1:17 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-kernel, linux-pci, Ley Foon Tan, Ley Foon Tan

On Fri, Aug 26, 2016 at 9:47 AM, Ley Foon Tan <lftan@altera.com> wrote:
> Altera PCIe IP can be configured as rootport or device and they might have
> same vendor ID. It will cause the system hang issue if Altera PCIe is in
> endpoint mode and work with other PCIe rootport that from other vendors.
>
> This series of patch rework configs accessors and move retrain function
> from _FIXUP to altera_pcie_host_init().
>
> History:
> v2: change to check PCIe type is PCI_EXP_TYPE_ROOT_PORT
> v3: Move retrain function to before pci_scan_root_bus and remove _FIXUP
> v4: Split patch to 2 patches
>
> Ley Foon Tan (2):
>   PCI: altera: Rework configs accessors
>   PCI: altera: Move retrain from _FIXUP to altera_pcie_host_init()
>
>  drivers/pci/host/pcie-altera.c | 215 +++++++++++++++++++++++++----------------
>  1 file changed, 132 insertions(+), 83 deletions(-)
>
Hi Bjorn

Do you have further comment on this patch series?
Thanks.

Regards
Ley Foon

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only
  2016-08-26  1:47 [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
                   ` (2 preceding siblings ...)
  2016-09-01  1:17 ` [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
@ 2016-09-12 21:55 ` Bjorn Helgaas
  3 siblings, 0 replies; 5+ messages in thread
From: Bjorn Helgaas @ 2016-09-12 21:55 UTC (permalink / raw)
  To: Ley Foon Tan; +Cc: Bjorn Helgaas, linux-kernel, linux-pci, Ley Foon Tan

On Fri, Aug 26, 2016 at 09:47:23AM +0800, Ley Foon Tan wrote:
> Altera PCIe IP can be configured as rootport or device and they might have
> same vendor ID. It will cause the system hang issue if Altera PCIe is in
> endpoint mode and work with other PCIe rootport that from other vendors.
> 
> This series of patch rework configs accessors and move retrain function
> from _FIXUP to altera_pcie_host_init().
> 
> History:
> v2: change to check PCIe type is PCI_EXP_TYPE_ROOT_PORT
> v3: Move retrain function to before pci_scan_root_bus and remove _FIXUP
> v4: Split patch to 2 patches
> 
> Ley Foon Tan (2):
>   PCI: altera: Rework configs accessors
>   PCI: altera: Move retrain from _FIXUP to altera_pcie_host_init()
> 
>  drivers/pci/host/pcie-altera.c | 215 +++++++++++++++++++++++++----------------
>  1 file changed, 132 insertions(+), 83 deletions(-)

Applied to pci/host-altera for v4.9, thanks!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-09-12 21:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-26  1:47 [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
2016-08-26  1:47 ` [PATCH v4 1/2] PCI: altera: Rework configs accessors Ley Foon Tan
2016-08-26  1:47 ` [PATCH v4 2/2] PCI: altera: Move retrain from _FIXUP to altera_pcie_host_init() Ley Foon Tan
2016-09-01  1:17 ` [PATCH v4 0/2] PCI: altera: Retrain link in rootport mode only Ley Foon Tan
2016-09-12 21:55 ` Bjorn Helgaas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).