[RFC PATCH 2/3] PCI: Add PCIe Gen 7 (128 GT/s) speed detection and reporting

Ionut Nechita (Sunlight Linux) posted 3 patches 1 month, 2 weeks ago
[RFC PATCH 2/3] PCI: Add PCIe Gen 7 (128 GT/s) speed detection and reporting
Posted by Ionut Nechita (Sunlight Linux) 1 month, 2 weeks ago
From: Ionut Nechita <ionut_n2001@yahoo.com>

Add kernel infrastructure to detect and report PCIe Gen 7 128 GT/s
link speeds:

  - Extend PCIE_LNKCAP_SLS2SPEED, PCIE_LNKCAP2_SLS2SPEED, and
    PCIE_LNKCTL2_TLS2SPEED macros with 128 GT/s mapping
  - Add 128 GT/s to PCIE_SPEED2MBS_ENC bandwidth calculation using
    1:1 Flit mode encoding (no overhead), consistent with Gen 6
  - Add PCIE_SPEED_128_0GT to pcie_dev_speed_mbps() switch
  - Map link speed encoding 7 to PCIE_SPEED_128_0GT in
    pcie_link_speed[] table
  - Add "128.0 GT/s PCIe" display string
  - Add pcie_speed_requires_flit() helper for Gen 6+ speed
    validation with proper range check against PCI_SPEED_UNKNOWN
  - Widen pcie_get_supported_speeds() return type from u8 to u16
  - Add Flit mode diagnostic warning when Gen 6+ speed is active
    but PCI_EXP_LNKSTA2_FLIT is not set

Signed-off-by: Ionut Nechita <ionut_n2001@yahoo.com>
---
 drivers/pci/pci.c   |  7 +++++--
 drivers/pci/pci.h   | 28 ++++++++++++++++++++++------
 drivers/pci/probe.c |  3 ++-
 3 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 13dbb405dc31f..8091f7bf30e6f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5912,10 +5912,10 @@ EXPORT_SYMBOL(pcie_bandwidth_available);
  *
  * Return: Supported Link Speeds Vector (+ reserved 0 at LSB).
  */
-u8 pcie_get_supported_speeds(struct pci_dev *dev)
+u16 pcie_get_supported_speeds(struct pci_dev *dev)
 {
 	u32 lnkcap2, lnkcap;
-	u8 speeds;
+	u16 speeds;
 
 	/*
 	 * Speeds retain the reserved 0 at LSB before PCIe Supported Link
@@ -6020,6 +6020,9 @@ void __pcie_print_link_status(struct pci_dev *dev, bool verbose)
 
 	if (dev->bus && dev->bus->flit_mode)
 		flit_mode = ", in Flit mode";
+	else if (dev->bus && pcie_speed_requires_flit(dev->bus->cur_bus_speed))
+		pci_warn(dev, "Flit mode not active at %s, expected for Gen 6+\n",
+			 pci_speed_string(dev->bus->cur_bus_speed));
 
 	if (bw_avail >= bw_cap && verbose)
 		pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth (%s x%d link)%s\n",
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 60542b05de0c6..4dd23f0d5de9f 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -487,7 +487,8 @@ void pci_bus_put(struct pci_bus *bus);
 ({									\
 	u32 lnkcap_sls = (lnkcap) & PCI_EXP_LNKCAP_SLS;			\
 									\
-	(lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT :	\
+	(lnkcap_sls == PCI_EXP_LNKCAP_SLS_128_0GB ? PCIE_SPEED_128_0GT :	\
+	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT :	\
 	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT :	\
 	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT :	\
 	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT :	\
@@ -498,7 +499,8 @@ void pci_bus_put(struct pci_bus *bus);
 
 /* PCIe link information from Link Capabilities 2 */
 #define PCIE_LNKCAP2_SLS2SPEED(lnkcap2) \
-	((lnkcap2) & PCI_EXP_LNKCAP2_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
+	((lnkcap2) & PCI_EXP_LNKCAP2_SLS_128_0GB ? PCIE_SPEED_128_0GT : \
+	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
 	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
 	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
 	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
@@ -510,7 +512,8 @@ void pci_bus_put(struct pci_bus *bus);
 ({									\
 	u16 lnkctl2_tls = (lnkctl2) & PCI_EXP_LNKCTL2_TLS;		\
 									\
-	(lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT :	\
+	(lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_128_0GT ? PCIE_SPEED_128_0GT :	\
+	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT :	\
 	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT :	\
 	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT :	\
 	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT :	\
@@ -519,9 +522,14 @@ void pci_bus_put(struct pci_bus *bus);
 	 PCI_SPEED_UNKNOWN);						\
 })
 
-/* PCIe speed to Mb/s reduced by encoding overhead */
+/* PCIe speed to Mb/s reduced by encoding overhead:
+ *   Gen 1-2 (2.5, 5 GT/s):       8b/10b encoding
+ *   Gen 3-5 (8, 16, 32 GT/s):    128b/130b encoding
+ *   Gen 6+  (64, 128 GT/s):      Flit mode, 1:1 (no encoding overhead)
+ */
 #define PCIE_SPEED2MBS_ENC(speed) \
-	((speed) == PCIE_SPEED_64_0GT ? 64000*1/1 : \
+	((speed) == PCIE_SPEED_128_0GT ? 128000*1/1 : \
+	 (speed) == PCIE_SPEED_64_0GT ? 64000*1/1 : \
 	 (speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \
 	 (speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \
 	 (speed) == PCIE_SPEED_8_0GT  ?  8000*128/130 : \
@@ -544,6 +552,8 @@ static inline int pcie_dev_speed_mbps(enum pci_bus_speed speed)
 		return 32000;
 	case PCIE_SPEED_64_0GT:
 		return 64000;
+	case PCIE_SPEED_128_0GT:
+		return 128000;
 	default:
 		break;
 	}
@@ -551,7 +561,13 @@ static inline int pcie_dev_speed_mbps(enum pci_bus_speed speed)
 	return -EINVAL;
 }
 
-u8 pcie_get_supported_speeds(struct pci_dev *dev);
+/* PCIe Gen 6+ (>= 64 GT/s) requires Flit mode with 1:1 encoding */
+static inline bool pcie_speed_requires_flit(enum pci_bus_speed speed)
+{
+	return speed >= PCIE_SPEED_64_0GT && speed <= PCIE_SPEED_128_0GT;
+}
+
+u16 pcie_get_supported_speeds(struct pci_dev *dev);
 const char *pci_speed_string(enum pci_bus_speed speed);
 void __pcie_print_link_status(struct pci_dev *dev, bool verbose);
 void pcie_report_downtraining(struct pci_dev *dev);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 9d4eeda5ea946..031c3ec8615d2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -774,7 +774,7 @@ const unsigned char pcie_link_speed[] = {
 	PCIE_SPEED_16_0GT,		/* 4 */
 	PCIE_SPEED_32_0GT,		/* 5 */
 	PCIE_SPEED_64_0GT,		/* 6 */
-	PCI_SPEED_UNKNOWN,		/* 7 */
+	PCIE_SPEED_128_0GT,		/* 7 */
 	PCI_SPEED_UNKNOWN,		/* 8 */
 	PCI_SPEED_UNKNOWN,		/* 9 */
 	PCI_SPEED_UNKNOWN,		/* A */
@@ -816,6 +816,7 @@ const char *pci_speed_string(enum pci_bus_speed speed)
 	    "16.0 GT/s PCIe",		/* 0x17 */
 	    "32.0 GT/s PCIe",		/* 0x18 */
 	    "64.0 GT/s PCIe",		/* 0x19 */
+	    "128.0 GT/s PCIe",		/* 0x1a */
 	};
 
 	if (speed < ARRAY_SIZE(speed_strings))
-- 
2.53.0
Re: [RFC PATCH 2/3] PCI: Add PCIe Gen 7 (128 GT/s) speed detection and reporting
Posted by Ilpo Järvinen 1 month, 1 week ago
On Tue, 17 Feb 2026, Ionut Nechita (Sunlight Linux) wrote:

> From: Ionut Nechita <ionut_n2001@yahoo.com>
> 
> Add kernel infrastructure to detect and report PCIe Gen 7 128 GT/s
> link speeds:
> 
>   - Extend PCIE_LNKCAP_SLS2SPEED, PCIE_LNKCAP2_SLS2SPEED, and
>     PCIE_LNKCTL2_TLS2SPEED macros with 128 GT/s mapping
>   - Add 128 GT/s to PCIE_SPEED2MBS_ENC bandwidth calculation using
>     1:1 Flit mode encoding (no overhead), consistent with Gen 6
>   - Add PCIE_SPEED_128_0GT to pcie_dev_speed_mbps() switch
>   - Map link speed encoding 7 to PCIE_SPEED_128_0GT in
>     pcie_link_speed[] table
>   - Add "128.0 GT/s PCIe" display string
>   - Add pcie_speed_requires_flit() helper for Gen 6+ speed
>     validation with proper range check against PCI_SPEED_UNKNOWN
>   - Widen pcie_get_supported_speeds() return type from u8 to u16

These are all visible from the patch and as such seem pretty redundant 
information.

>   - Add Flit mode diagnostic warning when Gen 6+ speed is active
>     but PCI_EXP_LNKSTA2_FLIT is not set
> 
> Signed-off-by: Ionut Nechita <ionut_n2001@yahoo.com>
> ---
>  drivers/pci/pci.c   |  7 +++++--
>  drivers/pci/pci.h   | 28 ++++++++++++++++++++++------
>  drivers/pci/probe.c |  3 ++-
>  3 files changed, 29 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 13dbb405dc31f..8091f7bf30e6f 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5912,10 +5912,10 @@ EXPORT_SYMBOL(pcie_bandwidth_available);
>   *
>   * Return: Supported Link Speeds Vector (+ reserved 0 at LSB).
>   */
> -u8 pcie_get_supported_speeds(struct pci_dev *dev)
> +u16 pcie_get_supported_speeds(struct pci_dev *dev)
>  {
>  	u32 lnkcap2, lnkcap;
> -	u8 speeds;
> +	u16 speeds;
>  
>  	/*
>  	 * Speeds retain the reserved 0 at LSB before PCIe Supported Link
> @@ -6020,6 +6020,9 @@ void __pcie_print_link_status(struct pci_dev *dev, bool verbose)
>  
>  	if (dev->bus && dev->bus->flit_mode)
>  		flit_mode = ", in Flit mode";
> +	else if (dev->bus && pcie_speed_requires_flit(dev->bus->cur_bus_speed))
> +		pci_warn(dev, "Flit mode not active at %s, expected for Gen 6+\n",
> +			 pci_speed_string(dev->bus->cur_bus_speed));

This looks entirely unrelated to the new speed, please put it into own 
patch (and justification in the changelog).

>  
>  	if (bw_avail >= bw_cap && verbose)
>  		pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth (%s x%d link)%s\n",
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 60542b05de0c6..4dd23f0d5de9f 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -487,7 +487,8 @@ void pci_bus_put(struct pci_bus *bus);
>  ({									\
>  	u32 lnkcap_sls = (lnkcap) & PCI_EXP_LNKCAP_SLS;			\
>  									\
> -	(lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT :	\
> +	(lnkcap_sls == PCI_EXP_LNKCAP_SLS_128_0GB ? PCIE_SPEED_128_0GT :	\
> +	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT :	\
>  	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT :	\
>  	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT :	\
>  	 lnkcap_sls == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT :	\
> @@ -498,7 +499,8 @@ void pci_bus_put(struct pci_bus *bus);
>  
>  /* PCIe link information from Link Capabilities 2 */
>  #define PCIE_LNKCAP2_SLS2SPEED(lnkcap2) \
> -	((lnkcap2) & PCI_EXP_LNKCAP2_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
> +	((lnkcap2) & PCI_EXP_LNKCAP2_SLS_128_0GB ? PCIE_SPEED_128_0GT : \
> +	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
>  	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
>  	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
>  	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
> @@ -510,7 +512,8 @@ void pci_bus_put(struct pci_bus *bus);
>  ({									\
>  	u16 lnkctl2_tls = (lnkctl2) & PCI_EXP_LNKCTL2_TLS;		\
>  									\
> -	(lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT :	\
> +	(lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_128_0GT ? PCIE_SPEED_128_0GT :	\
> +	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT :	\
>  	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT :	\
>  	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT :	\
>  	 lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT :	\
> @@ -519,9 +522,14 @@ void pci_bus_put(struct pci_bus *bus);
>  	 PCI_SPEED_UNKNOWN);						\
>  })
>  
> -/* PCIe speed to Mb/s reduced by encoding overhead */
> +/* PCIe speed to Mb/s reduced by encoding overhead:
> + *   Gen 1-2 (2.5, 5 GT/s):       8b/10b encoding
> + *   Gen 3-5 (8, 16, 32 GT/s):    128b/130b encoding
> + *   Gen 6+  (64, 128 GT/s):      Flit mode, 1:1 (no encoding overhead)
> + */
>  #define PCIE_SPEED2MBS_ENC(speed) \
> -	((speed) == PCIE_SPEED_64_0GT ? 64000*1/1 : \
> +	((speed) == PCIE_SPEED_128_0GT ? 128000*1/1 : \
> +	 (speed) == PCIE_SPEED_64_0GT ? 64000*1/1 : \
>  	 (speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \
>  	 (speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \
>  	 (speed) == PCIE_SPEED_8_0GT  ?  8000*128/130 : \
> @@ -544,6 +552,8 @@ static inline int pcie_dev_speed_mbps(enum pci_bus_speed speed)
>  		return 32000;
>  	case PCIE_SPEED_64_0GT:
>  		return 64000;
> +	case PCIE_SPEED_128_0GT:
> +		return 128000;
>  	default:
>  		break;
>  	}
> @@ -551,7 +561,13 @@ static inline int pcie_dev_speed_mbps(enum pci_bus_speed speed)
>  	return -EINVAL;
>  }
>  
> -u8 pcie_get_supported_speeds(struct pci_dev *dev);
> +/* PCIe Gen 6+ (>= 64 GT/s) requires Flit mode with 1:1 encoding */
> +static inline bool pcie_speed_requires_flit(enum pci_bus_speed speed)
> +{
> +	return speed >= PCIE_SPEED_64_0GT && speed <= PCIE_SPEED_128_0GT;
> +}
> +
> +u16 pcie_get_supported_speeds(struct pci_dev *dev);
>  const char *pci_speed_string(enum pci_bus_speed speed);
>  void __pcie_print_link_status(struct pci_dev *dev, bool verbose);
>  void pcie_report_downtraining(struct pci_dev *dev);
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 9d4eeda5ea946..031c3ec8615d2 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -774,7 +774,7 @@ const unsigned char pcie_link_speed[] = {
>  	PCIE_SPEED_16_0GT,		/* 4 */
>  	PCIE_SPEED_32_0GT,		/* 5 */
>  	PCIE_SPEED_64_0GT,		/* 6 */
> -	PCI_SPEED_UNKNOWN,		/* 7 */
> +	PCIE_SPEED_128_0GT,		/* 7 */
>  	PCI_SPEED_UNKNOWN,		/* 8 */
>  	PCI_SPEED_UNKNOWN,		/* 9 */
>  	PCI_SPEED_UNKNOWN,		/* A */
> @@ -816,6 +816,7 @@ const char *pci_speed_string(enum pci_bus_speed speed)
>  	    "16.0 GT/s PCIe",		/* 0x17 */
>  	    "32.0 GT/s PCIe",		/* 0x18 */
>  	    "64.0 GT/s PCIe",		/* 0x19 */
> +	    "128.0 GT/s PCIe",		/* 0x1a */
>  	};
>  
>  	if (speed < ARRAY_SIZE(speed_strings))
> 

-- 
 i.