All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: Koichiro Den <den@valinux.co.jp>
Cc: Dave Jiang <dave.jiang@intel.com>,
	Davidlohr Bueso <dave@stgolabs.net>,
	Jonathan Cameron <jic23@kernel.org>,
	Alison Schofield <alison.schofield@intel.com>,
	Vishal Verma <vishal.l.verma@intel.com>,
	Dan Williams <djbw@kernel.org>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Ira Weiny <iweiny@kernel.org>, Li Ming <ming.li@zohomail.com>,
	Richard Cheng <icheng@nvidia.com>,
	Terry Bowman <terry.bowman@amd.com>,
	Alejandro Lucero <alucerop@amd.com>,
	linux-cxl@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-pci@vger.kernel.org
Subject: Re: [PATCH 2/3] cxl: Account for link width in latency calculation
Date: Fri, 9 Oct 2026 10:09:31 -0500	[thread overview]
Message-ID: <20261009150931.GA974538@bhelgaas> (raw)
In-Reply-To: <20261009045452.1107921-3-den@valinux.co.jp>

On Fri, Oct 09, 2026 at 01:54:51PM +0900, Koichiro Den wrote:
> cxl_pci_get_latency() derives bandwidth from the per-lane speed returned
> by pcie_link_speed_mbps(), ignoring the negotiated link width. This
> overestimates the FlitLatency contribution for multi-lane links.
> Sections 2.11.3 and 2.11.4 of the Intel CXL Memory Device Software Guide
> describe the link bandwidth as the product of the negotiated speed and
> width.
> 
> Replace pcie_link_speed_mbps() with pcie_link_bandwidth_mbps() and
> migrate both CXL callers (the only users of the API). The new helper
> obtains speed and width from a single Link Status read. The CXL
> bandwidth calculation no longer needs a separate width read and
> multiplication.
> 
> While at it, make error handling more robust by converting PCI config
> read errors to negative errno values and checking for zero bandwidth
> before calculating latency.
> 
> Fixes: 4d07a05397c8 ("cxl: Calculate and store PCI link latency for the downstream ports")
> Cc: stable@vger.kernel.org
> Signed-off-by: Koichiro Den <den@valinux.co.jp>

Acked-by: Bjorn Helgaas <bhelgaas@google.com>	# pci/pci.c

> ---
>  drivers/cxl/core/pci.c | 22 ++++++++--------------
>  drivers/pci/pci.c      | 23 ++++++++++++++++++-----
>  include/linux/pci.h    |  2 +-
>  3 files changed, 27 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 43b9b7afff29..8b52621ffea1 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -660,8 +660,8 @@ long cxl_pci_get_latency(struct pci_dev *pdev)
>  {
>  	long bw;
>  
> -	bw = pcie_link_speed_mbps(pdev);
> -	if (bw < 0)
> +	bw = pcie_link_bandwidth_mbps(pdev);
> +	if (bw <= 0)
>  		return 0;
>  	bw /= BITS_PER_BYTE;
>  
> @@ -765,18 +765,12 @@ EXPORT_SYMBOL_NS_GPL(cxl_pci_setup_regs, "CXL");
>  
>  int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c)
>  {
> -	int speed, bw;
> -	u16 lnksta;
> -	u32 width;
> -
> -	speed = pcie_link_speed_mbps(pdev);
> -	if (speed < 0)
> -		return speed;
> -	speed /= BITS_PER_BYTE;
> -
> -	pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta);
> -	width = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
> -	bw = speed * width;
> +	int bw;
> +
> +	bw = pcie_link_bandwidth_mbps(pdev);
> +	if (bw < 0)
> +		return bw;
> +	bw /= BITS_PER_BYTE;
>  
>  	for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
>  		c[i].read_bandwidth = bw;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b2879a6be5f8..aa3d180de56e 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5980,18 +5980,31 @@ static enum pci_bus_speed to_pcie_link_speed(u16 lnksta)
>  	return pcie_link_speed[FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta)];
>  }
>  
> -int pcie_link_speed_mbps(struct pci_dev *pdev)
> +/**
> + * pcie_link_bandwidth_mbps - get the current bandwidth of a single PCIe link
> + * @pdev: PCI device to query
> + *
> + * The bandwidth includes all negotiated lanes and does not account for
> + * encoding overhead. A negotiated width of zero gives zero bandwidth.
> + *
> + * Return: Bandwidth in Mb/s, or a negative errno on failure.
> + */
> +int pcie_link_bandwidth_mbps(struct pci_dev *pdev)
>  {
>  	u16 lnksta;
> -	int err;
> +	int speed, err;
>  
>  	err = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta);
>  	if (err)
> -		return err;
> +		return pcibios_err_to_errno(err);
> +
> +	speed = pcie_dev_speed_mbps(to_pcie_link_speed(lnksta));
> +	if (speed < 0)
> +		return speed;
>  
> -	return pcie_dev_speed_mbps(to_pcie_link_speed(lnksta));
> +	return speed * FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
>  }
> -EXPORT_SYMBOL(pcie_link_speed_mbps);
> +EXPORT_SYMBOL(pcie_link_bandwidth_mbps);
>  
>  /**
>   * pcie_bandwidth_available - determine minimum link settings of a PCIe
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index d31a8d107b1e..bbfb0b98ff46 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1477,7 +1477,7 @@ int pcie_set_mps(struct pci_dev *dev, int mps);
>  u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
>  			     enum pci_bus_speed *speed,
>  			     enum pcie_link_width *width);
> -int pcie_link_speed_mbps(struct pci_dev *pdev);
> +int pcie_link_bandwidth_mbps(struct pci_dev *pdev);
>  void pcie_print_link_status(struct pci_dev *dev);
>  int pcie_reset_flr(struct pci_dev *dev, bool probe);
>  int pcie_flr(struct pci_dev *dev);
> -- 
> 2.51.0
> 

  parent reply	other threads:[~2026-10-09 15:09 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09  4:54 [PATCH 0/3] cxl: Fix link latency calculations and QTG latency units Koichiro Den
2026-10-09  4:54 ` [PATCH 1/3] cxl/port: Convert PCIe link latency to nanoseconds Koichiro Den
2026-10-09  5:02   ` sashiko-bot
2026-10-09 18:22   ` Alison Schofield
2026-10-09  4:54 ` [PATCH 2/3] cxl: Account for link width in latency calculation Koichiro Den
2026-10-09  5:01   ` sashiko-bot
2026-10-09 15:09   ` Bjorn Helgaas [this message]
2026-10-09 18:26   ` Alison Schofield
2026-10-09  4:54 ` [PATCH 3/3] cxl/acpi: Convert QTG _DSM latencies to picoseconds Koichiro Den
2026-10-09  5:02   ` sashiko-bot
2026-10-09 18:27   ` Alison Schofield
2026-10-09 17:15 ` [PATCH 0/3] cxl: Fix link latency calculations and QTG latency units Dave Jiang
2026-10-09 21:49 ` Dave Jiang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261009150931.GA974538@bhelgaas \
    --to=helgaas@kernel.org \
    --cc=alison.schofield@intel.com \
    --cc=alucerop@amd.com \
    --cc=bhelgaas@google.com \
    --cc=dave.jiang@intel.com \
    --cc=dave@stgolabs.net \
    --cc=den@valinux.co.jp \
    --cc=djbw@kernel.org \
    --cc=icheng@nvidia.com \
    --cc=iweiny@kernel.org \
    --cc=jic23@kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=ming.li@zohomail.com \
    --cc=terry.bowman@amd.com \
    --cc=vishal.l.verma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.