diff options
-rw-r--r-- | drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 87 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 81 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 32 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/main.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 38 | ||||
-rw-r--r-- | drivers/pci/pci.c | 174 | ||||
-rw-r--r-- | drivers/pci/pci.h | 21 | ||||
-rw-r--r-- | drivers/pci/probe.c | 2 | ||||
-rw-r--r-- | drivers/pci/slot.c | 1 | ||||
-rw-r--r-- | include/linux/pci.h | 5 | ||||
-rw-r--r-- | include/uapi/linux/pci_regs.h | 7 |
11 files changed, 221 insertions, 231 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index a434fecfdfeb..aa05fb534942 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c | |||
@@ -2120,91 +2120,6 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, | |||
2120 | return 0; | 2120 | return 0; |
2121 | } | 2121 | } |
2122 | 2122 | ||
2123 | static void fm10k_slot_warn(struct fm10k_intfc *interface) | ||
2124 | { | ||
2125 | enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN; | ||
2126 | enum pci_bus_speed speed = PCI_SPEED_UNKNOWN; | ||
2127 | struct fm10k_hw *hw = &interface->hw; | ||
2128 | int max_gts = 0, expected_gts = 0; | ||
2129 | |||
2130 | if (pcie_get_minimum_link(interface->pdev, &speed, &width) || | ||
2131 | speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) { | ||
2132 | dev_warn(&interface->pdev->dev, | ||
2133 | "Unable to determine PCI Express bandwidth.\n"); | ||
2134 | return; | ||
2135 | } | ||
2136 | |||
2137 | switch (speed) { | ||
2138 | case PCIE_SPEED_2_5GT: | ||
2139 | /* 8b/10b encoding reduces max throughput by 20% */ | ||
2140 | max_gts = 2 * width; | ||
2141 | break; | ||
2142 | case PCIE_SPEED_5_0GT: | ||
2143 | /* 8b/10b encoding reduces max throughput by 20% */ | ||
2144 | max_gts = 4 * width; | ||
2145 | break; | ||
2146 | case PCIE_SPEED_8_0GT: | ||
2147 | /* 128b/130b encoding has less than 2% impact on throughput */ | ||
2148 | max_gts = 8 * width; | ||
2149 | break; | ||
2150 | default: | ||
2151 | dev_warn(&interface->pdev->dev, | ||
2152 | "Unable to determine PCI Express bandwidth.\n"); | ||
2153 | return; | ||
2154 | } | ||
2155 | |||
2156 | dev_info(&interface->pdev->dev, | ||
2157 | "PCI Express bandwidth of %dGT/s available\n", | ||
2158 | max_gts); | ||
2159 | dev_info(&interface->pdev->dev, | ||
2160 | "(Speed:%s, Width: x%d, Encoding Loss:%s, Payload:%s)\n", | ||
2161 | (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" : | ||
2162 | speed == PCIE_SPEED_5_0GT ? "5.0GT/s" : | ||
2163 | speed == PCIE_SPEED_2_5GT ? "2.5GT/s" : | ||
2164 | "Unknown"), | ||
2165 | hw->bus.width, | ||
2166 | (speed == PCIE_SPEED_2_5GT ? "20%" : | ||
2167 | speed == PCIE_SPEED_5_0GT ? "20%" : | ||
2168 | speed == PCIE_SPEED_8_0GT ? "<2%" : | ||
2169 | "Unknown"), | ||
2170 | (hw->bus.payload == fm10k_bus_payload_128 ? "128B" : | ||
2171 | hw->bus.payload == fm10k_bus_payload_256 ? "256B" : | ||
2172 | hw->bus.payload == fm10k_bus_payload_512 ? "512B" : | ||
2173 | "Unknown")); | ||
2174 | |||
2175 | switch (hw->bus_caps.speed) { | ||
2176 | case fm10k_bus_speed_2500: | ||
2177 | /* 8b/10b encoding reduces max throughput by 20% */ | ||
2178 | expected_gts = 2 * hw->bus_caps.width; | ||
2179 | break; | ||
2180 | case fm10k_bus_speed_5000: | ||
2181 | /* 8b/10b encoding reduces max throughput by 20% */ | ||
2182 | expected_gts = 4 * hw->bus_caps.width; | ||
2183 | break; | ||
2184 | case fm10k_bus_speed_8000: | ||
2185 | /* 128b/130b encoding has less than 2% impact on throughput */ | ||
2186 | expected_gts = 8 * hw->bus_caps.width; | ||
2187 | break; | ||
2188 | default: | ||
2189 | dev_warn(&interface->pdev->dev, | ||
2190 | "Unable to determine expected PCI Express bandwidth.\n"); | ||
2191 | return; | ||
2192 | } | ||
2193 | |||
2194 | if (max_gts >= expected_gts) | ||
2195 | return; | ||
2196 | |||
2197 | dev_warn(&interface->pdev->dev, | ||
2198 | "This device requires %dGT/s of bandwidth for optimal performance.\n", | ||
2199 | expected_gts); | ||
2200 | dev_warn(&interface->pdev->dev, | ||
2201 | "A %sslot with x%d lanes is suggested.\n", | ||
2202 | (hw->bus_caps.speed == fm10k_bus_speed_2500 ? "2.5GT/s " : | ||
2203 | hw->bus_caps.speed == fm10k_bus_speed_5000 ? "5.0GT/s " : | ||
2204 | hw->bus_caps.speed == fm10k_bus_speed_8000 ? "8.0GT/s " : ""), | ||
2205 | hw->bus_caps.width); | ||
2206 | } | ||
2207 | |||
2208 | /** | 2123 | /** |
2209 | * fm10k_probe - Device Initialization Routine | 2124 | * fm10k_probe - Device Initialization Routine |
2210 | * @pdev: PCI device information struct | 2125 | * @pdev: PCI device information struct |
@@ -2326,7 +2241,7 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2326 | mod_timer(&interface->service_timer, (HZ * 2) + jiffies); | 2241 | mod_timer(&interface->service_timer, (HZ * 2) + jiffies); |
2327 | 2242 | ||
2328 | /* print warning for non-optimal configurations */ | 2243 | /* print warning for non-optimal configurations */ |
2329 | fm10k_slot_warn(interface); | 2244 | pcie_print_link_status(interface->pdev); |
2330 | 2245 | ||
2331 | /* report MAC address for logging */ | 2246 | /* report MAC address for logging */ |
2332 | dev_info(&pdev->dev, "%pM\n", netdev->dev_addr); | 2247 | dev_info(&pdev->dev, "%pM\n", netdev->dev_addr); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 4d84cab77105..30cacac54e69 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -623,85 +623,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
623 | return 0; | 623 | return 0; |
624 | } | 624 | } |
625 | 625 | ||
626 | static int mlx4_get_pcie_dev_link_caps(struct mlx4_dev *dev, | ||
627 | enum pci_bus_speed *speed, | ||
628 | enum pcie_link_width *width) | ||
629 | { | ||
630 | u32 lnkcap1, lnkcap2; | ||
631 | int err1, err2; | ||
632 | |||
633 | #define PCIE_MLW_CAP_SHIFT 4 /* start of MLW mask in link capabilities */ | ||
634 | |||
635 | *speed = PCI_SPEED_UNKNOWN; | ||
636 | *width = PCIE_LNK_WIDTH_UNKNOWN; | ||
637 | |||
638 | err1 = pcie_capability_read_dword(dev->persist->pdev, PCI_EXP_LNKCAP, | ||
639 | &lnkcap1); | ||
640 | err2 = pcie_capability_read_dword(dev->persist->pdev, PCI_EXP_LNKCAP2, | ||
641 | &lnkcap2); | ||
642 | if (!err2 && lnkcap2) { /* PCIe r3.0-compliant */ | ||
643 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) | ||
644 | *speed = PCIE_SPEED_8_0GT; | ||
645 | else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) | ||
646 | *speed = PCIE_SPEED_5_0GT; | ||
647 | else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) | ||
648 | *speed = PCIE_SPEED_2_5GT; | ||
649 | } | ||
650 | if (!err1) { | ||
651 | *width = (lnkcap1 & PCI_EXP_LNKCAP_MLW) >> PCIE_MLW_CAP_SHIFT; | ||
652 | if (!lnkcap2) { /* pre-r3.0 */ | ||
653 | if (lnkcap1 & PCI_EXP_LNKCAP_SLS_5_0GB) | ||
654 | *speed = PCIE_SPEED_5_0GT; | ||
655 | else if (lnkcap1 & PCI_EXP_LNKCAP_SLS_2_5GB) | ||
656 | *speed = PCIE_SPEED_2_5GT; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | if (*speed == PCI_SPEED_UNKNOWN || *width == PCIE_LNK_WIDTH_UNKNOWN) { | ||
661 | return err1 ? err1 : | ||
662 | err2 ? err2 : -EINVAL; | ||
663 | } | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static void mlx4_check_pcie_caps(struct mlx4_dev *dev) | ||
668 | { | ||
669 | enum pcie_link_width width, width_cap; | ||
670 | enum pci_bus_speed speed, speed_cap; | ||
671 | int err; | ||
672 | |||
673 | #define PCIE_SPEED_STR(speed) \ | ||
674 | (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" : \ | ||
675 | speed == PCIE_SPEED_5_0GT ? "5.0GT/s" : \ | ||
676 | speed == PCIE_SPEED_2_5GT ? "2.5GT/s" : \ | ||
677 | "Unknown") | ||
678 | |||
679 | err = mlx4_get_pcie_dev_link_caps(dev, &speed_cap, &width_cap); | ||
680 | if (err) { | ||
681 | mlx4_warn(dev, | ||
682 | "Unable to determine PCIe device BW capabilities\n"); | ||
683 | return; | ||
684 | } | ||
685 | |||
686 | err = pcie_get_minimum_link(dev->persist->pdev, &speed, &width); | ||
687 | if (err || speed == PCI_SPEED_UNKNOWN || | ||
688 | width == PCIE_LNK_WIDTH_UNKNOWN) { | ||
689 | mlx4_warn(dev, | ||
690 | "Unable to determine PCI device chain minimum BW\n"); | ||
691 | return; | ||
692 | } | ||
693 | |||
694 | if (width != width_cap || speed != speed_cap) | ||
695 | mlx4_warn(dev, | ||
696 | "PCIe BW is different than device's capability\n"); | ||
697 | |||
698 | mlx4_info(dev, "PCIe link speed is %s, device supports %s\n", | ||
699 | PCIE_SPEED_STR(speed), PCIE_SPEED_STR(speed_cap)); | ||
700 | mlx4_info(dev, "PCIe link width is x%d, device supports x%d\n", | ||
701 | width, width_cap); | ||
702 | return; | ||
703 | } | ||
704 | |||
705 | /*The function checks if there are live vf, return the num of them*/ | 626 | /*The function checks if there are live vf, return the num of them*/ |
706 | static int mlx4_how_many_lives_vf(struct mlx4_dev *dev) | 627 | static int mlx4_how_many_lives_vf(struct mlx4_dev *dev) |
707 | { | 628 | { |
@@ -3475,7 +3396,7 @@ slave_start: | |||
3475 | * express device capabilities are under-satisfied by the bus. | 3396 | * express device capabilities are under-satisfied by the bus. |
3476 | */ | 3397 | */ |
3477 | if (!mlx4_is_slave(dev)) | 3398 | if (!mlx4_is_slave(dev)) |
3478 | mlx4_check_pcie_caps(dev); | 3399 | pcie_print_link_status(dev->persist->pdev); |
3479 | 3400 | ||
3480 | /* In master functions, the communication channel must be initialized | 3401 | /* In master functions, the communication channel must be initialized |
3481 | * after obtaining its address from fw */ | 3402 | * after obtaining its address from fw */ |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 47bab842c5ee..93291ec4a3d1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c | |||
@@ -3864,36 +3864,6 @@ void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len, | |||
3864 | indirection_rqt[i] = i % num_channels; | 3864 | indirection_rqt[i] = i % num_channels; |
3865 | } | 3865 | } |
3866 | 3866 | ||
3867 | static int mlx5e_get_pci_bw(struct mlx5_core_dev *mdev, u32 *pci_bw) | ||
3868 | { | ||
3869 | enum pcie_link_width width; | ||
3870 | enum pci_bus_speed speed; | ||
3871 | int err = 0; | ||
3872 | |||
3873 | err = pcie_get_minimum_link(mdev->pdev, &speed, &width); | ||
3874 | if (err) | ||
3875 | return err; | ||
3876 | |||
3877 | if (speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) | ||
3878 | return -EINVAL; | ||
3879 | |||
3880 | switch (speed) { | ||
3881 | case PCIE_SPEED_2_5GT: | ||
3882 | *pci_bw = 2500 * width; | ||
3883 | break; | ||
3884 | case PCIE_SPEED_5_0GT: | ||
3885 | *pci_bw = 5000 * width; | ||
3886 | break; | ||
3887 | case PCIE_SPEED_8_0GT: | ||
3888 | *pci_bw = 8000 * width; | ||
3889 | break; | ||
3890 | default: | ||
3891 | return -EINVAL; | ||
3892 | } | ||
3893 | |||
3894 | return 0; | ||
3895 | } | ||
3896 | |||
3897 | static bool cqe_compress_heuristic(u32 link_speed, u32 pci_bw) | 3867 | static bool cqe_compress_heuristic(u32 link_speed, u32 pci_bw) |
3898 | { | 3868 | { |
3899 | return (link_speed && pci_bw && | 3869 | return (link_speed && pci_bw && |
@@ -3979,7 +3949,7 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev, | |||
3979 | params->num_tc = 1; | 3949 | params->num_tc = 1; |
3980 | 3950 | ||
3981 | mlx5e_get_max_linkspeed(mdev, &link_speed); | 3951 | mlx5e_get_max_linkspeed(mdev, &link_speed); |
3982 | mlx5e_get_pci_bw(mdev, &pci_bw); | 3952 | pci_bw = pcie_bandwidth_available(mdev->pdev, NULL, NULL, NULL); |
3983 | mlx5_core_dbg(mdev, "Max link speed = %d, PCI BW = %d\n", | 3953 | mlx5_core_dbg(mdev, "Max link speed = %d, PCI BW = %d\n", |
3984 | link_speed, pci_bw); | 3954 | link_speed, pci_bw); |
3985 | 3955 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 2ef641c91c26..622f02d34aae 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c | |||
@@ -1043,6 +1043,10 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, | |||
1043 | dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev), | 1043 | dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev), |
1044 | fw_rev_min(dev), fw_rev_sub(dev)); | 1044 | fw_rev_min(dev), fw_rev_sub(dev)); |
1045 | 1045 | ||
1046 | /* Only PFs hold the relevant PCIe information for this query */ | ||
1047 | if (mlx5_core_is_pf(dev)) | ||
1048 | pcie_print_link_status(dev->pdev); | ||
1049 | |||
1046 | /* on load removing any previous indication of internal error, device is | 1050 | /* on load removing any previous indication of internal error, device is |
1047 | * up | 1051 | * up |
1048 | */ | 1052 | */ |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index eb6bee8724cc..63d0952684fb 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -158,45 +158,18 @@ static DEVICE_ATTR_RO(resource); | |||
158 | static ssize_t max_link_speed_show(struct device *dev, | 158 | static ssize_t max_link_speed_show(struct device *dev, |
159 | struct device_attribute *attr, char *buf) | 159 | struct device_attribute *attr, char *buf) |
160 | { | 160 | { |
161 | struct pci_dev *pci_dev = to_pci_dev(dev); | 161 | struct pci_dev *pdev = 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_8_0GB: | ||
172 | speed = "8 GT/s"; | ||
173 | break; | ||
174 | case PCI_EXP_LNKCAP_SLS_5_0GB: | ||
175 | speed = "5 GT/s"; | ||
176 | break; | ||
177 | case PCI_EXP_LNKCAP_SLS_2_5GB: | ||
178 | speed = "2.5 GT/s"; | ||
179 | break; | ||
180 | default: | ||
181 | speed = "Unknown speed"; | ||
182 | } | ||
183 | 162 | ||
184 | return sprintf(buf, "%s\n", speed); | 163 | return sprintf(buf, "%s\n", PCIE_SPEED2STR(pcie_get_speed_cap(pdev))); |
185 | } | 164 | } |
186 | static DEVICE_ATTR_RO(max_link_speed); | 165 | static DEVICE_ATTR_RO(max_link_speed); |
187 | 166 | ||
188 | static ssize_t max_link_width_show(struct device *dev, | 167 | static ssize_t max_link_width_show(struct device *dev, |
189 | struct device_attribute *attr, char *buf) | 168 | struct device_attribute *attr, char *buf) |
190 | { | 169 | { |
191 | struct pci_dev *pci_dev = to_pci_dev(dev); | 170 | struct pci_dev *pdev = to_pci_dev(dev); |
192 | u32 linkcap; | ||
193 | int err; | ||
194 | |||
195 | err = pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &linkcap); | ||
196 | if (err) | ||
197 | return -EINVAL; | ||
198 | 171 | ||
199 | return sprintf(buf, "%u\n", (linkcap & PCI_EXP_LNKCAP_MLW) >> 4); | 172 | return sprintf(buf, "%u\n", pcie_get_width_cap(pdev)); |
200 | } | 173 | } |
201 | static DEVICE_ATTR_RO(max_link_width); | 174 | static DEVICE_ATTR_RO(max_link_width); |
202 | 175 | ||
@@ -213,6 +186,9 @@ static ssize_t current_link_speed_show(struct device *dev, | |||
213 | return -EINVAL; | 186 | return -EINVAL; |
214 | 187 | ||
215 | switch (linkstat & PCI_EXP_LNKSTA_CLS) { | 188 | switch (linkstat & PCI_EXP_LNKSTA_CLS) { |
189 | case PCI_EXP_LNKSTA_CLS_16_0GB: | ||
190 | speed = "16 GT/s"; | ||
191 | break; | ||
216 | case PCI_EXP_LNKSTA_CLS_8_0GB: | 192 | case PCI_EXP_LNKSTA_CLS_8_0GB: |
217 | speed = "8 GT/s"; | 193 | speed = "8 GT/s"; |
218 | break; | 194 | break; |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f6a4dd10d9b0..e7a3917ed389 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -5147,6 +5147,180 @@ int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed, | |||
5147 | EXPORT_SYMBOL(pcie_get_minimum_link); | 5147 | EXPORT_SYMBOL(pcie_get_minimum_link); |
5148 | 5148 | ||
5149 | /** | 5149 | /** |
5150 | * pcie_bandwidth_available - determine minimum link settings of a PCIe | ||
5151 | * device and its bandwidth limitation | ||
5152 | * @dev: PCI device to query | ||
5153 | * @limiting_dev: storage for device causing the bandwidth limitation | ||
5154 | * @speed: storage for speed of limiting device | ||
5155 | * @width: storage for width of limiting device | ||
5156 | * | ||
5157 | * Walk up the PCI device chain and find the point where the minimum | ||
5158 | * bandwidth is available. Return the bandwidth available there and (if | ||
5159 | * limiting_dev, speed, and width pointers are supplied) information about | ||
5160 | * that point. The bandwidth returned is in Mb/s, i.e., megabits/second of | ||
5161 | * raw bandwidth. | ||
5162 | */ | ||
5163 | u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev, | ||
5164 | enum pci_bus_speed *speed, | ||
5165 | enum pcie_link_width *width) | ||
5166 | { | ||
5167 | u16 lnksta; | ||
5168 | enum pci_bus_speed next_speed; | ||
5169 | enum pcie_link_width next_width; | ||
5170 | u32 bw, next_bw; | ||
5171 | |||
5172 | if (speed) | ||
5173 | *speed = PCI_SPEED_UNKNOWN; | ||
5174 | if (width) | ||
5175 | *width = PCIE_LNK_WIDTH_UNKNOWN; | ||
5176 | |||
5177 | bw = 0; | ||
5178 | |||
5179 | while (dev) { | ||
5180 | pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); | ||
5181 | |||
5182 | next_speed = pcie_link_speed[lnksta & PCI_EXP_LNKSTA_CLS]; | ||
5183 | next_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> | ||
5184 | PCI_EXP_LNKSTA_NLW_SHIFT; | ||
5185 | |||
5186 | next_bw = next_width * PCIE_SPEED2MBS_ENC(next_speed); | ||
5187 | |||
5188 | /* Check if current device limits the total bandwidth */ | ||
5189 | if (!bw || next_bw <= bw) { | ||
5190 | bw = next_bw; | ||
5191 | |||
5192 | if (limiting_dev) | ||
5193 | *limiting_dev = dev; | ||
5194 | if (speed) | ||
5195 | *speed = next_speed; | ||
5196 | if (width) | ||
5197 | *width = next_width; | ||
5198 | } | ||
5199 | |||
5200 | dev = pci_upstream_bridge(dev); | ||
5201 | } | ||
5202 | |||
5203 | return bw; | ||
5204 | } | ||
5205 | EXPORT_SYMBOL(pcie_bandwidth_available); | ||
5206 | |||
5207 | /** | ||
5208 | * pcie_get_speed_cap - query for the PCI device's link speed capability | ||
5209 | * @dev: PCI device to query | ||
5210 | * | ||
5211 | * Query the PCI device speed capability. Return the maximum link speed | ||
5212 | * supported by the device. | ||
5213 | */ | ||
5214 | enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev) | ||
5215 | { | ||
5216 | u32 lnkcap2, lnkcap; | ||
5217 | |||
5218 | /* | ||
5219 | * PCIe r4.0 sec 7.5.3.18 recommends using the Supported Link | ||
5220 | * Speeds Vector in Link Capabilities 2 when supported, falling | ||
5221 | * back to Max Link Speed in Link Capabilities otherwise. | ||
5222 | */ | ||
5223 | pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2); | ||
5224 | if (lnkcap2) { /* PCIe r3.0-compliant */ | ||
5225 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB) | ||
5226 | return PCIE_SPEED_16_0GT; | ||
5227 | else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) | ||
5228 | return PCIE_SPEED_8_0GT; | ||
5229 | else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) | ||
5230 | return PCIE_SPEED_5_0GT; | ||
5231 | else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) | ||
5232 | return PCIE_SPEED_2_5GT; | ||
5233 | return PCI_SPEED_UNKNOWN; | ||
5234 | } | ||
5235 | |||
5236 | pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); | ||
5237 | if (lnkcap) { | ||
5238 | if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB) | ||
5239 | return PCIE_SPEED_16_0GT; | ||
5240 | else if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB) | ||
5241 | return PCIE_SPEED_8_0GT; | ||
5242 | else if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB) | ||
5243 | return PCIE_SPEED_5_0GT; | ||
5244 | else if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB) | ||
5245 | return PCIE_SPEED_2_5GT; | ||
5246 | } | ||
5247 | |||
5248 | return PCI_SPEED_UNKNOWN; | ||
5249 | } | ||
5250 | |||
5251 | /** | ||
5252 | * pcie_get_width_cap - query for the PCI device's link width capability | ||
5253 | * @dev: PCI device to query | ||
5254 | * | ||
5255 | * Query the PCI device width capability. Return the maximum link width | ||
5256 | * supported by the device. | ||
5257 | */ | ||
5258 | enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev) | ||
5259 | { | ||
5260 | u32 lnkcap; | ||
5261 | |||
5262 | pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); | ||
5263 | if (lnkcap) | ||
5264 | return (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4; | ||
5265 | |||
5266 | return PCIE_LNK_WIDTH_UNKNOWN; | ||
5267 | } | ||
5268 | |||
5269 | /** | ||
5270 | * pcie_bandwidth_capable - calculate a PCI device's link bandwidth capability | ||
5271 | * @dev: PCI device | ||
5272 | * @speed: storage for link speed | ||
5273 | * @width: storage for link width | ||
5274 | * | ||
5275 | * Calculate a PCI device's link bandwidth by querying for its link speed | ||
5276 | * and width, multiplying them, and applying encoding overhead. The result | ||
5277 | * is in Mb/s, i.e., megabits/second of raw bandwidth. | ||
5278 | */ | ||
5279 | u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed, | ||
5280 | enum pcie_link_width *width) | ||
5281 | { | ||
5282 | *speed = pcie_get_speed_cap(dev); | ||
5283 | *width = pcie_get_width_cap(dev); | ||
5284 | |||
5285 | if (*speed == PCI_SPEED_UNKNOWN || *width == PCIE_LNK_WIDTH_UNKNOWN) | ||
5286 | return 0; | ||
5287 | |||
5288 | return *width * PCIE_SPEED2MBS_ENC(*speed); | ||
5289 | } | ||
5290 | |||
5291 | /** | ||
5292 | * pcie_print_link_status - Report the PCI device's link speed and width | ||
5293 | * @dev: PCI device to query | ||
5294 | * | ||
5295 | * Report the available bandwidth at the device. If this is less than the | ||
5296 | * device is capable of, report the device's maximum possible bandwidth and | ||
5297 | * the upstream link that limits its performance to less than that. | ||
5298 | */ | ||
5299 | void pcie_print_link_status(struct pci_dev *dev) | ||
5300 | { | ||
5301 | enum pcie_link_width width, width_cap; | ||
5302 | enum pci_bus_speed speed, speed_cap; | ||
5303 | struct pci_dev *limiting_dev = NULL; | ||
5304 | u32 bw_avail, bw_cap; | ||
5305 | |||
5306 | bw_cap = pcie_bandwidth_capable(dev, &speed_cap, &width_cap); | ||
5307 | bw_avail = pcie_bandwidth_available(dev, &limiting_dev, &speed, &width); | ||
5308 | |||
5309 | if (bw_avail >= bw_cap) | ||
5310 | pci_info(dev, "%u.%03u Gb/s available bandwidth (%s x%d link)\n", | ||
5311 | bw_cap / 1000, bw_cap % 1000, | ||
5312 | PCIE_SPEED2STR(speed_cap), width_cap); | ||
5313 | else | ||
5314 | pci_info(dev, "%u.%03u Gb/s available bandwidth, limited by %s x%d link at %s (capable of %u.%03u Gb/s with %s x%d link)\n", | ||
5315 | bw_avail / 1000, bw_avail % 1000, | ||
5316 | PCIE_SPEED2STR(speed), width, | ||
5317 | limiting_dev ? pci_name(limiting_dev) : "<unknown>", | ||
5318 | bw_cap / 1000, bw_cap % 1000, | ||
5319 | PCIE_SPEED2STR(speed_cap), width_cap); | ||
5320 | } | ||
5321 | EXPORT_SYMBOL(pcie_print_link_status); | ||
5322 | |||
5323 | /** | ||
5150 | * pci_select_bars - Make BAR mask from the type of resource | 5324 | * pci_select_bars - Make BAR mask from the type of resource |
5151 | * @dev: the PCI device for which BAR mask is made | 5325 | * @dev: the PCI device for which BAR mask is made |
5152 | * @flags: resource type mask to be selected | 5326 | * @flags: resource type mask to be selected |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fcd81911b127..ce9adec6c66e 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -253,6 +253,27 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx); | |||
253 | void pci_reassigndev_resource_alignment(struct pci_dev *dev); | 253 | void pci_reassigndev_resource_alignment(struct pci_dev *dev); |
254 | void pci_disable_bridge_window(struct pci_dev *dev); | 254 | void pci_disable_bridge_window(struct pci_dev *dev); |
255 | 255 | ||
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 | /* PCIe speed to Mb/s reduced by encoding overhead */ | ||
265 | #define PCIE_SPEED2MBS_ENC(speed) \ | ||
266 | ((speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \ | ||
267 | (speed) == PCIE_SPEED_8_0GT ? 8000*128/130 : \ | ||
268 | (speed) == PCIE_SPEED_5_0GT ? 5000*8/10 : \ | ||
269 | (speed) == PCIE_SPEED_2_5GT ? 2500*8/10 : \ | ||
270 | 0) | ||
271 | |||
272 | enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev); | ||
273 | enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev); | ||
274 | u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed, | ||
275 | enum pcie_link_width *width); | ||
276 | |||
256 | /* Single Root I/O Virtualization */ | 277 | /* Single Root I/O Virtualization */ |
257 | struct pci_sriov { | 278 | struct pci_sriov { |
258 | int pos; /* Capability position */ | 279 | int pos; /* Capability position */ |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ef5377438a1e..86bf045f3d59 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -592,7 +592,7 @@ const unsigned char pcie_link_speed[] = { | |||
592 | PCIE_SPEED_2_5GT, /* 1 */ | 592 | PCIE_SPEED_2_5GT, /* 1 */ |
593 | PCIE_SPEED_5_0GT, /* 2 */ | 593 | PCIE_SPEED_5_0GT, /* 2 */ |
594 | PCIE_SPEED_8_0GT, /* 3 */ | 594 | PCIE_SPEED_8_0GT, /* 3 */ |
595 | PCI_SPEED_UNKNOWN, /* 4 */ | 595 | PCIE_SPEED_16_0GT, /* 4 */ |
596 | PCI_SPEED_UNKNOWN, /* 5 */ | 596 | PCI_SPEED_UNKNOWN, /* 5 */ |
597 | PCI_SPEED_UNKNOWN, /* 6 */ | 597 | PCI_SPEED_UNKNOWN, /* 6 */ |
598 | PCI_SPEED_UNKNOWN, /* 7 */ | 598 | PCI_SPEED_UNKNOWN, /* 7 */ |
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index d10f556dc03e..191893e19d5c 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
@@ -76,6 +76,7 @@ static const char *pci_bus_speed_strings[] = { | |||
76 | "2.5 GT/s PCIe", /* 0x14 */ | 76 | "2.5 GT/s PCIe", /* 0x14 */ |
77 | "5.0 GT/s PCIe", /* 0x15 */ | 77 | "5.0 GT/s PCIe", /* 0x15 */ |
78 | "8.0 GT/s PCIe", /* 0x16 */ | 78 | "8.0 GT/s PCIe", /* 0x16 */ |
79 | "16.0 GT/s PCIe", /* 0x17 */ | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) | 82 | static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 24e15510a946..926a8cb5d6d4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -256,6 +256,7 @@ enum pci_bus_speed { | |||
256 | PCIE_SPEED_2_5GT = 0x14, | 256 | PCIE_SPEED_2_5GT = 0x14, |
257 | PCIE_SPEED_5_0GT = 0x15, | 257 | PCIE_SPEED_5_0GT = 0x15, |
258 | PCIE_SPEED_8_0GT = 0x16, | 258 | PCIE_SPEED_8_0GT = 0x16, |
259 | PCIE_SPEED_16_0GT = 0x17, | ||
259 | PCI_SPEED_UNKNOWN = 0xff, | 260 | PCI_SPEED_UNKNOWN = 0xff, |
260 | }; | 261 | }; |
261 | 262 | ||
@@ -1077,6 +1078,10 @@ int pcie_get_mps(struct pci_dev *dev); | |||
1077 | int pcie_set_mps(struct pci_dev *dev, int mps); | 1078 | int pcie_set_mps(struct pci_dev *dev, int mps); |
1078 | int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed, | 1079 | int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed, |
1079 | enum pcie_link_width *width); | 1080 | enum pcie_link_width *width); |
1081 | u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev, | ||
1082 | enum pci_bus_speed *speed, | ||
1083 | enum pcie_link_width *width); | ||
1084 | void pcie_print_link_status(struct pci_dev *dev); | ||
1080 | void pcie_flr(struct pci_dev *dev); | 1085 | void pcie_flr(struct pci_dev *dev); |
1081 | int __pci_reset_function_locked(struct pci_dev *dev); | 1086 | int __pci_reset_function_locked(struct pci_dev *dev); |
1082 | int pci_reset_function(struct pci_dev *dev); | 1087 | int pci_reset_function(struct pci_dev *dev); |
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 0c79eac5e9b8..103ba797a8f3 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h | |||
@@ -520,6 +520,7 @@ | |||
520 | #define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */ | 520 | #define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */ |
521 | #define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */ | 521 | #define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */ |
522 | #define PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003 /* LNKCAP2 SLS Vector bit 2 */ | 522 | #define PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003 /* LNKCAP2 SLS Vector bit 2 */ |
523 | #define PCI_EXP_LNKCAP_SLS_16_0GB 0x00000004 /* LNKCAP2 SLS Vector bit 3 */ | ||
523 | #define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */ | 524 | #define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */ |
524 | #define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ | 525 | #define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ |
525 | #define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */ | 526 | #define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */ |
@@ -547,6 +548,7 @@ | |||
547 | #define PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */ | 548 | #define PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */ |
548 | #define PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */ | 549 | #define PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */ |
549 | #define PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */ | 550 | #define PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */ |
551 | #define PCI_EXP_LNKSTA_CLS_16_0GB 0x0004 /* Current Link Speed 16.0GT/s */ | ||
550 | #define PCI_EXP_LNKSTA_NLW 0x03f0 /* Negotiated Link Width */ | 552 | #define PCI_EXP_LNKSTA_NLW 0x03f0 /* Negotiated Link Width */ |
551 | #define PCI_EXP_LNKSTA_NLW_X1 0x0010 /* Current Link Width x1 */ | 553 | #define PCI_EXP_LNKSTA_NLW_X1 0x0010 /* Current Link Width x1 */ |
552 | #define PCI_EXP_LNKSTA_NLW_X2 0x0020 /* Current Link Width x2 */ | 554 | #define PCI_EXP_LNKSTA_NLW_X2 0x0020 /* Current Link Width x2 */ |
@@ -648,8 +650,9 @@ | |||
648 | #define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints without link end here */ | 650 | #define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints without link end here */ |
649 | #define PCI_EXP_LNKCAP2 44 /* Link Capabilities 2 */ | 651 | #define PCI_EXP_LNKCAP2 44 /* Link Capabilities 2 */ |
650 | #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x00000002 /* Supported Speed 2.5GT/s */ | 652 | #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x00000002 /* Supported Speed 2.5GT/s */ |
651 | #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004 /* Supported Speed 5.0GT/s */ | 653 | #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004 /* Supported Speed 5GT/s */ |
652 | #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8.0GT/s */ | 654 | #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8GT/s */ |
655 | #define PCI_EXP_LNKCAP2_SLS_16_0GB 0x00000010 /* Supported Speed 16GT/s */ | ||
653 | #define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */ | 656 | #define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */ |
654 | #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ | 657 | #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ |
655 | #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ | 658 | #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ |