forked from mirrors/linux
		
	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
					
				
					 3 changed files with 56 additions and 26 deletions
				
			
		| 
						 | 
				
			
			@ -158,33 +158,9 @@ static DEVICE_ATTR_RO(resource);
 | 
			
		|||
static ssize_t max_link_speed_show(struct device *dev,
 | 
			
		||||
				   struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct pci_dev *pci_dev = to_pci_dev(dev);
 | 
			
		||||
	u32 linkcap;
 | 
			
		||||
	int err;
 | 
			
		||||
	const char *speed;
 | 
			
		||||
	struct pci_dev *pdev = to_pci_dev(dev);
 | 
			
		||||
 | 
			
		||||
	err = pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &linkcap);
 | 
			
		||||
	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);
 | 
			
		||||
	return sprintf(buf, "%s\n", PCIE_SPEED2STR(pcie_get_speed_cap(pdev)));
 | 
			
		||||
}
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 * @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_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 */
 | 
			
		||||
struct pci_sriov {
 | 
			
		||||
	int		pos;		/* Capability position */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue