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>
This commit is contained in:
parent
1acfb9b7ee
commit
6cf57be0f7
@ -158,33 +158,9 @@ static DEVICE_ATTR_RO(resource);
|
|||||||
static ssize_t max_link_speed_show(struct device *dev,
|
static ssize_t max_link_speed_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
struct pci_dev *pdev = to_pci_dev(dev);
|
||||||
u32 linkcap;
|
|
||||||
int err;
|
|
||||||
const char *speed;
|
|
||||||
|
|
||||||
err = pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &linkcap);
|
return sprintf(buf, "%s\n", PCIE_SPEED2STR(pcie_get_speed_cap(pdev)));
|
||||||
if (err)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
switch (linkcap & PCI_EXP_LNKCAP_SLS) {
|
|
||||||
case PCI_EXP_LNKCAP_SLS_16_0GB:
|
|
||||||
speed = "16 GT/s";
|
|
||||||
break;
|
|
||||||
case PCI_EXP_LNKCAP_SLS_8_0GB:
|
|
||||||
speed = "8 GT/s";
|
|
||||||
break;
|
|
||||||
case PCI_EXP_LNKCAP_SLS_5_0GB:
|
|
||||||
speed = "5 GT/s";
|
|
||||||
break;
|
|
||||||
case PCI_EXP_LNKCAP_SLS_2_5GB:
|
|
||||||
speed = "2.5 GT/s";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
speed = "Unknown speed";
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", speed);
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(max_link_speed);
|
static DEVICE_ATTR_RO(max_link_speed);
|
||||||
|
|
||||||
|
@ -5146,6 +5146,50 @@ int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pcie_get_minimum_link);
|
EXPORT_SYMBOL(pcie_get_minimum_link);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pcie_get_speed_cap - query for the PCI device's link speed capability
|
||||||
|
* @dev: PCI device to query
|
||||||
|
*
|
||||||
|
* Query the PCI device speed capability. Return the maximum link speed
|
||||||
|
* supported by the device.
|
||||||
|
*/
|
||||||
|
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
u32 lnkcap2, lnkcap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PCIe r4.0 sec 7.5.3.18 recommends using the Supported Link
|
||||||
|
* Speeds Vector in Link Capabilities 2 when supported, falling
|
||||||
|
* back to Max Link Speed in Link Capabilities otherwise.
|
||||||
|
*/
|
||||||
|
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
|
||||||
|
if (lnkcap2) { /* PCIe r3.0-compliant */
|
||||||
|
if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB)
|
||||||
|
return PCIE_SPEED_16_0GT;
|
||||||
|
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
|
||||||
|
return PCIE_SPEED_8_0GT;
|
||||||
|
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
|
||||||
|
return PCIE_SPEED_5_0GT;
|
||||||
|
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
|
||||||
|
return PCIE_SPEED_2_5GT;
|
||||||
|
return PCI_SPEED_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
|
||||||
|
if (lnkcap) {
|
||||||
|
if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
|
||||||
|
return PCIE_SPEED_16_0GT;
|
||||||
|
else if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
|
||||||
|
return PCIE_SPEED_8_0GT;
|
||||||
|
else if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
|
||||||
|
return PCIE_SPEED_5_0GT;
|
||||||
|
else if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
|
||||||
|
return PCIE_SPEED_2_5GT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PCI_SPEED_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_select_bars - Make BAR mask from the type of resource
|
* pci_select_bars - Make BAR mask from the type of resource
|
||||||
* @dev: the PCI device for which BAR mask is made
|
* @dev: the PCI device for which BAR mask is made
|
||||||
|
@ -253,6 +253,16 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx);
|
|||||||
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
|
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
|
||||||
void pci_disable_bridge_window(struct pci_dev *dev);
|
void pci_disable_bridge_window(struct pci_dev *dev);
|
||||||
|
|
||||||
|
/* PCIe link information */
|
||||||
|
#define PCIE_SPEED2STR(speed) \
|
||||||
|
((speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \
|
||||||
|
(speed) == PCIE_SPEED_8_0GT ? "8 GT/s" : \
|
||||||
|
(speed) == PCIE_SPEED_5_0GT ? "5 GT/s" : \
|
||||||
|
(speed) == PCIE_SPEED_2_5GT ? "2.5 GT/s" : \
|
||||||
|
"Unknown speed")
|
||||||
|
|
||||||
|
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev);
|
||||||
|
|
||||||
/* Single Root I/O Virtualization */
|
/* Single Root I/O Virtualization */
|
||||||
struct pci_sriov {
|
struct pci_sriov {
|
||||||
int pos; /* Capability position */
|
int pos; /* Capability position */
|
||||||
|
Loading…
Reference in New Issue
Block a user