RE: [PATCH 6/6] drm/amdgpu: check if we need to reset at init time (v2)
Series is Reviewed-by: Evan Quan > -Original Message- > From: amd-gfx On Behalf Of Alex > Deucher > Sent: 2019年1月9日 6:12 > To: amd-gfx@lists.freedesktop.org > Cc: Deucher, Alexander > Subject: [PATCH 6/6] drm/amdgpu: check if we need to reset at init time (v2) > > To deal with situations like kexec or GPU VM passthrough where the device > may have been used previously without a proper GPU reset between. > > v2: rebase > > bug: https://bugs.freedesktop.org/show_bug.cgi?id=108585 > bug: https://bugs.freedesktop.org/show_bug.cgi?id=108754 > Signed-off-by: Alex Deucher > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +++ > 1 file changed, 11 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > index 1a558dc41ba6..8a61764e64cf 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > @@ -2550,6 +2550,17 @@ int amdgpu_device_init(struct amdgpu_device > *adev, > /* detect if we are with an SRIOV vbios */ > amdgpu_device_detect_sriov_bios(adev); > > + /* check if we need to reset the asic > + * E.g., driver was not cleanly unloaded previously, etc. > + */ > + if (amdgpu_asic_need_reset_on_init(adev)) { > + r = amdgpu_asic_reset(adev); > + if (r) { > + dev_err(adev->dev, "asic reset on init failed\n"); > + goto failed; > + } > + } > + > /* Post card if necessary */ > if (amdgpu_device_need_post(adev)) { > if (!adev->bios) { > -- > 2.20.1 > > ___ > amd-gfx mailing list > amd-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
RE: [PATCH] drm/amdgpu: expose sclk and mclk via hwmon
Reviewed-by: Evan Quan > -Original Message- > From: amd-gfx On Behalf Of Alex > Deucher > Sent: 2018年12月11日 5:17 > To: amd-gfx@lists.freedesktop.org > Cc: Deucher, Alexander > Subject: [PATCH] drm/amdgpu: expose sclk and mclk via hwmon > > Expose sclk (gfx clock) and mclk (memory clock) via > hwmon compatible interface. hwmon does not actually > formally specify a frequency type attribute, but these > are compatible with the format of the other attributes > exposed via hwmon. Units are hertz. > > freq1_input - GPU gfx/compute clock in hertz > freq2_input - GPU memory clock in hertz (dGPU only) > > Signed-off-by: Alex Deucher > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 93 > ++ > 1 file changed, 93 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > index 1f61ed95727c..6d52428fc45b 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > @@ -1516,6 +1516,75 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > return count; > } > > +static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct amdgpu_device *adev = dev_get_drvdata(dev); > + struct drm_device *ddev = adev->ddev; > + uint32_t sclk; > + int r, size = sizeof(sclk); > + > + /* Can't get voltage when the card is off */ > + if ((adev->flags & AMD_IS_PX) && > + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) > + return -EINVAL; > + > + /* sanity check PP is enabled */ > + if (!(adev->powerplay.pp_funcs && > + adev->powerplay.pp_funcs->read_sensor)) > + return -EINVAL; > + > + /* get the sclk */ > + r = amdgpu_dpm_read_sensor(adev, > AMDGPU_PP_SENSOR_GFX_SCLK, > +(void *), ); > + if (r) > + return r; > + > + return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000); > +} > + > +static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + return snprintf(buf, PAGE_SIZE, "sclk\n"); > +} > + > +static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct amdgpu_device *adev = dev_get_drvdata(dev); > + struct drm_device *ddev = adev->ddev; > + uint32_t mclk; > + int r, size = sizeof(mclk); > + > + /* Can't get voltage when the card is off */ > + if ((adev->flags & AMD_IS_PX) && > + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) > + return -EINVAL; > + > + /* sanity check PP is enabled */ > + if (!(adev->powerplay.pp_funcs && > + adev->powerplay.pp_funcs->read_sensor)) > + return -EINVAL; > + > + /* get the sclk */ > + r = amdgpu_dpm_read_sensor(adev, > AMDGPU_PP_SENSOR_GFX_MCLK, > +(void *), ); > + if (r) > + return r; > + > + return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000); > +} > + > +static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + return snprintf(buf, PAGE_SIZE, "mclk\n"); > +} > > /** > * DOC: hwmon > @@ -1532,6 +1601,10 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > * > * - GPU fan > * > + * - GPU gfx/compute engine clock > + * > + * - GPU memory clock (dGPU only) > + * > * hwmon interfaces for GPU temperature: > * > * - temp1_input: the on die GPU temperature in millidegrees Celsius > @@ -1576,6 +1649,12 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > * > * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable > * > + * hwmon interfaces for GPU clocks: > + * > + * - freq1_input: the gfx/compute clock in hertz > + * > + * - freq2_input: the memory clock in hertz > + * > * You can use hwmon tools like sensors to view this information on your > system. > * > */ > @@ -1600,6 +1679,10 @@ static SENSOR_DEVICE_ATTR(power1_average, > S_IRUGO, amdgpu_hwmon_show_power_avg, > static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, > amdgpu_hwmon_show_power_cap_max, NULL, 0); > static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, > amdgpu_hwmon_show_power_cap_min, NULL, 0); > static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, > amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0); > +static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, > amdgpu_hwmon_show_sclk, NULL, 0); > +static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, >
Re: [PATCH 1/1] drm/amdkfd: Don't assign dGPUs to APU topology devices
On Tue, Jan 8, 2019 at 6:29 PM Kuehling, Felix wrote: > > dGPUs need their own topology devices. Don't assign them to APU topology > devices with CPU cores. > > Bug: https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/issues/66 > Signed-off-by: Felix Kuehling Acked-by: Alex Deucher > --- > drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 12 +--- > 1 file changed, 9 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c > b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c > index 4734f1a..09da916 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c > @@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu) > * the GPU device is not already present in the topology device > * list then return NULL. This means a new topology device has to > * be created for this GPU. > - * TODO: Rather than assiging @gpu to first topology device withtout > - * gpu attached, it will better to have more stringent check. > */ > static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) > { > @@ -1102,12 +1100,20 @@ static struct kfd_topology_device > *kfd_assign_gpu(struct kfd_dev *gpu) > struct kfd_topology_device *out_dev = NULL; > > down_write(_lock); > - list_for_each_entry(dev, _device_list, list) > + list_for_each_entry(dev, _device_list, list) { > + /* Discrete GPUs need their own topology device list > +* entries. Don't assign them to CPU/APU nodes. > +*/ > + if (!gpu->device_info->needs_iommu_device && > + dev->node_props.cpu_cores_count) > + continue; > + > if (!dev->gpu && (dev->node_props.simd_count > 0)) { > dev->gpu = gpu; > out_dev = dev; > break; > } > + } > up_write(_lock); > return out_dev; > } > -- > 2.7.4 > > ___ > amd-gfx mailing list > amd-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH] drm/amdgpu: fix CPDMA hang in PRT mode for VEGA20
On 1/9/19 10:23 AM, Zhou1, Tao wrote: -Original Message- From: amd-gfx On Behalf Of Zhang, Jerry(Junwei) Sent: 2019年1月9日 9:39 To: Zhou1, Tao ; amd-gfx@lists.freedesktop.org Cc: Li, Yukun1 Subject: Re: [PATCH] drm/amdgpu: fix CPDMA hang in PRT mode for VEGA20 On 1/8/19 6:55 PM, Tao Zhou wrote: Fix CPDMA hang in PRT mode for both of VEGA10 and VEGA20 Change-Id: I0e5e089d2192063c4a04fa6dbd534f25eb0177be Signed-off-by: Tao Zhou Tested-by: Yukun.Li --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 968b127c6c8f..fbca0494f871 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0x, 0x4a2c0e68), SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0x, 0xb5d3f197), SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x1920), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x0fff, 0x03ff) + SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x0fff, 0x03ff), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x, 0x0800), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x, 0x0800), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, 0x8000) IIRC, the CP_DEBUG is the key to fix the CPDMA hang, do we need other settings? or just to align the settings with latest status? Jerry Set CPF_INT_DMA in reg CP_MECx_F32_INT_DIS for Compute and set DISABLE_GFX_HALT_ON_UTCL1_ERROR in CP_DEBUG for GFX. All the settings are needed. Thanks for confirmation. Almost forgot compute. That's fine. BTW, not sure PRT is used for compute as well. Jerry Tao }; static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = @@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x0003, 0x0002), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x000f, 0x01000107), SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x1800, 0x0800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x0800, 0x0880), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x, 0x0800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x, 0x0800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, 0x8000) + SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x0800, +0x0880) }; static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] = ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
RE: [PATCH] drm/amdgpu: fix CPDMA hang in PRT mode for VEGA20
> -Original Message- > From: amd-gfx On Behalf Of > Zhang, Jerry(Junwei) > Sent: 2019年1月9日 9:39 > To: Zhou1, Tao ; amd-gfx@lists.freedesktop.org > Cc: Li, Yukun1 > Subject: Re: [PATCH] drm/amdgpu: fix CPDMA hang in PRT mode for VEGA20 > > On 1/8/19 6:55 PM, Tao Zhou wrote: > > Fix CPDMA hang in PRT mode for both of VEGA10 and VEGA20 > > > > Change-Id: I0e5e089d2192063c4a04fa6dbd534f25eb0177be > > Signed-off-by: Tao Zhou > > Tested-by: Yukun.Li > > --- > > drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- > > 1 file changed, 5 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > > b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > > index 968b127c6c8f..fbca0494f871 100644 > > --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > > +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > > @@ -113,7 +113,10 @@ static const struct soc15_reg_golden > golden_settings_gc_9_0[] = > > SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, > 0x, 0x4a2c0e68), > > SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, > 0x, 0xb5d3f197), > > SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, > 0x3fff3af3, 0x1920), > > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, > 0x0fff, 0x03ff) > > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, > 0x0fff, 0x03ff), > > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, > 0x, 0x0800), > > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, > 0x, 0x0800), > > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, > 0x8000) > IIRC, the CP_DEBUG is the key to fix the CPDMA hang, do we need other > settings? > or just to align the settings with latest status? > > Jerry > Set CPF_INT_DMA in reg CP_MECx_F32_INT_DIS for Compute and set DISABLE_GFX_HALT_ON_UTCL1_ERROR in CP_DEBUG for GFX. All the settings are needed. Tao > > }; > > > > static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = > > @@ -135,10 +138,7 @@ static const struct soc15_reg_golden > golden_settings_gc_9_0_vg10[] = > > SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, > 0x0003, 0x0002), > > SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, > 0x000f, 0x01000107), > > SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x1800, > 0x0800), > > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, > 0x0800, 0x0880), > > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, > 0x, 0x0800), > > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, > 0x, 0x0800), > > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, > 0x8000) > > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, > 0x0800, > > +0x0880) > > }; > > > > static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] = > > ___ > amd-gfx mailing list > amd-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH] drm/amdgpu: fix CPDMA hang in PRT mode for VEGA20
On 1/8/19 6:55 PM, Tao Zhou wrote: Fix CPDMA hang in PRT mode for both of VEGA10 and VEGA20 Change-Id: I0e5e089d2192063c4a04fa6dbd534f25eb0177be Signed-off-by: Tao Zhou Tested-by: Yukun.Li --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 968b127c6c8f..fbca0494f871 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0x, 0x4a2c0e68), SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0x, 0xb5d3f197), SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x1920), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x0fff, 0x03ff) + SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x0fff, 0x03ff), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x, 0x0800), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x, 0x0800), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, 0x8000) IIRC, the CP_DEBUG is the key to fix the CPDMA hang, do we need other settings? or just to align the settings with latest status? Jerry }; static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = @@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x0003, 0x0002), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x000f, 0x01000107), SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x1800, 0x0800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x0800, 0x0880), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x, 0x0800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x, 0x0800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, 0x8000) + SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x0800, 0x0880) }; static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] = ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 0/6] kexec fixes
Yes, the checks are taken from the existing SMU and PSP code. Alex From: Kuehling, Felix Sent: Tuesday, January 8, 2019 6:22:48 PM To: Alex Deucher; amd-gfx@lists.freedesktop.org Cc: Deucher, Alexander Subject: Re: [PATCH 0/6] kexec fixes Thanks for this. I trust that your method for detecting that SMU or PSP are running is correct. With that caveat the series is Reviewed-by: Felix Kuehling Regards, Felix On 2019-01-08 5:11 p.m., Alex Deucher wrote: > Fixes for kexec. The GPU needs to be reset before the driver > can be loaded again reliably. Needed for kexec for booting some > ppc platforms. See: > https://bugs.freedesktop.org/show_bug.cgi?id=108585 > > Alex Deucher (6): > drm/amdgpu: add need_reset_on_init asic callback (v2) > drm/amdgpu/si: add need_reset_on_init asic callback for SI (v2) > drm/amdgpu/cik: add need_reset_on_init asic callback for CIK (v2) > drm/amdgpu/vi: add need_reset_on_init asic callback for VI (v2) > drm/amdgpu/soc15: add need_reset_on_init asic callback for SOC15 (v2) > drm/amdgpu: check if we need to reset at init time (v2) > > drivers/gpu/drm/amd/amdgpu/amdgpu.h| 3 +++ > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +++ > drivers/gpu/drm/amd/amdgpu/cik.c | 18 ++ > drivers/gpu/drm/amd/amdgpu/si.c| 6 ++ > drivers/gpu/drm/amd/amdgpu/soc15.c | 20 > drivers/gpu/drm/amd/amdgpu/vi.c| 18 ++ > 6 files changed, 76 insertions(+) > ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 18/20] drm/dp_mst: Start tracking per-port VCPI allocations
There has been a TODO waiting for quite a long time in drm_dp_mst_topology.c: /* We cannot rely on port->vcpi.num_slots to update * topology_state->avail_slots as the port may not exist if the parent * branch device was unplugged. This should be fixed by tracking * per-port slot allocation in drm_dp_mst_topology_state instead of * depending on the caller to tell us how many slots to release. */ That's not the only reason we should fix this: forcing the driver to track the VCPI allocations throughout a state's atomic check is error prone, because it means that extra care has to be taken with the order that drm_dp_atomic_find_vcpi_slots() and drm_dp_atomic_release_vcpi_slots() are called in in order to ensure idempotency. Currently the only driver actually using these helpers, i915, doesn't even do this correctly: multiple ->best_encoder() checks with i915's current implementation would not be idempotent and would over-allocate VCPI slots, something I learned trying to implement fallback retraining in MST. So: simplify this whole mess, and teach drm_dp_atomic_find_vcpi_slots() and drm_dp_atomic_release_vcpi_slots() to track the VCPI allocations for each port. This allows us to ensure idempotency without having to rely on the driver as much. Additionally: the driver doesn't need to do any kind of VCPI slot tracking anymore if it doesn't need it for it's own internal state. Additionally; this adds a new drm_dp_mst_atomic_check() helper which must be used by atomic drivers to perform validity checks for the new VCPI allocations incurred by a state. Also: update the documentation and make it more obvious that these /must/ be called by /all/ atomic drivers supporting MST. Changes since v9: * Add some missing changes that were requested by danvet that I forgot about after I redid all of the kref stuff: * Remove unnecessary state changes in intel_dp_mst_atomic_check * Cleanup atomic check logic for VCPI allocations - all we need to check in compute_config is whether or not this state disables a CRTC, then free VCPI based off that Changes since v8: * Fix compile errors, whoops! Changes since v7: - Don't check for mixed stale/valid VCPI allocations, just rely on connector registration to stop such erroneous modesets Changes since v6: - Keep a kref to all of the ports we have allocations on. This required a good bit of changing to when we call drm_dp_find_vcpi_slots(), mainly that we need to ensure that we only redo VCPI allocations on actual mode or CRTC changes, not crtc_state->active changes. Additionally, we no longer take the registration of the DRM connector for each port into account because so long as we have a kref to the port in the new or previous atomic state, the connector will stay registered. - Use the small changes to drm_dp_put_port() to add even more error checking to make misusage of the helpers more obvious. I added this after having to chase down various use-after-free conditions that started popping up from the new helpers so no one else has to troubleshoot that. - Move some accidental DRM_DEBUG_KMS() calls to DRM_DEBUG_ATOMIC() - Update documentation again, note that find/release() should both not be called on the same port in a single atomic check phase (but multiple calls to one or the other is OK) Changes since v4: - Don't skip the atomic checks for VCPI allocations if no new VCPI allocations happen in a state. This makes the next change I'm about to list here a lot easier to implement. - Don't ignore VCPI allocations on destroyed ports, instead ensure that when ports are destroyed and still have VCPI allocations in the topology state, the only state changes allowed are releasing said ports' VCPI. This prevents a state with a mix of VCPI allocations from destroyed ports, and allocations from valid ports. Changes since v3: - Don't release VCPI allocations in the topology state immediately in drm_dp_atomic_release_vcpi_slots(), instead mark them as 0 and skip over them in drm_dp_mst_duplicate_state(). This makes it so drm_dp_atomic_release_vcpi_slots() is still idempotent while also throwing warnings if the driver messes up it's book keeping and tries to release VCPI slots on a port that doesn't have any pre-existing VCPI allocation - danvet - Change mst_state/state in some debugging messages to "mst state" Changes since v2: - Use kmemdup() for duplicating MST state - danvet - Move port validation out of duplicate state callback - danvet - Handle looping through MST topology states in drm_dp_mst_atomic_check() so the driver doesn't have to do it - Fix documentation in drm_dp_atomic_find_vcpi_slots() - Move the atomic check for each individual topology state into it's own function, reduces indenting - Don't consider "stale" MST ports when calculating the bandwidth requirements. This is needed because originally we
[PATCH v5 20/20] drm/nouveau: Use atomic VCPI helpers for MST
Currently, nouveau uses the yolo method of setting up MST displays: it uses the old VCPI helpers (drm_dp_find_vcpi_slots()) for computing the display configuration. These helpers don't take care to make sure they take a reference to the mstb port that they're checking, and additionally don't actually check whether or not the topology still has enough bandwidth to provide the VCPI tokens required. So, drop usage of the old helpers and move entirely over to the atomic helpers. Changes since v6: * Cleanup atomic check logic and remove a bunch of unneeded checks - danvet Changes since v5: * Update nv50_msto_atomic_check() and nv50_mstc_atomic_check() to the new requirements for drm_dp_atomic_find_vcpi_slots() and drm_dp_atomic_release_vcpi_slots() Signed-off-by: Lyude Paul Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 54 ++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 67f7bf97e5d9..53d6c8df8f68 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -762,16 +762,23 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { - struct nv50_mstc *mstc = nv50_mstc(conn_state->connector); + struct drm_atomic_state *state = crtc_state->state; + struct drm_connector *connector = conn_state->connector; + struct nv50_mstc *mstc = nv50_mstc(connector); struct nv50_mstm *mstm = mstc->mstm; - int bpp = conn_state->connector->display_info.bpc * 3; + int bpp = connector->display_info.bpc * 3; int slots; - mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock, bpp); + mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock, +bpp); - slots = drm_dp_find_vcpi_slots(>mgr, mstc->pbn); - if (slots < 0) - return slots; + if (drm_atomic_crtc_needs_modeset(crtc_state) && + !drm_connector_is_unregistered(connector)) { + slots = drm_dp_atomic_find_vcpi_slots(state, >mgr, + mstc->port, mstc->pbn); + if (slots < 0) + return slots; + } return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state, mstc->native); @@ -934,12 +941,43 @@ nv50_mstc_get_modes(struct drm_connector *connector) return ret; } +static int +nv50_mstc_atomic_check(struct drm_connector *connector, + struct drm_connector_state *new_conn_state) +{ + struct drm_atomic_state *state = new_conn_state->state; + struct nv50_mstc *mstc = nv50_mstc(connector); + struct drm_dp_mst_topology_mgr *mgr = >mstm->mgr; + struct drm_connector_state *old_conn_state = + drm_atomic_get_old_connector_state(state, connector); + struct drm_crtc_state *crtc_state; + struct drm_crtc *new_crtc = new_conn_state->crtc; + + if (!old_conn_state->crtc) + return 0; + + /* We only want to free VCPI if this state disables the CRTC on this +* connector +*/ + if (new_crtc) { + crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); + + if (!crtc_state || + !drm_atomic_crtc_needs_modeset(crtc_state) || + crtc_state->enable) + return 0; + } + + return drm_dp_atomic_release_vcpi_slots(state, mgr, mstc->port); +} + static const struct drm_connector_helper_funcs nv50_mstc_help = { .get_modes = nv50_mstc_get_modes, .mode_valid = nv50_mstc_mode_valid, .best_encoder = nv50_mstc_best_encoder, .atomic_best_encoder = nv50_mstc_atomic_best_encoder, + .atomic_check = nv50_mstc_atomic_check, }; static enum drm_connector_status @@ -2121,6 +2159,10 @@ nv50_disp_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) return ret; } + ret = drm_dp_mst_atomic_check(state); + if (ret) + return ret; + return 0; } -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 16/20] drm/nouveau: Grab payload lock in nv50_msto_payload()
Going through the currently programmed payloads isn't safe without holding mgr->payload_lock, so actually do that and warn if anyone tries calling nv50_msto_payload() in the future without grabbing the right locks. Signed-off-by: Lyude Paul Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 157d208d37b5..67f7bf97e5d9 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -680,6 +680,8 @@ nv50_msto_payload(struct nv50_msto *msto) struct nv50_mstm *mstm = mstc->mstm; int vcpi = mstc->port->vcpi.vcpi, i; + WARN_ON(!mutex_is_locked(>mgr.payload_lock)); + NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi); for (i = 0; i < mstm->mgr.max_payloads; i++) { struct drm_dp_payload *payload = >mgr.payloads[i]; @@ -733,6 +735,8 @@ nv50_msto_prepare(struct nv50_msto *msto) (0x0100 << msto->head->base.index), }; + mutex_lock(>mgr.payload_lock); + NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name); if (mstc->port->vcpi.vcpi > 0) { struct drm_dp_payload *payload = nv50_msto_payload(msto); @@ -748,7 +752,9 @@ nv50_msto_prepare(struct nv50_msto *msto) msto->encoder.name, msto->head->base.base.name, args.vcpi.start_slot, args.vcpi.num_slots, args.vcpi.pbn, args.vcpi.aligned_pbn); + nvif_mthd(>display->disp.object, 0, , sizeof(args)); + mutex_unlock(>mgr.payload_lock); } static int -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 14/20] drm/nouveau: Keep malloc references to MST ports
Now that we finally have a sane way to keep port allocations around, use it to fix the potential unchecked ->port accesses that nouveau makes by making sure we keep the mst port allocated for as long as it's drm_connector is accessible. Additionally, now that we've guaranteed that mstc->port is allocated for as long as we keep mstc around we can remove the connector registration checks for codepaths which release payloads, allowing us to release payloads on active topologies properly. These registration checks were only required before in order to avoid situations where mstc->port could technically be pointing at freed memory. Signed-off-by: Lyude Paul Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 0f7d72518604..982054bbcc8b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -964,7 +964,11 @@ static void nv50_mstc_destroy(struct drm_connector *connector) { struct nv50_mstc *mstc = nv50_mstc(connector); + drm_connector_cleanup(>connector); + if (mstc->port) + drm_dp_mst_put_port_malloc(mstc->port); + kfree(mstc); } @@ -1012,6 +1016,7 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port, drm_object_attach_property(>connector.base, dev->mode_config.path_property, 0); drm_object_attach_property(>connector.base, dev->mode_config.tile_property, 0); drm_connector_set_path_property(>connector, path); + drm_dp_mst_get_port_malloc(port); return 0; } @@ -1077,6 +1082,7 @@ nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr, drm_fb_helper_remove_one_connector(>fbcon->helper, >connector); drm_modeset_lock(>dev->mode_config.connection_mutex, NULL); + drm_dp_mst_put_port_malloc(mstc->port); mstc->port = NULL; drm_modeset_unlock(>dev->mode_config.connection_mutex); -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 10/20] drm/i915: Keep malloc references to MST ports
So that the ports stay around until we've destroyed the connectors, in order to ensure that we don't pass an invalid pointer to any MST helpers once we introduce the new MST VCPI helpers. Changes since v1: * Move drm_dp_mst_get_port_malloc() to where we assign intel_connector->port - danvet Signed-off-by: Lyude Paul Reviewed-by: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/i915/intel_connector.c | 4 drivers/gpu/drm/i915/intel_dp_mst.c| 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_connector.c b/drivers/gpu/drm/i915/intel_connector.c index 18e370f607bc..37d2c644f4b8 100644 --- a/drivers/gpu/drm/i915/intel_connector.c +++ b/drivers/gpu/drm/i915/intel_connector.c @@ -95,6 +95,10 @@ void intel_connector_destroy(struct drm_connector *connector) intel_panel_fini(_connector->panel); drm_connector_cleanup(connector); + + if (intel_connector->port) + drm_dp_mst_put_port_malloc(intel_connector->port); + kfree(connector); } diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index f05427b74e34..631fd1537252 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -457,6 +457,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo intel_connector->get_hw_state = intel_dp_mst_get_hw_state; intel_connector->mst_port = intel_dp; intel_connector->port = port; + drm_dp_mst_get_port_malloc(port); connector = _connector->base; ret = drm_connector_init(dev, connector, _dp_mst_connector_funcs, -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 19/20] drm/dp_mst: Check payload count in drm_dp_mst_atomic_check()
It occurred to me that we never actually check this! So let's start doing that. Signed-off-by: Lyude Paul Reviewed-by: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index fc778c6d487e..41cf814207bf 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3650,7 +3650,7 @@ drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_topology_state *mst_state) { struct drm_dp_vcpi_allocation *vcpi; - int avail_slots = 63; + int avail_slots = 63, payload_count = 0; list_for_each_entry(vcpi, _state->vcpis, next) { /* Releasing VCPI is always OK-even if the port is gone */ @@ -3670,6 +3670,12 @@ drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr, avail_slots + vcpi->vcpi); return -ENOSPC; } + + if (++payload_count > mgr->max_payloads) { + DRM_DEBUG_ATOMIC("[MST MGR:%p] state %p has too many payloads (max=%d)\n", +mgr, mst_state, mgr->max_payloads); + return -EINVAL; + } } DRM_DEBUG_ATOMIC("[MST MGR:%p] mst state %p VCPI avail=%d used=%d\n", mgr, mst_state, avail_slots, -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 17/20] drm/dp_mst: Add some atomic state iterator macros
Changes since v6: - Move EXPORT_SYMBOL() for drm_dp_mst_topology_state_funcs to this commit - Document __drm_dp_mst_state_iter_get() and note that it shouldn't be called directly Signed-off-by: Lyude Paul Reviewed-by: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 5 +- include/drm/drm_dp_mst_helper.h | 96 +++ 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index efd8fa29fff6..370371145cdd 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3530,10 +3530,11 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, kfree(mst_state); } -static const struct drm_private_state_funcs mst_state_funcs = { +const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs = { .atomic_duplicate_state = drm_dp_mst_duplicate_state, .atomic_destroy_state = drm_dp_mst_destroy_state, }; +EXPORT_SYMBOL(drm_dp_mst_topology_state_funcs); /** * drm_atomic_get_mst_topology_state: get MST topology state @@ -3617,7 +3618,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, drm_atomic_private_obj_init(dev, >base, _state->base, - _state_funcs); + _dp_mst_topology_state_funcs); return 0; } diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 8eca5f29242c..581163c8d7d7 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -650,4 +650,100 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); +extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs; + +/** + * __drm_dp_mst_state_iter_get - private atomic state iterator function for + * macro-internal use + * @state: drm_atomic_state pointer + * @mgr: pointer to the drm_dp_mst_topology_mgr iteration cursor + * @old_state: optional pointer to the old drm_dp_mst_topology_state + * iteration cursor + * @new_state: optional pointer to the new drm_dp_mst_topology_state + * iteration cursor + * @i: int iteration cursor, for macro-internal use + * + * Used by for_each_oldnew_mst_mgr_in_state(), + * for_each_old_mst_mgr_in_state(), and for_each_new_mst_mgr_in_state(). Don't + * call this directly. + * + * Returns: + * True if the current drm_private_obj is a + * drm_dp_mst_topology_mgr, false otherwise. + */ +static inline bool +__drm_dp_mst_state_iter_get(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr **mgr, + struct drm_dp_mst_topology_state **old_state, + struct drm_dp_mst_topology_state **new_state, + int i) +{ + struct __drm_private_objs_state *objs_state = >private_objs[i]; + + if (objs_state->ptr->funcs != _dp_mst_topology_state_funcs) + return false; + + *mgr = to_dp_mst_topology_mgr(objs_state->ptr); + if (old_state) + *old_state = to_dp_mst_topology_state(objs_state->old_state); + if (new_state) + *new_state = to_dp_mst_topology_state(objs_state->new_state); + + return true; +} + +/** + * for_each_oldnew_mst_mgr_in_state - iterate over all DP MST topology + * managers in an atomic update + * @__state: drm_atomic_state pointer + * @mgr: drm_dp_mst_topology_mgr iteration cursor + * @old_state: drm_dp_mst_topology_state iteration cursor for the old + * state + * @new_state: drm_dp_mst_topology_state iteration cursor for the new + * state + * @__i: int iteration cursor, for macro-internal use + * + * This iterates over all DRM DP MST topology managers in an atomic update, + * tracking both old and new state. This is useful in places where the state + * delta needs to be considered, for example in atomic check functions. + */ +#define for_each_oldnew_mst_mgr_in_state(__state, mgr, old_state, new_state, __i) \ + for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ + for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), &(new_state), (__i))) + +/** + * for_each_old_mst_mgr_in_state - iterate over all DP MST topology managers + * in an atomic update + * @__state: drm_atomic_state pointer + * @mgr: drm_dp_mst_topology_mgr iteration cursor + * @old_state: drm_dp_mst_topology_state iteration cursor for the old + * state + * @__i: int iteration cursor, for macro-internal use + * + * This iterates over all DRM DP MST topology managers in an atomic update, + * tracking only the old state. This is useful in disable functions, where we + * need the old
[PATCH v5 11/20] drm/amdgpu/display: Keep malloc ref to MST port
Just like i915 and nouveau, it's a good idea for us to hold a malloc reference to the port here so that we never pass a freed pointer to any of the DP MST helper functions. Also, we stop unsetting aconnector->port in dm_dp_destroy_mst_connector(). There's literally no point to that assignment that I can see anyway. Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 5e7ca1f3a8d1..24632727e127 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -191,6 +191,7 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) drm_encoder_cleanup(_encoder->base); kfree(amdgpu_encoder); drm_connector_cleanup(connector); + drm_dp_mst_put_port_malloc(amdgpu_dm_connector->port); kfree(amdgpu_dm_connector); } @@ -363,7 +364,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, amdgpu_dm_connector_funcs_reset(connector); DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n", - aconnector, connector->base.id, aconnector->mst_port); +aconnector, connector->base.id, aconnector->mst_port); + + drm_dp_mst_get_port_malloc(port); DRM_DEBUG_KMS(":%d\n", connector->base.id); @@ -379,12 +382,12 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n", - aconnector, connector->base.id, aconnector->mst_port); +aconnector, connector->base.id, aconnector->mst_port); - aconnector->port = NULL; if (aconnector->dc_sink) { amdgpu_dm_update_freesync_caps(connector, NULL); - dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink); + dc_link_remove_remote_sink(aconnector->dc_link, + aconnector->dc_sink); dc_sink_release(aconnector->dc_sink); aconnector->dc_sink = NULL; } -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 08/20] drm/dp_mst: Stop releasing VCPI when removing ports from topology
This has never actually worked, and isn't needed anyway: the driver's always going to try to deallocate VCPI when it tears down the display that the VCPI belongs to. Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 8 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index bafc85f08606..8088527a7aea 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1176,8 +1176,6 @@ static void drm_dp_destroy_port(struct kref *kref) struct drm_dp_mst_topology_mgr *mgr = port->mgr; if (!port->input) { - port->vcpi.num_slots = 0; - kfree(port->cached_edid); /* @@ -3496,12 +3494,6 @@ static void drm_dp_destroy_connector_work(struct work_struct *work) drm_dp_port_teardown_pdt(port, port->pdt); port->pdt = DP_PEER_DEVICE_NONE; - if (!port->input && port->vcpi.vcpi > 0) { - drm_dp_mst_reset_vcpi_slots(mgr, port); - drm_dp_update_payload_part1(mgr); - drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); - } - drm_dp_mst_put_port_malloc(port); send_hotplug = true; } -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 05/20] drm/dp_mst: Rename drm_dp_mst_get_validated_(port|mstb)_ref and friends
s/drm_dp_get_validated_port_ref/drm_dp_mst_topology_get_port_validated/ s/drm_dp_put_port/drm_dp_mst_topology_put_port/ s/drm_dp_get_validated_mstb_ref/drm_dp_mst_topology_get_mstb_validated/ s/drm_dp_put_mst_branch_device/drm_dp_mst_topology_put_mstb/ This is a much more consistent naming scheme, and will make even more sense once we redesign how the current refcounting scheme here works. Signed-off-by: Lyude Paul Reviewed-by: Daniel Vetter Reviewed-by: Harry Wentland Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 114 ++ 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 75cca6a843fb..074e985093ca 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -46,7 +46,7 @@ static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr, char *buf); static int test_calc_pbn_mode(void); -static void drm_dp_put_port(struct drm_dp_mst_port *port); +static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port); static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr, int id, @@ -888,7 +888,7 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref) */ list_for_each_entry_safe(port, tmp, >ports, next) { list_del(>next); - drm_dp_put_port(port); + drm_dp_mst_topology_put_port(port); } /* drop any tx slots msg */ @@ -911,7 +911,7 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref) kref_put(kref, drm_dp_free_mst_branch_device); } -static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb) +static void drm_dp_mst_topology_put_mstb(struct drm_dp_mst_branch *mstb) { kref_put(>kref, drm_dp_destroy_mst_branch_device); } @@ -930,7 +930,7 @@ static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt) case DP_PEER_DEVICE_MST_BRANCHING: mstb = port->mstb; port->mstb = NULL; - drm_dp_put_mst_branch_device(mstb); + drm_dp_mst_topology_put_mstb(mstb); break; } } @@ -970,12 +970,14 @@ static void drm_dp_destroy_port(struct kref *kref) kfree(port); } -static void drm_dp_put_port(struct drm_dp_mst_port *port) +static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port) { kref_put(>kref, drm_dp_destroy_port); } -static struct drm_dp_mst_branch *drm_dp_mst_get_validated_mstb_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_branch *to_find) +static struct drm_dp_mst_branch * +drm_dp_mst_topology_get_mstb_validated_locked(struct drm_dp_mst_branch *mstb, + struct drm_dp_mst_branch *to_find) { struct drm_dp_mst_port *port; struct drm_dp_mst_branch *rmstb; @@ -985,7 +987,8 @@ static struct drm_dp_mst_branch *drm_dp_mst_get_validated_mstb_ref_locked(struct } list_for_each_entry(port, >ports, next) { if (port->mstb) { - rmstb = drm_dp_mst_get_validated_mstb_ref_locked(port->mstb, to_find); + rmstb = drm_dp_mst_topology_get_mstb_validated_locked( + port->mstb, to_find); if (rmstb) return rmstb; } @@ -993,12 +996,15 @@ static struct drm_dp_mst_branch *drm_dp_mst_get_validated_mstb_ref_locked(struct return NULL; } -static struct drm_dp_mst_branch *drm_dp_get_validated_mstb_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_branch *mstb) +static struct drm_dp_mst_branch * +drm_dp_mst_topology_get_mstb_validated(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_branch *mstb) { struct drm_dp_mst_branch *rmstb = NULL; mutex_lock(>lock); if (mgr->mst_primary) - rmstb = drm_dp_mst_get_validated_mstb_ref_locked(mgr->mst_primary, mstb); + rmstb = drm_dp_mst_topology_get_mstb_validated_locked( + mgr->mst_primary, mstb); mutex_unlock(>lock); return rmstb; } @@ -1021,7 +1027,9 @@ static struct drm_dp_mst_port *drm_dp_mst_get_port_ref_locked(struct drm_dp_mst_ return NULL; } -static struct drm_dp_mst_port *drm_dp_get_validated_port_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) +static struct drm_dp_mst_port * +drm_dp_mst_topology_get_port_validated(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port) { struct drm_dp_mst_port *rport = NULL; mutex_lock(>lock); @@ -1215,7 +1223,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
[PATCH v5 13/20] drm/nouveau: Remove unnecessary VCPI checks in nv50_msto_cleanup()
There is no need to look at the port's VCPI allocation before calling drm_dp_mst_deallocate_vcpi(), as we already have msto->disabled to let us avoid cleaning up an msto more then once. The DP MST core will never call drm_dp_mst_deallocate_vcpi() on it's own, which is presumably what these checks are meant to protect against. More importantly though, we're about to stop clearing mstc->port in the next commit, which means if we could potentially hit a use-after-free error if we tried to check mstc->port->vcpi here. So to make life easier for anyone who bisects this code in the future, use msto->disabled instead to check whether or not we need to deallocate VCPI instead. Signed-off-by: Lyude Paul Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 641252208e67..0f7d72518604 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -704,14 +704,17 @@ nv50_msto_cleanup(struct nv50_msto *msto) struct nv50_mstc *mstc = msto->mstc; struct nv50_mstm *mstm = mstc->mstm; + if (!msto->disabled) + return; + NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name); - if (mstc->port && mstc->port->vcpi.vcpi > 0 && !nv50_msto_payload(msto)) + + if (mstc->port) drm_dp_mst_deallocate_vcpi(>mgr, mstc->port); - if (msto->disabled) { - msto->mstc = NULL; - msto->head = NULL; - msto->disabled = false; - } + + msto->mstc = NULL; + msto->head = NULL; + msto->disabled = false; } static void -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 15/20] drm/nouveau: Stop unsetting mstc->port, use malloc refs
Same as we did for i915, but for nouveau this time. Additionally, we grab a malloc reference to the port that lasts for the entire lifetime of nv50_mstc, which gives us the guarantee that mstc->port will always point to valid memory for as long as the mstc stays around. Signed-off-by: Lyude Paul Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 18 +- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 982054bbcc8b..157d208d37b5 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -709,8 +709,7 @@ nv50_msto_cleanup(struct nv50_msto *msto) NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name); - if (mstc->port) - drm_dp_mst_deallocate_vcpi(>mgr, mstc->port); + drm_dp_mst_deallocate_vcpi(>mgr, mstc->port); msto->mstc = NULL; msto->head = NULL; @@ -735,7 +734,7 @@ nv50_msto_prepare(struct nv50_msto *msto) }; NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name); - if (mstc->port && mstc->port->vcpi.vcpi > 0) { + if (mstc->port->vcpi.vcpi > 0) { struct drm_dp_payload *payload = nv50_msto_payload(msto); if (payload) { args.vcpi.start_slot = payload->start_slot; @@ -832,8 +831,7 @@ nv50_msto_disable(struct drm_encoder *encoder) struct nv50_mstc *mstc = msto->mstc; struct nv50_mstm *mstm = mstc->mstm; - if (mstc->port) - drm_dp_mst_reset_vcpi_slots(>mgr, mstc->port); + drm_dp_mst_reset_vcpi_slots(>mgr, mstc->port); mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0); mstm->modified = true; @@ -945,7 +943,7 @@ nv50_mstc_detect(struct drm_connector *connector, bool force) enum drm_connector_status conn_status; int ret; - if (!mstc->port) + if (drm_connector_is_unregistered(connector)) return connector_status_disconnected; ret = pm_runtime_get_sync(connector->dev->dev); @@ -966,8 +964,7 @@ nv50_mstc_destroy(struct drm_connector *connector) struct nv50_mstc *mstc = nv50_mstc(connector); drm_connector_cleanup(>connector); - if (mstc->port) - drm_dp_mst_put_port_malloc(mstc->port); + drm_dp_mst_put_port_malloc(mstc->port); kfree(mstc); } @@ -1081,11 +1078,6 @@ nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr, drm_fb_helper_remove_one_connector(>fbcon->helper, >connector); - drm_modeset_lock(>dev->mode_config.connection_mutex, NULL); - drm_dp_mst_put_port_malloc(mstc->port); - mstc->port = NULL; - drm_modeset_unlock(>dev->mode_config.connection_mutex); - drm_connector_put(>connector); } -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 12/20] drm/nouveau: Remove bogus cleanup in nv50_mstm_add_connector()
Trying to destroy the connector using mstc->connector.funcs->destroy() if connector initialization fails is wrong: there is no possible codepath in nv50_mstc_new where nv50_mstm_add_connector() would return <0 and mstc would be non-NULL. Signed-off-by: Lyude Paul Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 26af45785939..641252208e67 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1099,11 +1099,8 @@ nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr, int ret; ret = nv50_mstc_new(mstm, port, path, ); - if (ret) { - if (mstc) - mstc->connector.funcs->destroy(>connector); + if (ret) return NULL; - } return >connector; } -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 07/20] drm/dp_mst: Restart last_connected_port_and_mstb() if topology ref fails
While this isn't a complete fix, this will improve the reliability of drm_dp_get_last_connected_port_and_mstb() pretty significantly during hotplug events, since there's a chance that the in-memory topology tree may not be fully updated when drm_dp_get_last_connected_port_and_mstb() is called and thus might end up causing our search to fail on an mstb whose topology refcount has reached 0, but has not yet been removed from it's parent. Ideally, we should further fix this problem by ensuring that we deal with the potential for racing with a hotplug event, which would look like this: * drm_dp_payload_send_msg() retrieves the last living relative of mstb with drm_dp_get_last_connected_port_and_mstb() * drm_dp_payload_send_msg() starts building payload message At the same time, mstb gets unplugged from the topology and is no longer the actual last living relative of the original mstb * drm_dp_payload_send_msg() tries sending the payload message, hub times out * Hub timed out, we give up and run away-resulting in the payload being leaked This could be fixed by restarting the drm_dp_get_last_connected_port_and_mstb() search whenever we get a timeout, sending the payload to the new mstb, then repeating until either the entire topology is removed from the system or drm_dp_get_last_connected_port_and_mstb() fails. But since the above race condition is not terribly likely, we'll address that in a later patch series once we've improved the recovery handling for VCPI allocations in the rest of the DP MST helpers. Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 54 ++- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index c53cf7eb1dbc..bafc85f08606 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2047,24 +2047,50 @@ static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent); } -static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, -struct drm_dp_mst_branch *mstb, -int *port_num) +/** + * drm_dp_get_last_connected_port_and_mstb() - Find the last living relatives + * in a topology of a given branch device + * @mgr: The topology manager to use + * @mstb: The disconnected branch device + * @port_num: Where to store the number of the last connected port + * + * Searches upwards in the topology starting from @mstb to try to find the + * closest available parent of @mstb that's still connected to the rest of the + * topology. This can be used in order to perform operations like releasing + * payloads, where the branch device which owned the payload may no longer be + * around and thus would require that the payload on the last living relative + * be freed instead. + * + * Returns: + * The last connected _dp_mst_branch in the topology that was a parent of + * @mstb, if there is one. + */ +static struct drm_dp_mst_branch * +drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_branch *mstb, + int *port_num) { struct drm_dp_mst_branch *rmstb = NULL; struct drm_dp_mst_port *found_port; + mutex_lock(>lock); - if (mgr->mst_primary) { + if (!mgr->mst_primary) + goto out; + + do { found_port = drm_dp_get_last_connected_port_to_mstb(mstb); + if (!found_port) + break; - if (found_port) { + if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) { rmstb = found_port->parent; - if (drm_dp_mst_topology_try_get_mstb(rmstb)) - *port_num = found_port->port_num; - else - rmstb = NULL; + *port_num = found_port->port_num; + } else { + /* Search again, starting from this parent */ + mstb = found_port->parent; } - } + } while (!rmstb); +out: mutex_unlock(>lock); return rmstb; } @@ -2113,6 +2139,14 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, drm_dp_queue_down_tx(mgr, txmsg); + /* +* FIXME: there is a small chance that between getting the last +* connected mstb and sending the payload message, the last connected +* mstb could also be removed from the topology. In the
[PATCH v5 04/20] drm/dp_mst: Fix some formatting in drm_dp_mst_deallocate_vcpi()
Split some stuff across multiple lines Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index a63a4d32962a..75cca6a843fb 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2790,7 +2790,8 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); * @mgr: manager for this port * @port: unverified port to deallocate vcpi for */ -void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) +void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port) { port = drm_dp_get_validated_port_ref(mgr, port); if (!port) -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 02/20] drm/dp_mst: Fix some formatting in drm_dp_payload_send_msg()
Split some stuff across multiple lines, remove some unnecessary braces Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index c93bff5527fd..fc93a71c42b0 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1331,9 +1331,9 @@ static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper( return NULL; } -static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid( - struct drm_dp_mst_topology_mgr *mgr, - uint8_t *guid) +static struct drm_dp_mst_branch * +drm_dp_get_mst_branch_device_by_guid(struct drm_dp_mst_topology_mgr *mgr, +uint8_t *guid) { struct drm_dp_mst_branch *mstb; @@ -1739,7 +1739,9 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, port_num = port->port_num; mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); if (!mstb) { - mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, _num); + mstb = drm_dp_get_last_connected_port_and_mstb(mgr, + port->parent, + _num); if (!mstb) { drm_dp_put_port(port); @@ -1765,9 +1767,9 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, ret = drm_dp_mst_wait_tx_reply(mstb, txmsg); if (ret > 0) { - if (txmsg->reply.reply_type == 1) { + if (txmsg->reply.reply_type == 1) ret = -EINVAL; - } else + else ret = 0; } kfree(txmsg); -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 00/20] MST refcounting/atomic helpers cleanup
This is the series I've been working on for a while now to get all of the atomic DRM drivers in the tree to use the atomic MST helpers, and to make the atomic MST helpers actually idempotent. Turns out it's a lot more difficult to do that without also fixing how port and branch device refcounting works so that it actually makes sense, since the current upstream implementation requires a ton of magic in the atomic helpers to work around properly and in many situations just plain doesn't work as intended. There's still more cleanup that can be done, but I think this is a good place to start off for now :). Also available on gitlab: https://gitlab.freedesktop.org/lyudess/linux/commits/wip/mst-dual-kref-start-v5 Cc: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li Lyude Paul (20): drm/dp_mst: Fix some formatting in drm_dp_add_port() drm/dp_mst: Fix some formatting in drm_dp_payload_send_msg() drm/dp_mst: Fix some formatting in drm_dp_mst_allocate_vcpi() drm/dp_mst: Fix some formatting in drm_dp_mst_deallocate_vcpi() drm/dp_mst: Rename drm_dp_mst_get_validated_(port|mstb)_ref and friends drm/dp_mst: Introduce new refcounting scheme for mstbs and ports drm/dp_mst: Restart last_connected_port_and_mstb() if topology ref fails drm/dp_mst: Stop releasing VCPI when removing ports from topology drm/dp_mst: Fix payload deallocation on hotplugs using malloc refs drm/i915: Keep malloc references to MST ports drm/amdgpu/display: Keep malloc ref to MST port drm/nouveau: Remove bogus cleanup in nv50_mstm_add_connector() drm/nouveau: Remove unnecessary VCPI checks in nv50_msto_cleanup() drm/nouveau: Keep malloc references to MST ports drm/nouveau: Stop unsetting mstc->port, use malloc refs drm/nouveau: Grab payload lock in nv50_msto_payload() drm/dp_mst: Add some atomic state iterator macros drm/dp_mst: Start tracking per-port VCPI allocations drm/dp_mst: Check payload count in drm_dp_mst_atomic_check() drm/nouveau: Use atomic VCPI helpers for MST .../gpu/dp-mst/topology-figure-1.dot | 52 + .../gpu/dp-mst/topology-figure-2.dot | 56 + .../gpu/dp-mst/topology-figure-3.dot | 59 ++ Documentation/gpu/drm-kms-helpers.rst | 26 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 +- drivers/gpu/drm/drm_dp_mst_topology.c | 955 ++ drivers/gpu/drm/i915/intel_connector.c| 4 + drivers/gpu/drm/i915/intel_display.c | 4 + drivers/gpu/drm/i915/intel_dp_mst.c | 55 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 96 +- include/drm/drm_dp_mst_helper.h | 151 ++- 11 files changed, 1213 insertions(+), 256 deletions(-) create mode 100644 Documentation/gpu/dp-mst/topology-figure-1.dot create mode 100644 Documentation/gpu/dp-mst/topology-figure-2.dot create mode 100644 Documentation/gpu/dp-mst/topology-figure-3.dot -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 06/20] drm/dp_mst: Introduce new refcounting scheme for mstbs and ports
The current way of handling refcounting in the DP MST helpers is really confusing and probably just plain wrong because it's been hacked up many times over the years without anyone actually going over the code and seeing if things could be simplified. To the best of my understanding, the current scheme works like this: drm_dp_mst_port and drm_dp_mst_branch both have a single refcount. When this refcount hits 0 for either of the two, they're removed from the topology state, but not immediately freed. Both ports and branch devices will reinitialize their kref once it's hit 0 before actually destroying themselves. The intended purpose behind this is so that we can avoid problems like not being able to free a remote payload that might still be active, due to us having removed all of the port/branch device structures in memory, as per: commit 91a25e463130 ("drm/dp/mst: deallocate payload on port destruction") Which may have worked, but then it caused use-after-free errors. Being new to MST at the time, I tried fixing it; commit 263efde31f97 ("drm/dp/mst: Get validated port ref in drm_dp_update_payload_part1()") But, that was broken: both drm_dp_mst_port and drm_dp_mst_branch structs are validated in almost every DP MST helper function. Simply put, this means we go through the topology and try to see if the given drm_dp_mst_branch or drm_dp_mst_port is still attached to something before trying to use it in order to avoid dereferencing freed memory (something that has happened a LOT in the past with this library). Because of this it doesn't actually matter whether or not we keep keep the ports and branches around in memory as that's not enough, because any function that validates the branches and ports passed to it will still reject them anyway since they're no longer in the topology structure. So, use-after-free errors were fixed but payload deallocation was completely broken. Two years later, AMD informed me about this issue and I attempted to come up with a temporary fix, pending a long-overdue cleanup of this library: commit c54c7374ff44 ("drm/dp_mst: Skip validating ports during destruction, just ref") But then that introduced use-after-free errors, so I quickly reverted it: commit 9765635b3075 ("Revert "drm/dp_mst: Skip validating ports during destruction, just ref"") And in the process, learned that there is just no simple fix for this: the design is just broken. Unfortunately, the usage of these helpers are quite broken as well. Some drivers like i915 have been smart enough to avoid accessing any kind of information from MST port structures, but others like nouveau have assumed, understandably so, that drm_dp_mst_port structures are normal and can just be accessed at any time without worrying about use-after-free errors. After a lot of discussion, me and Daniel Vetter came up with a better idea to replace all of this. To summarize, since this is documented far more indepth in the documentation this patch introduces, we make it so that drm_dp_mst_port and drm_dp_mst_branch structures have two different classes of refcounts: topology_kref, and malloc_kref. topology_kref corresponds to the lifetime of the given drm_dp_mst_port or drm_dp_mst_branch in it's given topology. Once it hits zero, any associated connectors are removed and the branch or port can no longer be validated. malloc_kref corresponds to the lifetime of the memory allocation for the actual structure, and will always be non-zero so long as the topology_kref is non-zero. This gives us a way to allow callers to hold onto port and branch device structures past their topology lifetime, and dramatically simplifies the lifetimes of both structures. This also finally fixes the port deallocation problem, properly. Additionally: since this now means that we can keep ports and branch devices allocated in memory for however long we need, we no longer need a significant amount of the port validation that we currently do. Additionally, there is one last scenario that this fixes, which couldn't have been fixed properly beforehand: - CPU1 unrefs port from topology (refcount 1->0) - CPU2 refs port in topology(refcount 0->1) Since we now can guarantee memory safety for ports and branches as-needed, we also can make our main reference counting functions fix this problem by using kref_get_unless_zero() internally so that topology refcounts can only ever reach 0 once. Changes since v3: * Remove rebase detritus - danvet * Split out purely style changes into separate patches - hwentlan Changes since v2: * Fix commit message - checkpatch * s/)-1/) - 1/g - checkpatch Changes since v1: * Remove forward declarations - danvet * Move "Branch device and port refcounting" section from documentation into kernel-doc comments - danvet * Export internal topology lifetime functions into their own section in the kernel-docs - danvet * s/@/&/g for struct references in kernel-docs - danvet * Drop the "when they are no longer being used" bits from the
[PATCH v5 03/20] drm/dp_mst: Fix some formatting in drm_dp_mst_allocate_vcpi()
Fix some indenting, split some stuff across multiple lines. Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index fc93a71c42b0..a63a4d32962a 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2731,7 +2731,8 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, return false; if (port->vcpi.vcpi > 0) { - DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn); + DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", + port->vcpi.vcpi, port->vcpi.pbn, pbn); if (pbn == port->vcpi.pbn) { drm_dp_put_port(port); return true; @@ -2741,11 +2742,11 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, ret = drm_dp_init_vcpi(mgr, >vcpi, pbn, slots); if (ret) { DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n", - DIV_ROUND_UP(pbn, mgr->pbn_div), ret); + DIV_ROUND_UP(pbn, mgr->pbn_div), ret); goto out; } DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n", - pbn, port->vcpi.num_slots); + pbn, port->vcpi.num_slots); drm_dp_put_port(port); return true; -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v5 01/20] drm/dp_mst: Fix some formatting in drm_dp_add_port()
Reindent some stuff, and split some stuff across multiple lines so we aren't going over the text width limit. Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 2ab16c9e6243..c93bff5527fd 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1184,11 +1184,13 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, if (old_ddps != port->ddps) { if (port->ddps) { - if (!port->input) - drm_dp_send_enum_path_resources(mstb->mgr, mstb, port); + if (!port->input) { + drm_dp_send_enum_path_resources(mstb->mgr, + mstb, port); + } } else { port->available_pbn = 0; - } + } } if (old_pdt != port->pdt && !port->input) { @@ -1202,8 +1204,11 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, if (created && !port->input) { char proppath[255]; - build_mst_prop_path(mstb, port->port_num, proppath, sizeof(proppath)); - port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath); + build_mst_prop_path(mstb, port->port_num, proppath, + sizeof(proppath)); + port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, + port, + proppath); if (!port->connector) { /* remove it from the port list */ mutex_lock(>mgr->lock); @@ -1216,7 +1221,8 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV || port->pdt == DP_PEER_DEVICE_SST_SINK) && port->port_num >= DP_MST_LOGICAL_PORT_0) { - port->cached_edid = drm_get_edid(port->connector, >aux.ddc); + port->cached_edid = drm_get_edid(port->connector, +>aux.ddc); drm_connector_set_tile_property(port->connector); } (*mstb->mgr->cbs->register_connector)(port->connector); -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 1/1] drm/amdkfd: Don't assign dGPUs to APU topology devices
dGPUs need their own topology devices. Don't assign them to APU topology devices with CPU cores. Bug: https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/issues/66 Signed-off-by: Felix Kuehling --- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 12 +--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 4734f1a..09da916 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu) * the GPU device is not already present in the topology device * list then return NULL. This means a new topology device has to * be created for this GPU. - * TODO: Rather than assiging @gpu to first topology device withtout - * gpu attached, it will better to have more stringent check. */ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) { @@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) struct kfd_topology_device *out_dev = NULL; down_write(_lock); - list_for_each_entry(dev, _device_list, list) + list_for_each_entry(dev, _device_list, list) { + /* Discrete GPUs need their own topology device list +* entries. Don't assign them to CPU/APU nodes. +*/ + if (!gpu->device_info->needs_iommu_device && + dev->node_props.cpu_cores_count) + continue; + if (!dev->gpu && (dev->node_props.simd_count > 0)) { dev->gpu = gpu; out_dev = dev; break; } + } up_write(_lock); return out_dev; } -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 0/6] kexec fixes
Thanks for this. I trust that your method for detecting that SMU or PSP are running is correct. With that caveat the series is Reviewed-by: Felix Kuehling Regards, Felix On 2019-01-08 5:11 p.m., Alex Deucher wrote: > Fixes for kexec. The GPU needs to be reset before the driver > can be loaded again reliably. Needed for kexec for booting some > ppc platforms. See: > https://bugs.freedesktop.org/show_bug.cgi?id=108585 > > Alex Deucher (6): > drm/amdgpu: add need_reset_on_init asic callback (v2) > drm/amdgpu/si: add need_reset_on_init asic callback for SI (v2) > drm/amdgpu/cik: add need_reset_on_init asic callback for CIK (v2) > drm/amdgpu/vi: add need_reset_on_init asic callback for VI (v2) > drm/amdgpu/soc15: add need_reset_on_init asic callback for SOC15 (v2) > drm/amdgpu: check if we need to reset at init time (v2) > > drivers/gpu/drm/amd/amdgpu/amdgpu.h| 3 +++ > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +++ > drivers/gpu/drm/amd/amdgpu/cik.c | 18 ++ > drivers/gpu/drm/amd/amdgpu/si.c| 6 ++ > drivers/gpu/drm/amd/amdgpu/soc15.c | 20 > drivers/gpu/drm/amd/amdgpu/vi.c| 18 ++ > 6 files changed, 76 insertions(+) > ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 5/6] drm/amdgpu/soc15: add need_reset_on_init asic callback for SOC15 (v2)
SOC15 chips require a reset if the driver was previously loaded because the PSP can only be loaded once between each reset. v2: rebase, handle multiple asic funcs Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 8849b74078d6..fb01a6cda262 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -43,6 +43,7 @@ #include "hdp/hdp_4_0_sh_mask.h" #include "smuio/smuio_9_0_offset.h" #include "smuio/smuio_9_0_sh_mask.h" +#include "mp/mp_9_0_offset.h" #include "soc15.h" #include "soc15_common.h" @@ -602,6 +603,23 @@ static bool soc15_need_full_reset(struct amdgpu_device *adev) return true; } +static bool soc15_need_reset_on_init(struct amdgpu_device *adev) +{ + u32 sol_reg; + + if (adev->flags & AMD_IS_APU) + return false; + + /* Check sOS sign of life register to confirm sys driver and sOS +* are already been loaded. +*/ + sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); + if (sol_reg) + return true; + + return false; +} + static const struct amdgpu_asic_funcs soc15_asic_funcs = { .read_disabled_bios = _read_disabled_bios, @@ -617,6 +635,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs = .invalidate_hdp = _invalidate_hdp, .need_full_reset = _need_full_reset, .init_doorbell_index = _doorbell_index_init, + .need_reset_on_init = _need_reset_on_init, }; static const struct amdgpu_asic_funcs vega20_asic_funcs = @@ -634,6 +653,7 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs = .invalidate_hdp = _invalidate_hdp, .need_full_reset = _need_full_reset, .init_doorbell_index = _doorbell_index_init, + .need_reset_on_init = _need_reset_on_init, }; static int soc15_common_early_init(void *handle) -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 6/6] drm/amdgpu: check if we need to reset at init time (v2)
To deal with situations like kexec or GPU VM passthrough where the device may have been used previously without a proper GPU reset between. v2: rebase bug: https://bugs.freedesktop.org/show_bug.cgi?id=108585 bug: https://bugs.freedesktop.org/show_bug.cgi?id=108754 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1a558dc41ba6..8a61764e64cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2550,6 +2550,17 @@ int amdgpu_device_init(struct amdgpu_device *adev, /* detect if we are with an SRIOV vbios */ amdgpu_device_detect_sriov_bios(adev); + /* check if we need to reset the asic +* E.g., driver was not cleanly unloaded previously, etc. +*/ + if (amdgpu_asic_need_reset_on_init(adev)) { + r = amdgpu_asic_reset(adev); + if (r) { + dev_err(adev->dev, "asic reset on init failed\n"); + goto failed; + } + } + /* Post card if necessary */ if (amdgpu_device_need_post(adev)) { if (!adev->bios) { -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 2/6] drm/amdgpu/si: add need_reset_on_init asic callback for SI (v2)
SI chips don't require a reset on reload due to the nature of the SMU on them. v2: rebase Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index f8408f88cd37..51adfe986da3 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1258,6 +1258,11 @@ static bool si_need_full_reset(struct amdgpu_device *adev) return true; } +static bool si_need_reset_on_init(struct amdgpu_device *adev) +{ + return false; +} + static int si_get_pcie_lanes(struct amdgpu_device *adev) { u32 link_width_cntl; @@ -1339,6 +1344,7 @@ static const struct amdgpu_asic_funcs si_asic_funcs = .flush_hdp = _flush_hdp, .invalidate_hdp = _invalidate_hdp, .need_full_reset = _need_full_reset, + .need_reset_on_init = _need_reset_on_init, }; static uint32_t si_get_rev_id(struct amdgpu_device *adev) -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 1/6] drm/amdgpu: add need_reset_on_init asic callback (v2)
Used to determine if we need to reset the asic on init due to the driver having been previously loaded or not shutdown cleanly. E.g., kexec or VM passthrough. v2: rebase Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index bcef6ea4bcf9..d27fa2ffb2f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -542,6 +542,8 @@ struct amdgpu_asic_funcs { bool (*need_full_reset)(struct amdgpu_device *adev); /* initialize doorbell layout for specific asic*/ void (*init_doorbell_index)(struct amdgpu_device *adev); + /* do we need to reset the asic at init time (e.g., kexec) */ + bool (*need_reset_on_init)(struct amdgpu_device *adev); }; /* @@ -1042,6 +1044,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r)) #define amdgpu_asic_need_full_reset(adev) (adev)->asic_funcs->need_full_reset((adev)) #define amdgpu_asic_init_doorbell_index(adev) (adev)->asic_funcs->init_doorbell_index((adev)) +#define amdgpu_asic_need_reset_on_init(adev) (adev)->asic_funcs->need_reset_on_init((adev)) /* Common functions */ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 0/6] kexec fixes
Fixes for kexec. The GPU needs to be reset before the driver can be loaded again reliably. Needed for kexec for booting some ppc platforms. See: https://bugs.freedesktop.org/show_bug.cgi?id=108585 Alex Deucher (6): drm/amdgpu: add need_reset_on_init asic callback (v2) drm/amdgpu/si: add need_reset_on_init asic callback for SI (v2) drm/amdgpu/cik: add need_reset_on_init asic callback for CIK (v2) drm/amdgpu/vi: add need_reset_on_init asic callback for VI (v2) drm/amdgpu/soc15: add need_reset_on_init asic callback for SOC15 (v2) drm/amdgpu: check if we need to reset at init time (v2) drivers/gpu/drm/amd/amdgpu/amdgpu.h| 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +++ drivers/gpu/drm/amd/amdgpu/cik.c | 18 ++ drivers/gpu/drm/amd/amdgpu/si.c| 6 ++ drivers/gpu/drm/amd/amdgpu/soc15.c | 20 drivers/gpu/drm/amd/amdgpu/vi.c| 18 ++ 6 files changed, 76 insertions(+) -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 3/6] drm/amdgpu/cik: add need_reset_on_init asic callback for CIK (v2)
CIK chips require a reset if the driver was previously loaded because the SMU can only be loaded once between each reset. v2: rebase Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 71c50d8900e3..09dfaff63502 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1741,6 +1741,23 @@ static bool cik_need_full_reset(struct amdgpu_device *adev) return true; } +static bool cik_need_reset_on_init(struct amdgpu_device *adev) +{ + u32 clock_cntl, pc; + + if (adev->flags & AMD_IS_APU) + return false; + + /* check if the SMC is already running */ + clock_cntl = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); + pc = RREG32_SMC(ixSMC_PC_C); + if ((0 == REG_GET_FIELD(clock_cntl, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) && + (0x20100 <= pc)) + return true; + + return false; +} + static const struct amdgpu_asic_funcs cik_asic_funcs = { .read_disabled_bios = _read_disabled_bios, @@ -1756,6 +1773,7 @@ static const struct amdgpu_asic_funcs cik_asic_funcs = .invalidate_hdp = _invalidate_hdp, .need_full_reset = _need_full_reset, .init_doorbell_index = _doorbell_index_init, + .need_reset_on_init = _need_reset_on_init, }; static int cik_common_early_init(void *handle) -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 4/6] drm/amdgpu/vi: add need_reset_on_init asic callback for VI (v2)
VI chips require a reset if the driver was previously loaded because the SMU can only be loaded once between each reset. v2: rebase Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 03e7be595a0d..60ce2c1dac5c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -941,6 +941,23 @@ static bool vi_need_full_reset(struct amdgpu_device *adev) } } +static bool vi_need_reset_on_init(struct amdgpu_device *adev) +{ + u32 clock_cntl, pc; + + if (adev->flags & AMD_IS_APU) + return false; + + /* check if the SMC is already running */ + clock_cntl = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); + pc = RREG32_SMC(ixSMC_PC_C); + if ((0 == REG_GET_FIELD(clock_cntl, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) && + (0x20100 <= pc)) + return true; + + return false; +} + static const struct amdgpu_asic_funcs vi_asic_funcs = { .read_disabled_bios = _read_disabled_bios, @@ -956,6 +973,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs = .invalidate_hdp = _invalidate_hdp, .need_full_reset = _need_full_reset, .init_doorbell_index = _doorbell_index_init, + .need_reset_on_init = _need_reset_on_init, }; #define CZ_REV_BRISTOL(rev) \ -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
RE: [PATCH] drm/amdgpu: expose sclk and mclk via hwmon
Ditto...except if those files Felix mentioned were to go away as pp_od_clk_voltage more widely used, then we would need this. I think Alex had mentioned there was some redundancy between those, but pp_od_clk_voltage didn't indicate the current frequencies. Chris -Original Message- From: Kuehling, Felix Sent: Tuesday, January 8, 2019 3:44 PM To: Deucher, Alexander ; Alex Deucher ; amd-gfx@lists.freedesktop.org; Russell, Kent ; Freehill, Chris Subject: Re: [PATCH] drm/amdgpu: expose sclk and mclk via hwmon I'm not saying it's useless. But rocm-smi can already get the clocks from sysfs (pp_dpm_sclk and pp_dpm_mclk). Are these clocks any different? Regards, Felix On 2019-01-08 4:32 p.m., Deucher, Alexander wrote: > > Ping? Useful for rocm-smi? > > -- > -- > *From:* Alex Deucher > *Sent:* Monday, December 10, 2018 4:17:27 PM > *To:* amd-gfx@lists.freedesktop.org > *Cc:* Deucher, Alexander > *Subject:* [PATCH] drm/amdgpu: expose sclk and mclk via hwmon > > Expose sclk (gfx clock) and mclk (memory clock) via hwmon compatible > interface. hwmon does not actually formally specify a frequency type > attribute, but these are compatible with the format of the other > attributes exposed via hwmon. Units are hertz. > > freq1_input - GPU gfx/compute clock in hertz freq2_input - GPU memory > clock in hertz (dGPU only) > > Signed-off-by: Alex Deucher > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 93 > ++ > 1 file changed, 93 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > index 1f61ed95727c..6d52428fc45b 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > @@ -1516,6 +1516,75 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > return count; > } > > +static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, > + struct device_attribute *attr, > + char *buf) { > + struct amdgpu_device *adev = dev_get_drvdata(dev); > + struct drm_device *ddev = adev->ddev; > + uint32_t sclk; > + int r, size = sizeof(sclk); > + > + /* Can't get voltage when the card is off */ > + if ((adev->flags & AMD_IS_PX) && > + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) > + return -EINVAL; > + > + /* sanity check PP is enabled */ > + if (!(adev->powerplay.pp_funcs && > + adev->powerplay.pp_funcs->read_sensor)) > + return -EINVAL; > + > + /* get the sclk */ > + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, > + (void *), ); > + if (r) > + return r; > + > + return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000); } > + > +static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev, > + struct device_attribute > +*attr, > + char *buf) { > + return snprintf(buf, PAGE_SIZE, "sclk\n"); } > + > +static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, > + struct device_attribute *attr, > + char *buf) { > + struct amdgpu_device *adev = dev_get_drvdata(dev); > + struct drm_device *ddev = adev->ddev; > + uint32_t mclk; > + int r, size = sizeof(mclk); > + > + /* Can't get voltage when the card is off */ > + if ((adev->flags & AMD_IS_PX) && > + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) > + return -EINVAL; > + > + /* sanity check PP is enabled */ > + if (!(adev->powerplay.pp_funcs && > + adev->powerplay.pp_funcs->read_sensor)) > + return -EINVAL; > + > + /* get the sclk */ > + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, > + (void *), ); > + if (r) > + return r; > + > + return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000); } > + > +static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev, > + struct device_attribute > +*attr, > + char *buf) { > + return snprintf(buf, PAGE_SIZE, "mclk\n"); } > > /** > * DOC: hwmon > @@ -1532,6 +1601,10 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > * > * - GPU fan > * > + * - GPU gfx/compute engine clock > + * > + * - GPU memory clock (dGPU only) > + * > * hwmon interfaces for GPU temperature: > * > * - temp1_input: the on die GPU temperature in millidegrees Celsius > @@ -1576,6 +1649,12 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > * > * - fan[1-*]_enable: Enable or
Re: [PATCH] drm/amdgpu: expose sclk and mclk via hwmon
I'm not saying it's useless. But rocm-smi can already get the clocks from sysfs (pp_dpm_sclk and pp_dpm_mclk). Are these clocks any different? Regards, Felix On 2019-01-08 4:32 p.m., Deucher, Alexander wrote: > > Ping? Useful for rocm-smi? > > > *From:* Alex Deucher > *Sent:* Monday, December 10, 2018 4:17:27 PM > *To:* amd-gfx@lists.freedesktop.org > *Cc:* Deucher, Alexander > *Subject:* [PATCH] drm/amdgpu: expose sclk and mclk via hwmon > > Expose sclk (gfx clock) and mclk (memory clock) via > hwmon compatible interface. hwmon does not actually > formally specify a frequency type attribute, but these > are compatible with the format of the other attributes > exposed via hwmon. Units are hertz. > > freq1_input - GPU gfx/compute clock in hertz > freq2_input - GPU memory clock in hertz (dGPU only) > > Signed-off-by: Alex Deucher > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 93 > ++ > 1 file changed, 93 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > index 1f61ed95727c..6d52428fc45b 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > @@ -1516,6 +1516,75 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > return count; > } > > +static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct amdgpu_device *adev = dev_get_drvdata(dev); > + struct drm_device *ddev = adev->ddev; > + uint32_t sclk; > + int r, size = sizeof(sclk); > + > + /* Can't get voltage when the card is off */ > + if ((adev->flags & AMD_IS_PX) && > + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) > + return -EINVAL; > + > + /* sanity check PP is enabled */ > + if (!(adev->powerplay.pp_funcs && > + adev->powerplay.pp_funcs->read_sensor)) > + return -EINVAL; > + > + /* get the sclk */ > + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, > + (void *), ); > + if (r) > + return r; > + > + return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000); > +} > + > +static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + return snprintf(buf, PAGE_SIZE, "sclk\n"); > +} > + > +static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct amdgpu_device *adev = dev_get_drvdata(dev); > + struct drm_device *ddev = adev->ddev; > + uint32_t mclk; > + int r, size = sizeof(mclk); > + > + /* Can't get voltage when the card is off */ > + if ((adev->flags & AMD_IS_PX) && > + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) > + return -EINVAL; > + > + /* sanity check PP is enabled */ > + if (!(adev->powerplay.pp_funcs && > + adev->powerplay.pp_funcs->read_sensor)) > + return -EINVAL; > + > + /* get the sclk */ > + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, > + (void *), ); > + if (r) > + return r; > + > + return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000); > +} > + > +static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + return snprintf(buf, PAGE_SIZE, "mclk\n"); > +} > > /** > * DOC: hwmon > @@ -1532,6 +1601,10 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > * > * - GPU fan > * > + * - GPU gfx/compute engine clock > + * > + * - GPU memory clock (dGPU only) > + * > * hwmon interfaces for GPU temperature: > * > * - temp1_input: the on die GPU temperature in millidegrees Celsius > @@ -1576,6 +1649,12 @@ static ssize_t > amdgpu_hwmon_set_power_cap(struct device *dev, > * > * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable > * > + * hwmon interfaces for GPU clocks: > + * > + * - freq1_input: the gfx/compute clock in hertz > + * > + * - freq2_input: the memory clock in hertz > + * > * You can use hwmon tools like sensors to view this information on > your system. > * > */ > @@ -1600,6 +1679,10 @@ static SENSOR_DEVICE_ATTR(power1_average, > S_IRUGO, amdgpu_hwmon_show_power_avg, > static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, > amdgpu_hwmon_show_power_cap_max, NULL, 0); > static
Re: [PATCH] drm/amdgpu: expose sclk and mclk via hwmon
Ping? Useful for rocm-smi? From: Alex Deucher Sent: Monday, December 10, 2018 4:17:27 PM To: amd-gfx@lists.freedesktop.org Cc: Deucher, Alexander Subject: [PATCH] drm/amdgpu: expose sclk and mclk via hwmon Expose sclk (gfx clock) and mclk (memory clock) via hwmon compatible interface. hwmon does not actually formally specify a frequency type attribute, but these are compatible with the format of the other attributes exposed via hwmon. Units are hertz. freq1_input - GPU gfx/compute clock in hertz freq2_input - GPU memory clock in hertz (dGPU only) Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 93 ++ 1 file changed, 93 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 1f61ed95727c..6d52428fc45b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1516,6 +1516,75 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, return count; } +static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + struct drm_device *ddev = adev->ddev; + uint32_t sclk; + int r, size = sizeof(sclk); + + /* Can't get voltage when the card is off */ + if ((adev->flags & AMD_IS_PX) && +(ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + + /* sanity check PP is enabled */ + if (!(adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->read_sensor)) + return -EINVAL; + + /* get the sclk */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, + (void *), ); + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000); +} + +static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "sclk\n"); +} + +static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + struct drm_device *ddev = adev->ddev; + uint32_t mclk; + int r, size = sizeof(mclk); + + /* Can't get voltage when the card is off */ + if ((adev->flags & AMD_IS_PX) && +(ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + + /* sanity check PP is enabled */ + if (!(adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->read_sensor)) + return -EINVAL; + + /* get the sclk */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, + (void *), ); + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000); +} + +static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "mclk\n"); +} /** * DOC: hwmon @@ -1532,6 +1601,10 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, * * - GPU fan * + * - GPU gfx/compute engine clock + * + * - GPU memory clock (dGPU only) + * * hwmon interfaces for GPU temperature: * * - temp1_input: the on die GPU temperature in millidegrees Celsius @@ -1576,6 +1649,12 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, * * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable * + * hwmon interfaces for GPU clocks: + * + * - freq1_input: the gfx/compute clock in hertz + * + * - freq2_input: the memory clock in hertz + * * You can use hwmon tools like sensors to view this information on your system. * */ @@ -1600,6 +1679,10 @@ static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg, static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0); static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0); static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0); +static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0); +static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0); +static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, amdgpu_hwmon_show_mclk, NULL, 0); +static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, amdgpu_hwmon_show_mclk_label,
Re: [PATCH v2 0/3] drm/amdgpu: Fix suspend/resume issues with MST
On Tue, 2019-01-08 at 16:17 -0500, Alex Deucher wrote: > On Tue, Jan 8, 2019 at 4:11 PM Lyude Paul wrote: > > Fix the suspend/issues that Jerry Zuo found in amdgpu, and add some > > compiler warnings for drivers ignoring the return code of > > drm_dp_mst_topology_mgr_resume() to help ensure we don't need to fix > > this again in the future for someone else's driver. > > > > Cc: Jerry Zuo > > > > Lyude Paul (3): > > drm/amdgpu: Don't ignore rc from drm_dp_mst_topology_mgr_resume() > > drm/amdgpu: Don't fail resume process if resuming atomic state fails > > drm/dp_mst: Add __must_check to drm_dp_mst_topology_mgr_resume() > > I can take these through the amdgpu tree or you can commit them to > drm-misc (assuming you have commit rights). Either way works for me. I don't mind just pushing these to drm-misc since you seem OK with it. Thanks! > > Thanks, > > Alex > > > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 +-- > > include/drm/drm_dp_mst_helper.h | 3 +- > > 2 files changed, 27 insertions(+), 13 deletions(-) > > > > -- > > 2.20.1 > > > > ___ > > amd-gfx mailing list > > amd-gfx@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/amd-gfx -- Cheers, Lyude Paul ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH v2 0/3] drm/amdgpu: Fix suspend/resume issues with MST
On Tue, Jan 8, 2019 at 4:11 PM Lyude Paul wrote: > > Fix the suspend/issues that Jerry Zuo found in amdgpu, and add some > compiler warnings for drivers ignoring the return code of > drm_dp_mst_topology_mgr_resume() to help ensure we don't need to fix > this again in the future for someone else's driver. > > Cc: Jerry Zuo > > Lyude Paul (3): > drm/amdgpu: Don't ignore rc from drm_dp_mst_topology_mgr_resume() > drm/amdgpu: Don't fail resume process if resuming atomic state fails > drm/dp_mst: Add __must_check to drm_dp_mst_topology_mgr_resume() I can take these through the amdgpu tree or you can commit them to drm-misc (assuming you have commit rights). Either way works for me. Thanks, Alex > > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 +-- > include/drm/drm_dp_mst_helper.h | 3 +- > 2 files changed, 27 insertions(+), 13 deletions(-) > > -- > 2.20.1 > > ___ > amd-gfx mailing list > amd-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v2 3/3] drm/dp_mst: Add __must_check to drm_dp_mst_topology_mgr_resume()
Since I've had to fix two cases of drivers not checking the return code from this function, let's make the compiler complain so this doesn't come up again in the future. Changes since v1: * Remove unneeded __must_check in function declaration - danvet Signed-off-by: Lyude Paul Cc: Jerry Zuo Reviewed-by: Daniel Vetter Reviewed-by: Harry Wentland --- include/drm/drm_dp_mst_helper.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 371cc2816477..4355b55d0081 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -614,7 +614,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m, struct drm_dp_mst_topology_mgr *mgr); void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr); -int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr); +int __must_check +drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr); struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr); int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v2 2/3] drm/amdgpu: Don't fail resume process if resuming atomic state fails
This is an ugly one unfortunately. Currently, all DRM drivers supporting atomic modesetting will save the state that userspace had set before suspending, then attempt to restore that state on resume. This probably worked very well at one point, like many other things, until DP MST came into the picture. While it's easy to restore state on normal display connectors that were disconnected during suspend regardless of their state post-resume, this can't really be done with MST because of the fact that setting up a downstream sink requires performing sideband transactions between the source and the MST hub, sending out the ACT packets, etc. Because of this, there isn't really a guarantee that we can restore the atomic state we had before suspend once we've resumed. This sucks pretty bad, but so far I haven't run into any compositors that this actually causes serious issues with. Most compositors will notice the hotplug we send afterwards, and then reprobe state. Since nouveau and i915 also don't fail the suspend/resume process due to failing to restore the atomic state, let's make amdgpu match this behavior. Better to resume the GPU properly, then to stop the process half way because of a potentially unavoidable atomic commit failure. Eventually, we'll have a real fix for this problem on the DRM level. But we've got some more important low-hanging fruit to deal with first. Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Jerry Zuo Cc: # v4.15+ --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3f326a2c513b..a3e65e457348 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -912,7 +912,6 @@ static int dm_resume(void *handle) struct drm_plane_state *new_plane_state; struct dm_plane_state *dm_new_plane_state; enum dc_connection_type new_connection_type = dc_connection_none; - int ret; int i; /* power on hardware */ @@ -985,13 +984,13 @@ static int dm_resume(void *handle) } } - ret = drm_atomic_helper_resume(ddev, dm->cached_state); + drm_atomic_helper_resume(ddev, dm->cached_state); dm->cached_state = NULL; amdgpu_dm_irq_resume_late(adev); - return ret; + return 0; } /** -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v2 1/3] drm/amdgpu: Don't ignore rc from drm_dp_mst_topology_mgr_resume()
drm_dp_mst_topology_mgr_resume() returns whether or not it managed to find the topology in question after a suspend resume cycle, and the driver is supposed to check this value and disable MST accordingly if it's gone-in addition to sending a hotplug in order to notify userspace that something changed during suspend. Currently, amdgpu just makes the mistake of ignoring the return code from drm_dp_mst_topology_mgr_resume() which means that if a topology was removed in suspend, amdgpu never notices and assumes it's still connected which leads to all sorts of problems. So, fix this by actually checking the rc from drm_dp_mst_topology_mgr_resume(). Also, reformat the rest of the function while we're at it to fix the over-indenting. Signed-off-by: Lyude Paul Reviewed-by: Harry Wentland Cc: Jerry Zuo Cc: # v4.15+ --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 +-- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8a626d16e8e3..3f326a2c513b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) { struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; + struct drm_dp_mst_topology_mgr *mgr; + int ret; + bool need_hotplug = false; drm_modeset_lock(>mode_config.connection_mutex, NULL); - list_for_each_entry(connector, >mode_config.connector_list, head) { - aconnector = to_amdgpu_dm_connector(connector); - if (aconnector->dc_link->type == dc_connection_mst_branch && - !aconnector->mst_port) { + list_for_each_entry(connector, >mode_config.connector_list, + head) { + aconnector = to_amdgpu_dm_connector(connector); + if (aconnector->dc_link->type != dc_connection_mst_branch || + aconnector->mst_port) + continue; + + mgr = >mst_mgr; - if (suspend) - drm_dp_mst_topology_mgr_suspend(>mst_mgr); - else - drm_dp_mst_topology_mgr_resume(>mst_mgr); - } + if (suspend) { + drm_dp_mst_topology_mgr_suspend(mgr); + } else { + ret = drm_dp_mst_topology_mgr_resume(mgr); + if (ret < 0) { + drm_dp_mst_topology_mgr_set_mst(mgr, false); + need_hotplug = true; + } + } } drm_modeset_unlock(>mode_config.connection_mutex); + + if (need_hotplug) + drm_kms_helper_hotplug_event(dev); } /** -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH v2 0/3] drm/amdgpu: Fix suspend/resume issues with MST
Fix the suspend/issues that Jerry Zuo found in amdgpu, and add some compiler warnings for drivers ignoring the return code of drm_dp_mst_topology_mgr_resume() to help ensure we don't need to fix this again in the future for someone else's driver. Cc: Jerry Zuo Lyude Paul (3): drm/amdgpu: Don't ignore rc from drm_dp_mst_topology_mgr_resume() drm/amdgpu: Don't fail resume process if resuming atomic state fails drm/dp_mst: Add __must_check to drm_dp_mst_topology_mgr_resume() .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 +-- include/drm/drm_dp_mst_helper.h | 3 +- 2 files changed, 27 insertions(+), 13 deletions(-) -- 2.20.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH v4 00/16] MST refcounting/atomic helpers cleanup
On Tue, 2019-01-08 at 19:57 +, Wentland, Harry wrote: > On 2019-01-04 7:14 p.m., Lyude Paul wrote: > > This is the series I've been working on for a while now to get all of > > the atomic DRM drivers in the tree to use the atomic MST helpers, and to > > make the atomic MST helpers actually idempotent. Turns out it's a lot > > more difficult to do that without also fixing how port and branch device > > refcounting works so that it actually makes sense, since the current > > upstream implementation requires a ton of magic in the atomic helpers to > > work around properly and in many situations just plain doesn't work as > > intended. > > > > There's still more cleanup that can be done, but I think this is a good > > place to start off for now :). > > > > This version just contains some changes that I forgot to make that had > > been requested much earlier, mainly in regards to the atomic checking > > code I added to i915 and nouveau (but not the helpers). > > > > Also, per-request I've made a gitlab branch available for this: > > > > https://gitlab.freedesktop.org/lyudess/linux/commits/wip/mst-dual-kref-start-v4 > > > > Lyude Paul (16): > > drm/dp_mst: Rename drm_dp_mst_get_validated_(port|mstb)_ref and > > friends > > drm/dp_mst: Introduce new refcounting scheme for mstbs and ports > > drm/dp_mst: Restart last_connected_port_and_mstb() if topology ref > > fails > > drm/dp_mst: Stop releasing VCPI when removing ports from topology > > drm/dp_mst: Fix payload deallocation on hotplugs using malloc refs > > drm/i915: Keep malloc references to MST ports > > drm/amdgpu/display: Keep malloc ref to MST port > > drm/nouveau: Remove bogus cleanup in nv50_mstm_add_connector() > > drm/nouveau: Remove unnecessary VCPI checks in nv50_msto_cleanup() > > drm/nouveau: Keep malloc references to MST ports > > drm/nouveau: Stop unsetting mstc->port, use malloc refs > > drm/nouveau: Grab payload lock in nv50_msto_payload() > > drm/dp_mst: Add some atomic state iterator macros > > drm/dp_mst: Start tracking per-port VCPI allocations > > drm/dp_mst: Check payload count in drm_dp_mst_atomic_check() > > drm/nouveau: Use atomic VCPI helpers for MST > > > > Somehow I left my RB on v2 for a while. Either way patches 2-5, and 7 are > Reviewed-by: Harry Wentland > > Haven't had a chance to take a look at 13-15 but noticed the "Changes since > v" mention versions that either aren't on the mailing list or don't line up > with the patch versioning. That's intentional! Those were patches that were part of a different series that got replaced by this one, so the older versions are from the previous series > > Harry > > > .../gpu/dp-mst/topology-figure-1.dot | 52 + > > .../gpu/dp-mst/topology-figure-2.dot | 56 ++ > > .../gpu/dp-mst/topology-figure-3.dot | 59 ++ > > Documentation/gpu/drm-kms-helpers.rst | 26 +- > > .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 +- > > drivers/gpu/drm/drm_dp_mst_topology.c | 938 ++ > > drivers/gpu/drm/i915/intel_connector.c| 4 + > > drivers/gpu/drm/i915/intel_display.c | 4 + > > drivers/gpu/drm/i915/intel_dp_mst.c | 55 +- > > drivers/gpu/drm/nouveau/dispnv50/disp.c | 96 +- > > include/drm/drm_dp_mst_helper.h | 151 ++- > > 11 files changed, 1203 insertions(+), 249 deletions(-) > > create mode 100644 Documentation/gpu/dp-mst/topology-figure-1.dot > > create mode 100644 Documentation/gpu/dp-mst/topology-figure-2.dot > > create mode 100644 Documentation/gpu/dp-mst/topology-figure-3.dot > > -- Cheers, Lyude Paul ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH v4 00/16] MST refcounting/atomic helpers cleanup
On 2019-01-04 7:14 p.m., Lyude Paul wrote: > This is the series I've been working on for a while now to get all of > the atomic DRM drivers in the tree to use the atomic MST helpers, and to > make the atomic MST helpers actually idempotent. Turns out it's a lot > more difficult to do that without also fixing how port and branch device > refcounting works so that it actually makes sense, since the current > upstream implementation requires a ton of magic in the atomic helpers to > work around properly and in many situations just plain doesn't work as > intended. > > There's still more cleanup that can be done, but I think this is a good > place to start off for now :). > > This version just contains some changes that I forgot to make that had > been requested much earlier, mainly in regards to the atomic checking > code I added to i915 and nouveau (but not the helpers). > > Also, per-request I've made a gitlab branch available for this: > > https://gitlab.freedesktop.org/lyudess/linux/commits/wip/mst-dual-kref-start-v4 > > Lyude Paul (16): > drm/dp_mst: Rename drm_dp_mst_get_validated_(port|mstb)_ref and > friends > drm/dp_mst: Introduce new refcounting scheme for mstbs and ports > drm/dp_mst: Restart last_connected_port_and_mstb() if topology ref > fails > drm/dp_mst: Stop releasing VCPI when removing ports from topology > drm/dp_mst: Fix payload deallocation on hotplugs using malloc refs > drm/i915: Keep malloc references to MST ports > drm/amdgpu/display: Keep malloc ref to MST port > drm/nouveau: Remove bogus cleanup in nv50_mstm_add_connector() > drm/nouveau: Remove unnecessary VCPI checks in nv50_msto_cleanup() > drm/nouveau: Keep malloc references to MST ports > drm/nouveau: Stop unsetting mstc->port, use malloc refs > drm/nouveau: Grab payload lock in nv50_msto_payload() > drm/dp_mst: Add some atomic state iterator macros > drm/dp_mst: Start tracking per-port VCPI allocations > drm/dp_mst: Check payload count in drm_dp_mst_atomic_check() > drm/nouveau: Use atomic VCPI helpers for MST > Somehow I left my RB on v2 for a while. Either way patches 2-5, and 7 are Reviewed-by: Harry Wentland Haven't had a chance to take a look at 13-15 but noticed the "Changes since v" mention versions that either aren't on the mailing list or don't line up with the patch versioning. Harry > .../gpu/dp-mst/topology-figure-1.dot | 52 + > .../gpu/dp-mst/topology-figure-2.dot | 56 ++ > .../gpu/dp-mst/topology-figure-3.dot | 59 ++ > Documentation/gpu/drm-kms-helpers.rst | 26 +- > .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 +- > drivers/gpu/drm/drm_dp_mst_topology.c | 938 ++ > drivers/gpu/drm/i915/intel_connector.c| 4 + > drivers/gpu/drm/i915/intel_display.c | 4 + > drivers/gpu/drm/i915/intel_dp_mst.c | 55 +- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 96 +- > include/drm/drm_dp_mst_helper.h | 151 ++- > 11 files changed, 1203 insertions(+), 249 deletions(-) > create mode 100644 Documentation/gpu/dp-mst/topology-figure-1.dot > create mode 100644 Documentation/gpu/dp-mst/topology-figure-2.dot > create mode 100644 Documentation/gpu/dp-mst/topology-figure-3.dot > ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH v2 07/16] drm/amdgpu/display: Keep malloc ref to MST port
On 2018-12-19 7:19 p.m., Lyude Paul wrote: > Just like i915 and nouveau, it's a good idea for us to hold a malloc > reference to the port here so that we never pass a freed pointer to any > of the DP MST helper functions. > > Also, we stop unsetting aconnector->port in > dm_dp_destroy_mst_connector(). There's literally no point to that > assignment that I can see anyway. > > Signed-off-by: Lyude Paul > Cc: Daniel Vetter > Cc: David Airlie > Cc: Jerry Zuo > Cc: Harry Wentland > Cc: Juston Li Reviewed-by: Harry Wentland Harry > --- > .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 +++ > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > index 5e7ca1f3a8d1..24632727e127 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > @@ -191,6 +191,7 @@ dm_dp_mst_connector_destroy(struct drm_connector > *connector) > drm_encoder_cleanup(_encoder->base); > kfree(amdgpu_encoder); > drm_connector_cleanup(connector); > + drm_dp_mst_put_port_malloc(amdgpu_dm_connector->port); > kfree(amdgpu_dm_connector); > } > > @@ -363,7 +364,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr > *mgr, > amdgpu_dm_connector_funcs_reset(connector); > > DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n", > - aconnector, connector->base.id, aconnector->mst_port); > + aconnector, connector->base.id, aconnector->mst_port); > + > + drm_dp_mst_get_port_malloc(port); > > DRM_DEBUG_KMS(":%d\n", connector->base.id); > > @@ -379,12 +382,12 @@ static void dm_dp_destroy_mst_connector(struct > drm_dp_mst_topology_mgr *mgr, > struct amdgpu_dm_connector *aconnector = > to_amdgpu_dm_connector(connector); > > DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n", > - aconnector, connector->base.id, > aconnector->mst_port); > + aconnector, connector->base.id, aconnector->mst_port); > > - aconnector->port = NULL; > if (aconnector->dc_sink) { > amdgpu_dm_update_freesync_caps(connector, NULL); > - dc_link_remove_remote_sink(aconnector->dc_link, > aconnector->dc_sink); > + dc_link_remove_remote_sink(aconnector->dc_link, > +aconnector->dc_sink); > dc_sink_release(aconnector->dc_sink); > aconnector->dc_sink = NULL; > } > ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.4 07/28] drm/amdgpu: Correct get_crtc_scanoutpos behavior when vpos >= vtotal
From: Nicholas Kazlauskas [ Upstream commit 520f08df45fbe300ed650da786a74093d658b7e1 ] When variable refresh rate is active the hardware counter can return a position >= vtotal. This results in a vpos being returned from amdgpu_display_get_crtc_scanoutpos that's a positive value. The positive value indicates to the caller that the display is currently in scanout when the display is actually still in vblank. This is because the vfront porch duration is unknown with variable refresh active and will end when either a page flip occurs or the timeout specified by the driver/display is reached. The behavior of the amdgpu_display_get_crtc_scanoutpos remains the same when the position is below vtotal. When the position is above vtotal the function will return a value that is effectively -vbl_end, the size of the vback porch. The only caller affected by this change is the DRM helper for calculating vblank timestamps. This change corrects behavior for calculating the page flip timestamp from being the previous timestamp to the calculation to the next timestamp when position >= vtotal. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index c555781685ea..0947567900bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -883,7 +883,12 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { vtotal = mode->crtc_vtotal; - *vpos = *vpos - vtotal; + + /* With variable refresh rate displays the vpos can exceed +* the vtotal value. Clamp to 0 to return -vbl_end instead +* of guessing the remaining number of lines until scanout. +*/ + *vpos = (*vpos < vtotal) ? (*vpos - vtotal) : 0; } /* Correct for shifted end of vbl at vbl_end. */ -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.9 10/36] drm/amdgpu: Correct get_crtc_scanoutpos behavior when vpos >= vtotal
From: Nicholas Kazlauskas [ Upstream commit 520f08df45fbe300ed650da786a74093d658b7e1 ] When variable refresh rate is active the hardware counter can return a position >= vtotal. This results in a vpos being returned from amdgpu_display_get_crtc_scanoutpos that's a positive value. The positive value indicates to the caller that the display is currently in scanout when the display is actually still in vblank. This is because the vfront porch duration is unknown with variable refresh active and will end when either a page flip occurs or the timeout specified by the driver/display is reached. The behavior of the amdgpu_display_get_crtc_scanoutpos remains the same when the position is below vtotal. When the position is above vtotal the function will return a value that is effectively -vbl_end, the size of the vback porch. The only caller affected by this change is the DRM helper for calculating vblank timestamps. This change corrects behavior for calculating the page flip timestamp from being the previous timestamp to the calculation to the next timestamp when position >= vtotal. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 15a2d8f3725d..5042ae072386 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -856,7 +856,12 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { vtotal = mode->crtc_vtotal; - *vpos = *vpos - vtotal; + + /* With variable refresh rate displays the vpos can exceed +* the vtotal value. Clamp to 0 to return -vbl_end instead +* of guessing the remaining number of lines until scanout. +*/ + *vpos = (*vpos < vtotal) ? (*vpos - vtotal) : 0; } /* Correct for shifted end of vbl at vbl_end. */ -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.14 13/53] drm/amdgpu: Correct get_crtc_scanoutpos behavior when vpos >= vtotal
From: Nicholas Kazlauskas [ Upstream commit 520f08df45fbe300ed650da786a74093d658b7e1 ] When variable refresh rate is active the hardware counter can return a position >= vtotal. This results in a vpos being returned from amdgpu_display_get_crtc_scanoutpos that's a positive value. The positive value indicates to the caller that the display is currently in scanout when the display is actually still in vblank. This is because the vfront porch duration is unknown with variable refresh active and will end when either a page flip occurs or the timeout specified by the driver/display is reached. The behavior of the amdgpu_display_get_crtc_scanoutpos remains the same when the position is below vtotal. When the position is above vtotal the function will return a value that is effectively -vbl_end, the size of the vback porch. The only caller affected by this change is the DRM helper for calculating vblank timestamps. This change corrects behavior for calculating the page flip timestamp from being the previous timestamp to the calculation to the next timestamp when position >= vtotal. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 6ad243293a78..8c0a208e43c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -855,7 +855,12 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { vtotal = mode->crtc_vtotal; - *vpos = *vpos - vtotal; + + /* With variable refresh rate displays the vpos can exceed +* the vtotal value. Clamp to 0 to return -vbl_end instead +* of guessing the remaining number of lines until scanout. +*/ + *vpos = (*vpos < vtotal) ? (*vpos - vtotal) : 0; } /* Correct for shifted end of vbl at vbl_end. */ -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.19 30/97] drm/amdgpu: Reorder uvd ring init before uvd resume
From: Chris Wilson [ Upstream commit 3b34c14fd50c302db091f020f26dd00ede902c80 ] As amd_uvd_resume() accesses the uvd ring, it must be initialised first or else we trigger errors like: [5.595963] [drm] Found UVD firmware Version: 1.87 Family ID: 17 [5.595969] [drm] PSP loading UVD firmware [5.596266] [ cut here ] [5.596268] ODEBUG: assert_init not available (active state 0) object type: timer_list hint: (null) [5.596285] WARNING: CPU: 0 PID: 507 at lib/debugobjects.c:329 debug_print_object+0x6a/0x80 [5.596286] Modules linked in: amdgpu(+) hid_logitech_hidpp(+) chash gpu_sched amd_iommu_v2 ttm drm_kms_helper crc32c_intel drm hid_sony ff_memless igb hid_logitech_dj nvme dca i2c_algo_bit nvme_core wmi pinctrl_amd uas usb_storage [5.596299] CPU: 0 PID: 507 Comm: systemd-udevd Tainted: GW 4.20.0-0.rc1.git4.1.fc30.x86_64 #1 [5.596301] Hardware name: System manufacturer System Product Name/ROG STRIX X470-I GAMING, BIOS 0901 07/23/2018 [5.596303] RIP: 0010:debug_print_object+0x6a/0x80 [5.596305] Code: 8b 43 10 83 c2 01 8b 4b 14 4c 89 e6 89 15 e6 82 b0 02 4c 8b 45 00 48 c7 c7 60 fd 34 a6 48 8b 14 c5 a0 da 08 a6 e8 6a 6a b8 ff <0f> 0b 5b 83 05 d0 45 3e 01 01 5d 41 5c c3 83 05 c5 45 3e 01 01 c3 [5.596306] RSP: 0018:a02ac863f8c0 EFLAGS: 00010282 [5.596307] RAX: RBX: a02ac863f8e0 RCX: 0006 [5.596308] RDX: 0007 RSI: 9160e9a7bfe8 RDI: 9160f91d6c60 [5.596310] RBP: a6742740 R08: 0002 R09: [5.596311] R10: R11: R12: a634ff69 [5.596312] R13: 000b79d0 R14: a80f76d8 R15: 00266000 [5.596313] FS: 7f762abf7940() GS:9160f900() knlGS: [5.596314] CS: 0010 DS: ES: CR0: 80050033 [5.596315] CR2: 55fdc593f000 CR3: 0007e999c000 CR4: 003406f0 [5.596317] Call Trace: [5.596321] debug_object_assert_init+0x14a/0x180 [5.596327] del_timer+0x2e/0x90 [5.596383] amdgpu_fence_process+0x47/0x100 [amdgpu] [5.596430] amdgpu_uvd_resume+0xf6/0x120 [amdgpu] [5.596475] uvd_v7_0_sw_init+0xe0/0x280 [amdgpu] [5.596523] amdgpu_device_init.cold.30+0xf97/0x14b6 [amdgpu] [5.596563] ? amdgpu_driver_load_kms+0x53/0x330 [amdgpu] [5.596604] amdgpu_driver_load_kms+0x86/0x330 [amdgpu] [5.596614] drm_dev_register+0x115/0x150 [drm] [5.596654] amdgpu_pci_probe+0xbd/0x120 [amdgpu] [5.596658] local_pci_probe+0x41/0x90 [5.596661] pci_device_probe+0x188/0x1a0 [5.59] really_probe+0xf8/0x3b0 [5.596669] driver_probe_device+0xb3/0xf0 [5.596672] __driver_attach+0xe1/0x110 [5.596674] ? driver_probe_device+0xf0/0xf0 [5.596676] bus_for_each_dev+0x79/0xc0 [5.596679] bus_add_driver+0x155/0x230 [5.596681] ? 0xc07d9000 [5.596683] driver_register+0x6b/0xb0 [5.596685] ? 0xc07d9000 [5.596688] do_one_initcall+0x5d/0x2be [5.596691] ? rcu_read_lock_sched_held+0x79/0x80 [5.596693] ? kmem_cache_alloc_trace+0x264/0x290 [5.596695] ? do_init_module+0x22/0x210 [5.596698] do_init_module+0x5a/0x210 [5.596701] load_module+0x2137/0x2430 [5.596703] ? lockdep_hardirqs_on+0xed/0x180 [5.596714] ? __do_sys_init_module+0x150/0x1a0 [5.596715] __do_sys_init_module+0x150/0x1a0 [5.596722] do_syscall_64+0x60/0x1f0 [5.596725] entry_SYSCALL_64_after_hwframe+0x49/0xbe [5.596726] RIP: 0033:0x7f762b877dee [5.596728] Code: 48 8b 0d 9d 20 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 af 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 6a 20 0c 00 f7 d8 64 89 01 48 [5.596729] RSP: 002b:7ffc777b8558 EFLAGS: 0246 ORIG_RAX: 00af [5.596730] RAX: ffda RBX: 55fdc48da320 RCX: 7f762b877dee [5.596731] RDX: 7f762b9f284d RSI: 006c5fc6 RDI: 55fdc527a060 [5.596732] RBP: 7f762b9f284d R08: 0003 R09: 0002 [5.596733] R10: 55fdc48ad010 R11: 0246 R12: 55fdc527a060 [5.596734] R13: 55fdc48dca20 R14: 0002 R15: [5.596740] irq event stamp: 134618 [5.596743] hardirqs last enabled at (134617): [] console_unlock+0x45e/0x610 [5.596744] hardirqs last disabled at (134618): [] trace_hardirqs_off_thunk+0x1a/0x1c [5.596746] softirqs last enabled at (133146): [] __do_softirq+0x365/0x47c [5.596748] softirqs last disabled at (133139): [] irq_exit+0x119/0x120 [5.596749] ---[ end trace eaee508abfebccdc ]--- Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108709 Reviewed-by: Christian König Signed-off-by: Chris Wilson Cc: Alex Deucher Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 8
[PATCH AUTOSEL 4.19 26/97] drm/amdgpu: Correct get_crtc_scanoutpos behavior when vpos >= vtotal
From: Nicholas Kazlauskas [ Upstream commit 520f08df45fbe300ed650da786a74093d658b7e1 ] When variable refresh rate is active the hardware counter can return a position >= vtotal. This results in a vpos being returned from amdgpu_display_get_crtc_scanoutpos that's a positive value. The positive value indicates to the caller that the display is currently in scanout when the display is actually still in vblank. This is because the vfront porch duration is unknown with variable refresh active and will end when either a page flip occurs or the timeout specified by the driver/display is reached. The behavior of the amdgpu_display_get_crtc_scanoutpos remains the same when the position is below vtotal. When the position is above vtotal the function will return a value that is effectively -vbl_end, the size of the vback porch. The only caller affected by this change is the DRM helper for calculating vblank timestamps. This change corrects behavior for calculating the page flip timestamp from being the previous timestamp to the calculation to the next timestamp when position >= vtotal. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 686a26de50f9..9c940bbed608 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -857,7 +857,12 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev, /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { vtotal = mode->crtc_vtotal; - *vpos = *vpos - vtotal; + + /* With variable refresh rate displays the vpos can exceed +* the vtotal value. Clamp to 0 to return -vbl_end instead +* of guessing the remaining number of lines until scanout. +*/ + *vpos = (*vpos < vtotal) ? (*vpos - vtotal) : 0; } /* Correct for shifted end of vbl at vbl_end. */ -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.19 03/97] drm/amd/display: Guard against null stream_state in set_crc_source
From: Nicholas Kazlauskas [ Upstream commit f41a895026b8cb6f765190de7d2e7bc3ccbbd183 ] [Why] The igt@kms_plane@pixel-format-pipe tests can create a sequence where stream_state is NULL during amdgpu_dm_crtc_set_crc_source which results in a null pointer dereference. [How] Guard against stream_state being NULL before accessing its fields. This doesn't fix the root cause of the issue so a DRM_ERROR is generated to still fail the tests. Signed-off-by: Nicholas Kazlauskas Reviewed-by: David Francis Acked-by: Leo Li Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index 9bfb040352e9..6a6d977ddd7a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -60,6 +60,11 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name, return -EINVAL; } + if (!stream_state) { + DRM_ERROR("No stream state for CRTC%d\n", crtc->index); + return -EINVAL; + } + /* When enabling CRC, we should also disable dithering. */ if (source == AMDGPU_DM_PIPE_CRC_SOURCE_AUTO) { if (dc_stream_configure_crc(stream_state->ctx->dc, -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.19 04/97] drm/amdkfd: fix interrupt spin lock
From: Christian König [ Upstream commit 2383a767c0ca06f96534456d8313909017c6c8d0 ] Vega10 has multiple interrupt rings, so this can be called from multiple calles at the same time resulting in: [ 71.779334] [ 71.779406] WARNING: inconsistent lock state [ 71.779478] 4.19.0-rc1+ #44 Tainted: GW [ 71.779565] [ 71.779637] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. [ 71.779740] kworker/6:1/120 [HC0[0]:SC0[0]:HE1:SE1] takes: [ 71.779832] ad761971 (&(>interrupt_lock)->rlock){?...}, at: kgd2kfd_interrupt+0x75/0x100 [amdgpu] [ 71.780058] {IN-HARDIRQ-W} state was registered at: [ 71.780115] _raw_spin_lock+0x2c/0x40 [ 71.780180] kgd2kfd_interrupt+0x75/0x100 [amdgpu] [ 71.780248] amdgpu_irq_callback+0x6c/0x150 [amdgpu] [ 71.780315] amdgpu_ih_process+0x88/0x100 [amdgpu] [ 71.780380] amdgpu_irq_handler+0x20/0x40 [amdgpu] [ 71.780409] __handle_irq_event_percpu+0x49/0x2a0 [ 71.780436] handle_irq_event_percpu+0x30/0x70 [ 71.780461] handle_irq_event+0x37/0x60 [ 71.780484] handle_edge_irq+0x83/0x1b0 [ 71.780506] handle_irq+0x1f/0x30 [ 71.780526] do_IRQ+0x53/0x110 [ 71.780544] ret_from_intr+0x0/0x22 [ 71.780566] cpuidle_enter_state+0xaa/0x330 [ 71.780591] do_idle+0x203/0x280 [ 71.780610] cpu_startup_entry+0x6f/0x80 [ 71.780634] start_secondary+0x1b0/0x200 [ 71.780657] secondary_startup_64+0xa4/0xb0 Fix this by always using irq save spin locks. Signed-off-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 1427675d0e5a..5aba50f63ac6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -661,6 +661,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) { uint32_t patched_ihre[KFD_MAX_RING_ENTRY_SIZE]; bool is_patched = false; + unsigned long flags; if (!kfd->init_complete) return; @@ -670,7 +671,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) return; } - spin_lock(>interrupt_lock); + spin_lock_irqsave(>interrupt_lock, flags); if (kfd->interrupts_active && interrupt_is_wanted(kfd, ih_ring_entry, @@ -679,7 +680,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) is_patched ? patched_ihre : ih_ring_entry)) queue_work(kfd->ih_wq, >interrupt_work); - spin_unlock(>interrupt_lock); + spin_unlock_irqrestore(>interrupt_lock, flags); } int kgd2kfd_quiesce_mm(struct mm_struct *mm) -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH v2 05/16] drm/dp_mst: Fix payload deallocation on hotplugs using malloc refs
On 2018-12-19 7:19 p.m., Lyude Paul wrote: > Up until now, freeing payloads on remote MST hubs that just had ports > removed has almost never worked because we've been relying on port > validation in order to stop us from accessing ports that have already > been freed from memory, but ports which need their payloads released due > to being removed will never be a valid part of the topology after > they've been removed. > > Since we've introduced malloc refs, we can replace all of the validation > logic in payload helpers which are used for deallocation with some > well-placed malloc krefs. This ensures that regardless of whether or not > the ports are still valid and in the topology, any port which has an > allocated payload will remain allocated in memory until it's payloads > have been removed - finally allowing us to actually release said > payloads correctly. > > Signed-off-by: Lyude Paul > Reviewed-by: Daniel Vetter > Cc: David Airlie > Cc: Jerry Zuo > Cc: Harry Wentland > Cc: Juston Li Reviewed-by: Harry Wentland Harry > --- > drivers/gpu/drm/drm_dp_mst_topology.c | 54 +++ > 1 file changed, 30 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > b/drivers/gpu/drm/drm_dp_mst_topology.c > index ef8637f37564..11dd3ede7b7d 100644 > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > @@ -2100,10 +2100,6 @@ static int drm_dp_payload_send_msg(struct > drm_dp_mst_topology_mgr *mgr, > u8 sinks[DRM_DP_MAX_SDP_STREAMS]; > int i; > > - port = drm_dp_mst_topology_get_port_validated(mgr, port); > - if (!port) > - return -EINVAL; > - > port_num = port->port_num; > mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent); > if (!mstb) { > @@ -2111,10 +2107,8 @@ static int drm_dp_payload_send_msg(struct > drm_dp_mst_topology_mgr *mgr, > port->parent, > _num); > > - if (!mstb) { > - drm_dp_mst_topology_put_port(port); > + if (!mstb) > return -EINVAL; > - } > } > > txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); > @@ -2151,7 +2145,6 @@ static int drm_dp_payload_send_msg(struct > drm_dp_mst_topology_mgr *mgr, > kfree(txmsg); > fail_put: > drm_dp_mst_topology_put_mstb(mstb); > - drm_dp_mst_topology_put_port(port); > return ret; > } > > @@ -2256,15 +2249,16 @@ static int drm_dp_destroy_payload_step2(struct > drm_dp_mst_topology_mgr *mgr, > */ > int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) > { > - int i, j; > - int cur_slots = 1; > struct drm_dp_payload req_payload; > struct drm_dp_mst_port *port; > + int i, j; > + int cur_slots = 1; > > mutex_lock(>payload_lock); > for (i = 0; i < mgr->max_payloads; i++) { > struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i]; > struct drm_dp_payload *payload = >payloads[i]; > + bool put_port = false; > > /* solve the current payloads - compare to the hw ones > - update the hw view */ > @@ -2272,12 +2266,20 @@ int drm_dp_update_payload_part1(struct > drm_dp_mst_topology_mgr *mgr) > if (vcpi) { > port = container_of(vcpi, struct drm_dp_mst_port, > vcpi); > - port = drm_dp_mst_topology_get_port_validated(mgr, > - port); > - if (!port) { > - mutex_unlock(>payload_lock); > - return -EINVAL; > + > + /* Validated ports don't matter if we're releasing > + * VCPI > + */ > + if (vcpi->num_slots) { > + port = drm_dp_mst_topology_get_port_validated( > + mgr, port); > + if (!port) { > + mutex_unlock(>payload_lock); > + return -EINVAL; > + } > + put_port = true; > } > + > req_payload.num_slots = vcpi->num_slots; > req_payload.vcpi = vcpi->vcpi; > } else { > @@ -2309,7 +2311,7 @@ int drm_dp_update_payload_part1(struct > drm_dp_mst_topology_mgr *mgr) > } > cur_slots += req_payload.num_slots; > > - if (port) > + if (put_port) > drm_dp_mst_topology_put_port(port); > } > > @@ -3124,6 +3126,8 @@ bool drm_dp_mst_allocate_vcpi(struct > drm_dp_mst_topology_mgr *mgr, >
[PATCH AUTOSEL 4.20 039/117] drm/amdgpu: Reorder uvd ring init before uvd resume
From: Chris Wilson [ Upstream commit 3b34c14fd50c302db091f020f26dd00ede902c80 ] As amd_uvd_resume() accesses the uvd ring, it must be initialised first or else we trigger errors like: [5.595963] [drm] Found UVD firmware Version: 1.87 Family ID: 17 [5.595969] [drm] PSP loading UVD firmware [5.596266] [ cut here ] [5.596268] ODEBUG: assert_init not available (active state 0) object type: timer_list hint: (null) [5.596285] WARNING: CPU: 0 PID: 507 at lib/debugobjects.c:329 debug_print_object+0x6a/0x80 [5.596286] Modules linked in: amdgpu(+) hid_logitech_hidpp(+) chash gpu_sched amd_iommu_v2 ttm drm_kms_helper crc32c_intel drm hid_sony ff_memless igb hid_logitech_dj nvme dca i2c_algo_bit nvme_core wmi pinctrl_amd uas usb_storage [5.596299] CPU: 0 PID: 507 Comm: systemd-udevd Tainted: GW 4.20.0-0.rc1.git4.1.fc30.x86_64 #1 [5.596301] Hardware name: System manufacturer System Product Name/ROG STRIX X470-I GAMING, BIOS 0901 07/23/2018 [5.596303] RIP: 0010:debug_print_object+0x6a/0x80 [5.596305] Code: 8b 43 10 83 c2 01 8b 4b 14 4c 89 e6 89 15 e6 82 b0 02 4c 8b 45 00 48 c7 c7 60 fd 34 a6 48 8b 14 c5 a0 da 08 a6 e8 6a 6a b8 ff <0f> 0b 5b 83 05 d0 45 3e 01 01 5d 41 5c c3 83 05 c5 45 3e 01 01 c3 [5.596306] RSP: 0018:a02ac863f8c0 EFLAGS: 00010282 [5.596307] RAX: RBX: a02ac863f8e0 RCX: 0006 [5.596308] RDX: 0007 RSI: 9160e9a7bfe8 RDI: 9160f91d6c60 [5.596310] RBP: a6742740 R08: 0002 R09: [5.596311] R10: R11: R12: a634ff69 [5.596312] R13: 000b79d0 R14: a80f76d8 R15: 00266000 [5.596313] FS: 7f762abf7940() GS:9160f900() knlGS: [5.596314] CS: 0010 DS: ES: CR0: 80050033 [5.596315] CR2: 55fdc593f000 CR3: 0007e999c000 CR4: 003406f0 [5.596317] Call Trace: [5.596321] debug_object_assert_init+0x14a/0x180 [5.596327] del_timer+0x2e/0x90 [5.596383] amdgpu_fence_process+0x47/0x100 [amdgpu] [5.596430] amdgpu_uvd_resume+0xf6/0x120 [amdgpu] [5.596475] uvd_v7_0_sw_init+0xe0/0x280 [amdgpu] [5.596523] amdgpu_device_init.cold.30+0xf97/0x14b6 [amdgpu] [5.596563] ? amdgpu_driver_load_kms+0x53/0x330 [amdgpu] [5.596604] amdgpu_driver_load_kms+0x86/0x330 [amdgpu] [5.596614] drm_dev_register+0x115/0x150 [drm] [5.596654] amdgpu_pci_probe+0xbd/0x120 [amdgpu] [5.596658] local_pci_probe+0x41/0x90 [5.596661] pci_device_probe+0x188/0x1a0 [5.59] really_probe+0xf8/0x3b0 [5.596669] driver_probe_device+0xb3/0xf0 [5.596672] __driver_attach+0xe1/0x110 [5.596674] ? driver_probe_device+0xf0/0xf0 [5.596676] bus_for_each_dev+0x79/0xc0 [5.596679] bus_add_driver+0x155/0x230 [5.596681] ? 0xc07d9000 [5.596683] driver_register+0x6b/0xb0 [5.596685] ? 0xc07d9000 [5.596688] do_one_initcall+0x5d/0x2be [5.596691] ? rcu_read_lock_sched_held+0x79/0x80 [5.596693] ? kmem_cache_alloc_trace+0x264/0x290 [5.596695] ? do_init_module+0x22/0x210 [5.596698] do_init_module+0x5a/0x210 [5.596701] load_module+0x2137/0x2430 [5.596703] ? lockdep_hardirqs_on+0xed/0x180 [5.596714] ? __do_sys_init_module+0x150/0x1a0 [5.596715] __do_sys_init_module+0x150/0x1a0 [5.596722] do_syscall_64+0x60/0x1f0 [5.596725] entry_SYSCALL_64_after_hwframe+0x49/0xbe [5.596726] RIP: 0033:0x7f762b877dee [5.596728] Code: 48 8b 0d 9d 20 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 af 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 6a 20 0c 00 f7 d8 64 89 01 48 [5.596729] RSP: 002b:7ffc777b8558 EFLAGS: 0246 ORIG_RAX: 00af [5.596730] RAX: ffda RBX: 55fdc48da320 RCX: 7f762b877dee [5.596731] RDX: 7f762b9f284d RSI: 006c5fc6 RDI: 55fdc527a060 [5.596732] RBP: 7f762b9f284d R08: 0003 R09: 0002 [5.596733] R10: 55fdc48ad010 R11: 0246 R12: 55fdc527a060 [5.596734] R13: 55fdc48dca20 R14: 0002 R15: [5.596740] irq event stamp: 134618 [5.596743] hardirqs last enabled at (134617): [] console_unlock+0x45e/0x610 [5.596744] hardirqs last disabled at (134618): [] trace_hardirqs_off_thunk+0x1a/0x1c [5.596746] softirqs last enabled at (133146): [] __do_softirq+0x365/0x47c [5.596748] softirqs last disabled at (133139): [] irq_exit+0x119/0x120 [5.596749] ---[ end trace eaee508abfebccdc ]--- Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108709 Reviewed-by: Christian König Signed-off-by: Chris Wilson Cc: Alex Deucher Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 8
Re: [PATCH v2 04/16] drm/dp_mst: Stop releasing VCPI when removing ports from topology
On 2018-12-19 7:19 p.m., Lyude Paul wrote: > This has never actually worked, and isn't needed anyway: the driver's > always going to try to deallocate VCPI when it tears down the display > that the VCPI belongs to. > > Signed-off-by: Lyude Paul > Reviewed-by: Daniel Vetter > Cc: David Airlie > Cc: Jerry Zuo > Cc: Harry Wentland > Cc: Juston Li Reviewed-by: Harry Wentland Harry > --- > drivers/gpu/drm/drm_dp_mst_topology.c | 8 > 1 file changed, 8 deletions(-) > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > b/drivers/gpu/drm/drm_dp_mst_topology.c > index 356a95aba2d8..ef8637f37564 100644 > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > @@ -1175,8 +1175,6 @@ static void drm_dp_destroy_port(struct kref *kref) > struct drm_dp_mst_topology_mgr *mgr = port->mgr; > > if (!port->input) { > - port->vcpi.num_slots = 0; > - > kfree(port->cached_edid); > > /* > @@ -3491,12 +3489,6 @@ static void drm_dp_destroy_connector_work(struct > work_struct *work) > drm_dp_port_teardown_pdt(port, port->pdt); > port->pdt = DP_PEER_DEVICE_NONE; > > - if (!port->input && port->vcpi.vcpi > 0) { > - drm_dp_mst_reset_vcpi_slots(mgr, port); > - drm_dp_update_payload_part1(mgr); > - drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); > - } > - > drm_dp_mst_put_port_malloc(port); > send_hotplug = true; > } > ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.20 034/117] drm/amdgpu: Correct get_crtc_scanoutpos behavior when vpos >= vtotal
From: Nicholas Kazlauskas [ Upstream commit 520f08df45fbe300ed650da786a74093d658b7e1 ] When variable refresh rate is active the hardware counter can return a position >= vtotal. This results in a vpos being returned from amdgpu_display_get_crtc_scanoutpos that's a positive value. The positive value indicates to the caller that the display is currently in scanout when the display is actually still in vblank. This is because the vfront porch duration is unknown with variable refresh active and will end when either a page flip occurs or the timeout specified by the driver/display is reached. The behavior of the amdgpu_display_get_crtc_scanoutpos remains the same when the position is below vtotal. When the position is above vtotal the function will return a value that is effectively -vbl_end, the size of the vback porch. The only caller affected by this change is the DRM helper for calculating vblank timestamps. This change corrects behavior for calculating the page flip timestamp from being the previous timestamp to the calculation to the next timestamp when position >= vtotal. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 686a26de50f9..9c940bbed608 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -857,7 +857,12 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev, /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { vtotal = mode->crtc_vtotal; - *vpos = *vpos - vtotal; + + /* With variable refresh rate displays the vpos can exceed +* the vtotal value. Clamp to 0 to return -vbl_end instead +* of guessing the remaining number of lines until scanout. +*/ + *vpos = (*vpos < vtotal) ? (*vpos - vtotal) : 0; } /* Correct for shifted end of vbl at vbl_end. */ -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.20 005/117] drm/amdkfd: fix interrupt spin lock
From: Christian König [ Upstream commit 2383a767c0ca06f96534456d8313909017c6c8d0 ] Vega10 has multiple interrupt rings, so this can be called from multiple calles at the same time resulting in: [ 71.779334] [ 71.779406] WARNING: inconsistent lock state [ 71.779478] 4.19.0-rc1+ #44 Tainted: GW [ 71.779565] [ 71.779637] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. [ 71.779740] kworker/6:1/120 [HC0[0]:SC0[0]:HE1:SE1] takes: [ 71.779832] ad761971 (&(>interrupt_lock)->rlock){?...}, at: kgd2kfd_interrupt+0x75/0x100 [amdgpu] [ 71.780058] {IN-HARDIRQ-W} state was registered at: [ 71.780115] _raw_spin_lock+0x2c/0x40 [ 71.780180] kgd2kfd_interrupt+0x75/0x100 [amdgpu] [ 71.780248] amdgpu_irq_callback+0x6c/0x150 [amdgpu] [ 71.780315] amdgpu_ih_process+0x88/0x100 [amdgpu] [ 71.780380] amdgpu_irq_handler+0x20/0x40 [amdgpu] [ 71.780409] __handle_irq_event_percpu+0x49/0x2a0 [ 71.780436] handle_irq_event_percpu+0x30/0x70 [ 71.780461] handle_irq_event+0x37/0x60 [ 71.780484] handle_edge_irq+0x83/0x1b0 [ 71.780506] handle_irq+0x1f/0x30 [ 71.780526] do_IRQ+0x53/0x110 [ 71.780544] ret_from_intr+0x0/0x22 [ 71.780566] cpuidle_enter_state+0xaa/0x330 [ 71.780591] do_idle+0x203/0x280 [ 71.780610] cpu_startup_entry+0x6f/0x80 [ 71.780634] start_secondary+0x1b0/0x200 [ 71.780657] secondary_startup_64+0xa4/0xb0 Fix this by always using irq save spin locks. Signed-off-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index e4ded890b1cb..6edaf11d69aa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -688,6 +688,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) { uint32_t patched_ihre[KFD_MAX_RING_ENTRY_SIZE]; bool is_patched = false; + unsigned long flags; if (!kfd->init_complete) return; @@ -697,7 +698,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) return; } - spin_lock(>interrupt_lock); + spin_lock_irqsave(>interrupt_lock, flags); if (kfd->interrupts_active && interrupt_is_wanted(kfd, ih_ring_entry, @@ -706,7 +707,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) is_patched ? patched_ihre : ih_ring_entry)) queue_work(kfd->ih_wq, >interrupt_work); - spin_unlock(>interrupt_lock); + spin_unlock_irqrestore(>interrupt_lock, flags); } int kgd2kfd_quiesce_mm(struct mm_struct *mm) -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH AUTOSEL 4.20 004/117] drm/amd/display: Guard against null stream_state in set_crc_source
From: Nicholas Kazlauskas [ Upstream commit f41a895026b8cb6f765190de7d2e7bc3ccbbd183 ] [Why] The igt@kms_plane@pixel-format-pipe tests can create a sequence where stream_state is NULL during amdgpu_dm_crtc_set_crc_source which results in a null pointer dereference. [How] Guard against stream_state being NULL before accessing its fields. This doesn't fix the root cause of the issue so a DRM_ERROR is generated to still fail the tests. Signed-off-by: Nicholas Kazlauskas Reviewed-by: David Francis Acked-by: Leo Li Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index 01fc5717b657..f088ac585978 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -75,6 +75,11 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) return -EINVAL; } + if (!stream_state) { + DRM_ERROR("No stream state for CRTC%d\n", crtc->index); + return -EINVAL; + } + /* When enabling CRC, we should also disable dithering. */ if (source == AMDGPU_DM_PIPE_CRC_SOURCE_AUTO) { if (dc_stream_configure_crc(stream_state->ctx->dc, -- 2.19.1 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH v2 03/16] drm/dp_mst: Restart last_connected_port_and_mstb() if topology ref fails
On 2018-12-19 7:19 p.m., Lyude Paul wrote: > While this isn't a complete fix, this will improve the reliability of > drm_dp_get_last_connected_port_and_mstb() pretty significantly during > hotplug events, since there's a chance that the in-memory topology tree > may not be fully updated when drm_dp_get_last_connected_port_and_mstb() > is called and thus might end up causing our search to fail on an mstb > whose topology refcount has reached 0, but has not yet been removed from > it's parent. > > Ideally, we should further fix this problem by ensuring that we deal > with the potential for racing with a hotplug event, which would look > like this: > > * drm_dp_payload_send_msg() retrieves the last living relative of mstb > with drm_dp_get_last_connected_port_and_mstb() > * drm_dp_payload_send_msg() starts building payload message > At the same time, mstb gets unplugged from the topology and is no > longer the actual last living relative of the original mstb > * drm_dp_payload_send_msg() tries sending the payload message, hub times > out > * Hub timed out, we give up and run away-resulting in the payload being > leaked > > This could be fixed by restarting the > drm_dp_get_last_connected_port_and_mstb() search whenever we get a > timeout, sending the payload to the new mstb, then repeating until > either the entire topology is removed from the system or > drm_dp_get_last_connected_port_and_mstb() fails. But since the above > race condition is not terribly likely, we'll address that in a later > patch series once we've improved the recovery handling for VCPI > allocations in the rest of the DP MST helpers. > > Signed-off-by: Lyude Paul > Cc: Daniel Vetter > Cc: David Airlie > Cc: Jerry Zuo > Cc: Harry Wentland > Cc: Juston Li Reviewed-by: Harry Wentland Harry > --- > drivers/gpu/drm/drm_dp_mst_topology.c | 55 +-- > 1 file changed, 44 insertions(+), 11 deletions(-) > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > b/drivers/gpu/drm/drm_dp_mst_topology.c > index b380ada09e90..356a95aba2d8 100644 > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > @@ -2043,25 +2043,50 @@ static struct drm_dp_mst_port > *drm_dp_get_last_connected_port_to_mstb(struct drm > return > drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent); > } > > -static struct drm_dp_mst_branch > *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, > - struct > drm_dp_mst_branch *mstb, > - int > *port_num) > +/** > + * drm_dp_get_last_connected_port_and_mstb() - Find the last living relatives > + * in a topology of a given branch device > + * @mgr: The topology manager to use > + * @mstb: The disconnected branch device > + * @port_num: Where to store the number of the last connected port > + * > + * Searches upwards in the topology starting from @mstb to try to find the > + * closest available parent of @mstb that's still connected to the rest of > the > + * topology. This can be used in order to perform operations like releasing > + * payloads, where the branch device which owned the payload may no longer be > + * around and thus would require that the payload on the last living relative > + * be freed instead. > + * > + * Returns: > + * The last connected _dp_mst_branch in the topology that was a parent of > + * @mstb, if there is one. > + */ > +static struct drm_dp_mst_branch * > +drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, > + struct drm_dp_mst_branch *mstb, > + int *port_num) > { > struct drm_dp_mst_branch *rmstb = NULL; > struct drm_dp_mst_port *found_port; > + > mutex_lock(>lock); > - if (mgr->mst_primary) { > + if (!mgr->mst_primary) > + goto out; > + > + do { > found_port = drm_dp_get_last_connected_port_to_mstb(mstb); > + if (!found_port) > + break; > > - if (found_port) { > + if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) { > rmstb = found_port->parent; > - if (drm_dp_mst_topology_try_get_mstb(rmstb)) { > - *port_num = found_port->port_num; > - } else { > - rmstb = NULL; > - } > + *port_num = found_port->port_num; > + } else { > + /* Search again, starting from this parent */ > + mstb = found_port->parent; > } > - } > + } while (!rmstb); > +out: > mutex_unlock(>lock); > return rmstb; > } > @@ -2110,6 +2135,14 @@ static int drm_dp_payload_send_msg(struct > drm_dp_mst_topology_mgr *mgr,
Re: [PATCH v4 02/16] drm/dp_mst: Introduce new refcounting scheme for mstbs and ports
On 2019-01-04 7:14 p.m., Lyude Paul wrote: > The current way of handling refcounting in the DP MST helpers is really > confusing and probably just plain wrong because it's been hacked up many > times over the years without anyone actually going over the code and > seeing if things could be simplified. > > To the best of my understanding, the current scheme works like this: > drm_dp_mst_port and drm_dp_mst_branch both have a single refcount. When > this refcount hits 0 for either of the two, they're removed from the > topology state, but not immediately freed. Both ports and branch devices > will reinitialize their kref once it's hit 0 before actually destroying > themselves. The intended purpose behind this is so that we can avoid > problems like not being able to free a remote payload that might still > be active, due to us having removed all of the port/branch device > structures in memory, as per: > > commit 91a25e463130 ("drm/dp/mst: deallocate payload on port destruction") > > Which may have worked, but then it caused use-after-free errors. Being > new to MST at the time, I tried fixing it; > > commit 263efde31f97 ("drm/dp/mst: Get validated port ref in > drm_dp_update_payload_part1()") > > But, that was broken: both drm_dp_mst_port and drm_dp_mst_branch structs > are validated in almost every DP MST helper function. Simply put, this > means we go through the topology and try to see if the given > drm_dp_mst_branch or drm_dp_mst_port is still attached to something > before trying to use it in order to avoid dereferencing freed memory > (something that has happened a LOT in the past with this library). > Because of this it doesn't actually matter whether or not we keep keep > the ports and branches around in memory as that's not enough, because > any function that validates the branches and ports passed to it will > still reject them anyway since they're no longer in the topology > structure. So, use-after-free errors were fixed but payload deallocation > was completely broken. > > Two years later, AMD informed me about this issue and I attempted to > come up with a temporary fix, pending a long-overdue cleanup of this > library: > > commit c54c7374ff44 ("drm/dp_mst: Skip validating ports during destruction, > just ref") > > But then that introduced use-after-free errors, so I quickly reverted > it: > > commit 9765635b3075 ("Revert "drm/dp_mst: Skip validating ports during > destruction, just ref"") > > And in the process, learned that there is just no simple fix for this: > the design is just broken. Unfortuntely, the usage of these helpers are > quite broken as well. Some drivers like i915 have been smart enough to > avoid accessing any kind of information from MST port structures, but > others like nouveau have assumed, understandably so, that > drm_dp_mst_port structures are normal and can just be accessed at any > time without worrying about use-after-free errors. > > After a lot of discussion, me and Daniel Vetter came up with a better > idea to replace all of this. > > To summarize, since this is documented far more indepth in the > documentation this patch introduces, we make it so that drm_dp_mst_port > and drm_dp_mst_branch structures have two different classes of > refcounts: topology_kref, and malloc_kref. topology_kref corresponds to > the lifetime of the given drm_dp_mst_port or drm_dp_mst_branch in it's > given topology. Once it hits zero, any associated connectors are removed > and the branch or port can no longer be validated. malloc_kref > corresponds to the lifetime of the memory allocation for the actual > structure, and will always be non-zero so long as the topology_kref is > non-zero. This gives us a way to allow callers to hold onto port and > branch device structures past their topology lifetime, and dramatically > simplifies the lifetimes of both structures. This also finally fixes the > port deallocation problem, properly. > > Additionally: since this now means that we can keep ports and branch > devices allocated in memory for however long we need, we no longer need > a significant amount of the port validation that we currently do. > > Additionally, there is one last scenario that this fixes, which couldn't > have been fixed properly beforehand: > > - CPU1 unrefs port from topology (refcount 1->0) > - CPU2 refs port in topology(refcount 0->1) > > Since we now can guarantee memory safety for ports and branches > as-needed, we also can make our main reference counting functions fix > this problem by using kref_get_unless_zero() internally so that topology > refcounts can only ever reach 0 once. > > Changes since v2: > * Fix commit message - checkpatch > Changes since v1: > * Remove forward declarations - danvet > * Move "Branch device and port refcounting" section from documentation > into kernel-doc comments - danvet > * Export internal topology lifetime functions into their own section in > the kernel-docs - danvet > * s/@/&/g for struct
Re: [PATCH 0/3] drm/amdgpu: Fix suspend/resume issues with MST
On 2019-01-07 7:56 p.m., Lyude Paul wrote: > Fix the suspend/issues that Jerry Zuo found in amdgpu, and add some > compiler warnings for drivers ignoring the return code of > drm_dp_mst_topology_mgr_resume() to help ensure we don't need to fix > this again in the future for someone else's driver. > > Cc: Jerry Zuo With the small change Daniel mentioned this series is Reviewed-by: Harry Wentland Harry > > Lyude Paul (3): > drm/amdgpu: Don't ignore rc from drm_dp_mst_topology_mgr_resume() > drm/amdgpu: Don't fail resume process if resuming atomic state fails > drm/dp_mst: Add __must_check to drm_dp_mst_topology_mgr_resume() > > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 +-- > drivers/gpu/drm/drm_dp_mst_topology.c | 3 +- > include/drm/drm_dp_mst_helper.h | 3 +- > 3 files changed, 29 insertions(+), 14 deletions(-) > ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 3/4] drm/radeon: Use drm_hdmi_avi_infoframe_quant_range()
From: Ville Syrjälä Fill out the AVI infoframe quantization range bits using drm_hdmi_avi_infoframe_quant_range() instead of hand rolling it. This changes the behaviour slightly as drm_hdmi_avi_infoframe_quant_range() will set a non-zero Q bit even when QS==0 iff the Q bit matched the default quantization range for the given mode. This matches the recommendation in HDMI 2.0 and is allowed even before that. Cc: Alex Deucher Cc: "Christian König" Cc: "David (ChunMing) Zhou" Cc: amd-gfx@lists.freedesktop.org Signed-off-by: Ville Syrjälä Acked-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_audio.c | 13 + 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 5a7d48339b32..708765bf9e66 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -523,14 +523,11 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, } if (radeon_encoder->output_csc != RADEON_OUTPUT_CSC_BYPASS) { - if (drm_rgb_quant_range_selectable(radeon_connector_edid(connector))) { - if (radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB) - frame.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED; - else - frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; - } else { - frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; - } + drm_hdmi_avi_infoframe_quant_range(, connector, mode, + radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB ? + HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL, + drm_rgb_quant_range_selectable(radeon_connector_edid(connector))); } err = hdmi_avi_infoframe_pack(, buffer, sizeof(buffer)); -- 2.19.2 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 1/4] drm/edid: Pass connector to AVI infoframe functions
From: Ville Syrjälä Make life easier for drivers by simply passing the connector to drm_hdmi_avi_infoframe_from_display_mode() and drm_hdmi_avi_infoframe_quant_range(). That way drivers don't need to worry about is_hdmi2_sink mess. v2: Make is_hdmi2_sink() return true for sil-sii8620 Adapt to omap/vc4 changes Cc: Alex Deucher Cc: "Christian König" Cc: "David (ChunMing) Zhou" Cc: Archit Taneja Cc: Andrzej Hajda Cc: Laurent Pinchart Cc: Inki Dae Cc: Joonyoung Shim Cc: Seung-Woo Kim Cc: Kyungmin Park Cc: Russell King Cc: CK Hu Cc: Philipp Zabel Cc: Rob Clark Cc: Ben Skeggs Cc: Tomi Valkeinen Cc: Sandy Huang Cc: "Heiko Stübner" Cc: Benjamin Gaignard Cc: Vincent Abriou Cc: Thierry Reding Cc: Eric Anholt Cc: Shawn Guo Cc: Ilia Mirkin Cc: amd-gfx@lists.freedesktop.org Cc: linux-arm-...@vger.kernel.org Cc: freedr...@lists.freedesktop.org Cc: nouv...@lists.freedesktop.org Cc: linux-te...@vger.kernel.org Signed-off-by: Ville Syrjälä Acked-by: Thierry Reding Acked-by: Russell King Reviewed-by: Laurent Pinchart Reviewed-by: Jani Nikula --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c| 2 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c| 2 +- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 2 +- drivers/gpu/drm/bridge/analogix-anx78xx.c | 5 ++-- drivers/gpu/drm/bridge/sii902x.c | 3 ++- drivers/gpu/drm/bridge/sil-sii8620.c | 3 +-- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 3 ++- drivers/gpu/drm/drm_edid.c| 33 ++- drivers/gpu/drm/exynos/exynos_hdmi.c | 3 ++- drivers/gpu/drm/i2c/tda998x_drv.c | 3 ++- drivers/gpu/drm/i915/intel_hdmi.c | 14 +- drivers/gpu/drm/i915/intel_lspcon.c | 15 ++- drivers/gpu/drm/i915/intel_sdvo.c | 10 --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 3 ++- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c| 3 ++- drivers/gpu/drm/nouveau/dispnv50/disp.c | 7 +++-- drivers/gpu/drm/omapdrm/omap_encoder.c| 4 +-- drivers/gpu/drm/radeon/radeon_audio.c | 2 +- drivers/gpu/drm/rockchip/inno_hdmi.c | 4 ++- drivers/gpu/drm/sti/sti_hdmi.c| 3 ++- drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c| 3 ++- drivers/gpu/drm/tegra/hdmi.c | 3 ++- drivers/gpu/drm/tegra/sor.c | 3 ++- drivers/gpu/drm/vc4/vc4_hdmi.c| 9 --- drivers/gpu/drm/zte/zx_hdmi.c | 4 ++- include/drm/drm_edid.h| 8 +++--- 27 files changed, 91 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 4cfecdce29a3..1f0426d2fc2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -1682,7 +1682,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder, dce_v10_0_audio_write_sad_regs(encoder); dce_v10_0_audio_write_latency_fields(encoder, mode); - err = drm_hdmi_avi_infoframe_from_display_mode(, mode, false); + err = drm_hdmi_avi_infoframe_from_display_mode(, connector, mode); if (err < 0) { DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); return; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 7c868916d90f..2280b971d758 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -1724,7 +1724,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, dce_v11_0_audio_write_sad_regs(encoder); dce_v11_0_audio_write_latency_fields(encoder, mode); - err = drm_hdmi_avi_infoframe_from_display_mode(, mode, false); + err = drm_hdmi_avi_infoframe_from_display_mode(, connector, mode); if (err < 0) { DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); return; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 17eaaba36017..db443ec53d3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1423,6 +1423,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; + struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); struct hdmi_avi_infoframe frame; u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; uint8_t *payload = buffer + 3; @@ -1430,7 +1431,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, ssize_t err; u32 tmp; - err = drm_hdmi_avi_infoframe_from_display_mode(, mode, false); + err = drm_hdmi_avi_infoframe_from_display_mode(, connector,
[PATCH 4/4] drm/edid: Add display_info.rgb_quant_range_selectable
From: Ville Syrjälä Move the CEA-861 QS bit handling entirely into the edid code. No need to bother the drivers with this. Cc: Alex Deucher Cc: "Christian König" Cc: "David (ChunMing) Zhou" Cc: amd-gfx@lists.freedesktop.org Cc: Eric Anholt (supporter:DRM DRIVERS FOR VC4) Signed-off-by: Ville Syrjälä Acked-by: Alex Deucher Acked-by: Eric Anholt --- drivers/gpu/drm/drm_edid.c| 70 --- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_hdmi.c | 8 +-- drivers/gpu/drm/i915/intel_lspcon.c | 3 +- drivers/gpu/drm/i915/intel_sdvo.c | 7 +-- drivers/gpu/drm/radeon/radeon_audio.c | 3 +- drivers/gpu/drm/vc4/vc4_hdmi.c| 9 +--- include/drm/drm_connector.h | 6 +++ include/drm/drm_edid.h| 4 +- 9 files changed, 43 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index cd25bd08bf53..990b1909f9d7 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3641,6 +3641,20 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db) return oui == HDMI_FORUM_IEEE_OUI; } +static bool cea_db_is_vcdb(const u8 *db) +{ + if (cea_db_tag(db) != USE_EXTENDED_TAG) + return false; + + if (cea_db_payload_len(db) != 2) + return false; + + if (cea_db_extended_tag(db) != EXT_VIDEO_CAPABILITY_BLOCK) + return false; + + return true; +} + static bool cea_db_is_y420cmdb(const u8 *db) { if (cea_db_tag(db) != USE_EXTENDED_TAG) @@ -4223,41 +4237,6 @@ bool drm_detect_monitor_audio(struct edid *edid) } EXPORT_SYMBOL(drm_detect_monitor_audio); -/** - * drm_rgb_quant_range_selectable - is RGB quantization range selectable? - * @edid: EDID block to scan - * - * Check whether the monitor reports the RGB quantization range selection - * as supported. The AVI infoframe can then be used to inform the monitor - * which quantization range (full or limited) is used. - * - * Return: True if the RGB quantization range is selectable, false otherwise. - */ -bool drm_rgb_quant_range_selectable(struct edid *edid) -{ - u8 *edid_ext; - int i, start, end; - - edid_ext = drm_find_cea_extension(edid); - if (!edid_ext) - return false; - - if (cea_db_offsets(edid_ext, , )) - return false; - - for_each_cea_db(edid_ext, i, start, end) { - if (cea_db_tag(_ext[i]) == USE_EXTENDED_TAG && - cea_db_payload_len(_ext[i]) == 2 && - cea_db_extended_tag(_ext[i]) == - EXT_VIDEO_CAPABILITY_BLOCK) { - DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", edid_ext[i + 2]); - return edid_ext[i + 2] & EDID_CEA_VCDB_QS; - } - } - - return false; -} -EXPORT_SYMBOL(drm_rgb_quant_range_selectable); /** * drm_default_rgb_quant_range - default RGB quantization range @@ -4278,6 +4257,16 @@ drm_default_rgb_quant_range(const struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_default_rgb_quant_range); +static void drm_parse_vcdb(struct drm_connector *connector, const u8 *db) +{ + struct drm_display_info *info = >display_info; + + DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", db[2]); + + if (db[2] & EDID_CEA_VCDB_QS) + info->rgb_quant_range_selectable = true; +} + static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector, const u8 *db) { @@ -4452,6 +4441,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector, drm_parse_hdmi_forum_vsdb(connector, db); if (cea_db_is_y420cmdb(db)) drm_parse_y420cmdb_bitmap(connector, db); + if (cea_db_is_vcdb(db)) + drm_parse_vcdb(connector, db); } } @@ -4472,6 +4463,7 @@ drm_reset_display_info(struct drm_connector *connector) info->max_tmds_clock = 0; info->dvi_dual = false; info->has_hdmi_infoframe = false; + info->rgb_quant_range_selectable = false; memset(>hdmi, 0, sizeof(info->hdmi)); info->non_desktop = 0; @@ -4939,15 +4931,15 @@ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode); * @connector: the connector * @mode: DRM display mode * @rgb_quant_range: RGB quantization range (Q) - * @rgb_quant_range_selectable: Sink support selectable RGB quantization range (QS) */ void drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, struct drm_connector *connector, const struct drm_display_mode *mode, - enum hdmi_quantization_range rgb_quant_range, - bool rgb_quant_range_selectable) + enum hdmi_quantization_range rgb_quant_range) { + const
[PATCH 25/25] drm/amd/display: 3.2.14
From: Steven Chiu Signed-off-by: Steven Chiu Reviewed-by: Yongqiang Sun Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 98f716be..f362b04 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.13" +#define DC_VER "3.2.14" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 23/25] drm/amd/display: Check if registers are available before accessing
From: Eric Bernstein Check if VERT_FILTER_INIT_BOT and BLACK_OFFSET registers exists in the DCN SCL IP block before trying to access. Signed-off-by: Eric Bernstein Reviewed-by: Dmytro Laktyushkin Acked-by: Leo Li --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 42 -- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 4a863a5d..c7642e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -597,11 +597,13 @@ static void dpp1_dscl_set_manual_ratio_init( SCL_V_INIT_FRAC, init_frac, SCL_V_INIT_INT, init_int); - init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5; - init_int = dc_fixpt_floor(data->inits.v_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, - SCL_V_INIT_FRAC_BOT, init_frac, - SCL_V_INIT_INT_BOT, init_int); + if (REG(SCL_VERT_FILTER_INIT_BOT)) { + init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5; + init_int = dc_fixpt_floor(data->inits.v_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, + SCL_V_INIT_FRAC_BOT, init_frac, + SCL_V_INIT_INT_BOT, init_int); + } init_frac = dc_fixpt_u0d19(data->inits.v_c) << 5; init_int = dc_fixpt_floor(data->inits.v_c); @@ -609,11 +611,13 @@ static void dpp1_dscl_set_manual_ratio_init( SCL_V_INIT_FRAC_C, init_frac, SCL_V_INIT_INT_C, init_int); - init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5; - init_int = dc_fixpt_floor(data->inits.v_c_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, - SCL_V_INIT_FRAC_BOT_C, init_frac, - SCL_V_INIT_INT_BOT_C, init_int); + if (REG(SCL_VERT_FILTER_INIT_BOT_C)) { + init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5; + init_int = dc_fixpt_floor(data->inits.v_c_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, + SCL_V_INIT_FRAC_BOT_C, init_frac, + SCL_V_INIT_INT_BOT_C, init_int); + } } @@ -688,15 +692,17 @@ void dpp1_dscl_set_scaler_manual_scale( return; /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else + if (REG(SCL_BLACK_OFFSET)) { + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + } /* Manually calculate scale ratio and init values */ dpp1_dscl_set_manual_ratio_init(dpp, scl_data); -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 20/25] drm/amd/display: add workaround for 4k video underflow
From: Eric Yang [Why] On DCN1, there is an issue where on high BW config on single channel systems, underflow will be observed if DCC is disabled. This issue can be observed on several use cases. For this particular case, it is observed when playing 4k video on 4k desktop with video downscaled to a certain size. [How] Block MPO for this particular case, this will prevent extra BW consumed from downscaling, working around the underflow. Signed-off-by: Eric Yang Reviewed-by: Yongqiang Sun Acked-by: Leo Li --- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 51 ++ 1 file changed, 51 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 3e6a602..ea0628b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1131,6 +1131,56 @@ static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_st return DC_OK; } +static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *context) +{ + int i, j; + bool video_down_scaled = false; + bool video_large = false; + bool desktop_large = false; + bool dcc_disabled = false; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 2) + return false; + + for (j = 0; j < context->stream_status[i].plane_count; j++) { + struct dc_plane_state *plane = + context->stream_status[i].plane_states[j]; + + + if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + + if (plane->src_rect.width > plane->dst_rect.width || + plane->src_rect.height > plane->dst_rect.height) + video_down_scaled = true; + + if (plane->src_rect.width >= 3840) + video_large = true; + + } else { + if (plane->src_rect.width >= 3840) + desktop_large = true; + if (!plane->dcc.enable) + dcc_disabled = true; + } + } + } + + /* +* Workaround: On DCN10 there is UMC issue that causes underflow when +* playing 4k video on 4k desktop with video downscaled and single channel +* memory +*/ + if (video_large && desktop_large && video_down_scaled && dcc_disabled && + dc->dcn_soc->number_of_channels == 1) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + static enum dc_status dcn10_get_default_swizzle_mode(struct dc_plane_state *plane_state) { enum dc_status result = DC_OK; @@ -1159,6 +1209,7 @@ static const struct resource_funcs dcn10_res_pool_funcs = { .validate_bandwidth = dcn_validate_bandwidth, .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, .validate_plane = dcn10_validate_plane, + .validate_global = dcn10_validate_global, .add_stream_to_ctx = dcn10_add_stream_to_ctx, .get_default_swizzle_mode = dcn10_get_default_swizzle_mode }; -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 13/25] drm/amd/display: Shift dc link aux to aux_payload
From: David Francis [Why] aux_payload should be the struct used inside dc to start aux transactions. This will allow the old aux interface to be seamlessly replaced. [How] Add three fields to aux_payload: reply, mot, defer_delay This will mean that aux_payload has all data required to submit a request. Shift dc_link to use this struct Signed-off-by: David Francis Reviewed-by: Harry Wentland Acked-by: Leo Li --- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c| 84 -- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 57 ++- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 3 +- drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 11 ++- .../gpu/drm/amd/display/include/i2caux_interface.h | 10 +++ 5 files changed, 70 insertions(+), 95 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 1b0d209..b400963 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -35,6 +35,8 @@ #include "dc_link_ddc.h" +#include "i2caux_interface.h" + /* #define TRACE_DPCD */ #ifdef TRACE_DPCD @@ -81,80 +83,24 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { ssize_t result = 0; - enum i2caux_transaction_action action; - enum aux_transaction_type type; + struct aux_payload payload; if (WARN_ON(msg->size > 16)) return -E2BIG; - switch (msg->request & ~DP_AUX_I2C_MOT) { - case DP_AUX_NATIVE_READ: - type = AUX_TRANSACTION_TYPE_DP; - action = I2CAUX_TRANSACTION_ACTION_DP_READ; - - result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, - msg->address, - >reply, - msg->buffer, - msg->size, - type, - action); - break; - case DP_AUX_NATIVE_WRITE: - type = AUX_TRANSACTION_TYPE_DP; - action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; - - dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, -msg->address, ->reply, -msg->buffer, -msg->size, -type, -action); - result = msg->size; - break; - case DP_AUX_I2C_READ: - type = AUX_TRANSACTION_TYPE_I2C; - if (msg->request & DP_AUX_I2C_MOT) - action = I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; - else - action = I2CAUX_TRANSACTION_ACTION_I2C_READ; - - result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, - msg->address, - >reply, - msg->buffer, - msg->size, - type, - action); - break; - case DP_AUX_I2C_WRITE: - type = AUX_TRANSACTION_TYPE_I2C; - if (msg->request & DP_AUX_I2C_MOT) - action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; - else - action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE; - - dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, -msg->address, ->reply, -msg->buffer, -msg->size, -type, -action); - result = msg->size; - break; - default: - return -EINVAL; - } + payload.address = msg->address; + payload.data = msg->buffer; + payload.length = msg->size; + payload.reply = >reply; + payload.i2c_over_aux = (msg->request & DP_AUX_NATIVE_WRITE) == 0; + payload.write = (msg->request & DP_AUX_I2C_READ) == 0; + payload.mot = (msg->request & DP_AUX_I2C_MOT) != 0; + payload.defer_delay = 0; -#ifdef TRACE_DPCD - log_dpcd(msg->request, -msg->address, -msg->buffer, -msg->size, -r == DDC_RESULT_SUCESSFULL); -#endif + result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, ); + + if (payload.write) + result = msg->size; if
[PATCH 15/25] drm/amd/display: Change from aux_engine to dce_aux
From: David Francis [Why] The aux_engine struct is needlessly complex and is defined multiple times. It contains function pointers that each have only one version and are called only from inside dce_aux. [How] Replace aux_engine with a new struct called dce_aux. Remove all function pointers and call functions directly. Remove unused functions Signed-off-by: David Francis Reviewed-by: Harry Wentland Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 557 + drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 20 +- .../drm/amd/display/dc/dce100/dce100_resource.c| 2 +- .../drm/amd/display/dc/dce110/dce110_resource.c| 2 +- .../drm/amd/display/dc/dce112/dce112_resource.c| 2 +- .../drm/amd/display/dc/dce120/dce120_resource.c| 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h| 2 +- 9 files changed, 45 insertions(+), 548 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 5660615..adbb222 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -42,17 +42,17 @@ container_of((ptr), struct aux_engine_dce110, base) #define FROM_ENGINE(ptr) \ - FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) + FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base)) #define FROM_AUX_ENGINE_ENGINE(ptr) \ - container_of((ptr), struct aux_engine, base) + container_of((ptr), struct dce_aux, base) enum { AUX_INVALID_REPLY_RETRY_COUNTER = 1, AUX_TIMED_OUT_RETRY_COUNTER = 2, AUX_DEFER_RETRY_COUNTER = 6 }; static void release_engine( - struct aux_engine *engine) + struct dce_aux *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -67,7 +67,7 @@ static void release_engine( #define DMCU_CAN_ACCESS_AUX 2 static bool is_engine_available( - struct aux_engine *engine) + struct dce_aux *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -80,7 +80,7 @@ static bool is_engine_available( return (field != DMCU_CAN_ACCESS_AUX); } static bool acquire_engine( - struct aux_engine *engine) + struct dce_aux *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -156,7 +156,7 @@ static bool acquire_engine( (0xFF & (address)) static void submit_channel_request( - struct aux_engine *engine, + struct dce_aux *engine, struct aux_request_transaction_data *request) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -248,7 +248,7 @@ static void submit_channel_request( REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); } -static int read_channel_reply(struct aux_engine *engine, uint32_t size, +static int read_channel_reply(struct dce_aux *engine, uint32_t size, uint8_t *buffer, uint8_t *reply_result, uint32_t *sw_status) { @@ -301,61 +301,8 @@ static int read_channel_reply(struct aux_engine *engine, uint32_t size, return 0; } -static void process_channel_reply( - struct aux_engine *engine, - struct aux_reply_transaction_data *reply) -{ - int bytes_replied; - uint8_t reply_result; - uint32_t sw_status; - - bytes_replied = read_channel_reply(engine, reply->length, reply->data, - _result, _status); - - /* in case HPD is LOW, exit AUX transaction */ - if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { - reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON; - return; - } - - if (bytes_replied < 0) { - /* Need to handle an error case... -* Hopefully, upper layer function won't call this function if -* the number of bytes in the reply was 0, because there was -* surely an error that was asserted that should have been -* handled for hot plug case, this could happens -*/ - if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { - reply->status = AUX_TRANSACTION_REPLY_INVALID; - ASSERT_CRITICAL(false); - return; - } - } else { - - switch (reply_result) { - case 0: /* ACK */ - reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; - break; - case 1: /* NACK */ - reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; - break; - case 2: /* DEFER */ - reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER; - break; -
[PATCH 24/25] drm/amd/display: Check for NULL when creating gamma struct
From: Krunoslav Kovac [Wjy] Some stress test is causing unexpected memory allocation failure. This prevents null dereference but there will likely be problems later, hard to gracefully handle memalloc fail for critical objects. Signed-off-by: Krunoslav Kovac Reviewed-by: Anthony Koo Acked-by: Leo Li Acked-by: Reza Amini --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index c60c9b4..ee6bd50 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -40,11 +40,14 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state plane_state->ctx = ctx; plane_state->gamma_correction = dc_create_gamma(); - plane_state->gamma_correction->is_identity = true; + if (plane_state->gamma_correction != NULL) + plane_state->gamma_correction->is_identity = true; plane_state->in_transfer_func = dc_create_transfer_func(); - plane_state->in_transfer_func->type = TF_TYPE_BYPASS; - plane_state->in_transfer_func->ctx = ctx; + if (plane_state->in_transfer_func != NULL) { + plane_state->in_transfer_func->type = TF_TYPE_BYPASS; + plane_state->in_transfer_func->ctx = ctx; + } } static void destruct(struct dc_plane_state *plane_state) -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 03/25] drm/amd/display: Pack DMCU iRAM alignment
From: Josip Pavic [Why] When the DMCU's iRAM definition was moved to the newly created power_helpers, a #pragma pack was lost, causing the iRAM to be misaligned [How] Restore the #pragma pack Signed-off-by: Josip Pavic Reviewed-by: Anthony Koo Acked-by: Leo Li --- drivers/gpu/drm/amd/display/modules/power/power_helpers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index 00f63b7..c11a443 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -57,6 +57,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le #define NUM_POWER_FN_SEGS 8 #define NUM_BL_CURVE_SEGS 16 +#pragma pack(push, 1) /* NOTE: iRAM is 256B in size */ struct iram_table_v_2 { /* flags */ @@ -100,6 +101,7 @@ struct iram_table_v_2 { uint8_t dummy8; /* 0xfe */ uint8_t dummy9; /* 0xff */ }; +#pragma pack(pop) static uint16_t backlight_8_to_16(unsigned int backlight_8bit) { -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 14/25] drm/amd/display: Switch ddc to new aux interface
From: David Francis [Why] The old aux interface goes through i2caux and the aux_engine and engine function pointers. The multiple layers of indirection make it hard to tell waht is happening. The aux algorithm does not need to be this complicated: attempt to submit the request. If you get an ack (reply = 0), stop. Otherwise, retry, up to 7 times. [How] Add a new helper function in dce_aux that performs aux retries Move the plumbing of the aux calling code into dce_aux Add functions in ddc that redirect directly to dce_aux Make all aux calls use these functions Signed-off-by: David Francis Reviewed-by: Harry Wentland Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 175 -- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 99 drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 6 + drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 12 +- 4 files changed, 137 insertions(+), 155 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 5ac6573..a343b8b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -34,6 +34,7 @@ #include "core_types.h" #include "dc_link_ddc.h" #include "aux_engine.h" +#include "dce/dce_aux.h" #define AUX_POWER_UP_WA_DELAY 500 #define I2C_OVER_AUX_DEFER_WA_DELAY 70 @@ -164,43 +165,6 @@ static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) } -static struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) -{ - struct aux_payloads *payloads; - - payloads = kzalloc(sizeof(struct aux_payloads), GFP_KERNEL); - - if (!payloads) - return NULL; - - if (dal_vector_construct( - >payloads, ctx, count, sizeof(struct aux_payload))) - return payloads; - - kfree(payloads); - return NULL; -} - -static struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) -{ - return (struct aux_payload *)p->payloads.container; -} - -static uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) -{ - return p->payloads.count; -} - -static void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) -{ - if (!p || !*p) - return; - - dal_vector_destruct(&(*p)->payloads); - kfree(*p); - *p = NULL; -} - #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) void dal_ddc_i2c_payloads_add( @@ -224,32 +188,6 @@ void dal_ddc_i2c_payloads_add( } -void dal_ddc_aux_payloads_add( - struct aux_payloads *payloads, - uint32_t address, - uint32_t len, - uint8_t *data, - bool write, - bool mot, - uint32_t defer_delay) -{ - uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE; - uint32_t pos; - - for (pos = 0; pos < len; pos += payload_size) { - struct aux_payload payload = { - .i2c_over_aux = true, - .write = write, - .address = address, - .length = DDC_MIN(payload_size, len - pos), - .data = data + pos, - .reply = NULL, - .mot = mot, - .defer_delay = defer_delay}; - dal_vector_append(>payloads, ); - } -} - static void construct( struct ddc_service *ddc_service, struct ddc_service_init_data *init_data) @@ -578,32 +516,34 @@ bool dal_ddc_service_query_ddc_data( /*TODO: len of payload data for i2c and aux is uint8, * but we want to read 256 over i2c*/ if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { - - struct aux_payloads *payloads = - dal_ddc_aux_payloads_create(ddc->ctx, payloads_num); - - struct aux_command command = { - .payloads = dal_ddc_aux_payloads_get(payloads), - .number_of_payloads = 0, + struct aux_payload write_payload = { + .i2c_over_aux = true, + .write = true, + .mot = true, + .address = address, + .length = write_size, + .data = write_buf, + .reply = NULL, .defer_delay = get_defer_delay(ddc), - .max_defer_write_retry = 0 }; + }; - dal_ddc_aux_payloads_add( - payloads, address, write_size, write_buf, true, true, get_defer_delay(ddc)); - - dal_ddc_aux_payloads_add( - payloads, address, read_size, read_buf, false, false, get_defer_delay(ddc)); - - command.number_of_payloads = - dal_ddc_aux_payloads_get_count(payloads); + struct
[PATCH 12/25] drm/amd/display: 3.2.13
From: Steven Chiu Signed-off-by: Steven Chiu Reviewed-by: Yongqiang Sun Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1c46249..98f716be 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.12" +#define DC_VER "3.2.13" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 00/25] DC Patches Jan 08, 2019
From: Leo Li Summary of change: * AUX interface cleanup and refactor * Fix potential warning storm on Raven * Fix vanishing cursor bug on Raven Bayan Zabihiyan (1): drm/amd/display: Add new infopacket definition Charlene Liu (2): drm/amd/display: fix PME notification not working in RV desktop drm/amd/display: dp interlace MSA timing programming for Interlace mode. David Francis (4): drm/amd/display: Shift dc link aux to aux_payload drm/amd/display: Switch ddc to new aux interface drm/amd/display: Change from aux_engine to dce_aux drm/amd/display: Remove i2caux folder Derek Lai (1): drm/amd/display: Set link rate set if eDP ver >= 1.4. Dmytro Laktyushkin (1): drm/amd/display: Rename configure_encoder to enc1_configure_encoder Eric Bernstein (1): drm/amd/display: Check if registers are available before accessing Eric Yang (1): drm/amd/display: add workaround for 4k video underflow Joshua Aberback (2): drm/amd/display: Fix missing hwss function for dce drm/amd/display: Fix for NULL ramp pointer crashing driver Josip Pavic (1): drm/amd/display: Pack DMCU iRAM alignment Krunoslav Kovac (1): drm/amd/display: Check for NULL when creating gamma struct Leo Li (1): Revert "drm/amd/display: Signal hw_done() after waiting for flip_done()" Martin Tsai (1): drm/amd/display: Redefine DMCU_SCRATCH to identify DMCU state Nicholas Kazlauskas (1): drm/amd/display: Fix disabled cursor on top screen edge Roman Li (1): drm/amd/display: fix warning on raven hotplug Steven Chiu (3): drm/amd/display: 3.2.12 drm/amd/display: 3.2.13 drm/amd/display: 3.2.14 Tony Cheng (1): drm/amd/display: refactor reg_update abdoulaye berthe (1): drm/amd/display: fix CTS 4.2.2.8 hersen wu (1): drm/amd/display: dal-pplib interface refactor dal part drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c| 84 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 57 ++ drivers/gpu/drm/amd/display/dc/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 161 +--- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 111 ++- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 9 +- drivers/gpu/drm/amd/display/dc/dc.h| 3 +- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 13 +- drivers/gpu/drm/amd/display/dc/dc_helper.c | 36 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 - drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 647 +++ drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 30 +- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 123 +-- .../drm/amd/display/dc/dce/dce_stream_encoder.c| 65 +- .../drm/amd/display/dc/dce100/dce100_resource.c| 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c| 30 +- .../drm/amd/display/dc/dce110/dce110_resource.c| 2 +- .../drm/amd/display/dc/dce112/dce112_resource.c| 2 +- .../drm/amd/display/dc/dce120/dce120_resource.c| 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 42 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 19 +- .../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 6 +- .../drm/amd/display/dc/dcn10/dcn10_link_encoder.h | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 55 +- .../amd/display/dc/dcn10/dcn10_stream_encoder.c| 68 +- drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c | 606 -- drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h | 86 -- .../amd/display/dc/i2caux/dce100/i2caux_dce100.c | 106 --- .../amd/display/dc/i2caux/dce100/i2caux_dce100.h | 32 - .../display/dc/i2caux/dce110/aux_engine_dce110.c | 505 .../display/dc/i2caux/dce110/aux_engine_dce110.h | 78 -- .../dc/i2caux/dce110/i2c_hw_engine_dce110.h| 218 - .../dc/i2caux/dce110/i2c_sw_engine_dce110.c| 160 .../dc/i2caux/dce110/i2c_sw_engine_dce110.h| 43 - .../amd/display/dc/i2caux/dce110/i2caux_dce110.c | 329 .../amd/display/dc/i2caux/dce110/i2caux_dce110.h | 54 -- .../amd/display/dc/i2caux/dce120/i2caux_dce120.c | 120 --- .../amd/display/dc/i2caux/dce120/i2caux_dce120.h | 32 - .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.c | 875 - .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.h | 54 -- .../display/dc/i2caux/dce80/i2c_sw_engine_dce80.h | 43 - .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c | 284 --- .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h | 38 - .../drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c | 120 --- .../drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h | 32 - .../display/dc/i2caux/diagnostics/i2caux_diag.c| 97 ---
[PATCH 18/25] drm/amd/display: fix warning on raven hotplug
From: Roman Li [Why] Hotplug on raven results in REG_WAIT_TIMEOUT warning due to failing attempt to lock disabled otg for the hubp interdependent pipes programming. [How] Don't setup pipe interdependencies for disabled otg. Also removed the unnecessary duplicate logic checks. Signed-off-by: Roman Li Reviewed-by: Dmytro Laktyushkin Acked-by: Leo Li --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 19 ++- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 93226fc..814f597 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2354,29 +2354,22 @@ static void dcn10_apply_ctx_for_surface( top_pipe_to_program->plane_state->update_flags.bits.full_update) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = >res_ctx.pipe_ctx[i]; - + tg = pipe_ctx->stream_res.tg; /* Skip inactive pipes and ones already updated */ if (!pipe_ctx->stream || pipe_ctx->stream == stream - || !pipe_ctx->plane_state) + || !pipe_ctx->plane_state + || !tg->funcs->is_tg_enabled(tg)) continue; - pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); + tg->funcs->lock(tg); pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent( pipe_ctx->plane_res.hubp, _ctx->dlg_regs, _ctx->ttu_regs); - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = >res_ctx.pipe_ctx[i]; - if (!pipe_ctx->stream || pipe_ctx->stream == stream - || !pipe_ctx->plane_state) - continue; - - dcn10_pipe_control_lock(dc, pipe_ctx, false); - } + tg->funcs->unlock(tg); + } if (num_planes == 0) false_optc_underflow_wa(dc, stream, tg); -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 22/25] drm/amd/display: Add new infopacket definition
From: Bayan Zabihiyan Modify freesync module to build VTEM infopackets when in HdmiVRR mode Signed-off-by: Bayan Zabihiyan Reviewed-by: Jun Lei Acked-by: Leo Li --- .../drm/amd/display/modules/freesync/freesync.c| 94 -- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 2 +- .../gpu/drm/amd/display/modules/inc/mod_shared.h | 3 +- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index d967ac0..94a84bc 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -461,6 +461,26 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, return false; } +static void build_vrr_infopacket_header_vtem(enum signal_type signal, + struct dc_info_packet *infopacket) +{ + // HEADER + + // HB0, HB1, HB2 indicates PacketType VTEMPacket + infopacket->hb0 = 0x7F; + infopacket->hb1 = 0xC0; + infopacket->hb2 = 0x00; + /* HB3 Bit Fields +* Reserved :1 = 0 +* Sync :1 = 0 +* VFR :1 = 1 +* Ds_Type :2 = 0 +* End :1 = 0 +* New :1 = 0 +*/ + infopacket->hb3 = 0x20; +} + static void build_vrr_infopacket_header_v1(enum signal_type signal, struct dc_info_packet *infopacket, unsigned int *payload_size) @@ -559,6 +579,54 @@ static void build_vrr_infopacket_header_v2(enum signal_type signal, } } +static void build_vrr_vtem_infopacket_data(const struct dc_stream_state *stream, + const struct mod_vrr_params *vrr, + struct dc_info_packet *infopacket) +{ + /* dc_info_packet to VtemPacket Translation of Bit-fields, +* SB[6] +* unsigned char VRR_EN:1 +* unsigned char M_CONST :1 +* unsigned char Reserved2 :2 +* unsigned char FVA_Factor_M1 :4 +* SB[7] +* unsigned char Base_Vfront :8 +* SB[8] +* unsigned char Base_Refresh_Rate_98 :2 +* unsigned char RB :1 +* unsigned char Reserved3:5 +* SB[9] +* unsigned char Base_RefreshRate_07 :8 +*/ + unsigned int fieldRateInHz; + + if (vrr->state == VRR_STATE_ACTIVE_VARIABLE || + vrr->state == VRR_STATE_ACTIVE_FIXED){ + infopacket->sb[6] |= 0x80; //VRR_EN Bit = 1 + } else { + infopacket->sb[6] &= 0x7F; //VRR_EN Bit = 0 + } + + if (!stream->timing.vic) { + infopacket->sb[7] = stream->timing.v_front_porch; + + /* TODO: In dal2, we check mode flags for a reduced blanking timing. +* Need a way to relay that information to this function. +* if("ReducedBlanking") +* { +* infopacket->sb[8] |= 0x20; //Set 3rd bit to 1 +* } +*/ + fieldRateInHz = (stream->timing.pix_clk_100hz * 100)/ + (stream->timing.h_total * stream->timing.v_total); + + infopacket->sb[8] |= ((fieldRateInHz & 0x300) >> 2); + infopacket->sb[9] |= fieldRateInHz & 0xFF; + + } + infopacket->valid = true; +} + static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr, struct dc_info_packet *infopacket) { @@ -672,6 +740,19 @@ static void build_vrr_infopacket_v2(enum signal_type signal, infopacket->valid = true; } +static void build_vrr_infopacket_vtem(const struct dc_stream_state *stream, + const struct mod_vrr_params *vrr, + struct dc_info_packet *infopacket) +{ + //VTEM info packet for HdmiVrr + + //VTEM Packet is structured differently + build_vrr_infopacket_header_vtem(stream->signal, infopacket); + build_vrr_vtem_infopacket_data(stream, vrr, infopacket); + + infopacket->valid = true; +} + void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, const struct dc_stream_state *stream, const struct mod_vrr_params *vrr, @@ -679,18 +760,21 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, const enum color_transfer_func *app_tf, struct dc_info_packet *infopacket) { - /* SPD info packet for FreeSync */ - - /* Check if Freesync is supported. Return if false. If true, + /* SPD info packet for FreeSync +* VTEM info packet for HdmiVRR +* Check if Freesync is supported. Return if false. If true, * set the corresponding bit in the info packet */ - if (!vrr->supported || !vrr->send_vsif) + if (!vrr->supported || (!vrr->send_info_frame && packet_type != PACKET_TYPE_VTEM))
[PATCH 02/25] drm/amd/display: Fix missing hwss function for dce
From: Joshua Aberback [Why] The driver will crash on dce hardware due to a null function pointer. [How] - bring back "program_csc_matrix" functionality as "program_output_csc" for dce110 - dce110 doesn't use the "opp_id" parameter, so use 0 when there's no hubp Signed-off-by: Joshua Aberback Reviewed-by: Anthony Koo Acked-by: Jun Lei Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c| 23 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index af907d5..c94bc40 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -451,7 +451,7 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) pipes, stream->output_color_space, stream->csc_color_matrix.matrix, - pipes->plane_res.hubp->opp_id); + pipes->plane_res.hubp ? pipes->plane_res.hubp->opp_id : 0); ret = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8e961e6..602a41d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2616,6 +2616,28 @@ static void dce110_wait_for_mpcc_disconnect( /* do nothing*/ } +static void program_output_csc(struct dc *dc, + struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix, + int opp_id) +{ + int i; + struct out_csc_color_matrix tbl_entry; + + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { + enum dc_color_space color_space = pipe_ctx->stream->output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; + + tbl_entry.color_space = color_space; + + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment( + pipe_ctx->plane_res.xfm, _entry); + } +} + void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) { struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; @@ -2666,6 +2688,7 @@ void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, + .program_output_csc = program_output_csc, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 17/25] drm/amd/display: dal-pplib interface refactor dal part
From: hersen wu [WHY] clarify dal input parameters to pplib interface, remove un-used parameters. dal knows exactly which parameters needed and their effects at pplib and smu sides. current dal sequence for dcn1_update_clock to pplib: 1.smu10_display_clock_voltage_request for dcefclk 2.smu10_display_clock_voltage_request for fclk 3.phm_store_dal_configuration_data { set_min_deep_sleep_dcfclk set_active_display_count store_cc6_data --- this data never be referenced new sequence will be: 1. set_display_count --- need add new pplib interface 2. set_min_deep_sleep_dcfclk -- new pplib interface 3. set_hard_min_dcfclk_by_freq 4. set_hard_min_fclk_by_freq after this code refactor, smu10_display_clock_voltage_request, phm_store_dal_configuration_data will not be needed for rv. Signed-off-by: hersen wu Reviewed-by: Harry Wentland Acked-by: Leo Li --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 57 ++ 1 file changed, 57 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index 9d2d698..e8e9eeb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -559,6 +559,58 @@ void pp_rv_set_pme_wa_enable(struct pp_smu *pp) pp_funcs->notify_smu_enable_pwe(pp_handle); } +void pp_rv_set_active_display_count(struct pp_smu *pp, int count) +{ + const struct dc_context *ctx = pp->dm; + struct amdgpu_device *adev = ctx->driver_context; + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs || !pp_funcs->set_active_display_count) + return; + + pp_funcs->set_active_display_count(pp_handle, count); +} + +void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock) +{ + const struct dc_context *ctx = pp->dm; + struct amdgpu_device *adev = ctx->driver_context; + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk) + return; + + pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, clock); +} + +void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock) +{ + const struct dc_context *ctx = pp->dm; + struct amdgpu_device *adev = ctx->driver_context; + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs || !pp_funcs->set_hard_min_dcefclk_by_freq) + return; + + pp_funcs->set_hard_min_dcefclk_by_freq(pp_handle, clock); +} + +void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz) +{ + const struct dc_context *ctx = pp->dm; + struct amdgpu_device *adev = ctx->driver_context; + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs || !pp_funcs->set_hard_min_fclk_by_freq) + return; + + pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz); +} + void dm_pp_get_funcs_rv( struct dc_context *ctx, struct pp_smu_funcs_rv *funcs) @@ -567,4 +619,9 @@ void dm_pp_get_funcs_rv( funcs->set_display_requirement = pp_rv_set_display_requirement; funcs->set_wm_ranges = pp_rv_set_wm_ranges; funcs->set_pme_wa_enable = pp_rv_set_pme_wa_enable; + funcs->set_display_count = pp_rv_set_active_display_count; + funcs->set_min_deep_sleep_dcfclk = pp_rv_set_min_deep_sleep_dcfclk; + funcs->set_hard_min_dcfclk_by_freq = pp_rv_set_hard_min_dcefclk_by_freq; + funcs->set_hard_min_fclk_by_freq = pp_rv_set_hard_min_fclk_by_freq; } + -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 11/25] drm/amd/display: Fix disabled cursor on top screen edge
From: Nicholas Kazlauskas [Why] The cursor vanishes when touching the top of edge of the screen for Raven on Linux. This occurs because the cursor height is not taken into account when deciding to disable the cursor. [How] Factor in the cursor height into the cursor calculations - and mimic the existing x position calculations. Fixes: 94a4ffd1d40b ("drm/amd/display: fix PIP bugs on Dal3") Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index dcb3c55..cd1ebe5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -463,7 +463,7 @@ void dpp1_set_cursor_position( if (src_y_offset >= (int)param->viewport.height) cur_en = 0; /* not visible beyond bottom edge*/ - if (src_y_offset < 0) + if (src_y_offset + (int)height <= 0) cur_en = 0; /* not visible beyond top edge*/ REG_UPDATE(CURSOR0_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index e24ea61..fae6247 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -1140,7 +1140,7 @@ void hubp1_cursor_set_position( if (src_y_offset >= (int)param->viewport.height) cur_en = 0; /* not visible beyond bottom edge*/ - if (src_y_offset < 0) //+ (int)hubp->curs_attr.height + if (src_y_offset + (int)hubp->curs_attr.height <= 0) cur_en = 0; /* not visible beyond top edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 09/25] drm/amd/display: Fix for NULL ramp pointer crashing driver
From: Joshua Aberback [Why] In certain scenarios the ramp parameter come in as NULL, which crashes because this function doesn't guard properly in the early return. [How] - parameter mapUserRamp should be the guard (false means no ramp) - remove checking ramp in early return Signed-off-by: Joshua Aberback Reviewed-by: Sivapiriyan Kumarasamy Acked-by: Eryk Brol Acked-by: Leo Li --- drivers/gpu/drm/amd/display/modules/color/color_gamma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index beb7bda..4cee084 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -1772,8 +1772,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, /* we can use hardcoded curve for plain SRGB TF */ if (input_tf->type == TF_TYPE_PREDEFINED && input_tf->tf == TRANSFER_FUNCTION_SRGB && - (!mapUserRamp && - (ramp->type == GAMMA_RGB_256 || ramp->num_entries == 0))) + !mapUserRamp) return true; input_tf->type = TF_TYPE_DISTRIBUTED_POINTS; -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 08/25] drm/amd/display: Redefine DMCU_SCRATCH to identify DMCU state
From: Martin Tsai [why] To resume system before entering S0i3 completely will cause PSP not reload DMCU FW since there is not HW power state change. In this case, driver cannot get correct DMCU version from IRAM since driver override it and DMCU didn't reload to update it. It makes driver return false in dcn10_dmcu_init(). [how] 1.To redefine DMCU_SCRATCH to identify different DMCU state. 2.To reserve IRAM 0xF0~0xFF write by DMCU only. 3.To remove dcn10_get_dmcu_state Signed-off-by: Martin Tsai Reviewed-by: Anthony Koo Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 123 +++-- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 10 +- .../drm/amd/display/modules/power/power_helpers.c | 3 +- 3 files changed, 52 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index dea40b3..e927c89 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -51,7 +51,6 @@ #define PSR_SET_WAITLOOP 0x31 #define MCP_INIT_DMCU 0x88 #define MCP_INIT_IRAM 0x89 -#define MCP_DMCU_VERSION 0x90 #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x0001L static bool dce_dmcu_init(struct dmcu *dmcu) @@ -317,38 +316,11 @@ static void dce_get_psr_wait_loop( } #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -static void dcn10_get_dmcu_state(struct dmcu *dmcu) -{ - struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); - uint32_t dmcu_state_offset = 0xf6; - - /* Enable write access to IRAM */ - REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, - IRAM_HOST_ACCESS_EN, 1, - IRAM_RD_ADDR_AUTO_INC, 1); - - REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); - - /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ - REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_state_offset); - - /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ - dmcu->dmcu_state = REG_READ(DMCU_IRAM_RD_DATA); - - /* Disable write access to IRAM to allow dynamic sleep state */ - REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, - IRAM_HOST_ACCESS_EN, 0, - IRAM_RD_ADDR_AUTO_INC, 0); -} - static void dcn10_get_dmcu_version(struct dmcu *dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); uint32_t dmcu_version_offset = 0xf1; - /* Clear scratch */ - REG_WRITE(DC_DMCU_SCRATCH, 0); - /* Enable write access to IRAM */ REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1, @@ -368,76 +340,65 @@ static void dcn10_get_dmcu_version(struct dmcu *dmcu) REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0, IRAM_RD_ADDR_AUTO_INC, 0); - - /* Send MCP command message to DMCU to get version reply from FW. -* We expect this version should match the one in IRAM, otherwise -* something is wrong with DMCU and we should fail and disable UC. -*/ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); - - /* Set command to get DMCU version from microcontroller */ - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, - MCP_DMCU_VERSION); - - /* Notify microcontroller of new command */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - /* Ensure command has been executed before continuing */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); - - /* Somehow version does not match, so fail and return version 0 */ - if (dmcu->dmcu_version.interface_version != REG_READ(DC_DMCU_SCRATCH)) - dmcu->dmcu_version.interface_version = 0; } static bool dcn10_dmcu_init(struct dmcu *dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + bool status = false; - /* DMCU FW should populate the scratch register if running */ - if (REG_READ(DC_DMCU_SCRATCH) == 0) - return false; - - /* Check state is uninitialized */ - dcn10_get_dmcu_state(dmcu); - - /* If microcontroller is already initialized, do nothing */ - if (dmcu->dmcu_state == DMCU_RUNNING) - return true; - - /* Retrieve and cache the DMCU firmware version. */ - dcn10_get_dmcu_version(dmcu); - - /* Check interface version to confirm firmware is loaded and running */ - if (dmcu->dmcu_version.interface_version == 0) - return false; + /* Definition of DC_DMCU_SCRATCH +* 0 : firmare not loaded +* 1 : PSP load DMCU FW but not initialized +* 2 : Firmware already initialized +*/ + dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH); - /* Wait until microcontroller is ready to process interrupt */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100,
[PATCH 04/25] drm/amd/display: fix CTS 4.2.2.8
From: abdoulaye berthe [Why] 1-Test equipment does not reset test automation flag after completing current test causing the next test to fail. 2.When test request is empty, we shouldn't ack the test. [How] 1-Driver should always clear test equipment automation test request when request is completed. 2-Driver should clear test equipement test automation if driver does not complete the request. Signed-off-by: abdoulaye berthe Reviewed-by: Wenjing Liu Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 568fdc9..cf93627 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2002,11 +2002,7 @@ static void handle_automated_test(struct dc_link *link) dp_test_send_phy_test_pattern(link); test_response.bits.ACK = 1; } - if (!test_request.raw) - /* no requests, revert all test signals -* TODO: revert all test signals -*/ - test_response.bits.ACK = 1; + /* send request acknowledgment */ if (test_response.bits.ACK) core_link_write_dpcd( -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 21/25] drm/amd/display: Rename configure_encoder to enc1_configure_encoder
From: Dmytro Laktyushkin Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index af0bcff..771449f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -440,7 +440,7 @@ static uint8_t get_frontend_source( } } -void configure_encoder( +void enc1_configure_encoder( struct dcn10_link_encoder *enc10, const struct dc_link_settings *link_settings) { @@ -910,7 +910,7 @@ void dcn10_link_encoder_enable_dp_output( * but it's not passed to asic_control. * We need to set number of lanes manually. */ - configure_encoder(enc10, link_settings); + enc1_configure_encoder(enc10, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; cntl.engine_id = enc->preferred_engine; @@ -949,7 +949,7 @@ void dcn10_link_encoder_enable_dp_mst_output( * but it's not passed to asic_control. * We need to set number of lanes manually. */ - configure_encoder(enc10, link_settings); + enc1_configure_encoder(enc10, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; cntl.engine_id = ENGINE_ID_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index 49ead12..670b46e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -271,7 +271,7 @@ void dcn10_link_encoder_setup( struct link_encoder *enc, enum signal_type signal); -void configure_encoder( +void enc1_configure_encoder( struct dcn10_link_encoder *enc10, const struct dc_link_settings *link_settings); -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 05/25] Revert "drm/amd/display: Signal hw_done() after waiting for flip_done()"
From: Leo Li This reverts commit 717276b9256f5d97b43e53adca1670cee2c45db2. The reverted patch was a workaround that addressed an issue fixed by: 4364bcb2cd21 ("drm: Get ref on CRTC commit object when waiting for flip_done") Signed-off-by: Leo Li Reviewed-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 70cd8bc..3ede2d1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5346,18 +5346,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) } spin_unlock_irqrestore(>ddev->event_lock, flags); + /* Signal HW programming completion */ + drm_atomic_helper_commit_hw_done(state); if (wait_for_vblank) drm_atomic_helper_wait_for_flip_done(dev, state); - /* -* FIXME: -* Delay hw_done() until flip_done() is signaled. This is to block -* another commit from freeing the CRTC state while we're still -* waiting on flip_done. -*/ - drm_atomic_helper_commit_hw_done(state); - drm_atomic_helper_cleanup_planes(dev, state); /* -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 07/25] drm/amd/display: fix PME notification not working in RV desktop
From: Charlene Liu [Why] PPLIB not receive the PME when unplug. Signed-off-by: Charlene Liu Reviewed-by: Chris Park Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 602a41d..144a1c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -997,7 +997,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); - if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) + if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ pp_smu->set_pme_wa_enable(_smu->pp_smu); /* un-mute audio */ @@ -1014,6 +1014,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, true); if (pipe_ctx->stream_res.audio) { + struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; + if (option != KEEP_ACQUIRED_RESOURCE || !dc->debug.az_endpoint_mute_only) { /*only disalbe az_endpoint if power down or free*/ @@ -1033,6 +1035,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) update_audio_usage(>current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); pipe_ctx->stream_res.audio = NULL; } + if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) + /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ + pp_smu->set_pme_wa_enable(_smu->pp_smu); /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 10/25] drm/amd/display: Set link rate set if eDP ver >= 1.4.
From: Derek Lai [Why] If eDP ver >= 1.4, the Source device must use LINK_RATE_SET. [How] Get LINK_RATE_SET by reading DPCD 10h-1fh, then write DPCD 00115h before link training. Signed-off-by: Derek Lai Reviewed-by: Tony Cheng Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 105 ++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 13 +-- 3 files changed, 111 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index cf93627..431805c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -117,6 +117,13 @@ static void dpcd_set_link_settings( core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, , sizeof(downspread)); + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 && + (link->dpcd_caps.link_rate_set >= 1 && + link->dpcd_caps.link_rate_set <= 8)) { + core_link_write_dpcd(link, DP_LINK_RATE_SET, + >dpcd_caps.link_rate_set, 1); + } + DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n", __func__, DP_LINK_BW_SET, @@ -2489,13 +2496,105 @@ bool detect_dp_sink_caps(struct dc_link *link) /* TODO save sink caps in link->sink */ } +enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz) +{ + enum dc_link_rate link_rate; + // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation. + switch (link_rate_in_khz) { + case 162: + link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane + break; + case 216: + link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane + break; + case 243: + link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane + break; + case 270: + link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane + break; + case 324: + link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane + break; + case 432: + link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane + break; + case 540: + link_rate = LINK_RATE_HIGH2;// Rate_7 (HBR2)- 5.40 Gbps/Lane + break; + case 810: + link_rate = LINK_RATE_HIGH3;// Rate_8 (HBR3)- 8.10 Gbps/Lane + break; + default: + link_rate = LINK_RATE_UNKNOWN; + break; + } + return link_rate; +} + void detect_edp_sink_caps(struct dc_link *link) { - retrieve_link_cap(link); + uint8_t supported_link_rates[16] = {0}; + uint32_t entry; + uint32_t link_rate_in_khz; + enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; + uint8_t link_rate_set = 0; - if (link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN) - link->reported_link_cap.link_rate = LINK_RATE_HIGH2; + retrieve_link_cap(link); + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) { + // Read DPCD 00010h - 0001Fh 16 bytes at one shot + core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, + supported_link_rates, sizeof(supported_link_rates)); + + link->dpcd_caps.link_rate_set = 0; + for (entry = 0; entry < 16; entry += 2) { + // DPCD register reports per-lane link rate = 16-bit link rate capability + // value X 200 kHz. Need multipler to find link rate in kHz. + link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 + + supported_link_rates[entry]) * 200; + + if (link_rate_in_khz != 0) { + link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz); + if (link->reported_link_cap.link_rate < link_rate) { + link->reported_link_cap.link_rate = link_rate; + + switch (link_rate) { + case LINK_RATE_LOW: + link_rate_set = 1; + break; + case LINK_RATE_RATE_2: + link_rate_set = 2; + break; +
[PATCH 01/25] drm/amd/display: 3.2.12
From: Steven Chiu Signed-off-by: Steven Chiu Reviewed-by: Yongqiang Sun Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ee70540..f80f52e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.11" +#define DC_VER "3.2.12" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH 06/25] drm/amd/display: refactor reg_update
From: Tony Cheng [why] separate register access from logic to allow us abstract register sequences [how] consolidate mask and value first then apply to register. Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Leo Li --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 36 ++ 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 4842d23..597d383 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -29,31 +29,59 @@ #include "dm_services.h" #include +struct dc_reg_value_masks { + uint32_t value; + uint32_t mask; +}; + +struct dc_reg_sequence { + uint32_t addr; + struct dc_reg_value_masks value_masks; +}; + +static inline void set_reg_field_value_masks( + struct dc_reg_value_masks *field_value_mask, + uint32_t value, + uint32_t mask, + uint8_t shift) +{ + ASSERT(mask != 0); + + field_value_mask->value = (field_value_mask->value & ~mask) | (mask & (value << shift)); + field_value_mask->mask = field_value_mask->mask | mask; +} + uint32_t generic_reg_update_ex(const struct dc_context *ctx, uint32_t addr, uint32_t reg_val, int n, uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...) { + struct dc_reg_value_masks field_value_mask = {0}; uint32_t shift, mask, field_value; int i = 1; va_list ap; va_start(ap, field_value1); - reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1); + /* gather all bits value/mask getting updated in this register */ + set_reg_field_value_masks(_value_mask, + field_value1, mask1, shift1); while (i < n) { shift = va_arg(ap, uint32_t); mask = va_arg(ap, uint32_t); field_value = va_arg(ap, uint32_t); - reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift); + set_reg_field_value_masks(_value_mask, + field_value, mask, shift); i++; } - - dm_write_reg(ctx, addr, reg_val); va_end(ap); + + /* mmio write directly */ + reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value; + dm_write_reg(ctx, addr, reg_val); return reg_val; } -- 2.7.4 ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH] drm/amdgpu: Add sysfs file for PCIe usage v3
On Tue, Jan 8, 2019 at 6:28 AM Russell, Kent wrote: > > Add a sysfs file that reports the number of bytes transmitted and > received in the last second. This can be used to approximate the PCIe > bandwidth usage over the last second. > > v2: Clarify use of mps as estimation of bandwidth > v3: Don't make the file on APUs > > Signed-off-by: Kent Russell > --- > drivers/gpu/drm/amd/amdgpu/amdgpu.h| 4 > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 38 + > drivers/gpu/drm/amd/amdgpu/cik.c | 41 +++ > drivers/gpu/drm/amd/amdgpu/si.c| 41 +++ > drivers/gpu/drm/amd/amdgpu/soc15.c | 44 > ++ > drivers/gpu/drm/amd/amdgpu/vi.c| 41 +++ > 6 files changed, 209 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > index e1b2c64..512b124 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > @@ -542,6 +542,9 @@ struct amdgpu_asic_funcs { > bool (*need_full_reset)(struct amdgpu_device *adev); > /* initialize doorbell layout for specific asic*/ > void (*init_doorbell_index)(struct amdgpu_device *adev); > + /* PCIe bandwidth usage */ > + void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0, > + uint64_t *count1); > }; > > /* > @@ -1045,6 +1048,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); > #define amdgpu_asic_invalidate_hdp(adev, r) > (adev)->asic_funcs->invalidate_hdp((adev), (r)) > #define amdgpu_asic_need_full_reset(adev) > (adev)->asic_funcs->need_full_reset((adev)) > #define amdgpu_asic_init_doorbell_index(adev) > (adev)->asic_funcs->init_doorbell_index((adev)) > +#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) > ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1))) > > /* Common functions */ > bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > index 6896dec..d2b29fd 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > @@ -990,6 +990,33 @@ static ssize_t amdgpu_get_busy_percent(struct device > *dev, > return snprintf(buf, PAGE_SIZE, "%d\n", value); > } > > +/** > + * DOC: pcie_bw > + * > + * The amdgpu driver provides a sysfs API for reading how much data > + * has been sent and received by the GPU in the last second through PCIe. > + * The file pcie_bw is used for this. > + * The Perf counters calculate this and return the number of sent and > received > + * messages, which we multiply by the maxsize of our PCIe packets (mps). > + * Note that it is not possible to easily and quickly obtain the size of each > + * packet transmitted, so we use the max payload size (mps) to estimate the > + * PCIe bandwidth usage > + */ > +static ssize_t amdgpu_get_pcie_bw(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + uint64_t mps = pcie_get_mps(adev->pdev); > + uint64_t count0, count1; > + > + amdgpu_asic_get_pcie_usage(adev, , ); > + return snprintf(buf, PAGE_SIZE, > + "Bytes received: %llu\nBytes sent: %llu\n", > + count0 * mps, count1 * mps); > +} > + > static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, > amdgpu_set_dpm_state); > static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, >amdgpu_get_dpm_forced_performance_level, > @@ -1025,6 +1052,7 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, > amdgpu_set_pp_od_clk_voltage); > static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, > amdgpu_get_busy_percent, NULL); > +static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); > > static ssize_t amdgpu_hwmon_show_temp(struct device *dev, > struct device_attribute *attr, > @@ -2108,6 +2136,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) > "gpu_busy_level\n"); > return ret; > } > + /* PCIe Perf counters won't work on APU nodes */ > + if (adev->flags & !AMD_IS_APU) { > + ret = device_create_file(adev->dev, _attr_pcie_bw); > + if (ret) { > + DRM_ERROR("failed to create device file pcie_bw\n"); > + return ret; > + } > + } > ret = amdgpu_debugfs_pm_init(adev); > if (ret) { > DRM_ERROR("Failed to register debugfs file for dpm!\n"); > @@ -2147,6 +2183,8 @@ void amdgpu_pm_sysfs_fini(struct
Re: [PATCH] drm/amdgpu: Add sysfs file for PCIe usage v3
On Tue, Jan 8, 2019 at 11:02 AM Kuehling, Felix wrote: > > > On 2019-01-08 6:28 a.m., Russell, Kent wrote: > > Add a sysfs file that reports the number of bytes transmitted and > > received in the last second. This can be used to approximate the PCIe > > bandwidth usage over the last second. > > > > v2: Clarify use of mps as estimation of bandwidth > > I think you only updated the code comment, but not the output in sysfs. > > More generally, most amdgpu sysfs files report a single value, or a set > of values separated by spaces. That makes it easier to parse by external > tools. It's also supposed to be a stable API. They don't usually include > human readable text such as "bytes received:". It would be up to a tool > such as rocm-smi to turn this into human-readable text. > > In keeping with that convention I'd suggest reporting the PCIe bandwidth > as three numbers: > > > > Then let the tool calculate the bytes estimate with the appropriate > warnings about how accurate that is. > > Alex does this match your understanding regarding sysfs conventions? Yes, agreed. Alex > > Regards, > Felix > > > v3: Don't make the file on APUs > > > > Signed-off-by: Kent Russell > > --- > > drivers/gpu/drm/amd/amdgpu/amdgpu.h| 4 > > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 38 + > > drivers/gpu/drm/amd/amdgpu/cik.c | 41 +++ > > drivers/gpu/drm/amd/amdgpu/si.c| 41 +++ > > drivers/gpu/drm/amd/amdgpu/soc15.c | 44 > > ++ > > drivers/gpu/drm/amd/amdgpu/vi.c| 41 +++ > > 6 files changed, 209 insertions(+) > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > > index e1b2c64..512b124 100644 > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > > @@ -542,6 +542,9 @@ struct amdgpu_asic_funcs { > > bool (*need_full_reset)(struct amdgpu_device *adev); > > /* initialize doorbell layout for specific asic*/ > > void (*init_doorbell_index)(struct amdgpu_device *adev); > > + /* PCIe bandwidth usage */ > > + void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0, > > +uint64_t *count1); > > }; > > > > /* > > @@ -1045,6 +1048,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); > > #define amdgpu_asic_invalidate_hdp(adev, r) > > (adev)->asic_funcs->invalidate_hdp((adev), (r)) > > #define amdgpu_asic_need_full_reset(adev) > > (adev)->asic_funcs->need_full_reset((adev)) > > #define amdgpu_asic_init_doorbell_index(adev) > > (adev)->asic_funcs->init_doorbell_index((adev)) > > +#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) > > ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1))) > > > > /* Common functions */ > > bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > > index 6896dec..d2b29fd 100644 > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > > @@ -990,6 +990,33 @@ static ssize_t amdgpu_get_busy_percent(struct device > > *dev, > > return snprintf(buf, PAGE_SIZE, "%d\n", value); > > } > > > > +/** > > + * DOC: pcie_bw > > + * > > + * The amdgpu driver provides a sysfs API for reading how much data > > + * has been sent and received by the GPU in the last second through PCIe. > > + * The file pcie_bw is used for this. > > + * The Perf counters calculate this and return the number of sent and > > received > > + * messages, which we multiply by the maxsize of our PCIe packets (mps). > > + * Note that it is not possible to easily and quickly obtain the size of > > each > > + * packet transmitted, so we use the max payload size (mps) to estimate the > > + * PCIe bandwidth usage > > + */ > > +static ssize_t amdgpu_get_pcie_bw(struct device *dev, > > + struct device_attribute *attr, > > + char *buf) > > +{ > > + struct drm_device *ddev = dev_get_drvdata(dev); > > + struct amdgpu_device *adev = ddev->dev_private; > > + uint64_t mps = pcie_get_mps(adev->pdev); > > + uint64_t count0, count1; > > + > > + amdgpu_asic_get_pcie_usage(adev, , ); > > + return snprintf(buf, PAGE_SIZE, > > + "Bytes received: %llu\nBytes sent: %llu\n", > > + count0 * mps, count1 * mps); > > +} > > + > > static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, > > amdgpu_get_dpm_state, amdgpu_set_dpm_state); > > static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, > > amdgpu_get_dpm_forced_performance_level, > > @@ -1025,6 +1052,7 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | > > S_IWUSR, > > amdgpu_set_pp_od_clk_voltage); > > static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, > >
Re: [PATCH] drm/amdgpu: Add sysfs file for PCIe usage v3
On 2019-01-08 6:28 a.m., Russell, Kent wrote: > Add a sysfs file that reports the number of bytes transmitted and > received in the last second. This can be used to approximate the PCIe > bandwidth usage over the last second. > > v2: Clarify use of mps as estimation of bandwidth I think you only updated the code comment, but not the output in sysfs. More generally, most amdgpu sysfs files report a single value, or a set of values separated by spaces. That makes it easier to parse by external tools. It's also supposed to be a stable API. They don't usually include human readable text such as "bytes received:". It would be up to a tool such as rocm-smi to turn this into human-readable text. In keeping with that convention I'd suggest reporting the PCIe bandwidth as three numbers: Then let the tool calculate the bytes estimate with the appropriate warnings about how accurate that is. Alex does this match your understanding regarding sysfs conventions? Regards, Felix > v3: Don't make the file on APUs > > Signed-off-by: Kent Russell > --- > drivers/gpu/drm/amd/amdgpu/amdgpu.h| 4 > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 38 + > drivers/gpu/drm/amd/amdgpu/cik.c | 41 +++ > drivers/gpu/drm/amd/amdgpu/si.c| 41 +++ > drivers/gpu/drm/amd/amdgpu/soc15.c | 44 > ++ > drivers/gpu/drm/amd/amdgpu/vi.c| 41 +++ > 6 files changed, 209 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > index e1b2c64..512b124 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > @@ -542,6 +542,9 @@ struct amdgpu_asic_funcs { > bool (*need_full_reset)(struct amdgpu_device *adev); > /* initialize doorbell layout for specific asic*/ > void (*init_doorbell_index)(struct amdgpu_device *adev); > + /* PCIe bandwidth usage */ > + void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0, > +uint64_t *count1); > }; > > /* > @@ -1045,6 +1048,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); > #define amdgpu_asic_invalidate_hdp(adev, r) > (adev)->asic_funcs->invalidate_hdp((adev), (r)) > #define amdgpu_asic_need_full_reset(adev) > (adev)->asic_funcs->need_full_reset((adev)) > #define amdgpu_asic_init_doorbell_index(adev) > (adev)->asic_funcs->init_doorbell_index((adev)) > +#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) > ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1))) > > /* Common functions */ > bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > index 6896dec..d2b29fd 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > @@ -990,6 +990,33 @@ static ssize_t amdgpu_get_busy_percent(struct device > *dev, > return snprintf(buf, PAGE_SIZE, "%d\n", value); > } > > +/** > + * DOC: pcie_bw > + * > + * The amdgpu driver provides a sysfs API for reading how much data > + * has been sent and received by the GPU in the last second through PCIe. > + * The file pcie_bw is used for this. > + * The Perf counters calculate this and return the number of sent and > received > + * messages, which we multiply by the maxsize of our PCIe packets (mps). > + * Note that it is not possible to easily and quickly obtain the size of each > + * packet transmitted, so we use the max payload size (mps) to estimate the > + * PCIe bandwidth usage > + */ > +static ssize_t amdgpu_get_pcie_bw(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + uint64_t mps = pcie_get_mps(adev->pdev); > + uint64_t count0, count1; > + > + amdgpu_asic_get_pcie_usage(adev, , ); > + return snprintf(buf, PAGE_SIZE, > + "Bytes received: %llu\nBytes sent: %llu\n", > + count0 * mps, count1 * mps); > +} > + > static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, > amdgpu_set_dpm_state); > static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, > amdgpu_get_dpm_forced_performance_level, > @@ -1025,6 +1052,7 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, > amdgpu_set_pp_od_clk_voltage); > static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, > amdgpu_get_busy_percent, NULL); > +static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); > > static ssize_t amdgpu_hwmon_show_temp(struct device *dev, > struct device_attribute *attr, > @@ -2108,6 +2136,14 @@ int amdgpu_pm_sysfs_init(struct
Re: [PATCH v6 1/2] drm/amd: validate user pitch alignment
On 2019-01-07 11:51 p.m., Yu Zhao wrote: > Userspace may request pitch alignment that is not supported by GPU. > Some requests 32, but GPU ignores it and uses default 64 when cpp is > 4. If GEM object is allocated based on the smaller alignment, GPU > DMA will go out of bound. > > Cc: sta...@vger.kernel.org # v4.2+ > Signed-off-by: Yu Zhao Both patches applied to amd-staging-drm-next (should land in 5.0), thanks! -- Earthling Michel Dänzer | http://www.amd.com Libre software enthusiast | Mesa and X developer ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: Adaptive Sync/VRR not working in multi-head with a non-freesync monitor
On 2019-01-08 1:41 p.m., Ilya Trukhanov wrote: > Tried Unigine Valley with bspwm and Plasma, Freesync does not get > engaged when second monitor (without Freesync support) is in use. > If I turn it off with e.g. > > $ xrandr --output HDMI-A-0 --off > > Freesync immediately starts working. Once I turn the monitor back on, > Freesync is gone. > > > Looking through one of the patches at > https://gitlab.freedesktop.org/xorg/driver/xf86-video-amdgpu/merge_requests/5 > I found this: > >> Per-CRTC support is gone for enabling variable refresh. >> A window must cover the entire X screen in order to flip >> so every CRTC must be enabled or disabled at the same time. > > If I understood correctly, in case of multi-head, a window must span > across all monitors, with all monitors having Freesync support. > Therefore, my setup won't work in this case. However, it *does* work on > Windows (albeit only one monitor has Freesync working, obviously). > > Am I missing something obvious? > Or is this some kind of X design limitation? Yes, it is. Variable refresh rate can only work with page flipping, and page flipping can only be used in Xorg when the application window spans the whole virtual desktop. -- Earthling Michel Dänzer | http://www.amd.com Libre software enthusiast | Mesa and X developer signature.asc Description: OpenPGP digital signature ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH] drm/amdgpu: fix CPDMA hang in PRT mode for VEGA20
On Tue, Jan 8, 2019 at 5:55 AM Tao Zhou wrote: > > Fix CPDMA hang in PRT mode for both of VEGA10 and VEGA20 > > Change-Id: I0e5e089d2192063c4a04fa6dbd534f25eb0177be > Signed-off-by: Tao Zhou > Tested-by: Yukun.Li Acked-by: Alex Deucher > --- > drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > index 968b127c6c8f..fbca0494f871 100644 > --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > @@ -113,7 +113,10 @@ static const struct soc15_reg_golden > golden_settings_gc_9_0[] = > SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0x, > 0x4a2c0e68), > SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0x, > 0xb5d3f197), > SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, > 0x1920), > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x0fff, > 0x03ff) > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x0fff, > 0x03ff), > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x, > 0x0800), > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x, > 0x0800), > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, 0x8000) > }; > > static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = > @@ -135,10 +138,7 @@ static const struct soc15_reg_golden > golden_settings_gc_9_0_vg10[] = > SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x0003, > 0x0002), > SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x000f, > 0x01000107), > SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x1800, 0x0800), > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x0800, > 0x0880), > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x, > 0x0800), > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x, > 0x0800), > - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x, 0x8000) > + SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x0800, 0x0880) > }; > > static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] = > -- > 2.17.1 > > ___ > amd-gfx mailing list > amd-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Adaptive Sync/VRR not working in multi-head with a non-freesync monitor
Tried Unigine Valley with bspwm and Plasma, Freesync does not get engaged when second monitor (without Freesync support) is in use. If I turn it off with e.g. $ xrandr --output HDMI-A-0 --off Freesync immediately starts working. Once I turn the monitor back on, Freesync is gone. Looking through one of the patches at https://gitlab.freedesktop.org/xorg/driver/xf86-video-amdgpu/merge_requests/5 I found this: > Per-CRTC support is gone for enabling variable refresh. > A window must cover the entire X screen in order to flip > so every CRTC must be enabled or disabled at the same time. If I understood correctly, in case of multi-head, a window must span across all monitors, with all monitors having Freesync support. Therefore, my setup won't work in this case. However, it *does* work on Windows (albeit only one monitor has Freesync working, obviously). Am I missing something obvious? Or is this some kind of X design limitation? Are there any possible workarounds to achieve the same functionality as on Windows? I would greatly appreciate some clarification on this topic. Thank you! signature.asc Description: Digital signature ___ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH] drm/amdgpu: Add sysfs file for PCIe usage v3
Add a sysfs file that reports the number of bytes transmitted and received in the last second. This can be used to approximate the PCIe bandwidth usage over the last second. v2: Clarify use of mps as estimation of bandwidth v3: Don't make the file on APUs Signed-off-by: Kent Russell --- drivers/gpu/drm/amd/amdgpu/amdgpu.h| 4 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 38 + drivers/gpu/drm/amd/amdgpu/cik.c | 41 +++ drivers/gpu/drm/amd/amdgpu/si.c| 41 +++ drivers/gpu/drm/amd/amdgpu/soc15.c | 44 ++ drivers/gpu/drm/amd/amdgpu/vi.c| 41 +++ 6 files changed, 209 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e1b2c64..512b124 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -542,6 +542,9 @@ struct amdgpu_asic_funcs { bool (*need_full_reset)(struct amdgpu_device *adev); /* initialize doorbell layout for specific asic*/ void (*init_doorbell_index)(struct amdgpu_device *adev); + /* PCIe bandwidth usage */ + void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0, + uint64_t *count1); }; /* @@ -1045,6 +1048,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r)) #define amdgpu_asic_need_full_reset(adev) (adev)->asic_funcs->need_full_reset((adev)) #define amdgpu_asic_init_doorbell_index(adev) (adev)->asic_funcs->init_doorbell_index((adev)) +#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1))) /* Common functions */ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 6896dec..d2b29fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -990,6 +990,33 @@ static ssize_t amdgpu_get_busy_percent(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", value); } +/** + * DOC: pcie_bw + * + * The amdgpu driver provides a sysfs API for reading how much data + * has been sent and received by the GPU in the last second through PCIe. + * The file pcie_bw is used for this. + * The Perf counters calculate this and return the number of sent and received + * messages, which we multiply by the maxsize of our PCIe packets (mps). + * Note that it is not possible to easily and quickly obtain the size of each + * packet transmitted, so we use the max payload size (mps) to estimate the + * PCIe bandwidth usage + */ +static ssize_t amdgpu_get_pcie_bw(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint64_t mps = pcie_get_mps(adev->pdev); + uint64_t count0, count1; + + amdgpu_asic_get_pcie_usage(adev, , ); + return snprintf(buf, PAGE_SIZE, + "Bytes received: %llu\nBytes sent: %llu\n", + count0 * mps, count1 * mps); +} + static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, amdgpu_get_dpm_forced_performance_level, @@ -1025,6 +1052,7 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, amdgpu_set_pp_od_clk_voltage); static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, amdgpu_get_busy_percent, NULL); +static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); static ssize_t amdgpu_hwmon_show_temp(struct device *dev, struct device_attribute *attr, @@ -2108,6 +2136,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) "gpu_busy_level\n"); return ret; } + /* PCIe Perf counters won't work on APU nodes */ + if (adev->flags & !AMD_IS_APU) { + ret = device_create_file(adev->dev, _attr_pcie_bw); + if (ret) { + DRM_ERROR("failed to create device file pcie_bw\n"); + return ret; + } + } ret = amdgpu_debugfs_pm_init(adev); if (ret) { DRM_ERROR("Failed to register debugfs file for dpm!\n"); @@ -2147,6 +2183,8 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) device_remove_file(adev->dev, _attr_pp_od_clk_voltage); device_remove_file(adev->dev, _attr_gpu_busy_percent); + if (adev->flags & !AMD_IS_APU) + device_remove_file(adev->dev,
[PATCH 2/2] drm/amdgpu: Add sysfs file for PCIe usage v2
Add a sysfs file that reports the number of bytes transmitted and received in the last second. This can be used to approximate the PCIe bandwidth usage over the last second. v2: Clarify use of mps as estimation of bandwidth Signed-off-by: Kent Russell --- drivers/gpu/drm/amd/amdgpu/amdgpu.h| 4 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 34 ++ drivers/gpu/drm/amd/amdgpu/cik.c | 41 +++ drivers/gpu/drm/amd/amdgpu/si.c| 41 +++ drivers/gpu/drm/amd/amdgpu/soc15.c | 44 ++ drivers/gpu/drm/amd/amdgpu/vi.c| 41 +++ 6 files changed, 205 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e1b2c64..512b124 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -542,6 +542,9 @@ struct amdgpu_asic_funcs { bool (*need_full_reset)(struct amdgpu_device *adev); /* initialize doorbell layout for specific asic*/ void (*init_doorbell_index)(struct amdgpu_device *adev); + /* PCIe bandwidth usage */ + void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0, + uint64_t *count1); }; /* @@ -1045,6 +1048,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r)) #define amdgpu_asic_need_full_reset(adev) (adev)->asic_funcs->need_full_reset((adev)) #define amdgpu_asic_init_doorbell_index(adev) (adev)->asic_funcs->init_doorbell_index((adev)) +#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1))) /* Common functions */ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 6896dec..9cf47ba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -990,6 +990,33 @@ static ssize_t amdgpu_get_busy_percent(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", value); } +/** + * DOC: pcie_bw + * + * The amdgpu driver provides a sysfs API for reading how much data + * has been sent and received by the GPU in the last second through PCIe. + * The file pcie_bw is used for this. + * The Perf counters calculate this and return the number of sent and received + * messages, which we multiply by the maxsize of our PCIe packets (mps). + * Note that it is not possible to easily and quickly obtain the size of each + * packet transmitted, so we use the max payload size (mps) to estimate the + * PCIe bandwidth usage + */ +static ssize_t amdgpu_get_pcie_bw(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint64_t mps = pcie_get_mps(adev->pdev); + uint64_t count0, count1; + + amdgpu_asic_get_pcie_usage(adev, , ); + return snprintf(buf, PAGE_SIZE, + "Bytes received: %llu\nBytes sent: %llu\n", + count0 * mps, count1 * mps); +} + static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, amdgpu_get_dpm_forced_performance_level, @@ -1025,6 +1052,7 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, amdgpu_set_pp_od_clk_voltage); static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, amdgpu_get_busy_percent, NULL); +static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); static ssize_t amdgpu_hwmon_show_temp(struct device *dev, struct device_attribute *attr, @@ -2108,6 +2136,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) "gpu_busy_level\n"); return ret; } + ret = device_create_file(adev->dev, _attr_pcie_bw); + if (ret) { + DRM_ERROR("failed to create device file pcie_bw\n"); + return ret; + } ret = amdgpu_debugfs_pm_init(adev); if (ret) { DRM_ERROR("Failed to register debugfs file for dpm!\n"); @@ -2147,6 +2180,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) device_remove_file(adev->dev, _attr_pp_od_clk_voltage); device_remove_file(adev->dev, _attr_gpu_busy_percent); + device_remove_file(adev->dev, _attr_pcie_bw); } void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 71c50d8..8681744 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++