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
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.
© 2016 - 2026 Red Hat, Inc.