--- /dev/null
+From 7a46f05e5e163c00e41892e671294286e53fe15c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 3 Feb 2021 13:42:41 +0100
+Subject: drm/amd/display: Add a backlight module option
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 7a46f05e5e163c00e41892e671294286e53fe15c upstream.
+
+There seem devices that don't work with the aux channel backlight
+control. For allowing such users to test with the other backlight
+control method, provide a new module option, aux_backlight, to specify
+enabling or disabling the aux backport support explicitly. As
+default, the aux support is detected by the hardware capability.
+
+v2: make the backlight option generic in case we add future
+backlight types (Alex)
+
+BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1180749
+BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1438
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 +
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++
+ 3 files changed, 10 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -179,6 +179,7 @@ extern uint amdgpu_smu_memory_pool_size;
+ extern uint amdgpu_dc_feature_mask;
+ extern uint amdgpu_dc_debug_mask;
+ extern uint amdgpu_dm_abm_level;
++extern int amdgpu_backlight;
+ extern struct amdgpu_mgpu_info mgpu_info;
+ extern int amdgpu_ras_enable;
+ extern uint amdgpu_ras_mask;
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -777,6 +777,10 @@ uint amdgpu_dm_abm_level;
+ MODULE_PARM_DESC(abmlevel, "ABM level (0 = off (default), 1-4 = backlight reduction level) ");
+ module_param_named(abmlevel, amdgpu_dm_abm_level, uint, 0444);
+
++int amdgpu_backlight = -1;
++MODULE_PARM_DESC(backlight, "Backlight control (0 = pwm, 1 = aux, -1 auto (default))");
++module_param_named(backlight, amdgpu_backlight, bint, 0444);
++
+ /**
+ * DOC: tmz (int)
+ * Trusted Memory Zone (TMZ) is a method to protect data being written
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2209,6 +2209,11 @@ static void update_connector_ext_caps(st
+ caps->ext_caps->bits.hdr_aux_backlight_control == 1)
+ caps->aux_support = true;
+
++ if (amdgpu_backlight == 0)
++ caps->aux_support = false;
++ else if (amdgpu_backlight == 1)
++ caps->aux_support = true;
++
+ /* From the specification (CTA-861-G), for calculating the maximum
+ * luminance we need to use:
+ * Luminance = 50*2**(CV/32)
--- /dev/null
+From 15e8b95d5f7509e0b09289be8c422c459c9f0412 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Holger=20Hoffst=C3=A4tte?= <holger@applied-asynchrony.com>
+Date: Fri, 5 Mar 2021 12:39:21 +0100
+Subject: drm/amd/display: Fix nested FPU context in dcn21_validate_bandwidth()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Holger Hoffstätte <holger@applied-asynchrony.com>
+
+commit 15e8b95d5f7509e0b09289be8c422c459c9f0412 upstream.
+
+Commit 41401ac67791 added FPU wrappers to dcn21_validate_bandwidth(),
+which was correct. Unfortunately a nested function alredy contained
+DC_FP_START()/DC_FP_END() calls, which results in nested FPU context
+enter/exit and complaints by kernel_fpu_begin_mask().
+This can be observed e.g. with 5.10.20, which backported 41401ac67791
+and now emits the following warning on boot:
+
+WARNING: CPU: 6 PID: 858 at arch/x86/kernel/fpu/core.c:129 kernel_fpu_begin_mask+0xa5/0xc0
+Call Trace:
+ dcn21_calculate_wm+0x47/0xa90 [amdgpu]
+ dcn21_validate_bandwidth_fp+0x15d/0x2b0 [amdgpu]
+ dcn21_validate_bandwidth+0x29/0x40 [amdgpu]
+ dc_validate_global_state+0x3c7/0x4c0 [amdgpu]
+
+The warning is emitted due to the additional DC_FP_START/END calls in
+patch_bounding_box(), which is inlined into dcn21_calculate_wm(),
+its only caller. Removing the calls brings the code in line with
+dcn20 and makes the warning disappear.
+
+Fixes: 41401ac67791 ("drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()")
+Signed-off-by: Holger Hoffstätte <holger@applied-asynchrony.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+@@ -1062,8 +1062,6 @@ static void patch_bounding_box(struct dc
+ {
+ int i;
+
+- DC_FP_START();
+-
+ if (dc->bb_overrides.sr_exit_time_ns) {
+ for (i = 0; i < WM_SET_COUNT; i++) {
+ dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us =
+@@ -1088,8 +1086,6 @@ static void patch_bounding_box(struct dc
+ dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
+ }
+ }
+-
+- DC_FP_END();
+ }
+
+ void dcn21_calculate_wm(
--- /dev/null
+From 50ceb1fe7acd50831180f4b5597bf7b39e8059c8 Mon Sep 17 00:00:00 2001
+From: Kenneth Feng <kenneth.feng@amd.com>
+Date: Tue, 9 Mar 2021 21:10:16 +0800
+Subject: drm/amd/pm: bug fix for pcie dpm
+
+From: Kenneth Feng <kenneth.feng@amd.com>
+
+commit 50ceb1fe7acd50831180f4b5597bf7b39e8059c8 upstream.
+
+Currently the pcie dpm has two problems.
+1. Only the high dpm level speed/width can be overrided
+if the requested values are out of the pcie capability.
+2. The high dpm level is always overrided though sometimes
+it's not necesarry.
+
+Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 48 +++++++++++++
+ drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 66 ++++++++++++++++++
+ drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 48 +++++++------
+ 3 files changed, 141 insertions(+), 21 deletions(-)
+
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+@@ -1506,6 +1506,48 @@ static int vega10_populate_single_lclk_l
+ return 0;
+ }
+
++static int vega10_override_pcie_parameters(struct pp_hwmgr *hwmgr)
++{
++ struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
++ struct vega10_hwmgr *data =
++ (struct vega10_hwmgr *)(hwmgr->backend);
++ uint32_t pcie_gen = 0, pcie_width = 0;
++ PPTable_t *pp_table = &(data->smc_state_table.pp_table);
++ int i;
++
++ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
++ pcie_gen = 3;
++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
++ pcie_gen = 2;
++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
++ pcie_gen = 1;
++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
++ pcie_gen = 0;
++
++ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
++ pcie_width = 6;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
++ pcie_width = 5;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
++ pcie_width = 4;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
++ pcie_width = 3;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
++ pcie_width = 2;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
++ pcie_width = 1;
++
++ for (i = 0; i < NUM_LINK_LEVELS; i++) {
++ if (pp_table->PcieGenSpeed[i] > pcie_gen)
++ pp_table->PcieGenSpeed[i] = pcie_gen;
++
++ if (pp_table->PcieLaneCount[i] > pcie_width)
++ pp_table->PcieLaneCount[i] = pcie_width;
++ }
++
++ return 0;
++}
++
+ static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
+ {
+ int result = -1;
+@@ -2557,6 +2599,11 @@ static int vega10_init_smc_table(struct
+ "Failed to initialize Link Level!",
+ return result);
+
++ result = vega10_override_pcie_parameters(hwmgr);
++ PP_ASSERT_WITH_CODE(!result,
++ "Failed to override pcie parameters!",
++ return result);
++
+ result = vega10_populate_all_graphic_levels(hwmgr);
+ PP_ASSERT_WITH_CODE(!result,
+ "Failed to initialize Graphics Level!",
+@@ -2923,6 +2970,7 @@ static int vega10_start_dpm(struct pp_hw
+ return 0;
+ }
+
++
+ static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable)
+ {
+ struct vega10_hwmgr *data = hwmgr->backend;
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
+@@ -481,6 +481,67 @@ static void vega12_init_dpm_state(struct
+ dpm_state->hard_max_level = 0xffff;
+ }
+
++static int vega12_override_pcie_parameters(struct pp_hwmgr *hwmgr)
++{
++ struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
++ struct vega12_hwmgr *data =
++ (struct vega12_hwmgr *)(hwmgr->backend);
++ uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
++ PPTable_t *pp_table = &(data->smc_state_table.pp_table);
++ int i;
++ int ret;
++
++ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
++ pcie_gen = 3;
++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
++ pcie_gen = 2;
++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
++ pcie_gen = 1;
++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
++ pcie_gen = 0;
++
++ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
++ pcie_width = 6;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
++ pcie_width = 5;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
++ pcie_width = 4;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
++ pcie_width = 3;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
++ pcie_width = 2;
++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
++ pcie_width = 1;
++
++ /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1
++ * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
++ * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
++ */
++ for (i = 0; i < NUM_LINK_LEVELS; i++) {
++ pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
++ pp_table->PcieGenSpeed[i];
++ pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
++ pp_table->PcieLaneCount[i];
++
++ if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
++ pp_table->PcieLaneCount[i]) {
++ smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
++ ret = smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
++ NULL);
++ PP_ASSERT_WITH_CODE(!ret,
++ "[OverridePcieParameters] Attempt to override pcie params failed!",
++ return ret);
++ }
++
++ /* update the pptable */
++ pp_table->PcieGenSpeed[i] = pcie_gen_arg;
++ pp_table->PcieLaneCount[i] = pcie_width_arg;
++ }
++
++ return 0;
++}
++
+ static int vega12_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
+ PPCLK_e clk_id, uint32_t *num_of_levels)
+ {
+@@ -969,6 +1030,11 @@ static int vega12_enable_dpm_tasks(struc
+ "Failed to enable all smu features!",
+ return result);
+
++ result = vega12_override_pcie_parameters(hwmgr);
++ PP_ASSERT_WITH_CODE(!result,
++ "[EnableDPMTasks] Failed to override pcie parameters!",
++ return result);
++
+ tmp_result = vega12_power_control_set_level(hwmgr);
+ PP_ASSERT_WITH_CODE(!tmp_result,
+ "Failed to power control set level!",
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
+@@ -832,7 +832,9 @@ static int vega20_override_pcie_paramete
+ struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+ struct vega20_hwmgr *data =
+ (struct vega20_hwmgr *)(hwmgr->backend);
+- uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg;
++ uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
++ PPTable_t *pp_table = &(data->smc_state_table.pp_table);
++ int i;
+ int ret;
+
+ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
+@@ -861,17 +863,27 @@ static int vega20_override_pcie_paramete
+ * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
+ * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
+ */
+- smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width;
+- ret = smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
+- NULL);
+- PP_ASSERT_WITH_CODE(!ret,
+- "[OverridePcieParameters] Attempt to override pcie params failed!",
+- return ret);
++ for (i = 0; i < NUM_LINK_LEVELS; i++) {
++ pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
++ pp_table->PcieGenSpeed[i];
++ pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
++ pp_table->PcieLaneCount[i];
++
++ if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
++ pp_table->PcieLaneCount[i]) {
++ smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
++ ret = smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
++ NULL);
++ PP_ASSERT_WITH_CODE(!ret,
++ "[OverridePcieParameters] Attempt to override pcie params failed!",
++ return ret);
++ }
+
+- data->pcie_parameters_override = true;
+- data->pcie_gen_level1 = pcie_gen;
+- data->pcie_width_level1 = pcie_width;
++ /* update the pptable */
++ pp_table->PcieGenSpeed[i] = pcie_gen_arg;
++ pp_table->PcieLaneCount[i] = pcie_width_arg;
++ }
+
+ return 0;
+ }
+@@ -3320,9 +3332,7 @@ static int vega20_print_clock_levels(str
+ data->od8_settings.od8_settings_array;
+ OverDriveTable_t *od_table =
+ &(data->smc_state_table.overdrive_table);
+- struct phm_ppt_v3_information *pptable_information =
+- (struct phm_ppt_v3_information *)hwmgr->pptable;
+- PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
++ PPTable_t *pptable = &(data->smc_state_table.pp_table);
+ struct pp_clock_levels_with_latency clocks;
+ struct vega20_single_dpm_table *fclk_dpm_table =
+ &(data->dpm_table.fclk_table);
+@@ -3421,13 +3431,9 @@ static int vega20_print_clock_levels(str
+ current_lane_width =
+ vega20_get_current_pcie_link_width_level(hwmgr);
+ for (i = 0; i < NUM_LINK_LEVELS; i++) {
+- if (i == 1 && data->pcie_parameters_override) {
+- gen_speed = data->pcie_gen_level1;
+- lane_width = data->pcie_width_level1;
+- } else {
+- gen_speed = pptable->PcieGenSpeed[i];
+- lane_width = pptable->PcieLaneCount[i];
+- }
++ gen_speed = pptable->PcieGenSpeed[i];
++ lane_width = pptable->PcieLaneCount[i];
++
+ size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
+ (gen_speed == 0) ? "2.5GT/s," :
+ (gen_speed == 1) ? "5.0GT/s," :
--- /dev/null
+From 48123d068fcb584838ce29912660c5e9490bad0e Mon Sep 17 00:00:00 2001
+From: Evan Quan <evan.quan@amd.com>
+Date: Fri, 5 Mar 2021 14:21:26 +0800
+Subject: drm/amd/pm: correct the watermark settings for Polaris
+
+From: Evan Quan <evan.quan@amd.com>
+
+commit 48123d068fcb584838ce29912660c5e9490bad0e upstream.
+
+The "/ 10" should be applied to the right-hand operand instead of
+the left-hand one.
+
+Signed-off-by: Evan Quan <evan.quan@amd.com>
+Noticed-by: Georgios Toptsidis <gtoptsid@gmail.com>
+Reviewed-by: Feifei Xu <Feifei.Xu@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+@@ -5216,10 +5216,10 @@ static int smu7_set_watermarks_for_clock
+ for (j = 0; j < dep_sclk_table->count; j++) {
+ valid_entry = false;
+ for (k = 0; k < watermarks->num_wm_sets; k++) {
+- if (dep_sclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz &&
+- dep_sclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz &&
+- dep_mclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz &&
+- dep_mclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz) {
++ if (dep_sclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz / 10 &&
++ dep_sclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz / 10 &&
++ dep_mclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz / 10 &&
++ dep_mclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz / 10) {
+ valid_entry = true;
+ table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k].wm_set_id;
+ break;
--- /dev/null
+From dfd8b7fbd985ec1cf76fe10f2875a50b10833740 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 10 Dec 2020 01:20:08 -0500
+Subject: drm/amdgpu/display: don't assert in set backlight function
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit dfd8b7fbd985ec1cf76fe10f2875a50b10833740 upstream.
+
+It just spams the logs.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+@@ -2571,7 +2571,6 @@ bool dc_link_set_backlight_level(const s
+ if (pipe_ctx->plane_state == NULL)
+ frame_ramp = 0;
+ } else {
+- ASSERT(false);
+ return false;
+ }
+
--- /dev/null
+From 0ad3e64eb46d8c47de3af552e282894e3893e973 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 10 Dec 2020 01:45:12 -0500
+Subject: drm/amdgpu/display: handle aux backlight in backlight_get_brightness
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 0ad3e64eb46d8c47de3af552e282894e3893e973 upstream.
+
+Need to fetch it via aux.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 ++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -3205,11 +3205,27 @@ static int amdgpu_dm_backlight_update_st
+ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
+ {
+ struct amdgpu_display_manager *dm = bl_get_data(bd);
+- int ret = dc_link_get_backlight_level(dm->backlight_link);
++ struct amdgpu_dm_backlight_caps caps;
+
+- if (ret == DC_ERROR_UNEXPECTED)
+- return bd->props.brightness;
+- return convert_brightness_to_user(&dm->backlight_caps, ret);
++ amdgpu_dm_update_backlight_caps(dm);
++ caps = dm->backlight_caps;
++
++ if (caps.aux_support) {
++ struct dc_link *link = (struct dc_link *)dm->backlight_link;
++ u32 avg, peak;
++ bool rc;
++
++ rc = dc_link_get_backlight_level_nits(link, &avg, &peak);
++ if (!rc)
++ return bd->props.brightness;
++ return convert_brightness_to_user(&caps, avg);
++ } else {
++ int ret = dc_link_get_backlight_level(dm->backlight_link);
++
++ if (ret == DC_ERROR_UNEXPECTED)
++ return bd->props.brightness;
++ return convert_brightness_to_user(&caps, ret);
++ }
+ }
+
+ static const struct backlight_ops amdgpu_dm_backlight_ops = {
--- /dev/null
+From a2f8d988698d7d3645b045f4940415b045140b81 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 10 Dec 2020 01:18:40 -0500
+Subject: drm/amdgpu/display: simplify backlight setting
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit a2f8d988698d7d3645b045f4940415b045140b81 upstream.
+
+Avoid the extra wrapper function.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 ++++----------------
+ 1 file changed, 4 insertions(+), 16 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -3132,19 +3132,6 @@ static void amdgpu_dm_update_backlight_c
+ #endif
+ }
+
+-static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness)
+-{
+- bool rc;
+-
+- if (!link)
+- return 1;
+-
+- rc = dc_link_set_backlight_level_nits(link, true, brightness,
+- AUX_BL_DEFAULT_TRANSITION_TIME_MS);
+-
+- return rc ? 0 : 1;
+-}
+-
+ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
+ unsigned *min, unsigned *max)
+ {
+@@ -3207,9 +3194,10 @@ static int amdgpu_dm_backlight_update_st
+ brightness = convert_brightness_from_user(&caps, bd->props.brightness);
+ // Change brightness based on AUX property
+ if (caps.aux_support)
+- return set_backlight_via_aux(link, brightness);
+-
+- rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0);
++ rc = dc_link_set_backlight_level_nits(link, true, brightness,
++ AUX_BL_DEFAULT_TRANSITION_TIME_MS);
++ else
++ rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0);
+
+ return rc ? 0 : 1;
+ }
--- /dev/null
+From 680174cfd1e1cea70a8f30ccb44d8fbdf996018e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Holger=20Hoffst=C3=A4tte?= <holger@applied-asynchrony.com>
+Date: Fri, 5 Mar 2021 15:23:18 +0100
+Subject: drm/amdgpu/display: use GFP_ATOMIC in dcn21_validate_bandwidth_fp()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Holger Hoffstätte <holger@applied-asynchrony.com>
+
+commit 680174cfd1e1cea70a8f30ccb44d8fbdf996018e upstream.
+
+After fixing nested FPU contexts caused by 41401ac67791 we're still seeing
+complaints about spurious kernel_fpu_end(). As it turns out this was
+already fixed for dcn20 in commit f41ed88cbd ("drm/amdgpu/display:
+use GFP_ATOMIC in dcn20_validate_bandwidth_internal") but never moved
+forward to dcn21.
+
+Signed-off-by: Holger Hoffstätte <holger@applied-asynchrony.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+@@ -1339,7 +1339,7 @@ static noinline bool dcn21_validate_band
+ int vlevel = 0;
+ int pipe_split_from[MAX_PIPES];
+ int pipe_cnt = 0;
+- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
++ display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
+ DC_LOGGER_INIT(dc->ctx->logger);
+
+ BW_VAL_TRACE_COUNT();
--- /dev/null
+From a5cb3c1a36376c25cd25fd3e99918dc48ac420bb Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 9 Mar 2021 22:58:47 -0500
+Subject: drm/amdgpu: fix S0ix handling when the CONFIG_AMD_PMC=m
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit a5cb3c1a36376c25cd25fd3e99918dc48ac420bb upstream.
+
+Need to check the module variant as well.
+
+Acked-by: Prike Liang <Prike.Liang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+@@ -903,7 +903,7 @@ void amdgpu_acpi_fini(struct amdgpu_devi
+ */
+ bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev)
+ {
+-#if defined(CONFIG_AMD_PMC)
++#if defined(CONFIG_AMD_PMC) || defined(CONFIG_AMD_PMC_MODULE)
+ if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
+ if (adev->flags & AMD_IS_APU)
+ return true;
--- /dev/null
+From de066e116306baf3a6a62691ac63cfc0b1dabddb Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Mon, 22 Feb 2021 11:06:43 +0100
+Subject: drm/compat: Clear bounce structures
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit de066e116306baf3a6a62691ac63cfc0b1dabddb upstream.
+
+Some of them have gaps, or fields we don't clear. Native ioctl code
+does full copies plus zero-extends on size mismatch, so nothing can
+leak. But compat is more hand-rolled so need to be careful.
+
+None of these matter for performance, so just memset.
+
+Also I didn't fix up the CONFIG_DRM_LEGACY or CONFIG_DRM_AGP ioctl, those
+are security holes anyway.
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Reported-by: syzbot+620cf21140fc7e772a5d@syzkaller.appspotmail.com # vblank ioctl
+Cc: syzbot+620cf21140fc7e772a5d@syzkaller.appspotmail.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210222100643.400935-1-daniel.vetter@ffwll.ch
+(cherry picked from commit e926c474ebee404441c838d18224cd6f246a71b7)
+Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_ioc32.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/gpu/drm/drm_ioc32.c
++++ b/drivers/gpu/drm/drm_ioc32.c
+@@ -99,6 +99,8 @@ static int compat_drm_version(struct fil
+ if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
+ return -EFAULT;
+
++ memset(&v, 0, sizeof(v));
++
+ v = (struct drm_version) {
+ .name_len = v32.name_len,
+ .name = compat_ptr(v32.name),
+@@ -137,6 +139,9 @@ static int compat_drm_getunique(struct f
+
+ if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
+ return -EFAULT;
++
++ memset(&uq, 0, sizeof(uq));
++
+ uq = (struct drm_unique){
+ .unique_len = uq32.unique_len,
+ .unique = compat_ptr(uq32.unique),
+@@ -265,6 +270,8 @@ static int compat_drm_getclient(struct f
+ if (copy_from_user(&c32, argp, sizeof(c32)))
+ return -EFAULT;
+
++ memset(&client, 0, sizeof(client));
++
+ client.idx = c32.idx;
+
+ err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
+@@ -852,6 +859,8 @@ static int compat_drm_wait_vblank(struct
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+
++ memset(&req, 0, sizeof(req));
++
+ req.request.type = req32.request.type;
+ req.request.sequence = req32.request.sequence;
+ req.request.signal = req32.request.signal;
+@@ -889,6 +898,8 @@ static int compat_drm_mode_addfb2(struct
+ struct drm_mode_fb_cmd2 req64;
+ int err;
+
++ memset(&req64, 0, sizeof(req64));
++
+ if (copy_from_user(&req64, argp,
+ offsetof(drm_mode_fb_cmd232_t, modifier)))
+ return -EFAULT;
--- /dev/null
+From 874a52f9b693ed8bf7a92b3592a547ce8a684e6f Mon Sep 17 00:00:00 2001
+From: Tong Zhang <ztong0001@gmail.com>
+Date: Sat, 27 Feb 2021 23:46:25 -0500
+Subject: drm/fb-helper: only unmap if buffer not null
+
+From: Tong Zhang <ztong0001@gmail.com>
+
+commit 874a52f9b693ed8bf7a92b3592a547ce8a684e6f upstream.
+
+drm_fbdev_cleanup() can be called when fb_helper->buffer is null, hence
+fb_helper->buffer should be checked before calling
+drm_client_buffer_vunmap(). This buffer is also checked in
+drm_client_framebuffer_delete(), so we should also do the same thing for
+drm_client_buffer_vunmap().
+
+[ 199.128742] RIP: 0010:drm_client_buffer_vunmap+0xd/0x20
+[ 199.129031] Code: 43 18 48 8b 53 20 49 89 45 00 49 89 55 08 5b 44 89 e0 41 5c 41 5d 41 5e 5d
+c3 0f 1f 00 53 48 89 fb 48 8d 7f 10 e8 73 7d a1 ff <48> 8b 7b 10 48 8d 73 18 5b e9 75 53 fc ff 0
+f 1f 44 00 00 48 b8 00
+[ 199.130041] RSP: 0018:ffff888103f3fc88 EFLAGS: 00010282
+[ 199.130329] RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffffffff8214d46d
+[ 199.130733] RDX: 1ffffffff079c6b9 RSI: 0000000000000246 RDI: ffffffff83ce35c8
+[ 199.131119] RBP: ffff888103d25458 R08: 0000000000000001 R09: fffffbfff0791761
+[ 199.131505] R10: ffffffff83c8bb07 R11: fffffbfff0791760 R12: 0000000000000000
+[ 199.131891] R13: ffff888103d25468 R14: ffff888103d25418 R15: ffff888103f18120
+[ 199.132277] FS: 00007f36fdcbb6a0(0000) GS:ffff88815b400000(0000) knlGS:0000000000000000
+[ 199.132721] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 199.133033] CR2: 0000000000000010 CR3: 0000000103d26000 CR4: 00000000000006f0
+[ 199.133420] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 199.133807] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 199.134195] Call Trace:
+[ 199.134333] drm_fbdev_cleanup+0x179/0x1a0
+[ 199.134562] drm_fbdev_client_unregister+0x2b/0x40
+[ 199.134828] drm_client_dev_unregister+0xa8/0x180
+[ 199.135088] drm_dev_unregister+0x61/0x110
+[ 199.135315] mgag200_pci_remove+0x38/0x52 [mgag200]
+[ 199.135586] pci_device_remove+0x62/0xe0
+[ 199.135806] device_release_driver_internal+0x148/0x270
+[ 199.136094] driver_detach+0x76/0xe0
+[ 199.136294] bus_remove_driver+0x7e/0x100
+[ 199.136521] pci_unregister_driver+0x28/0xf0
+[ 199.136759] __x64_sys_delete_module+0x268/0x300
+[ 199.137016] ? __ia32_sys_delete_module+0x300/0x300
+[ 199.137285] ? call_rcu+0x3e4/0x580
+[ 199.137481] ? fpregs_assert_state_consistent+0x4d/0x60
+[ 199.137767] ? exit_to_user_mode_prepare+0x2f/0x130
+[ 199.138037] do_syscall_64+0x33/0x40
+[ 199.138237] entry_SYSCALL_64_after_hwframe+0x44/0xae
+[ 199.138517] RIP: 0033:0x7f36fdc3dcf7
+
+Signed-off-by: Tong Zhang <ztong0001@gmail.com>
+Fixes: 763aea17bf57 ("drm/fb-helper: Unmap client buffer during shutdown")
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Sam Ravnborg <sam@ravnborg.org>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: David Airlie <airlied@linux.ie>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v5.11+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210228044625.171151-1-ztong0001@gmail.com
+Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_fb_helper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -2043,7 +2043,7 @@ static void drm_fbdev_cleanup(struct drm
+
+ if (shadow)
+ vfree(shadow);
+- else
++ else if (fb_helper->buffer)
+ drm_client_buffer_vunmap(fb_helper->buffer);
+
+ drm_client_framebuffer_delete(fb_helper->buffer);
--- /dev/null
+From a25955ba123499d7db520175c6be59c29f9215e3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Mon, 8 Mar 2021 19:35:14 +0100
+Subject: drm/radeon: also init GEM funcs in radeon_gem_prime_import_sg_table
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian König <christian.koenig@amd.com>
+
+commit a25955ba123499d7db520175c6be59c29f9215e3 upstream.
+
+Otherwise we will run into a NULL ptr deref.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Bug: https://bugzilla.kernel.org/show_bug.cgi?id=212137
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org # 5.11.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/radeon/radeon.h | 2 ++
+ drivers/gpu/drm/radeon/radeon_gem.c | 4 ++--
+ drivers/gpu/drm/radeon/radeon_prime.c | 2 ++
+ 3 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -575,6 +575,8 @@ struct radeon_gem {
+ struct list_head objects;
+ };
+
++extern const struct drm_gem_object_funcs radeon_gem_object_funcs;
++
+ int radeon_gem_init(struct radeon_device *rdev);
+ void radeon_gem_fini(struct radeon_device *rdev);
+ int radeon_gem_object_create(struct radeon_device *rdev, unsigned long size,
+--- a/drivers/gpu/drm/radeon/radeon_gem.c
++++ b/drivers/gpu/drm/radeon/radeon_gem.c
+@@ -43,7 +43,7 @@ struct sg_table *radeon_gem_prime_get_sg
+ int radeon_gem_prime_pin(struct drm_gem_object *obj);
+ void radeon_gem_prime_unpin(struct drm_gem_object *obj);
+
+-static const struct drm_gem_object_funcs radeon_gem_object_funcs;
++const struct drm_gem_object_funcs radeon_gem_object_funcs;
+
+ static void radeon_gem_object_free(struct drm_gem_object *gobj)
+ {
+@@ -227,7 +227,7 @@ static int radeon_gem_handle_lockup(stru
+ return r;
+ }
+
+-static const struct drm_gem_object_funcs radeon_gem_object_funcs = {
++const struct drm_gem_object_funcs radeon_gem_object_funcs = {
+ .free = radeon_gem_object_free,
+ .open = radeon_gem_object_open,
+ .close = radeon_gem_object_close,
+--- a/drivers/gpu/drm/radeon/radeon_prime.c
++++ b/drivers/gpu/drm/radeon/radeon_prime.c
+@@ -56,6 +56,8 @@ struct drm_gem_object *radeon_gem_prime_
+ if (ret)
+ return ERR_PTR(ret);
+
++ bo->tbo.base.funcs = &radeon_gem_object_funcs;
++
+ mutex_lock(&rdev->gem.mutex);
+ list_add_tail(&bo->list, &rdev->gem.objects);
+ mutex_unlock(&rdev->gem.mutex);
--- /dev/null
+From d611b4a0907cece060699f2fd347c492451cd2aa Mon Sep 17 00:00:00 2001
+From: Neil Roberts <nroberts@igalia.com>
+Date: Tue, 23 Feb 2021 16:51:24 +0100
+Subject: drm/shmem-helper: Check for purged buffers in fault handler
+
+From: Neil Roberts <nroberts@igalia.com>
+
+commit d611b4a0907cece060699f2fd347c492451cd2aa upstream.
+
+When a buffer is madvised as not needed and then purged, any attempts to
+access the buffer from user-space should cause a bus fault. This patch
+adds a check for that.
+
+Cc: stable@vger.kernel.org
+Fixes: 17acb9f35ed7 ("drm/shmem: Add madvise state and purge helpers")
+Signed-off-by: Neil Roberts <nroberts@igalia.com>
+Reviewed-by: Steven Price <steven.price@arm.com>
+Signed-off-by: Steven Price <steven.price@arm.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210223155125.199577-2-nroberts@igalia.com
+Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_gem_shmem_helper.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
++++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
+@@ -525,14 +525,24 @@ static vm_fault_t drm_gem_shmem_fault(st
+ struct drm_gem_object *obj = vma->vm_private_data;
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ loff_t num_pages = obj->size >> PAGE_SHIFT;
++ vm_fault_t ret;
+ struct page *page;
+
+- if (vmf->pgoff >= num_pages || WARN_ON_ONCE(!shmem->pages))
+- return VM_FAULT_SIGBUS;
++ mutex_lock(&shmem->pages_lock);
+
+- page = shmem->pages[vmf->pgoff];
++ if (vmf->pgoff >= num_pages ||
++ WARN_ON_ONCE(!shmem->pages) ||
++ shmem->madv < 0) {
++ ret = VM_FAULT_SIGBUS;
++ } else {
++ page = shmem->pages[vmf->pgoff];
+
+- return vmf_insert_page(vma, vmf->address, page);
++ ret = vmf_insert_page(vma, vmf->address, page);
++ }
++
++ mutex_unlock(&shmem->pages_lock);
++
++ return ret;
+ }
+
+ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
--- /dev/null
+From 11d5a4745e00e73745774671dbf2fb07bd6e2363 Mon Sep 17 00:00:00 2001
+From: Neil Roberts <nroberts@igalia.com>
+Date: Tue, 23 Feb 2021 16:51:25 +0100
+Subject: drm/shmem-helper: Don't remove the offset in vm_area_struct pgoff
+
+From: Neil Roberts <nroberts@igalia.com>
+
+commit 11d5a4745e00e73745774671dbf2fb07bd6e2363 upstream.
+
+When mmapping the shmem, it would previously adjust the pgoff in the
+vm_area_struct to remove the fake offset that is added to be able to
+identify the buffer. This patch removes the adjustment and makes the
+fault handler use the vm_fault address to calculate the page offset
+instead. Although using this address is apparently discouraged, several
+DRM drivers seem to be doing it anyway.
+
+The problem with removing the pgoff is that it prevents
+drm_vma_node_unmap from working because that searches the mapping tree
+by address. That doesn't work because all of the mappings are at offset
+0. drm_vma_node_unmap is being used by the shmem helpers when purging
+the buffer.
+
+This fixes a bug in Panfrost which is using drm_gem_shmem_purge. Without
+this the mapping for the purged buffer can still be accessed which might
+mean it would access random pages from other buffers
+
+v2: Don't check whether the unsigned page_offset is less than 0.
+
+Cc: stable@vger.kernel.org
+Fixes: 17acb9f35ed7 ("drm/shmem: Add madvise state and purge helpers")
+Signed-off-by: Neil Roberts <nroberts@igalia.com>
+Reviewed-by: Steven Price <steven.price@arm.com>
+Signed-off-by: Steven Price <steven.price@arm.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210223155125.199577-3-nroberts@igalia.com
+Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_gem_shmem_helper.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
++++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
+@@ -527,15 +527,19 @@ static vm_fault_t drm_gem_shmem_fault(st
+ loff_t num_pages = obj->size >> PAGE_SHIFT;
+ vm_fault_t ret;
+ struct page *page;
++ pgoff_t page_offset;
++
++ /* We don't use vmf->pgoff since that has the fake offset */
++ page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
+
+ mutex_lock(&shmem->pages_lock);
+
+- if (vmf->pgoff >= num_pages ||
++ if (page_offset >= num_pages ||
+ WARN_ON_ONCE(!shmem->pages) ||
+ shmem->madv < 0) {
+ ret = VM_FAULT_SIGBUS;
+ } else {
+- page = shmem->pages[vmf->pgoff];
++ page = shmem->pages[page_offset];
+
+ ret = vmf_insert_page(vma, vmf->address, page);
+ }
+@@ -591,9 +595,6 @@ int drm_gem_shmem_mmap(struct drm_gem_ob
+ struct drm_gem_shmem_object *shmem;
+ int ret;
+
+- /* Remove the fake offset */
+- vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
+-
+ if (obj->import_attach) {
+ /* Drop the reference drm_gem_mmap_obj() acquired.*/
+ drm_gem_object_put(obj);
--- /dev/null
+From 659ab7a49cbebe0deffcbe1f9560e82006b21817 Mon Sep 17 00:00:00 2001
+From: Thomas Zimmermann <tzimmermann@suse.de>
+Date: Wed, 3 Mar 2021 14:32:29 +0100
+Subject: drm: Use USB controller's DMA mask when importing dmabufs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+commit 659ab7a49cbebe0deffcbe1f9560e82006b21817 upstream.
+
+USB devices cannot perform DMA and hence have no dma_mask set in their
+device structure. Therefore importing dmabuf into a USB-based driver
+fails, which breaks joining and mirroring of display in X11.
+
+For USB devices, pick the associated USB controller as attachment device.
+This allows the DRM import helpers to perform the DMA setup. If the DMA
+controller does not support DMA transfers, we're out of luck and cannot
+import. Our current USB-based DRM drivers don't use DMA, so the actual
+DMA device is not important.
+
+Tested by joining/mirroring displays of udl and radeon under Gnome/X11.
+
+v8:
+ * release dmadev if device initialization fails (Noralf)
+ * fix commit description (Noralf)
+v7:
+ * fix use-before-init bug in gm12u320 (Dan)
+v6:
+ * implement workaround in DRM drivers and hold reference to
+ DMA device while USB device is in use
+ * remove dev_is_usb() (Greg)
+ * collapse USB helper into usb_intf_get_dma_device() (Alan)
+ * integrate Daniel's TODO statement (Daniel)
+ * fix typos (Greg)
+v5:
+ * provide a helper for USB interfaces (Alan)
+ * add FIXME item to documentation and TODO list (Daniel)
+v4:
+ * implement workaround with USB helper functions (Greg)
+ * use struct usb_device->bus->sysdev as DMA device (Takashi)
+v3:
+ * drop gem_create_object
+ * use DMA mask of USB controller, if any (Daniel, Christian, Noralf)
+v2:
+ * move fix to importer side (Christian, Daniel)
+ * update SHMEM and CMA helpers for new PRIME callbacks
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Fixes: 6eb0233ec2d0 ("usb: don't inherity DMA properties for USB devices")
+Tested-by: Pavel Machek <pavel@ucw.cz>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Acked-by: Christian König <christian.koenig@amd.com>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Acked-by: Noralf Trønnes <noralf@tronnes.org>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: <stable@vger.kernel.org> # v5.10+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210303133229.3288-1-tzimmermann@suse.de
+Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/gpu/todo.rst | 21 +++++++++++++++++++
+ drivers/gpu/drm/tiny/gm12u320.c | 44 ++++++++++++++++++++++++++++++++--------
+ drivers/gpu/drm/udl/udl_drv.c | 17 +++++++++++++++
+ drivers/gpu/drm/udl/udl_drv.h | 1
+ drivers/gpu/drm/udl/udl_main.c | 10 +++++++++
+ drivers/usb/core/usb.c | 32 +++++++++++++++++++++++++++++
+ include/linux/usb.h | 2 +
+ 7 files changed, 119 insertions(+), 8 deletions(-)
+
+--- a/Documentation/gpu/todo.rst
++++ b/Documentation/gpu/todo.rst
+@@ -594,6 +594,27 @@ Some of these date from the very introdu
+
+ Level: Intermediate
+
++Remove automatic page mapping from dma-buf importing
++----------------------------------------------------
++
++When importing dma-bufs, the dma-buf and PRIME frameworks automatically map
++imported pages into the importer's DMA area. drm_gem_prime_fd_to_handle() and
++drm_gem_prime_handle_to_fd() require that importers call dma_buf_attach()
++even if they never do actual device DMA, but only CPU access through
++dma_buf_vmap(). This is a problem for USB devices, which do not support DMA
++operations.
++
++To fix the issue, automatic page mappings should be removed from the
++buffer-sharing code. Fixing this is a bit more involved, since the import/export
++cache is also tied to &drm_gem_object.import_attach. Meanwhile we paper over
++this problem for USB devices by fishing out the USB host controller device, as
++long as that supports DMA. Otherwise importing can still needlessly fail.
++
++Contact: Thomas Zimmermann <tzimmermann@suse.de>, Daniel Vetter
++
++Level: Advanced
++
++
+ Better Testing
+ ==============
+
+--- a/drivers/gpu/drm/tiny/gm12u320.c
++++ b/drivers/gpu/drm/tiny/gm12u320.c
+@@ -83,6 +83,7 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco
+
+ struct gm12u320_device {
+ struct drm_device dev;
++ struct device *dmadev;
+ struct drm_simple_display_pipe pipe;
+ struct drm_connector conn;
+ unsigned char *cmd_buf;
+@@ -601,6 +602,22 @@ static const uint64_t gm12u320_pipe_modi
+ DRM_FORMAT_MOD_INVALID
+ };
+
++/*
++ * FIXME: Dma-buf sharing requires DMA support by the importing device.
++ * This function is a workaround to make USB devices work as well.
++ * See todo.rst for how to fix the issue in the dma-buf framework.
++ */
++static struct drm_gem_object *gm12u320_gem_prime_import(struct drm_device *dev,
++ struct dma_buf *dma_buf)
++{
++ struct gm12u320_device *gm12u320 = to_gm12u320(dev);
++
++ if (!gm12u320->dmadev)
++ return ERR_PTR(-ENODEV);
++
++ return drm_gem_prime_import_dev(dev, dma_buf, gm12u320->dmadev);
++}
++
+ DEFINE_DRM_GEM_FOPS(gm12u320_fops);
+
+ static const struct drm_driver gm12u320_drm_driver = {
+@@ -614,6 +631,7 @@ static const struct drm_driver gm12u320_
+
+ .fops = &gm12u320_fops,
+ DRM_GEM_SHMEM_DRIVER_OPS,
++ .gem_prime_import = gm12u320_gem_prime_import,
+ };
+
+ static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
+@@ -640,15 +658,18 @@ static int gm12u320_usb_probe(struct usb
+ struct gm12u320_device, dev);
+ if (IS_ERR(gm12u320))
+ return PTR_ERR(gm12u320);
++ dev = &gm12u320->dev;
++
++ gm12u320->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
++ if (!gm12u320->dmadev)
++ drm_warn(dev, "buffer sharing not supported"); /* not an error */
+
+ INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
+ mutex_init(&gm12u320->fb_update.lock);
+
+- dev = &gm12u320->dev;
+-
+ ret = drmm_mode_config_init(dev);
+ if (ret)
+- return ret;
++ goto err_put_device;
+
+ dev->mode_config.min_width = GM12U320_USER_WIDTH;
+ dev->mode_config.max_width = GM12U320_USER_WIDTH;
+@@ -658,15 +679,15 @@ static int gm12u320_usb_probe(struct usb
+
+ ret = gm12u320_usb_alloc(gm12u320);
+ if (ret)
+- return ret;
++ goto err_put_device;
+
+ ret = gm12u320_set_ecomode(gm12u320);
+ if (ret)
+- return ret;
++ goto err_put_device;
+
+ ret = gm12u320_conn_init(gm12u320);
+ if (ret)
+- return ret;
++ goto err_put_device;
+
+ ret = drm_simple_display_pipe_init(&gm12u320->dev,
+ &gm12u320->pipe,
+@@ -676,24 +697,31 @@ static int gm12u320_usb_probe(struct usb
+ gm12u320_pipe_modifiers,
+ &gm12u320->conn);
+ if (ret)
+- return ret;
++ goto err_put_device;
+
+ drm_mode_config_reset(dev);
+
+ usb_set_intfdata(interface, dev);
+ ret = drm_dev_register(dev, 0);
+ if (ret)
+- return ret;
++ goto err_put_device;
+
+ drm_fbdev_generic_setup(dev, 0);
+
+ return 0;
++
++err_put_device:
++ put_device(gm12u320->dmadev);
++ return ret;
+ }
+
+ static void gm12u320_usb_disconnect(struct usb_interface *interface)
+ {
+ struct drm_device *dev = usb_get_intfdata(interface);
++ struct gm12u320_device *gm12u320 = to_gm12u320(dev);
+
++ put_device(gm12u320->dmadev);
++ gm12u320->dmadev = NULL;
+ drm_dev_unplug(dev);
+ drm_atomic_helper_shutdown(dev);
+ }
+--- a/drivers/gpu/drm/udl/udl_drv.c
++++ b/drivers/gpu/drm/udl/udl_drv.c
+@@ -32,6 +32,22 @@ static int udl_usb_resume(struct usb_int
+ return drm_mode_config_helper_resume(dev);
+ }
+
++/*
++ * FIXME: Dma-buf sharing requires DMA support by the importing device.
++ * This function is a workaround to make USB devices work as well.
++ * See todo.rst for how to fix the issue in the dma-buf framework.
++ */
++static struct drm_gem_object *udl_driver_gem_prime_import(struct drm_device *dev,
++ struct dma_buf *dma_buf)
++{
++ struct udl_device *udl = to_udl(dev);
++
++ if (!udl->dmadev)
++ return ERR_PTR(-ENODEV);
++
++ return drm_gem_prime_import_dev(dev, dma_buf, udl->dmadev);
++}
++
+ DEFINE_DRM_GEM_FOPS(udl_driver_fops);
+
+ static const struct drm_driver driver = {
+@@ -40,6 +56,7 @@ static const struct drm_driver driver =
+ /* GEM hooks */
+ .fops = &udl_driver_fops,
+ DRM_GEM_SHMEM_DRIVER_OPS,
++ .gem_prime_import = udl_driver_gem_prime_import,
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+--- a/drivers/gpu/drm/udl/udl_drv.h
++++ b/drivers/gpu/drm/udl/udl_drv.h
+@@ -50,6 +50,7 @@ struct urb_list {
+ struct udl_device {
+ struct drm_device drm;
+ struct device *dev;
++ struct device *dmadev;
+
+ struct drm_simple_display_pipe display_pipe;
+
+--- a/drivers/gpu/drm/udl/udl_main.c
++++ b/drivers/gpu/drm/udl/udl_main.c
+@@ -315,6 +315,10 @@ int udl_init(struct udl_device *udl)
+
+ DRM_DEBUG("\n");
+
++ udl->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
++ if (!udl->dmadev)
++ drm_warn(dev, "buffer sharing not supported"); /* not an error */
++
+ mutex_init(&udl->gem_lock);
+
+ if (!udl_parse_vendor_descriptor(udl)) {
+@@ -343,12 +347,18 @@ int udl_init(struct udl_device *udl)
+ err:
+ if (udl->urbs.count)
+ udl_free_urb_list(dev);
++ put_device(udl->dmadev);
+ DRM_ERROR("%d\n", ret);
+ return ret;
+ }
+
+ int udl_drop_usb(struct drm_device *dev)
+ {
++ struct udl_device *udl = to_udl(dev);
++
+ udl_free_urb_list(dev);
++ put_device(udl->dmadev);
++ udl->dmadev = NULL;
++
+ return 0;
+ }
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -748,6 +748,38 @@ void usb_put_intf(struct usb_interface *
+ }
+ EXPORT_SYMBOL_GPL(usb_put_intf);
+
++/**
++ * usb_intf_get_dma_device - acquire a reference on the usb interface's DMA endpoint
++ * @intf: the usb interface
++ *
++ * While a USB device cannot perform DMA operations by itself, many USB
++ * controllers can. A call to usb_intf_get_dma_device() returns the DMA endpoint
++ * for the given USB interface, if any. The returned device structure must be
++ * released with put_device().
++ *
++ * See also usb_get_dma_device().
++ *
++ * Returns: A reference to the usb interface's DMA endpoint; or NULL if none
++ * exists.
++ */
++struct device *usb_intf_get_dma_device(struct usb_interface *intf)
++{
++ struct usb_device *udev = interface_to_usbdev(intf);
++ struct device *dmadev;
++
++ if (!udev->bus)
++ return NULL;
++
++ dmadev = get_device(udev->bus->sysdev);
++ if (!dmadev || !dmadev->dma_mask) {
++ put_device(dmadev);
++ return NULL;
++ }
++
++ return dmadev;
++}
++EXPORT_SYMBOL_GPL(usb_intf_get_dma_device);
++
+ /* USB device locking
+ *
+ * USB devices and interfaces are locked using the semaphore in their
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -746,6 +746,8 @@ extern int usb_lock_device_for_reset(str
+ extern int usb_reset_device(struct usb_device *dev);
+ extern void usb_queue_reset_device(struct usb_interface *dev);
+
++extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
++
+ #ifdef CONFIG_ACPI
+ extern int usb_acpi_set_power_state(struct usb_device *hdev, int index,
+ bool enable);
net-hns3-fix-bug-when-calculating-the-tcam-table-info.patch
s390-cio-return-efault-if-copy_to_user-fails.patch
bnxt_en-reliably-allocate-irq-table-on-reset-to-avoid-crash.patch
+drm-fb-helper-only-unmap-if-buffer-not-null.patch
+drm-compat-clear-bounce-structures.patch
+drm-radeon-also-init-gem-funcs-in-radeon_gem_prime_import_sg_table.patch
+drm-amd-display-add-a-backlight-module-option.patch
+drm-amdgpu-display-use-gfp_atomic-in-dcn21_validate_bandwidth_fp.patch
+drm-amd-display-fix-nested-fpu-context-in-dcn21_validate_bandwidth.patch
+drm-amd-pm-correct-the-watermark-settings-for-polaris.patch
+drm-amd-pm-bug-fix-for-pcie-dpm.patch
+drm-amdgpu-display-simplify-backlight-setting.patch
+drm-amdgpu-display-don-t-assert-in-set-backlight-function.patch
+drm-amdgpu-display-handle-aux-backlight-in-backlight_get_brightness.patch
+drm-shmem-helper-check-for-purged-buffers-in-fault-handler.patch
+drm-shmem-helper-don-t-remove-the-offset-in-vm_area_struct-pgoff.patch
+drm-use-usb-controller-s-dma-mask-when-importing-dmabufs.patch
+drm-amdgpu-fix-s0ix-handling-when-the-config_amd_pmc-m.patch