lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251028134601.3688030-1-s-vadapalli@ti.com>
Date: Tue, 28 Oct 2025 19:15:58 +0530
From: Siddharth Vadapalli <s-vadapalli@...com>
To: <lpieralisi@...nel.org>, <kwilczynski@...nel.org>, <mani@...nel.org>,
	<robh@...nel.org>, <bhelgaas@...gle.com>, <kishon@...nel.org>,
	<18255117159@....com>, <unicorn_wang@...look.com>
CC: <linux-pci@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
	<linux-arm-kernel@...ts.infradead.org>, <srk@...com>, <s-vadapalli@...com>
Subject: [PATCH v2] PCI: cadence: Enable support for applying lane equalization presets

The PCIe Link Equalization procedure allows peers on a PCIe Link to
improve the signal quality by exchanging transmitter presets and
receiver preset hints in the form of Ordered Sets.

For link speeds of 8.0 GT/s and above, the transmitter presets and the
receiver preset hints are configurable parameters which can be tuned to
establish a stable link. This allows setting up a stable link that is
specific to the peers across a Link.

The device-tree property 'eq-presets-Ngts' (eq-presets-8gts,
eq-presets-16gts, ...) specifies the transmitter presets and receiver
preset hints to be applied to every lane of the link for every supported
link speed that is greater than or equal to 8.0 GT/s.

Hence, enable support for applying the 'optional' lane equalization
presets when operating in the Root-Port (Root-Complex / Host) mode.

Signed-off-by: Siddharth Vadapalli <s-vadapalli@...com>
---

Hello,

This patch is based on linux-next tagged next-20251028.
It also applies cleanly on v6.18-rc1.

Link to v1 patch:
https://lore.kernel.org/r/20251027133013.2589119-1-s-vadapalli@ti.com/
Changes since v1:
- Implemented Bjorn's suggestion of adding 'fallthrough' keyword in
  switch-case to avoid compilation warnings, since 'fallthrough' is
  intentional.

Regards,
Siddharth.

 .../controller/cadence/pcie-cadence-host.c    | 85 +++++++++++++++++++
 drivers/pci/controller/cadence/pcie-cadence.h |  5 ++
 2 files changed, 90 insertions(+)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index fffd63d6665e..ae85ad8cce82 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -168,6 +168,90 @@ static void cdns_pcie_host_enable_ptm_response(struct cdns_pcie *pcie)
 	cdns_pcie_writel(pcie, CDNS_PCIE_LM_PTM_CTRL, val | CDNS_PCIE_LM_TPM_CTRL_PTMRSEN);
 }
 
+static void cdns_pcie_setup_lane_equalization_presets(struct cdns_pcie_rc *rc)
+{
+	struct cdns_pcie *pcie = &rc->pcie;
+	struct device *dev = pcie->dev;
+	struct device_node *np = dev->of_node;
+	int max_link_speed, max_lanes, ret;
+	u32 lane_eq_ctrl_reg;
+	u16 cap;
+	u16 *presets_8gts;
+	u8 *presets_ngts;
+	u8 i, j;
+
+	ret = of_property_read_u32(np, "num-lanes", &max_lanes);
+	if (ret)
+		return;
+
+	/* Lane Equalization presets are optional, so error message is not necessary */
+	ret = of_pci_get_equalization_presets(dev, &rc->eq_presets, max_lanes);
+	if (ret)
+		return;
+
+	max_link_speed = of_pci_get_max_link_speed(np);
+	if (max_link_speed < 0) {
+		dev_err(dev, "%s: link-speed unknown, skipping preset setup\n", __func__);
+		return;
+	}
+
+	/*
+	 * Setup presets for data rates including and upward of 8.0 GT/s until the
+	 * maximum supported data rate.
+	 */
+	switch (pcie_link_speed[max_link_speed]) {
+	case PCIE_SPEED_16_0GT:
+		presets_ngts = (u8 *)rc->eq_presets.eq_presets_Ngts[EQ_PRESET_TYPE_16GTS - 1];
+		if (presets_ngts[0] != PCI_EQ_RESV) {
+			cap = cdns_pcie_find_ext_capability(pcie, PCI_EXT_CAP_ID_PL_16GT);
+			if (!cap)
+				break;
+			lane_eq_ctrl_reg = cap + PCI_PL_16GT_LE_CTRL;
+			/*
+			 * For Link Speeds including and upward of 16.0 GT/s, the Lane Equalization
+			 * Control register has the following layout per Lane:
+			 * Bits 0-3: Downstream Port Transmitter Preset
+			 * Bits 4-7: Upstream Port Transmitter Preset
+			 *
+			 * 'eq_presets_Ngts' is an array of u8 (byte).
+			 * Therefore, we need to write to the Lane Equalization Control
+			 * register in units of bytes per-Lane.
+			 */
+			for (i = 0; i < max_lanes; i++)
+				cdns_pcie_rp_writeb(pcie, lane_eq_ctrl_reg + i, presets_ngts[i]);
+
+			dev_info(dev, "Link Equalization presets applied for 16.0 GT/s\n");
+		}
+		fallthrough;
+	case PCIE_SPEED_8_0GT:
+		presets_8gts = (u16 *)rc->eq_presets.eq_presets_8gts;
+		if ((presets_8gts[0] & PCI_EQ_RESV) != PCI_EQ_RESV) {
+			cap = cdns_pcie_find_ext_capability(pcie, PCI_EXT_CAP_ID_SECPCI);
+			if (!cap)
+				break;
+			lane_eq_ctrl_reg = cap + PCI_SECPCI_LE_CTRL;
+			/*
+			 * For a Link Speed of 8.0 GT/s, the Lane Equalization Control register has
+			 * the following layout per Lane:
+			 * Bits   0-3:  Downstream Port Transmitter Preset
+			 * Bits   4-6:  Downstream Port Receiver Preset Hint
+			 * Bit      7:  Reserved
+			 * Bits  8-11:  Upstream Port Transmitter Preset
+			 * Bits 12-14:  Upstream Port Receiver Preset Hint
+			 * Bit     15:  Reserved
+			 *
+			 * 'eq_presets_8gts' is an array of u16 (word).
+			 * Therefore, we need to write to the Lane Equalization Control
+			 * register in units of words per-Lane.
+			 */
+			for (i = 0, j = 0; i < max_lanes; i++, j += 2)
+				cdns_pcie_rp_writew(pcie, lane_eq_ctrl_reg + j, presets_8gts[i]);
+
+			dev_info(dev, "Link Equalization presets applied for 8.0 GT/s\n");
+		}
+	}
+}
+
 static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc)
 {
 	struct cdns_pcie *pcie = &rc->pcie;
@@ -600,6 +684,7 @@ int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
 		cdns_pcie_detect_quiet_min_delay_set(&rc->pcie);
 
 	cdns_pcie_host_enable_ptm_response(pcie);
+	cdns_pcie_setup_lane_equalization_presets(rc);
 
 	ret = cdns_pcie_start_link(pcie);
 	if (ret) {
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index e2a853d2c0ab..39d03b309978 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -11,6 +11,8 @@
 #include <linux/pci-epf.h>
 #include <linux/phy/phy.h>
 
+#include "../../pci.h"
+
 /* Parameters for the waiting for link up routine */
 #define LINK_WAIT_MAX_RETRIES	10
 #define LINK_WAIT_USLEEP_MIN	90000
@@ -288,6 +290,8 @@ struct cdns_pcie {
  *                available
  * @quirk_retrain_flag: Retrain link as quirk for PCIe Gen2
  * @quirk_detect_quiet_flag: LTSSM Detect Quiet min delay set as quirk
+ * @eq_presets: Lane Equalization presets for Link Speed including and upward
+ *              of 8.0 GT/s
  */
 struct cdns_pcie_rc {
 	struct cdns_pcie	pcie;
@@ -298,6 +302,7 @@ struct cdns_pcie_rc {
 	bool			avail_ib_bar[CDNS_PCIE_RP_MAX_IB];
 	unsigned int		quirk_retrain_flag:1;
 	unsigned int		quirk_detect_quiet_flag:1;
+	struct pci_eq_presets	eq_presets;
 };
 
 /**
-- 
2.51.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ