From: sashiko-bot@kernel.org
To: "Andrei Rusu de Castro" <arc@empyreal.works>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v2 3/4] drm/amd/display: pass userspace brightness to power module
Date: Thu, 03 Sep 2026 07:50:05 +0000 [thread overview]
Message-ID: <20260903075005.CEF921F000E9@smtp.kernel.org> (raw)
In-Reply-To: <065649410e7f8682d15048a7a49cff5d89e54fb3.1788388049.git.arc@empyreal.works>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
New issues:
- [Medium] The brightness quirk mask is not applied to `backlight_millinits` for AMD AUX panels, causing firmware to write unmasked values during autonomous operations
Pre-existing issues:
- [High] Unprotected traversal of drm_mode_config.connector_list
- [High] Unprotected access to `dm->dc->current_state` leading to potential Use-After-Free
- [High] Potential division by zero in brightness conversion functions when firmware capabilities are anomalous
- [High] Incomplete bounds validation during power module creation allows multi-display setups to trigger a division by zero
--
commit 8608a59a12eb05fd14ffc0e7cb1af582e44dade9
Author: Andrei Rusu de Castro <arc@empyreal.works>
Date: Wed Sep 2 22:31:59 2026 +0000
drm/amd/display: pass userspace brightness to power module
The patch adjusts how brightness is passed to the power module in amdgpu_dm,
keeping it as userspace percentage (millipercent) instead of converting to
PWM domain first. This fixes domain mismatch issues and handles panel-specific
brightness quirks for AMD AUX writes.
Closes: https://sashiko.dev/#/patchset/20260902-brightness-cover-abf809f2@empyreal.works?part=3
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
[ ... ]
> @@ -218,6 +218,39 @@ u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
> }
> EXPORT_IF_KUNIT(convert_brightness_to_user);
>
> +static u32 convert_brightness_to_millipercent(const struct amdgpu_dm_backlight_caps *caps,
> + u32 brightness)
> +{
> + unsigned int min, max;
> +
> + if (!get_brightness_range(caps, &min, &max) || max <= min)
> + return 0;
> +
> + if (brightness >= max)
> + return 100 * 1000;
> +
> + return DIV_ROUND_CLOSEST_ULL((u64)brightness * 100 * 1000, max);
> +}
> +
> +STATIC_IFN_KUNIT
> +u32 convert_brightness_for_power_module(const struct amdgpu_dm_backlight_caps *caps,
> + u32 user_brightness)
> +{
> + u32 brightness;
> +
> + if (!caps)
> + return user_brightness;
> +
> + if (!caps->aux_support)
> + return convert_brightness_to_millipercent(caps, user_brightness);
> +
> + brightness = convert_brightness_from_user(caps, user_brightness);
[Severity: High]
This is a pre-existing issue, but while convert_brightness_to_millipercent()
properly guards against max <= min to avoid division by zero, the
convert_brightness_from_user() function called here lacks these same guards.
Does convert_brightness_from_user() unconditionally divide by max, risking a
kernel panic if anomalous firmware sets max to zero? Similarly, does
convert_brightness_to_user() risk dividing by zero when evaluating max - min?
> +
> + return brightness;
> +}
[ ... ]
> @@ -262,7 +295,6 @@ void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
> bool rc = false, reallow_idle = false;
> struct drm_connector *connector;
> struct dc_stream_state *stream;
> - unsigned int min, max;
>
> list_for_each_entry(connector, &dm->ddev->mode_config.connector_list, head) {
[Severity: High]
This isn't a bug introduced by this patch, but is it safe to traverse the DRM
connector_list using the raw list_for_each_entry macro without holding
mode_config.mutex or using the drm_connector_list_iter API? Can a concurrent
hotplug event removing a connector leave this loop traversing a freed pointer,
resulting in a use-after-free?
[ ... ]
> @@ -285,12 +317,9 @@ void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
> /* update scratch register */
> if (bl_idx == 0)
> amdgpu_atombios_scratch_regs_set_backlight_level(dm->adev, dm->brightness[bl_idx]);
> - brightness = convert_brightness_from_user(caps, dm->brightness[bl_idx]);
> link = (struct dc_link *)dm->backlight_link[bl_idx];
> -
> - /* Apply brightness quirk */
> - if (caps->brightness_mask)
> - brightness |= caps->brightness_mask;
> + brightness = convert_brightness_for_power_module(caps,
> + dm->brightness[bl_idx]);
[Severity: High]
This is a pre-existing issue, but further down in this function,
dm_find_stream_with_link() is called before acquiring dc_lock. Inside
dm_find_stream_with_link(), the dm->dc->current_state pointer is dereferenced
and iterated over. Because this sysfs callback runs concurrently with atomic
commits (which free the old state), is there a risk of a use-after-free crash
by reading a stale current_state pointer before the lock is held?
[ ... ]
> --- a/drivers/gpu/drm/amd/display/modules/power/power.c
> +++ b/drivers/gpu/drm/amd/display/modules/power/power.c
> @@ -157,6 +157,8 @@ struct mod_power *mod_power_create(struct dc *dc,
> init_params[inst].use_custom_backlight_caps;
> core_power->bl_prop[inst].custom_backlight_caps_config_no =
> init_params[inst].custom_backlight_caps_config_no;
> + core_power->bl_prop[inst].brightness_mask =
> + init_params[inst].brightness_mask;
>
> // Do not allow less than 101 backlight levels
> if (init_params[inst].num_backlight_levels < 101)
[Severity: High]
This isn't a bug introduced by this patch, but further down in
mod_power_create(), a loop validates the brightness ranges for eDP instances:
for (inst = 0; inst < edp_num; inst++) {
if (core_power->bl_prop[inst].nits_range != 0 && ...) {
is_brightness_range_valid = true;
break;
}
}
Does this premature break cause the loop to exit without verifying remaining
instances? If panel 1 has a zero nits_range while panel 0 is valid, could
this lead to a division by zero later in backlight_millinit_to_pwm_legacy()
when it evaluates panel 1?
[ ... ]
> --- a/drivers/gpu/drm/amd/display/modules/power/power_abm.c
> +++ b/drivers/gpu/drm/amd/display/modules/power/power_abm.c
[ ... ]
> @@ -1020,6 +1050,11 @@ void fill_backlight_level_params(struct core_power *core_power,
>
> if (backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX && !is_hdr)
> backlight_level_params->control_type = BACKLIGHT_CONTROL_PWM;
> +
> + if (backlight_level_params->control_type == BACKLIGHT_CONTROL_PWM)
> + backlight_level_params->backlight_pwm_u16_16 =
> + backlight_apply_source_mask(core_power, backlight_pwm,
> + panel_inst);
> }
[Severity: Medium]
When backlight_level_params->control_type remains BACKLIGHT_CONTROL_AMD_AUX
(for instance, during HDR playback), the brightness_mask is not applied to
backlight_level_params->backlight_millinits here. Because these parameters
are subsequently passed to the DMCUB firmware for autonomous operations like
PSR/Replay exits, will this allow the firmware to write unmasked brightness
values directly to the panel, bypassing the quirk? Should
backlight_millinits also be masked here when the control type is AMD AUX?
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1788388049.git.arc@empyreal.works?part=3
next prev parent reply other threads:[~2026-09-03 7:50 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 12:31 [PATCH 0/4] drm/amd/display: fix brightness ownership through power module Andrei Rusu de Castro
2026-09-02 12:31 ` [PATCH 1/4] drm/amd/display: keep custom brightness curve in userspace domain Andrei Rusu de Castro
2026-09-02 12:31 ` [PATCH 2/4] drm/amd/display: test custom brightness with non-zero minimum Andrei Rusu de Castro
2026-09-02 12:32 ` [PATCH 3/4] drm/amd/display: pass userspace brightness to power module Andrei Rusu de Castro
2026-09-02 12:57 ` sashiko-bot
2026-09-02 12:33 ` [PATCH 4/4] drm/amd/display: test power module brightness input domain Andrei Rusu de Castro
2026-09-02 22:31 ` [PATCH v2 0/4] drm/amd/display: fix brightness ownership through power module Andrei Rusu de Castro
2026-09-02 22:31 ` [PATCH v2 1/4] drm/amd/display: keep custom brightness curve in userspace domain Andrei Rusu de Castro
2026-09-02 22:31 ` [PATCH v2 2/4] drm/amd/display: test custom brightness with non-zero minimum Andrei Rusu de Castro
2026-09-02 22:31 ` [PATCH v2 3/4] drm/amd/display: pass userspace brightness to power module Andrei Rusu de Castro
2026-09-03 7:50 ` sashiko-bot [this message]
2026-09-02 22:32 ` [PATCH v2 4/4] drm/amd/display: test power module brightness input domain Andrei Rusu de Castro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903075005.CEF921F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=arc@empyreal.works \
--cc=dri-devel@lists.freedesktop.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox