]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: ath12k: Use RMW accessors for changing LNKCTL
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 17 Jul 2023 12:05:01 +0000 (15:05 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Sep 2023 07:48:23 +0000 (09:48 +0200)
[ Upstream commit f5a7ac118faf6d4f794975947b3300717eae8fc5 ]

Don't assume that only the driver would be accessing LNKCTL. ASPM policy
changes can trigger write to LNKCTL outside of driver's control.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value. On restore, clear the ASPMC field
properly.

Suggested-by: Lukas Wunner <lukas@wunner.de>
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Link: https://lore.kernel.org/r/20230717120503.15276-10-ilpo.jarvinen@linux.intel.com
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Acked-by: Kalle Valo <kvalo@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/ath/ath12k/pci.c

index 9f174daf324c924268eae101a5274ece6e3549ea..e1e45eb50f3e389b44879d2c145952c6168316c7 100644 (file)
@@ -794,8 +794,8 @@ static void ath12k_pci_aspm_disable(struct ath12k_pci *ab_pci)
                   u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
 
        /* disable L0s and L1 */
-       pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
-                                  ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
+       pcie_capability_clear_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+                                  PCI_EXP_LNKCTL_ASPMC);
 
        set_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags);
 }
@@ -803,8 +803,10 @@ static void ath12k_pci_aspm_disable(struct ath12k_pci *ab_pci)
 static void ath12k_pci_aspm_restore(struct ath12k_pci *ab_pci)
 {
        if (test_and_clear_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags))
-               pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
-                                          ab_pci->link_ctl);
+               pcie_capability_clear_and_set_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+                                                  PCI_EXP_LNKCTL_ASPMC,
+                                                  ab_pci->link_ctl &
+                                                  PCI_EXP_LNKCTL_ASPMC);
 }
 
 static void ath12k_pci_kill_tasklets(struct ath12k_base *ab)