Skip to content

Commit d957ff7

Browse files
committed
Merge branch 'pci/bwctrl'
- Add read/modify/write locking for Link Control 2, which is used to manage Link speed (Ilpo Järvinen) - Cache all supported Link speeds for use by the PCIe bandwidth controller (Ilpo Järvinen) - Extract the Link Bandwidth Management Status check into pcie_lbms_seen(), where it can be shared between the bandwidth controller and quirks that use it to help retrain failed links (Ilpo Järvinen) - Re-add Link Bandwidth notification support with updates to address the reasons it was previously reverted (Alexandru Gagniuc, Ilpo Järvinen) - Add pcie_set_target_speed() and related functionality to manage PCIe Link speed based on thermal constraints (Ilpo Järvinen) - Add a thermal cooling driver to throttle PCIe Links via the existing thermal management framework (Ilpo Järvinen) - Add a userspace selftest for the PCIe bandwidth controller (Ilpo Järvinen) - Drop duplicate pcie_get_speed_cap(), pcie_get_width_cap() declarations (Bjorn Helgaas) * pci/bwctrl: PCI: Drop duplicate pcie_get_speed_cap(), pcie_get_width_cap() declarations selftests/pcie_bwctrl: Create selftests thermal: Add PCIe cooling driver PCI/bwctrl: Add pcie_set_target_speed() to set PCIe Link Speed PCI/bwctrl: Re-add BW notification portdrv as PCIe BW controller PCI: Abstract LBMS seen check into pcie_lbms_seen() PCI: Refactor pcie_update_link_speed() PCI: Store all PCIe Supported Link Speeds PCI: Protect Link Control 2 Register with RMW locking Documentation PCI: Reformat RMW ops documentation
2 parents 0182471 + ba58eee commit d957ff7

File tree

22 files changed

+842
-54
lines changed

22 files changed

+842
-54
lines changed

Documentation/PCI/pciebus-howto.rst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,12 @@ capability structure except the PCI Express capability structure,
217217
that is shared between many drivers including the service drivers.
218218
RMW Capability accessors (pcie_capability_clear_and_set_word(),
219219
pcie_capability_set_word(), and pcie_capability_clear_word()) protect
220-
a selected set of PCI Express Capability Registers (Link Control
221-
Register and Root Control Register). Any change to those registers
222-
should be performed using RMW accessors to avoid problems due to
223-
concurrent updates. For the up-to-date list of protected registers,
224-
see pcie_capability_clear_and_set_word().
220+
a selected set of PCI Express Capability Registers:
221+
222+
* Link Control Register
223+
* Root Control Register
224+
* Link Control 2 Register
225+
226+
Any change to those registers should be performed using RMW accessors to
227+
avoid problems due to concurrent updates. For the up-to-date list of
228+
protected registers, see pcie_capability_clear_and_set_word().

MAINTAINERS

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17933,6 +17933,15 @@ F: include/linux/of_pci.h
1793317933
F: include/linux/pci*
1793417934
F: include/uapi/linux/pci*
1793517935

17936+
PCIE BANDWIDTH CONTROLLER
17937+
M: Ilpo Järvinen <[email protected]>
17938+
17939+
S: Supported
17940+
F: drivers/pci/pcie/bwctrl.c
17941+
F: drivers/thermal/pcie_cooling.c
17942+
F: include/linux/pci-bwctrl.h
17943+
F: tools/testing/selftests/pcie_bwctrl/
17944+
1793617945
PCIE DRIVER FOR AMAZON ANNAPURNA LABS
1793717946
M: Jonathan Chocron <[email protected]>
1793817947

drivers/pci/hotplug/pciehp_ctrl.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <linux/types.h>
2020
#include <linux/pm_runtime.h>
2121
#include <linux/pci.h>
22+
23+
#include "../pci.h"
2224
#include "pciehp.h"
2325

2426
/* The following routines constitute the bulk of the
@@ -127,6 +129,9 @@ static void remove_board(struct controller *ctrl, bool safe_removal)
127129

128130
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
129131
INDICATOR_NOOP);
132+
133+
/* Don't carry LBMS indications across */
134+
pcie_reset_lbms_count(ctrl->pcie->port);
130135
}
131136

132137
static int pciehp_enable_slot(struct controller *ctrl);

drivers/pci/hotplug/pciehp_hpc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ int pciehp_check_link_status(struct controller *ctrl)
319319
return -1;
320320
}
321321

322-
pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
322+
__pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
323323

324324
if (!found) {
325325
ctrl_info(ctrl, "Slot(%s): No device found\n",

drivers/pci/pci.c

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4740,7 +4740,7 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt)
47404740
* to track link speed or width changes made by hardware itself
47414741
* in attempt to correct unreliable link operation.
47424742
*/
4743-
pcie_capability_write_word(pdev, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS);
4743+
pcie_reset_lbms_count(pdev);
47444744
return rc;
47454745
}
47464746

@@ -6189,38 +6189,64 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
61896189
EXPORT_SYMBOL(pcie_bandwidth_available);
61906190

61916191
/**
6192-
* pcie_get_speed_cap - query for the PCI device's link speed capability
6192+
* pcie_get_supported_speeds - query Supported Link Speed Vector
61936193
* @dev: PCI device to query
61946194
*
6195-
* Query the PCI device speed capability. Return the maximum link speed
6196-
* supported by the device.
6195+
* Query @dev supported link speeds.
6196+
*
6197+
* Implementation Note in PCIe r6.0 sec 7.5.3.18 recommends determining
6198+
* supported link speeds using the Supported Link Speeds Vector in the Link
6199+
* Capabilities 2 Register (when available).
6200+
*
6201+
* Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18.
6202+
*
6203+
* Without Link Capabilities 2, i.e., prior to PCIe r3.0, Supported Link
6204+
* Speeds field in Link Capabilities is used and only 2.5 GT/s and 5.0 GT/s
6205+
* speeds were defined.
6206+
*
6207+
* For @dev without Supported Link Speed Vector, the field is synthesized
6208+
* from the Max Link Speed field in the Link Capabilities Register.
6209+
*
6210+
* Return: Supported Link Speeds Vector (+ reserved 0 at LSB).
61976211
*/
6198-
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
6212+
u8 pcie_get_supported_speeds(struct pci_dev *dev)
61996213
{
62006214
u32 lnkcap2, lnkcap;
6215+
u8 speeds;
62016216

62026217
/*
6203-
* Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18. The
6204-
* implementation note there recommends using the Supported Link
6205-
* Speeds Vector in Link Capabilities 2 when supported.
6206-
*
6207-
* Without Link Capabilities 2, i.e., prior to PCIe r3.0, software
6208-
* should use the Supported Link Speeds field in Link Capabilities,
6209-
* where only 2.5 GT/s and 5.0 GT/s speeds were defined.
6218+
* Speeds retain the reserved 0 at LSB before PCIe Supported Link
6219+
* Speeds Vector to allow using SLS Vector bit defines directly.
62106220
*/
62116221
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
6222+
speeds = lnkcap2 & PCI_EXP_LNKCAP2_SLS;
62126223

62136224
/* PCIe r3.0-compliant */
6214-
if (lnkcap2)
6215-
return PCIE_LNKCAP2_SLS2SPEED(lnkcap2);
6225+
if (speeds)
6226+
return speeds;
62166227

62176228
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
6229+
6230+
/* Synthesize from the Max Link Speed field */
62186231
if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB)
6219-
return PCIE_SPEED_5_0GT;
6232+
speeds = PCI_EXP_LNKCAP2_SLS_5_0GB | PCI_EXP_LNKCAP2_SLS_2_5GB;
62206233
else if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_2_5GB)
6221-
return PCIE_SPEED_2_5GT;
6234+
speeds = PCI_EXP_LNKCAP2_SLS_2_5GB;
62226235

6223-
return PCI_SPEED_UNKNOWN;
6236+
return speeds;
6237+
}
6238+
6239+
/**
6240+
* pcie_get_speed_cap - query for the PCI device's link speed capability
6241+
* @dev: PCI device to query
6242+
*
6243+
* Query the PCI device speed capability.
6244+
*
6245+
* Return: the maximum link speed supported by the device.
6246+
*/
6247+
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
6248+
{
6249+
return PCIE_LNKCAP2_SLS2SPEED(dev->supported_speeds);
62246250
}
62256251
EXPORT_SYMBOL(pcie_get_speed_cap);
62266252

drivers/pci/pci.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,17 @@ void pci_disable_bridge_window(struct pci_dev *dev);
331331
struct pci_bus *pci_bus_get(struct pci_bus *bus);
332332
void pci_bus_put(struct pci_bus *bus);
333333

334+
#define PCIE_LNKCAP_SLS2SPEED(lnkcap) \
335+
({ \
336+
((lnkcap) == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
337+
(lnkcap) == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
338+
(lnkcap) == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
339+
(lnkcap) == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
340+
(lnkcap) == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \
341+
(lnkcap) == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \
342+
PCI_SPEED_UNKNOWN); \
343+
})
344+
334345
/* PCIe link information from Link Capabilities 2 */
335346
#define PCIE_LNKCAP2_SLS2SPEED(lnkcap2) \
336347
((lnkcap2) & PCI_EXP_LNKCAP2_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
@@ -341,6 +352,15 @@ void pci_bus_put(struct pci_bus *bus);
341352
(lnkcap2) & PCI_EXP_LNKCAP2_SLS_2_5GB ? PCIE_SPEED_2_5GT : \
342353
PCI_SPEED_UNKNOWN)
343354

355+
#define PCIE_LNKCTL2_TLS2SPEED(lnkctl2) \
356+
((lnkctl2) == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \
357+
(lnkctl2) == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \
358+
(lnkctl2) == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \
359+
(lnkctl2) == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \
360+
(lnkctl2) == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \
361+
(lnkctl2) == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \
362+
PCI_SPEED_UNKNOWN)
363+
344364
/* PCIe speed to Mb/s reduced by encoding overhead */
345365
#define PCIE_SPEED2MBS_ENC(speed) \
346366
((speed) == PCIE_SPEED_64_0GT ? 64000*1/1 : \
@@ -373,12 +393,16 @@ static inline int pcie_dev_speed_mbps(enum pci_bus_speed speed)
373393
return -EINVAL;
374394
}
375395

396+
u8 pcie_get_supported_speeds(struct pci_dev *dev);
376397
const char *pci_speed_string(enum pci_bus_speed speed);
377-
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev);
378-
enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev);
379398
void __pcie_print_link_status(struct pci_dev *dev, bool verbose);
380399
void pcie_report_downtraining(struct pci_dev *dev);
381-
void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
400+
401+
static inline void __pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
402+
{
403+
bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
404+
}
405+
void pcie_update_link_speed(struct pci_bus *bus);
382406

383407
/* Single Root I/O Virtualization */
384408
struct pci_sriov {
@@ -692,6 +716,17 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
692716
static inline void pcie_ecrc_get_policy(char *str) { }
693717
#endif
694718

719+
#ifdef CONFIG_PCIEPORTBUS
720+
void pcie_reset_lbms_count(struct pci_dev *port);
721+
int pcie_lbms_count(struct pci_dev *port, unsigned long *val);
722+
#else
723+
static inline void pcie_reset_lbms_count(struct pci_dev *port) {}
724+
static inline int pcie_lbms_count(struct pci_dev *port, unsigned long *val)
725+
{
726+
return -EOPNOTSUPP;
727+
}
728+
#endif
729+
695730
struct pci_dev_reset_methods {
696731
u16 vendor;
697732
u16 device;

drivers/pci/pcie/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
pcieportdrv-y := portdrv.o rcec.o
66

7-
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
7+
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o bwctrl.o
88

99
obj-y += aspm.o
1010
obj-$(CONFIG_PCIEAER) += aer.o err.o

0 commit comments

Comments
 (0)