From: sashiko-bot@kernel.org
To: "Mario Limonciello (AMD)" <superm1@kernel.org>
Cc: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
intel-xe@lists.freedesktop.org
Subject: Re: [PATCH v10 11/15] drm/gud: add connector luminance support
Date: Mon, 02 Nov 2026 19:02:26 +0000 [thread overview]
Message-ID: <sashiko-outbox-193969@kernel.org> (raw)
In-Reply-To: <20261102-superm1-backlight-property-v10-11-b2a6f24131f5@kernel.org>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Critical] drm/gud: use-after-free on disconnect via gud_connector_disable_luminance()
- [High] drm/gud: infinite commit loop in gud_connector_set_luminance()
- [High] drm/gud: brightness clobbered to 0 in gud_connector_disable_luminance()
- [Medium] drm/gud: late property creation in gud_connector_backlight_register()
- [Low] drm/gud: undefined reference to backlight_device_unregister()
--
commit 58c61672659ddff3d1dca17855a27dcf7212a5b6
Author: Mario Limonciello <mario.limonciello@amd.com>
drm/gud: add connector luminance support
This commit exposes GUD display brightness through the connector LUMINANCE
property when CONFIG_DRM_LUMINANCE is enabled, storing brightness state on
struct gud_connector and reusing the asynchronous backlight workqueue path.
> diff --git a/drivers/gpu/drm/gud/Kconfig b/drivers/gpu/drm/gud/Kconfig
> index b4d2136942f0e..6c250d3d5e203 100644
> --- a/drivers/gpu/drm/gud/Kconfig
> +++ b/drivers/gpu/drm/gud/Kconfig
> @@ -7,7 +7,7 @@ config DRM_GUD
> select DRM_CLIENT_SELECTION
> select DRM_KMS_HELPER
> select DRM_GEM_SHMEM_HELPER
> - select BACKLIGHT_CLASS_DEVICE
> + select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
> help
> This is a DRM display driver for GUD USB Displays or display
> adapters.
> diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
> index 8141c3a1e30ad..bd7688676e9e1 100644
> --- a/drivers/gpu/drm/gud/gud_connector.c
> +++ b/drivers/gpu/drm/gud/gud_connector.c
[ ... ]
> @@ -84,7 +86,7 @@ static void gud_connector_backlight_update_status_work(struct work_struct *work)
> }
>
> /* Reuse tv.brightness to avoid having to subclass */
> - connector_state->tv.brightness = gconn->backlight->props.brightness;
> + connector_state->tv.brightness = READ_ONCE(gconn->brightness);
>
> ret = drm_atomic_commit(state);
> out:
[ ... ]
> @@ -132,6 +136,19 @@ static int gud_connector_backlight_register(struct gud_connector *gconn)
> .brightness = gconn->initial_brightness,
> };
>
> + gconn->brightness = props.brightness;
> +
> + if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
> + int ret;
> +
> + ret = drm_connector_attach_luminance_property(connector, 0, props.max_brightness,
> + props.brightness);
> + if (ret)
> + return ret;
> +
> + return 0;
> + }
[Severity: Medium]
Won't attaching the LUMINANCE property in gud_connector_backlight_register()
trigger a WARN_ON in __drm_mode_object_add() on every probe when
CONFIG_DRM_LUMINANCE is enabled?
During gud_probe(), drm_dev_register() registers the DRM minor nodes and sets
dev->registered = true before calling:
drm_modeset_register_all()
-> drm_connector_register_all()
-> drm_connector_register()
-> gud_connector_late_register()
-> gud_connector_backlight_register()
-> drm_connector_attach_luminance_property()
-> drm_property_create_range()
-> drm_property_create()
-> drm_mode_object_add()
-> __drm_mode_object_add()
In drivers/gpu/drm/drm_mode_object.c:__drm_mode_object_add():
WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
Because gud_drm_driver.load is NULL, dev->registered is already true, and
obj_free_cb is NULL for DRM properties, this warning fires unconditionally and
mutates dev->mode_config.property_list, connector->base.properties, and
connector->state->luminance after userspace already has access to the DRM
device. Should drm_connector_attach_luminance_property() be called during
connector initialization in gud_connector_add_properties() before
drm_mode_config_reset() and drm_dev_register() instead?
> +
> name = kasprintf(GFP_KERNEL, "card%d-%s-backlight",
> connector->dev->primary->index, connector->name);
> if (!name)
> @@ -314,12 +331,37 @@ static int gud_connector_atomic_check(struct drm_connector *connector,
> return 0;
> }
>
> +static void gud_connector_set_luminance(const struct drm_connector_state *conn_state);
> +static void gud_connector_disable_luminance(const struct drm_connector_state *conn_state);
> +
> static const struct drm_connector_helper_funcs gud_connector_helper_funcs = {
> .detect_ctx = gud_connector_detect,
> .get_modes = gud_connector_get_modes,
> .atomic_check = gud_connector_atomic_check,
> + .set_luminance = gud_connector_set_luminance,
> + .disable_luminance = gud_connector_disable_luminance,
> };
>
> +static void gud_connector_set_luminance(const struct drm_connector_state *conn_state)
> +{
> + struct drm_connector *connector = conn_state->connector;
> + struct gud_connector *gconn = to_gud_connector(connector);
> + unsigned int luminance = conn_state->luminance;
> +
> + WRITE_ONCE(gconn->brightness, luminance);
> +
> + /* The workqueue will apply it to the hardware */
> + queue_work(system_long_wq, &gconn->backlight_work);
> +}
[Severity: High]
Does queueing gconn->backlight_work from gud_connector_set_luminance() cause
an infinite loop of atomic commits on system_long_wq whenever the connector is
active on a CRTC?
When gconn->backlight_work runs gud_connector_backlight_update_status_work(),
the workqueue core clears WORK_STRUCT_PENDING_BIT before invoking the work
callback. gud_connector_backlight_update_status_work() then adds the connector
to a new commit state via drm_atomic_get_connector_state(state, connector) and
calls drm_atomic_commit(state) synchronously:
gud_connector_backlight_update_status_work()
-> drm_atomic_commit()
-> drm_atomic_helper_commit_tail_rpm()
-> drm_atomic_helper_commit_modeset_enables()
-> drm_atomic_helper_commit_luminance_enables()
-> gud_connector_set_luminance()
In drivers/gpu/drm/drm_atomic_helper.c:drm_atomic_helper_commit_luminance_enables():
for_each_new_connector_in_state(state, connector, new_conn_state, i) {
const struct drm_connector_helper_funcs *funcs;
if (!connector->luminance_property || !new_conn_state->crtc ||
!new_conn_state->crtc->state->active)
continue;
funcs = connector->helper_private;
if (funcs && funcs->set_luminance)
funcs->set_luminance(new_conn_state);
}
Because the connector is in the commit state, connector->luminance_property is
non-NULL, and new_conn_state->crtc->state->active is true,
drm_atomic_helper_commit_luminance_enables() unconditionally invokes
gud_connector_set_luminance() again during the work item's own
drm_atomic_commit() call. That re-queues gconn->backlight_work while the work
function is still executing, so system_long_wq immediately runs
gud_connector_backlight_update_status_work() again in an unbounded loop.
In addition, when old_state->tv.brightness != new_state->tv.brightness,
gud_connector_atomic_check() sets new_crtc_state->connectors_changed = true,
causing drm_atomic_helper_commit_modeset_disables() to also call
drm_atomic_helper_commit_luminance_disables() ->
gud_connector_disable_luminance() before
drm_atomic_helper_commit_luminance_enables() runs.
> +
> +static void gud_connector_disable_luminance(const struct drm_connector_state *conn_state)
> +{
> + struct gud_connector *gconn = to_gud_connector(conn_state->connector);
> +
> + WRITE_ONCE(gconn->brightness, 0);
> + queue_work(system_long_wq, &gconn->backlight_work);
> +}
[Severity: Critical]
Can gud_connector_disable_luminance() re-queue gconn->backlight_work after
gud_connector_early_unregister() has already canceled it, leading to a
use-after-free of struct gud_connector on USB disconnect?
In drivers/gpu/drm/gud/gud_drv.c:gud_disconnect():
drm_kms_helper_poll_fini(drm);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
First, drm_dev_unplug() runs:
drm_dev_unplug()
-> drm_dev_unregister()
-> drm_modeset_unregister_all()
-> drm_connector_unregister()
-> gud_connector_early_unregister()
-> cancel_work_sync(&gconn->backlight_work)
Next, drm_atomic_helper_shutdown() disables all active outputs:
drm_atomic_helper_shutdown()
-> drm_atomic_helper_disable_all()
-> drm_atomic_commit()
-> drm_atomic_helper_commit_modeset_disables()
-> disable_outputs()
-> drm_atomic_helper_commit_luminance_disables()
-> gud_connector_disable_luminance()
-> queue_work(system_long_wq, &gconn->backlight_work)
When gud_disconnect() finishes and devres releases the drm_device,
drm_mode_config_cleanup() calls gud_connector_destroy(), which cleans up the
connector (zeroing connector->dev) and calls kfree(gconn) without canceling
gconn->backlight_work. If gud_connector_backlight_update_status_work() is
still queued or running on system_long_wq, won't it access freed gconn memory
and dereference a NULL or freed connector->dev in drm_dev_enter()?
[Severity: High]
Also in gud_connector_disable_luminance(), doesn't setting gconn->brightness
to 0 and queueing gconn->backlight_work clobber connector_state->tv.brightness
and send an unpaired GUD_REQ_SET_STATE_CHECK over USB when a CRTC enters DPMS
off?
When a CRTC is set to DPMS off (new_crtc_state->enable == true,
new_crtc_state->active == false), drm_atomic_helper_commit_luminance_disables()
calls gud_connector_disable_luminance(), whereas
drm_atomic_helper_commit_luminance_enables() does not run because
new_crtc_state->active is false.
When gud_connector_backlight_update_status_work() subsequently runs on
system_long_wq, it sets connector_state->tv.brightness = 0 and commits:
1. gud_connector_atomic_check() sees old_state->tv.brightness !=
new_state->tv.brightness and sets new_crtc_state->connectors_changed = true.
2. Because crtc_state->enable is still true, gud_plane_atomic_check()
serializes connector_state->tv.brightness = 0 into GUD_REQ_SET_STATE_CHECK
and sends it to the USB device.
3. Because new_crtc_state->active is false,
drm_atomic_helper_commit_crtc_enable() skips gud_crtc_atomic_enable(),
leaving GUD_REQ_SET_STATE_CHECK unpaired with GUD_REQ_SET_STATE_COMMIT.
4. When a later commit re-enables the CRTC (active = true),
gud_plane_atomic_check() and gud_crtc_atomic_enable() run before
drm_atomic_helper_commit_luminance_enables(), so the display is first
enabled with tv.brightness == 0 before gud_connector_set_luminance() queues
a second full modeset commit to restore conn_state->luminance.
> +
> static int gud_connector_late_register(struct drm_connector *connector)
> {
> struct gud_connector *gconn = to_gud_connector(connector);
> @@ -334,7 +376,9 @@ static void gud_connector_early_unregister(struct drm_connector *connector)
> {
> struct gud_connector *gconn = to_gud_connector(connector);
>
> - backlight_device_unregister(gconn->backlight);
> + if (gconn->backlight)
> + backlight_device_unregister(gconn->backlight);
> +
> cancel_work_sync(&gconn->backlight_work);
> }
[Severity: Low]
Will gud_connector_early_unregister() fail to link when CONFIG_DRM_LUMINANCE=y
and CONFIG_BACKLIGHT_CLASS_DEVICE is disabled (or when CONFIG_DRM_GUD=y and
CONFIG_BACKLIGHT_CLASS_DEVICE=m)?
The Kconfig change updates DRM_GUD to:
select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
However, include/linux/backlight.h declares backlight_device_unregister() as
an external function without an inline stub when CONFIG_BACKLIGHT_CLASS_DEVICE
is not enabled. Because if (gconn->backlight) is a runtime check on a struct
member rather than !IS_ENABLED(CONFIG_DRM_LUMINANCE), the compiler cannot
eliminate the call to backlight_device_unregister() at compile time.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-superm1-backlight-property-v10-0-b2a6f24131f5@kernel.org?part=11
next prev parent reply other threads:[~2026-11-02 19:02 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20261102-superm1-backlight-property-v10-0-b2a6f24131f5@kernel.org>
[not found] ` <20261102-superm1-backlight-property-v10-1-b2a6f24131f5@kernel.org>
2026-11-02 17:07 ` [PATCH v10 01/15] drm: add connector LUMINANCE property sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-3-b2a6f24131f5@kernel.org>
2026-11-02 17:32 ` [PATCH v10 03/15] drm/amd: add luminance property support sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-5-b2a6f24131f5@kernel.org>
2026-11-02 18:00 ` [PATCH v10 05/15] drm/amd/display: update KUnit luminance fixtures sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-6-b2a6f24131f5@kernel.org>
2026-11-02 18:17 ` [PATCH v10 06/15] drm/i915/display: add luminance property support sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-7-b2a6f24131f5@kernel.org>
2026-11-02 18:24 ` [PATCH v10 07/15] drm/bridge: add connector luminance operations sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-8-b2a6f24131f5@kernel.org>
2026-11-02 18:34 ` [PATCH v10 08/15] drm/panel: add connector luminance forwarding sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-10-b2a6f24131f5@kernel.org>
2026-11-02 18:49 ` [PATCH v10 10/15] drm/nouveau: add connector luminance support sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-11-b2a6f24131f5@kernel.org>
2026-11-02 19:02 ` sashiko-bot [this message]
[not found] ` <20261102-superm1-backlight-property-v10-12-b2a6f24131f5@kernel.org>
2026-11-02 19:13 ` [PATCH v10 12/15] drm/radeon: " sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-13-b2a6f24131f5@kernel.org>
2026-11-02 19:22 ` [PATCH v10 13/15] drm/gma500: " sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-14-b2a6f24131f5@kernel.org>
2026-11-02 19:31 ` [PATCH v10 14/15] drm/bridge: add PS8622 " sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-15-b2a6f24131f5@kernel.org>
2026-11-02 19:49 ` [PATCH v10 15/15] drm/solomon: add SSD130x " sashiko-bot
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=sashiko-outbox-193969@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=superm1@kernel.org \
/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