]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/radeon: Use RMW accessors for changing LNKCTL
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 17 Jul 2023 12:04:58 +0000 (15:04 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 19 Sep 2023 10:22:42 +0000 (12:22 +0200)
[ Upstream commit 7189576e8a829130192b33c5b64e8a475369c776 ]

Don't assume that only the driver would be accessing LNKCTL. ASPM policy
changes can trigger write to LNKCTL outside of driver's control.  And in
the case of upstream bridge, the driver does not even own the device it's
changing the registers for.

Use RMW capability accessors which do proper locking to avoid losing
concurrent updates to the register value.

Suggested-by: Lukas Wunner <lukas@wunner.de>
Fixes: 8a7cd27679d0 ("drm/radeon/cik: add support for pcie gen1/2/3 switching")
Fixes: b9d305dfb66c ("drm/radeon: implement pcie gen2/3 support for SI")
Link: https://lore.kernel.org/r/20230717120503.15276-7-ilpo.jarvinen@linux.intel.com
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/si.c

index 81b4de7be9f2b2710fd437ff805330aa8b366589..a42f29b6ed7cf005e3228e7df14bc810b6508208 100644 (file)
@@ -9534,17 +9534,8 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev)
                        u16 bridge_cfg2, gpu_cfg2;
                        u32 max_lw, current_lw, tmp;
 
-                       pcie_capability_read_word(root, PCI_EXP_LNKCTL,
-                                                 &bridge_cfg);
-                       pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
-                                                 &gpu_cfg);
-
-                       tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-                       pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-                       tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-                       pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL,
-                                                  tmp16);
+                       pcie_capability_set_word(root, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
+                       pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
 
                        tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
                        max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -9591,21 +9582,14 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev)
                                msleep(100);
 
                                /* linkctl */
-                               pcie_capability_read_word(root, PCI_EXP_LNKCTL,
-                                                         &tmp16);
-                               tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-                               tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-                               pcie_capability_write_word(root, PCI_EXP_LNKCTL,
-                                                          tmp16);
-
-                               pcie_capability_read_word(rdev->pdev,
-                                                         PCI_EXP_LNKCTL,
-                                                         &tmp16);
-                               tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-                               tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-                               pcie_capability_write_word(rdev->pdev,
-                                                          PCI_EXP_LNKCTL,
-                                                          tmp16);
+                               pcie_capability_clear_and_set_word(root, PCI_EXP_LNKCTL,
+                                                                  PCI_EXP_LNKCTL_HAWD,
+                                                                  bridge_cfg &
+                                                                  PCI_EXP_LNKCTL_HAWD);
+                               pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL,
+                                                                  PCI_EXP_LNKCTL_HAWD,
+                                                                  gpu_cfg &
+                                                                  PCI_EXP_LNKCTL_HAWD);
 
                                /* linkctl2 */
                                pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
index 013e44ed0f39a6f34ea4367f7a5640a0734adf96..4679b798a03841b6b123cc75a73dd6d4a96a738c 100644 (file)
@@ -7131,17 +7131,8 @@ static void si_pcie_gen3_enable(struct radeon_device *rdev)
                        u16 bridge_cfg2, gpu_cfg2;
                        u32 max_lw, current_lw, tmp;
 
-                       pcie_capability_read_word(root, PCI_EXP_LNKCTL,
-                                                 &bridge_cfg);
-                       pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL,
-                                                 &gpu_cfg);
-
-                       tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-                       pcie_capability_write_word(root, PCI_EXP_LNKCTL, tmp16);
-
-                       tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-                       pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL,
-                                                  tmp16);
+                       pcie_capability_set_word(root, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
+                       pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
 
                        tmp = RREG32_PCIE(PCIE_LC_STATUS1);
                        max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -7188,22 +7179,14 @@ static void si_pcie_gen3_enable(struct radeon_device *rdev)
                                msleep(100);
 
                                /* linkctl */
-                               pcie_capability_read_word(root, PCI_EXP_LNKCTL,
-                                                         &tmp16);
-                               tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-                               tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-                               pcie_capability_write_word(root,
-                                                          PCI_EXP_LNKCTL,
-                                                          tmp16);
-
-                               pcie_capability_read_word(rdev->pdev,
-                                                         PCI_EXP_LNKCTL,
-                                                         &tmp16);
-                               tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-                               tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-                               pcie_capability_write_word(rdev->pdev,
-                                                          PCI_EXP_LNKCTL,
-                                                          tmp16);
+                               pcie_capability_clear_and_set_word(root, PCI_EXP_LNKCTL,
+                                                                  PCI_EXP_LNKCTL_HAWD,
+                                                                  bridge_cfg &
+                                                                  PCI_EXP_LNKCTL_HAWD);
+                               pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL,
+                                                                  PCI_EXP_LNKCTL_HAWD,
+                                                                  gpu_cfg &
+                                                                  PCI_EXP_LNKCTL_HAWD);
 
                                /* linkctl2 */
                                pcie_capability_read_word(root, PCI_EXP_LNKCTL2,