From: sashiko-bot@kernel.org
To: "Yongxing Mou" <yongxing.mou@oss.qualcomm.com>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v7 24/35] drm/msm/dp: add atomic stream handling for MST
Date: Tue, 29 Sep 2026 04:54:28 +0000 [thread overview]
Message-ID: <20260929045429.1C7E41F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260929-msm-dp-mst-v7-24-4b81473185e7@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] drm/msm/dp: MST topology state corruption on early return in atomic_enable
- [High] drm/msm/dp: sleeping in atomic context via mutex_lock in encoder callbacks
- [High] drm/msm/dp: NULL pointer dereference in msm_dp_mst_remove_payload
- [High] drm/msm/dp: kernel panic from division by zero in drm_dp_atomic_find_time_slots
- [High] drm/msm/dp: hardware desynchronization and crash on atomic_enable failure
--
commit b9a18785615c02ba155b20dae0aa027c5d95b815
Author: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
drm/msm/dp: add atomic stream handling for MST
This commit adds the atomic check, enable, and disable operations for MST
streams. It reserves VC payload bandwidth based on the negotiated link
parameters and updates the MST payload when enabling or disabling streams. The
patch also serializes access to the shared MST link state.
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 533109b4365c3..933dbfd30b567 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -2747,16 +2747,29 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
> static void dpu_encoder_mst_atomic_enable(struct drm_encoder *enc,
> struct drm_atomic_commit *state)
> {
> + if (msm_dp_mst_stream_enable(enc, state))
> + return;
> +
[Severity: High]
Does this early return cause hardware desynchronization if
msm_dp_mst_stream_enable() fails?
The DRM core ignores atomic_enable failures, which means the state will
transition to active. The enable sequence bails out on error here, skipping the
virtual encoder initialization in dpu_encoder_virt_atomic_enable().
> dpu_encoder_virt_atomic_enable(enc, state);
> }
>
> static void dpu_encoder_mst_atomic_disable(struct drm_encoder *enc,
> struct drm_atomic_commit *state)
> {
> + msm_dp_mst_stream_disable(enc, state);
> dpu_encoder_virt_atomic_disable(enc, state);
[Severity: High]
Does this unconditionally access hardware during teardown, assuming
dpu_encoder_virt_atomic_enable() had succeeded?
Since the virtual encoder might never have been initialized or clocked if the
early return in dpu_encoder_mst_atomic_enable() was taken, this call attempts
to access unclocked hardware registers (e.g., waiting for TX completion) which
can result in a bus error, system hang, or kernel crash.
> diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
> index 88687b97ed6e6..fd8fd6fd10bdf 100644
> --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c
> +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
> @@ -133,6 +136,45 @@ static int msm_dp_mst_connector_atomic_check(struct drm_connector *connector,
[ ... ]
> +static void msm_dp_mst_remove_payload(struct msm_dp_mst *mst,
> + struct drm_dp_mst_topology_state *mst_state,
> + struct msm_dp_panel *panel)
> +{
> + struct msm_dp_panel *dp_panel;
> + struct drm_dp_mst_atomic_payload *payload;
> + int i;
> +
> + msm_dp_display_set_stream_info(mst->msm_dp, panel, 0, 0, 0);
> +
> + /* Apply the slot shift to the remaining payloads. */
> + for (i = 0; i < mst->max_streams; i++) {
> + dp_panel = mst->mst_encoders[i].dp_panel;
> + if (dp_panel == panel || !dp_panel->connector)
> + continue;
[Severity: High]
Could this dereference a NULL pointer?
The mst->mst_encoders array is zero-initialized. If an encoder was never
attached to a specific index, dp_panel will be NULL.
The || operator evaluates left-to-right. If dp_panel is NULL, the condition
dp_panel == panel evaluates to false, and the code immediately evaluates
!dp_panel->connector, which will dereference the NULL pointer.
> +
> + payload = drm_atomic_get_mst_payload_state(mst_state,
[ ... ]
> +int msm_dp_mst_stream_enable(struct drm_encoder *encoder,
> + struct drm_atomic_commit *state)
> +{
[ ... ]
> + int rc;
> +
> + guard(mutex)(&mst->mst_lock);
> +
[Severity: High]
Does this acquire a sleeping lock inside an atomic context?
The DRM subsystem guidelines state that display encoder atomic_enable and
atomic_disable callbacks execute in atomic context where sleeping is strictly
forbidden. This function is called from the atomic context via
dpu_encoder_mst_atomic_enable() and acquires a sleeping lock, which can cause
scheduler violations, kernel warnings, and potential deadlocks.
> + drm_connector_get(connector);
> + panel->connector = connector;
> +
> + rc = msm_dp_display_set_mode_helper(dp_display, state, encoder, panel);
> + if (rc) {
> + drm_err(dp_display->drm_dev,
> + "[MST] stream:%u set_mode failed rc=%d\n", panel->stream_id, rc);
> + return rc;
> + }
> +
[Severity: High]
Does this early return bypass drm_dp_add_payload_part1()?
By returning early here, the MST payload state is left uninitialized for the
later disable path. Because the DRM core does not handle atomic_enable
failures, the commit completes and the payload's vc_start_slot remains -1.
> + rc = msm_dp_display_prepare_link(dp_display);
> + if (rc) {
> + drm_err(dp_display->drm_dev,
> + "[MST] stream:%u prepare_link failed rc=%d\n", panel->stream_id, rc);
> + return rc;
> + }
> +
[Severity: High]
Does this early return also bypass the required MST software state updates?
> + drm_dp_mst_update_slots(mst_state, DP_CAP_ANSI_8B10B);
[ ... ]
> +void msm_dp_mst_stream_disable(struct drm_encoder *encoder,
> + struct drm_atomic_commit *state)
> +{
[ ... ]
> + struct drm_dp_mst_atomic_payload *new_payload =
> + drm_atomic_get_mst_payload_state(new_mst_state, mst_conn->mst_port);
> +
> + guard(mutex)(&mst->mst_lock);
> +
[Severity: High]
Is this mutex acquisition also performed in the atomic disable path?
> + drm_dp_remove_payload_part1(&mst->mst_mgr, new_mst_state, new_payload);
> +
> + drm_dp_remove_payload_part2(&mst->mst_mgr, new_mst_state, old_payload, new_payload);
> +
[Severity: High]
Does this unconditional cleanup execute during teardown regardless of whether
the enable succeeded?
If drm_dp_add_payload_part1() was bypassed during enable,
drm_dp_remove_payload_part2() will subtract old_payload->time_slots from
mgr->next_start_slot and shift all payloads with a vc_start_slot greater than
-1. Because the payload count was never incremented, this underflows the
payload count and incorrectly shifts the slots of all active payloads,
permanently corrupting the shared MST topology manager state.
> + msm_dp_mst_remove_payload(mst, new_mst_state, panel);
[ ... ]
> +void msm_dp_mst_stream_post_disable(struct drm_encoder *encoder,
> + struct drm_atomic_commit *state)
> +{
[ ... ]
> + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder);
> +
> + guard(mutex)(&mst->mst_lock);
> +
[Severity: High]
Is this mutex acquisition also performed in the atomic post-disable path?
> + msm_dp_display_atomic_post_disable_helper(mst->msm_dp, panel);
[ ... ]
> +int msm_dp_mst_stream_atomic_check(struct drm_encoder *enc,
> + struct drm_crtc_state *crtc_state,
> + struct drm_connector_state *conn_state)
> +{
[ ... ]
> + mst_state = drm_atomic_get_mst_topology_state(crtc_state->state, &mst->mst_mgr);
> + if (IS_ERR(mst_state))
> + return PTR_ERR(mst_state);
> +
> + if (!dfixed_trunc(mst_state->pbn_div)) {
> + mst_state->pbn_div =
> + drm_dp_get_vc_payload_bw(mst->link->link_caps.rate,
> + mst->link->link_caps.num_lanes);
> + }
> +
[Severity: High]
Can this calculate the payload bandwidth without verifying if the link rate is
valid, passing a zero divisor down to the DRM helpers?
If link_caps.rate is 0 (which can occur if the sink is disconnected or link
training failed prior to the atomic commit), drm_dp_get_vc_payload_bw() returns
0, setting pbn_div.full to 0.
The code then calls drm_dp_atomic_find_time_slots(), which executes
DIV_ROUND_UP(..., topology_state->pbn_div.full). Userspace can trigger an
atomic commit at any time via the DRM IOCTL, and doing so when the link rate
is 0 triggers a division by zero, which results in a kernel panic.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260929-msm-dp-mst-v7-0-4b81473185e7@oss.qualcomm.com?part=24
next prev parent reply other threads:[~2026-09-29 4:54 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 4:25 [PATCH v7 00/35] drm/msm/dp: Add MST support for MSM chipsets Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 01/35] drm/msm/dp: move link-level teardown from display_disable to display_unprepare Yongxing Mou
2026-09-29 4:49 ` sashiko-bot
2026-10-01 10:11 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 02/35] drm/msm/dp: Pass panel to msm_dp_ctrl_config_msa() Yongxing Mou
2026-10-01 10:13 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 03/35] drm/msm/dp: drop redundant config_ctrl_link() from msm_dp_ctrl_on_stream() Yongxing Mou
2026-10-01 10:13 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 04/35] drm/msm/dp: introduce stream_id for each DP panel Yongxing Mou
2026-09-29 4:44 ` sashiko-bot
2026-10-01 10:23 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 05/35] drm/msm/dp: add support for programming p1/p2/p3 register blocks Yongxing Mou
2026-10-01 10:24 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 06/35] drm/msm/dp: add MST stream register definitions Yongxing Mou
2026-10-01 10:26 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 07/35] drm/msm/dp: add stream-aware link register accessors Yongxing Mou
2026-09-29 4:48 ` sashiko-bot
2026-10-01 10:26 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 08/35] drm/msm/dp: add support to send ACT packets for MST Yongxing Mou
2026-09-29 4:42 ` sashiko-bot
2026-10-01 10:32 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 09/35] drm/msm/dp: add support to enable MST in mainlink control Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 10/35] drm/msm/dp: no need to update tu calculation for mst Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 11/35] drm/msm/dp: always program MST_FIFO_CONSTANT_FILL for MST use cases Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 12/35] drm/msm/dp: add support for sending VCPF packets in DP controller Yongxing Mou
2026-09-29 4:49 ` sashiko-bot
2026-10-01 10:34 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 13/35] drm/msm/dp: add support for MST channel slot allocation Yongxing Mou
2026-09-29 4:42 ` sashiko-bot
2026-10-01 10:52 ` Dmitry Baryshkov
2026-09-29 4:25 ` [PATCH v7 14/35] drm/msm/dp: replace power_on with active_stream_cnt Yongxing Mou
2026-09-29 4:44 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 15/35] drm/msm/dp: factor out _helper variants of bridge ops accepting a panel Yongxing Mou
2026-09-29 4:43 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 16/35] drm/msm/dp: add link_ready to manage link-level operations Yongxing Mou
2026-09-29 4:39 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 17/35] drm/msm/dp: add msm_dp_display_get_panel() to initialize DP panel Yongxing Mou
2026-09-29 4:44 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 18/35] drm/msm/dp: introduce dp_mst_drm module Yongxing Mou
2026-09-29 4:48 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 19/35] drm/msm/dp: add MST connector creation and topology callbacks Yongxing Mou
2026-09-29 4:48 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 20/35] drm/msm/dpu: pass msm_display_info to dpu_encoder_get_intf() Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 21/35] drm/msm/dpu: use stream_id to select MST interfaces Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 22/35] drm/msm/dpu: add per-stream MST encoders Yongxing Mou
2026-09-29 4:46 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 23/35] drm/msm/dp: move link capabilities to dp_link Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 24/35] drm/msm/dp: add atomic stream handling for MST Yongxing Mou
2026-09-29 4:54 ` sashiko-bot [this message]
2026-09-29 4:25 ` [PATCH v7 25/35] drm/bridge_connector: suppress hotplug for IRQ_HPD without status changes Yongxing Mou
2026-09-29 4:51 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 26/35] drm/bridge_connector: avoid detect-based HPD notifications for DisplayPort Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 27/35] drm/msm/dp: add HPD callback for dp MST Yongxing Mou
2026-09-29 4:55 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 28/35] drm/msm/dp: wire MST helpers into atomic check and commit paths Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 29/35] drm/msm/dp: mark the SST bridge disconnected when mst is active Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 30/35] drm/msm/dp: enable MST on capable sinks Yongxing Mou
2026-09-29 4:58 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 31/35] drm/msm/dp: mark the SST bridge disconnected when an MST-capable sink is present Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 32/35] drm/msm/dp: mark the SST connector disconnected when MST is enabled Yongxing Mou
2026-09-29 4:54 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 33/35] drm/msm/dp: wake threaded handler for HPD IRQs Yongxing Mou
2026-09-29 4:25 ` [PATCH v7 34/35] drm/msm/dp: order IRQ HPD handling with plug state changes Yongxing Mou
2026-09-29 4:54 ` sashiko-bot
2026-09-29 4:25 ` [PATCH v7 35/35] soc: qcom: pmic-glink-altmode: skip retimer reset on DP IRQ Yongxing Mou
2026-09-29 4:55 ` sashiko-bot
2026-10-03 0:46 ` [PATCH v7 00/35] drm/msm/dp: Add MST support for MSM chipsets Dmitry Baryshkov
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=20260929045429.1C7E41F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=yongxing.mou@oss.qualcomm.com \
/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