summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/cxl/core/pci.c22
-rw-r--r--drivers/pci/pci.c23
-rw-r--r--include/linux/pci.h2
3 files changed, 27 insertions, 20 deletions
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 713a75e68bb9..125abb36df7f 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;
@@ -771,18 +771,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);