LNKCTL register is written by a number of things in the kernel as RMW operations without any concurrency control. This could in the unlucky case lead to losing one of the updates. One of the most obvious path which can race with most of the other LNKCTL RMW operations seems to be ASPM policy sysfs write which triggers LNKCTL update. Add pcie_capability_clear_and_set_word_locked() that uses a per device spinlock to protect the RMW operations. Introduce helpers for updating LNKCTL and LNKCTL2 that internally do pcie_capability_clear_and_set_word_locked(). Convert RMW to use the new helpers. These could be mostly marked with Fixes tags but I've not spent the effort to find those out for each and every patch until this series has seen some discussion. I certainly will try to find the Fixes tags if asked to. There could be a few LNKCTL RMW that are so early into the init that they would be safe but I was not able to convince myself so I've included them (namely, some ASPM init paths and hp link enable). Even if that is the case, it seems safer to use an access pattern with these registers that is safe even if there would be a few cases where locking would not be stricly necessary. As for LNKCTL2, I think all current users are safe but these came up as a part of PCIe bandwidth control work (for thermal reasons) that will be adding a writer for LNKCTL2. I'll send PCI BW ctrl patches separately later as there's plenty of patches in this series already. If most of this series is deemed worthy of Fixes tags, I could separate those few LNKCTL2 changes into own patches. The series is based on top of the "PCI/ASPM: Handle link retraining race" patch I sent earlier but is not yet applied. Ilpo Järvinen (17): PCI: Add concurrency safe clear_and_set variants for LNKCTL{,2} PCI: pciehp: Protect LNKCTL changes PCI/ASPM: Use pcie_lnkctl_clear_and_set() drm/amdgpu: Use pcie_lnkctl{,2}_clear_and_set() for changing LNKCTL{,2} drm/radeon: Use pcie_lnkctl{,2}_clear_and_set() for changing LNKCTL{,2} IB/hfi1: Use pcie_lnkctl{,2}_clear_and_set() for changing LNKCTL{,2} e1000e: Use pcie_lnkctl_clear_and_set() for changing LNKCTL net/mlx5: Use pcie_lnkctl_clear_and_set() for changing LNKCTL wifi: ath9k: Use pcie_lnkctl_clear_and_set() for changing LNKCTL mt76: Use pcie_lnkctl_clear_and_set() for changing LNKCTL Bluetooth: hci_bcm4377: Use pcie_lnkctl_clear_and_set() for changing LNKCTL misc: rtsx: Use pcie_lnkctl_clear_and_set() for changing LNKCTL net/tg3: Use pcie_lnkctl_clear_and_set() for changing LNKCTL r8169: Use pcie_lnkctl_clear_and_set() for changing LNKCTL wifi: ath11k: Use pcie_lnkctl_clear_and_set() for changing LNKCTL wifi: ath12k: Use pcie_lnkctl_clear_and_set() for changing LNKCTL wifi: ath10k: Use pcie_lnkctl_clear_and_set() for changing LNKCTL drivers/bluetooth/hci_bcm4377.c | 3 +- drivers/gpu/drm/amd/amdgpu/cik.c | 72 +++++------------- drivers/gpu/drm/amd/amdgpu/si.c | 74 ++++++------------- drivers/gpu/drm/radeon/cik.c | 71 +++++------------- drivers/gpu/drm/radeon/si.c | 72 +++++------------- drivers/infiniband/hw/hfi1/aspm.c | 16 ++-- drivers/infiniband/hw/hfi1/pcie.c | 28 ++----- drivers/misc/cardreader/rts5228.c | 6 +- drivers/misc/cardreader/rts5261.c | 6 +- drivers/misc/cardreader/rtsx_pcr.c | 8 +- drivers/net/ethernet/broadcom/tg3.c | 14 ++-- drivers/net/ethernet/intel/e1000e/netdev.c | 6 +- .../ethernet/mellanox/mlx5/core/fw_reset.c | 9 +-- drivers/net/ethernet/realtek/r8169_main.c | 6 +- drivers/net/wireless/ath/ath10k/pci.c | 8 +- drivers/net/wireless/ath/ath11k/pci.c | 8 +- drivers/net/wireless/ath/ath12k/pci.c | 8 +- drivers/net/wireless/ath/ath9k/pci.c | 9 ++- drivers/net/wireless/mediatek/mt76/pci.c | 5 +- drivers/pci/access.c | 14 ++++ drivers/pci/hotplug/pciehp_hpc.c | 11 +-- drivers/pci/pcie/aspm.c | 48 ++++-------- drivers/pci/probe.c | 1 + include/linux/pci.h | 17 +++++ 24 files changed, 183 insertions(+), 337 deletions(-) -- 2.30.2