lkml.org 
[lkml]   [2023]   [May]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 05/17] drm/radeon: Use pcie_lnkctl{,2}_clear_and_set() for changing LNKCTL{,2}
    Date
    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 <lukas@wunner.de>
    Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
    ---
    drivers/gpu/drm/radeon/cik.c | 71 ++++++++++-------------------------
    drivers/gpu/drm/radeon/si.c | 72 ++++++++++--------------------------
    2 files changed, 40 insertions(+), 103 deletions(-)

    diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
    index 5819737c21c6..c592b3d68ae6 100644
    --- a/drivers/gpu/drm/radeon/cik.c
    +++ b/drivers/gpu/drm/radeon/cik.c
    @@ -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_lnkctl_clear_and_set(root, 0, PCI_EXP_LNKCTL_HAWD);
    + pcie_lnkctl_clear_and_set(rdev->pdev, 0, 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,45 +9582,24 @@ 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_lnkctl_clear_and_set(root, PCI_EXP_LNKCTL_HAWD,
    + bridge_cfg & PCI_EXP_LNKCTL_HAWD);
    + pcie_lnkctl_clear_and_set(rdev->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(rdev->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(rdev->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(rdev->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;
    @@ -9643,15 +9613,14 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev)
    speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
    WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);

    - pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
    - tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
    + tmp16 = 0;
    if (speed_cap == PCIE_SPEED_8_0GT)
    tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
    else if (speed_cap == PCIE_SPEED_5_0GT)
    tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
    else
    tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
    - pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
    + pcie_lnkctl2_clear_and_set(rdev->pdev, PCI_EXP_LNKCTL2_TLS, tmp16);

    speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
    speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
    diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
    index 8d5e4b25609d..769464e34f9f 100644
    --- a/drivers/gpu/drm/radeon/si.c
    +++ b/drivers/gpu/drm/radeon/si.c
    @@ -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_lnkctl_clear_and_set(root, 0, PCI_EXP_LNKCTL_HAWD);
    + pcie_lnkctl_clear_and_set(rdev->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;
    @@ -7188,46 +7179,24 @@ 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_lnkctl_clear_and_set(root, PCI_EXP_LNKCTL_HAWD,
    + bridge_cfg & PCI_EXP_LNKCTL_HAWD);
    + pcie_lnkctl_clear_and_set(rdev->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(rdev->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(rdev->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(rdev->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;
    @@ -7241,15 +7210,14 @@ static void si_pcie_gen3_enable(struct radeon_device *rdev)
    speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
    WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);

    - pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
    - tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
    + tmp16 = 0;
    if (speed_cap == PCIE_SPEED_8_0GT)
    tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
    else if (speed_cap == PCIE_SPEED_5_0GT)
    tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
    else
    tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
    - pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
    + pcie_lnkctl2_clear_and_set(rdev->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
    \
     
     \ /
      Last update: 2023-05-11 15:16    [W:4.190 / U:0.908 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site