Skip to content

Commit 6cf57be

Browse files
talgimellanoxbjorn-helgaas
authored andcommitted
PCI: Add pcie_get_speed_cap() to find max supported link speed
Add pcie_get_speed_cap() to find the max link speed supported by a device. Change max_link_speed_show() to use pcie_get_speed_cap(). Signed-off-by: Tal Gilboa <talgi@mellanox.com> [bhelgaas: return speed directly instead of error and *speed, don't export outside drivers/pci] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
1 parent 1acfb9b commit 6cf57be

File tree

3 files changed

+56
-26
lines changed

3 files changed

+56
-26
lines changed

drivers/pci/pci-sysfs.c

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -158,33 +158,9 @@ static DEVICE_ATTR_RO(resource);
158158
static ssize_t max_link_speed_show(struct device *dev,
159159
struct device_attribute *attr, char *buf)
160160
{
161-
struct pci_dev *pci_dev = to_pci_dev(dev);
162-
u32 linkcap;
163-
int err;
164-
const char *speed;
165-
166-
err = pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &linkcap);
167-
if (err)
168-
return -EINVAL;
169-
170-
switch (linkcap & PCI_EXP_LNKCAP_SLS) {
171-
case PCI_EXP_LNKCAP_SLS_16_0GB:
172-
speed = "16 GT/s";
173-
break;
174-
case PCI_EXP_LNKCAP_SLS_8_0GB:
175-
speed = "8 GT/s";
176-
break;
177-
case PCI_EXP_LNKCAP_SLS_5_0GB:
178-
speed = "5 GT/s";
179-
break;
180-
case PCI_EXP_LNKCAP_SLS_2_5GB:
181-
speed = "2.5 GT/s";
182-
break;
183-
default:
184-
speed = "Unknown speed";
185-
}
161+
struct pci_dev *pdev = to_pci_dev(dev);
186162

187-
return sprintf(buf, "%s\n", speed);
163+
return sprintf(buf, "%s\n", PCIE_SPEED2STR(pcie_get_speed_cap(pdev)));
188164
}
189165
static DEVICE_ATTR_RO(max_link_speed);
190166

drivers/pci/pci.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5146,6 +5146,50 @@ int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
51465146
}
51475147
EXPORT_SYMBOL(pcie_get_minimum_link);
51485148

5149+
/**
5150+
* pcie_get_speed_cap - query for the PCI device's link speed capability
5151+
* @dev: PCI device to query
5152+
*
5153+
* Query the PCI device speed capability. Return the maximum link speed
5154+
* supported by the device.
5155+
*/
5156+
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
5157+
{
5158+
u32 lnkcap2, lnkcap;
5159+
5160+
/*
5161+
* PCIe r4.0 sec 7.5.3.18 recommends using the Supported Link
5162+
* Speeds Vector in Link Capabilities 2 when supported, falling
5163+
* back to Max Link Speed in Link Capabilities otherwise.
5164+
*/
5165+
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
5166+
if (lnkcap2) { /* PCIe r3.0-compliant */
5167+
if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB)
5168+
return PCIE_SPEED_16_0GT;
5169+
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
5170+
return PCIE_SPEED_8_0GT;
5171+
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
5172+
return PCIE_SPEED_5_0GT;
5173+
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
5174+
return PCIE_SPEED_2_5GT;
5175+
return PCI_SPEED_UNKNOWN;
5176+
}
5177+
5178+
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
5179+
if (lnkcap) {
5180+
if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
5181+
return PCIE_SPEED_16_0GT;
5182+
else if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
5183+
return PCIE_SPEED_8_0GT;
5184+
else if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
5185+
return PCIE_SPEED_5_0GT;
5186+
else if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
5187+
return PCIE_SPEED_2_5GT;
5188+
}
5189+
5190+
return PCI_SPEED_UNKNOWN;
5191+
}
5192+
51495193
/**
51505194
* pci_select_bars - Make BAR mask from the type of resource
51515195
* @dev: the PCI device for which BAR mask is made

drivers/pci/pci.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,16 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx);
253253
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
254254
void pci_disable_bridge_window(struct pci_dev *dev);
255255

256+
/* PCIe link information */
257+
#define PCIE_SPEED2STR(speed) \
258+
((speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \
259+
(speed) == PCIE_SPEED_8_0GT ? "8 GT/s" : \
260+
(speed) == PCIE_SPEED_5_0GT ? "5 GT/s" : \
261+
(speed) == PCIE_SPEED_2_5GT ? "2.5 GT/s" : \
262+
"Unknown speed")
263+
264+
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev);
265+
256266
/* Single Root I/O Virtualization */
257267
struct pci_sriov {
258268
int pos; /* Capability position */

0 commit comments

Comments
 (0)