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

Use pcie_lnkctl_clear_and_set() and pcie_lnkctl2_clear_and_set() which
do proper locking to avoid losing concurrent updates to the register
value.

Suggested-by: Lukas Wunner <lu...@wunner.de>
Signed-off-by: Ilpo Järvinen <ilpo.jarvi...@linux.intel.com>
---
 drivers/gpu/drm/amd/amdgpu/cik.c | 72 +++++++++----------------------
 drivers/gpu/drm/amd/amdgpu/si.c  | 74 +++++++++-----------------------
 2 files changed, 41 insertions(+), 105 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index de6d10390ab2..f9f2c28c7125 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1574,17 +1574,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
                        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(adev->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(adev->pdev, PCI_EXP_LNKCTL,
-                                                  tmp16);
+                       pcie_lnkctl_clear_and_set(root, 0, PCI_EXP_LNKCTL_HAWD);
+                       pcie_lnkctl_clear_and_set(adev->pdev, 0, 
PCI_EXP_LNKCTL_HAWD);
 
                        tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
                        max_lw = (tmp & 
PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
@@ -1637,45 +1628,24 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
                                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(adev->pdev,
-                                                         PCI_EXP_LNKCTL,
-                                                         &tmp16);
-                               tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-                               tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-                               pcie_capability_write_word(adev->pdev,
-                                                          PCI_EXP_LNKCTL,
-                                                          tmp16);
+                               pcie_lnkctl_clear_and_set(root, 
PCI_EXP_LNKCTL_HAWD,
+                                                         bridge_cfg & 
PCI_EXP_LNKCTL_HAWD);
+                               pcie_lnkctl_clear_and_set(adev->pdev, 
PCI_EXP_LNKCTL_HAWD,
+                                                         gpu_cfg & 
PCI_EXP_LNKCTL_HAWD);
 
                                /* linkctl2 */
-                               pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
-                                                         &tmp16);
-                               tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN);
-                               tmp16 |= (bridge_cfg2 &
-                                         (PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN));
-                               pcie_capability_write_word(root,
-                                                          PCI_EXP_LNKCTL2,
-                                                          tmp16);
-
-                               pcie_capability_read_word(adev->pdev,
-                                                         PCI_EXP_LNKCTL2,
-                                                         &tmp16);
-                               tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN);
-                               tmp16 |= (gpu_cfg2 &
-                                         (PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN));
-                               pcie_capability_write_word(adev->pdev,
-                                                          PCI_EXP_LNKCTL2,
-                                                          tmp16);
+                               pcie_lnkctl2_clear_and_set(root,
+                                                          
PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                          
PCI_EXP_LNKCTL2_TX_MARGIN,
+                                                          bridge_cfg2 &
+                                                          
(PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                           
PCI_EXP_LNKCTL2_TX_MARGIN));
+                               pcie_lnkctl2_clear_and_set(adev->pdev,
+                                                          
PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                          
PCI_EXP_LNKCTL2_TX_MARGIN,
+                                                          gpu_cfg2 &
+                                                          
(PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                           
PCI_EXP_LNKCTL2_TX_MARGIN));
 
                                tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
                                tmp &= ~PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1690,16 +1660,14 @@ static void cik_pcie_gen3_enable(struct amdgpu_device 
*adev)
        speed_cntl &= ~PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK;
        WREG32_PCIE(ixPCIE_LC_SPEED_CNTL, speed_cntl);
 
-       pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-       tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
-
+       tmp16 = 0;
        if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
                tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
        else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
                tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
        else
                tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-       pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
+       pcie_lnkctl2_clear_and_set(adev->pdev, PCI_EXP_LNKCTL2_TLS, tmp16);
 
        speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
        speed_cntl |= PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK;
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 7f99e130acd0..e60174d0dfb8 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -2276,17 +2276,8 @@ static void si_pcie_gen3_enable(struct amdgpu_device 
*adev)
                        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(adev->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(adev->pdev, PCI_EXP_LNKCTL,
-                                                  tmp16);
+                       pcie_lnkctl_clear_and_set(root, 0, PCI_EXP_LNKCTL_HAWD);
+                       pcie_lnkctl_clear_and_set(adev->pdev, 0, 
PCI_EXP_LNKCTL_HAWD);
 
                        tmp = RREG32_PCIE(PCIE_LC_STATUS1);
                        max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> 
LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -2331,44 +2322,23 @@ static void si_pcie_gen3_enable(struct amdgpu_device 
*adev)
 
                                mdelay(100);
 
-                               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(adev->pdev,
-                                                         PCI_EXP_LNKCTL,
-                                                         &tmp16);
-                               tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-                               tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-                               pcie_capability_write_word(adev->pdev,
-                                                          PCI_EXP_LNKCTL,
-                                                          tmp16);
-
-                               pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
-                                                         &tmp16);
-                               tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN);
-                               tmp16 |= (bridge_cfg2 &
-                                         (PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN));
-                               pcie_capability_write_word(root,
-                                                          PCI_EXP_LNKCTL2,
-                                                          tmp16);
-
-                               pcie_capability_read_word(adev->pdev,
-                                                         PCI_EXP_LNKCTL2,
-                                                         &tmp16);
-                               tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN);
-                               tmp16 |= (gpu_cfg2 &
-                                         (PCI_EXP_LNKCTL2_ENTER_COMP |
-                                          PCI_EXP_LNKCTL2_TX_MARGIN));
-                               pcie_capability_write_word(adev->pdev,
-                                                          PCI_EXP_LNKCTL2,
-                                                          tmp16);
+                               pcie_lnkctl_clear_and_set(root, 
PCI_EXP_LNKCTL_HAWD,
+                                                         bridge_cfg & 
PCI_EXP_LNKCTL_HAWD);
+                               pcie_lnkctl_clear_and_set(adev->pdev, 
PCI_EXP_LNKCTL_HAWD,
+                                                         gpu_cfg & 
PCI_EXP_LNKCTL_HAWD);
+
+                               pcie_lnkctl2_clear_and_set(root,
+                                                          
PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                          
PCI_EXP_LNKCTL2_TX_MARGIN,
+                                                          bridge_cfg2 &
+                                                          
(PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                           
PCI_EXP_LNKCTL2_TX_MARGIN));
+                               pcie_lnkctl2_clear_and_set(adev->pdev,
+                                                          
PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                          
PCI_EXP_LNKCTL2_TX_MARGIN,
+                                                          gpu_cfg2 &
+                                                          
(PCI_EXP_LNKCTL2_ENTER_COMP |
+                                                           
PCI_EXP_LNKCTL2_TX_MARGIN));
 
                                tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
                                tmp &= ~LC_SET_QUIESCE;
@@ -2381,16 +2351,14 @@ static void si_pcie_gen3_enable(struct amdgpu_device 
*adev)
        speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
        WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-       pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
-       tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
-
+       tmp16 = 0;
        if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
                tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
        else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
                tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
        else
                tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
-       pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
+       pcie_lnkctl2_clear_and_set(adev->pdev, PCI_EXP_LNKCTL2_TLS, tmp16);
 
        speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
        speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
-- 
2.30.2

Reply via email to