From: sashiko-bot@kernel.org
To: "Jayant Shekhar" <jayant.shekhar@oss.qualcomm.com>
Cc: virtualization@lists.linux.dev, dri-devel@lists.freedesktop.org,
devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
media-ci@linuxtv.org, "Michael S. Tsirkin" <mst@redhat.com>,
"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH v2 15/23] drm/msm/dcp: Add DCP DSI host and panel support
Date: Mon, 26 Oct 2026 12:37:24 +0000 [thread overview]
Message-ID: <sashiko-outbox-185222@kernel.org> (raw)
In-Reply-To: <20261026-jshekhar-dcp-hlos-v2-15-7cf014efdee1@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
- [High] drm/msm/dcp: off-by-one DSC chroma and color space enums in dcp_dsi_host_attach()
- [High] drm/msm/dcp: deadlock and unsafe teardown in dcp_dsi_bridge_cleanup()
- [Medium] drm/msm/dcp: OF node leak of dcp_np on error in dcp_dsi_bridge_init()
- [Medium] drm/msm/dcp: dcp_dsi_bridge_setup_dsc() never sets dsc_rc_override
- [Medium] drm/msm/dcp: duplicate dsi_host_dev name in dcp_dsi_bridge_init()
- [Medium] drm/msm/dcp: invalid session close and goto mixing in dcp_dsi_bridge_prepare_session()
- [Medium] drm/msm/dcp: missing session_lock in dcp_dsi_bridge_atomic_enable()
- [Medium] drm/msm/dcp: unsynchronized session_id and packet_id in power control
- [Medium] drm/msm/dcp: firmware session leak on dcp_hfi_display_close() early return
- [Medium] drm/msm/dcp: wrong byte count returned for DSI reads in dcp_dsi_host_transfer()
--
commit 7535bc53c50473e4189f52c83b74358ab514c8d0
Author: Jayant Shekhar <jayant.shekhar@oss.qualcomm.com>
drm/msm/dcp: Add DCP DSI host and panel support
This commit implements the MIPI DSI host, panel-device support, bridge
state, DSC configuration, DCS transfers, and DSI buffer management for the
DCP display path.
> diff --git a/drivers/gpu/drm/msm/dcp/dcp_dsi_bridge.c b/drivers/gpu/drm/msm/dcp/dcp_dsi_bridge.c
> new file mode 100644
> index 0000000000000..b3e782b8f0470
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/dcp/dcp_dsi_bridge.c
> @@ -0,0 +1,1110 @@
[ ... ]
> +static void dcp_dsi_power_control_work(struct work_struct *work)
> +{
> + struct dcp_dsi_bridge *dsi_bridge =
> + container_of(work, struct dcp_dsi_bridge, power_control_work);
> + struct dcp_dpu_kms *kms = dsi_bridge->kms;
> +
> + dcp_hfi_display_power_control_ack(kms->hfi,
> + dsi_bridge->session_id,
> + dsi_bridge->power_packet_id);
> +
> + complete(&dsi_bridge->power_done);
> +}
> +
> +static void dcp_dsi_power_control_cb(void *priv, u32 display_id,
> + u32 power_mask, bool enable,
> + u32 packet_id)
> +{
> + struct dcp_dpu_kms *kms = priv;
> + struct dcp_dsi_bridge *dsi_bridge = NULL;
> + int idx;
> +
> + for (idx = 0; idx < ARRAY_SIZE(kms->dsi_bridge); idx++) {
> + struct dcp_dsi_bridge *b = kms->dsi_bridge[idx];
> +
> + if (b && b->session_id == display_id) {
> + dsi_bridge = b;
> + break;
> + }
> + }
> +
> + if (!dsi_bridge) {
> + dev_warn(kms->pm_dev,
> + "DSI: power_control for unknown display_id=%u\n", display_id);
> + return;
> + }
> +
> + dsi_bridge->power_packet_id = packet_id;
> + schedule_work(&dsi_bridge->power_control_work);
> +}
[Severity: Medium]
Are dsi_bridge->session_id and dsi_bridge->power_packet_id synchronized and
matched safely between dcp_dsi_power_control_cb() and
dcp_dsi_power_control_work()?
When dcp_hfi_dispatch_event() drops resp_drain_lock and invokes
dcp_dsi_power_control_cb(), the loop checks b->session_id == display_id
without checking b->session_open or holding session_lock. Since closed
bridges have session_id == 0, an unopened bridge matches when
display_id == 0, whereas a temporary session opened in
dcp_dsi_host_transfer() stores its session ID in a local variable and
leaves dsi_bridge->session_id == 0, failing to match a non-zero
display_id.
Furthermore, dcp_dsi_power_control_work() reads dsi_bridge->session_id and
dsi_bridge->power_packet_id without locking while
dcp_dsi_bridge_atomic_post_disable(), dcp_dsi_bridge_atomic_enable(), and
dcp_dsi_bridge_prepare_session() reset dsi_bridge->session_id = 0 without
flushing power_control_work. And in dcp_dsi_bridge_cleanup(),
dcp_hfi_clear_power_control_cb() does not wait for an in-flight callback
that already dropped resp_drain_lock, allowing
schedule_work(&dsi_bridge->power_control_work) to run after
cancel_work_sync().
[ ... ]
> +static int dcp_dsi_host_attach(struct mipi_dsi_host *host,
> + struct mipi_dsi_device *dsi)
> +{
> + struct dcp_dsi_bridge *dsi_bridge = to_dcp_dsi_host(host);
> + struct dcp_dsi_hfi_panel_config *cfg = &dsi_bridge->hfi_panel_config;
> + int ret;
[ ... ]
> + if (dsi->dsc) {
> + struct drm_dsc_config *dsc = dsi->dsc;
> + u32 chroma_format = 0;
> + u32 color_space = 0;
> +
> + if (dsc->native_422)
> + chroma_format = 1;
> + else if (dsc->native_420)
> + chroma_format = 2;
> + if (dsc->native_422 || dsc->native_420)
> + color_space = 1;
> +
> + cfg->dsc_enabled = true;
> + cfg->dsc_version_major = dsc->dsc_version_major;
> + cfg->dsc_version_minor = dsc->dsc_version_minor;
> + cfg->dsc_scr_version = 0;
> + cfg->dsc_slice_height = dsc->slice_height;
> + cfg->dsc_slice_width = dsc->slice_width;
> + cfg->dsc_slices_per_pkt = 1;
> + cfg->dsc_bits_per_component = dsc->bits_per_component;
> + cfg->dsc_pps_delay_ms = 0;
> + cfg->dsc_bits_per_pixel = dsc->bits_per_pixel;
> + cfg->dsc_chroma_format = chroma_format;
> + cfg->dsc_color_space = color_space;
[Severity: High]
Are chroma_format and color_space off by one here?
In drivers/gpu/drm/msm/dcp/hfi/hfi_defs_panel.h, the HFI protocol enums
packed into HFI_PROPERTY_PANEL_COMPRESSION_DATA by dcp_hfi_panel_init() are
1-based:
enum hfi_panel_chroma_format_type {
HFI_PANEL_CHROMA_FORMAT_444 = 1,
HFI_PANEL_CHROMA_FORMAT_422 = 2,
HFI_PANEL_CHROMA_FORMAT_420 = 3,
};
enum hfi_panel_color_space_type {
HFI_PANEL_COLOR_SPACE_RGB = 1,
HFI_PANEL_COLOR_SPACE_YUV = 2,
};
Should dcp_dsi_host_attach() use the HFI_PANEL_CHROMA_FORMAT_* and
HFI_PANEL_COLOR_SPACE_* constants instead of 0-based values?
[ ... ]
> +static ssize_t dcp_dsi_host_transfer(struct mipi_dsi_host *host,
> + const struct mipi_dsi_msg *msg)
> +{
> + struct dcp_dsi_bridge *dsi_bridge = to_dcp_dsi_host(host);
> + struct dcp_dpu_kms *kms = dsi_bridge->kms;
> + u32 session_id;
> + bool temporary_session = false;
> + ssize_t ret;
> +
> + guard(mutex)(&dsi_bridge->session_lock);
> + if (!dsi_bridge->dcs_tx_buf)
> + return -ENODEV;
> +
> + /* Serialize DCS transfers */
> + guard(mutex)(&dsi_bridge->dcs_lock);
> +
> + if (dsi_bridge->session_open) {
> + session_id = dsi_bridge->session_id;
> + } else {
> + /*
> + * mipi_dsi_host_ops::transfer() may be called while the host is
> + * disabled. Open a transaction-only DCP session in that case;
> + * atomic_pre_enable() will create the full display session later.
> + */
> + ret = dcp_hfi_display_enable(kms->hfi, dsi_bridge->intf_idx,
> + dsi_bridge->fw_display_id,
> + &session_id);
> + if (ret)
> + return ret;
> +
> + temporary_session = true;
> + }
> +
> + ret = dcp_hfi_dcs_transfer(kms->hfi, session_id, msg,
> + dsi_bridge->dcs_tx_buf, dsi_bridge->dcs_tx_iova,
> + dsi_bridge->dcs_rx_buf, dsi_bridge->dcs_rx_iova, 0,
> + dsi_bridge->hfi_panel_config.ctrl_indices[0]);
[Severity: Medium]
Does dcp_dsi_host_transfer() return the wrong byte count for DSI read
transfers and reject 0-parameter generic transfers?
In drivers/gpu/drm/msm/dcp/dcp_hfi_dsi_panel.c, dcp_hfi_dcs_transfer() ends
with:
if (msg->rx_len > 0)
memcpy(msg->rx_buf, rx_buf, msg->rx_len);
return msg->tx_len;
and rejects msg->tx_len == 0 at entry with -EINVAL.
For mipi_dsi_host_ops::transfer(), callers such as mipi_dsi_dcs_read() and
mipi_dsi_generic_read() expect the number of received bytes (msg->rx_len)
on read transfers, and 0-parameter generic transfers
(MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM and
MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) have msg->tx_len == 0.
> + if (temporary_session) {
> + int close_ret = dcp_hfi_display_close(kms->hfi, session_id);
> +
> + if (ret >= 0 && close_ret)
> + ret = close_ret;
> + }
[Severity: Medium]
Can calling dcp_hfi_display_close() here (and on the err_close path in
dcp_dsi_bridge_atomic_enable()) leak the firmware display session if
DISPLAY_DISABLE or DISPLAY_POST_DISABLE fails?
In drivers/gpu/drm/msm/dcp/dcp_hfi_dsi.c, dcp_hfi_display_close() returns
early before sending HFI_COMMAND_DISPLAY_CLOSE if either
dcp_hfi_display_disable() or dcp_hfi_display_post_disable() returns an
error:
int dcp_hfi_display_close(struct dcp_hfi *hfi, u32 session_id)
{
int ret;
ret = dcp_hfi_display_disable(hfi, session_id);
if (ret) {
dev_warn(hfi->dev, "HFI DISPLAY_DISABLE failed: %d\n", ret);
return ret;
}
ret = dcp_hfi_display_post_disable(hfi, session_id);
if (ret) {
dev_warn(hfi->dev, "HFI DISPLAY_POST_DISABLE failed: %d\n", ret);
return ret;
}
When closing a temporary session in dcp_dsi_host_transfer() (which only
called dcp_hfi_display_enable() and never called
dcp_hfi_display_post_enable()) or rolling back a partially enabled session
in dcp_dsi_bridge_atomic_enable(), an error from DISPLAY_DISABLE or
DISPLAY_POST_DISABLE skips HFI_COMMAND_DISPLAY_CLOSE while the driver drops
session_id and marks session_open = false. In contrast,
dcp_dsi_bridge_atomic_disable() and dcp_dsi_bridge_atomic_post_disable()
still send HFI_COMMAND_DISPLAY_CLOSE even if the preceding disable commands
warn.
[ ... ]
> +static int dcp_dsi_bridge_setup_dsc(struct dcp_dsi_bridge *dsi_bridge,
> + struct dcp_dsi_hfi_panel_config *cfg,
> + const struct drm_display_mode *mode)
> +{
[ ... ]
> + for (i = 0; i < ARRAY_SIZE(cfg->dsc_rc_min_qp); i++) {
> + cfg->dsc_rc_min_qp[i] = dsc->rc_range_params[i].range_min_qp;
> + cfg->dsc_rc_max_qp[i] = dsc->rc_range_params[i].range_max_qp;
> + cfg->dsc_rc_bpg_offsets[i] = dsc->rc_range_params[i].range_bpg_offset;
> + }
> +
> + return 0;
> +}
[Severity: Medium]
Should dcp_dsi_bridge_setup_dsc() also set cfg->dsc_rc_override = true?
dcp_dsi_host_attach() initializes cfg->dsc_rc_override = false, and
dcp_dsi_bridge_prepare_session() passes a stack-local copy of cfg to
dcp_dsi_bridge_setup_dsc() and then to dcp_hfi_panel_init(). In
drivers/gpu/drm/msm/dcp/dcp_hfi_dsi_panel.c, dcp_hfi_panel_init() only packs
HFI_PROPERTY_PANEL_COMPRESSION_RC_OVERRIDE when
(cfg->dsc_enabled && cfg->dsc_rc_override) is true, so the rate-control
parameters populated in cfg->dsc_rc_min_qp, cfg->dsc_rc_max_qp, and
cfg->dsc_rc_bpg_offsets are never sent to the firmware.
> +
> +int dcp_dsi_bridge_prepare_session(struct dcp_dsi_bridge *dsi_bridge,
> + const struct drm_display_mode *mode)
> +{
> + struct dcp_dpu_kms *kms = dsi_bridge->kms;
> + struct dcp_dsi_bridge_state *state = dcp_dsi_bridge_get_state(dsi_bridge);
> + struct dcp_dsi_hfi_panel_config cfg;
> + int ret;
> + u32 opened_session_id;
> +
> + if (!mode)
> + return -ENODEV;
> +
> + guard(mutex)(&dsi_bridge->session_lock);
> + if (dsi_bridge->session_open)
> + return 0;
> +
> + dsi_bridge->session_id = dsi_bridge->fw_display_id;
> +
> + if (!dsi_bridge->dsi_device)
> + return -ENODEV;
[ ... ]
> + ret = dcp_hfi_display_enable(kms->hfi,
> + dsi_bridge->intf_idx,
> + dsi_bridge->fw_display_id,
> + &opened_session_id);
> + if (ret) {
> + drm_err(kms->dev, "DSI%u: HFI DISPLAY_ENABLE failed: %d\n",
> + dsi_bridge->intf_idx, ret);
> + goto err_close;
> + }
> + dsi_bridge->session_id = opened_session_id;
> + dsi_bridge->session_open = true;
> + dcp_dsi_bridge_publish_session(dsi_bridge);
> +
> + drm_dbg_driver(kms->dev, "DSI%u: session prepared (session_id=%u)\n",
> + dsi_bridge->intf_idx, dsi_bridge->session_id);
> + return 0;
> +
> +err_close:
> + dcp_hfi_clear_power_control_cb(kms->hfi, kms);
> + dcp_hfi_display_close(kms->hfi, dsi_bridge->session_id);
> + dsi_bridge->session_id = 0;
> + dsi_bridge->session_open = false;
> + dcp_dsi_bridge_clear_session(dsi_bridge);
> +
> + return ret;
> +}
[Severity: Medium]
There appear to be several issues with error handling and cleanup in
dcp_dsi_bridge_prepare_session():
1. It mixes guard(mutex)(&dsi_bridge->session_lock) with goto err_close,
contrary to the cleanup.h guideline not to mix goto error paths and
scope-based cleanup helpers in the same function.
2. If !dsi_bridge->dsi_device is true, returning -ENODEV early leaves
dsi_bridge->session_id set to dsi_bridge->fw_display_id while
session_open is false.
3. Every goto err_close path triggers before dcp_hfi_display_enable() has
succeeded (even if dcp_dsi_bridge_setup_dsc() fails in software before
any HFI command is sent), yet err_close calls dcp_hfi_display_close() to
send DISPLAY_DISABLE, DISPLAY_POST_DISABLE, and DISPLAY_CLOSE for a
session that was never enabled.
4. Calling dcp_hfi_clear_power_control_cb(kms->hfi, kms) in err_close clears
the single shared power control callback on kms->hfi for all DSI bridges
in kms->dsi_bridge[].
> +
> +static void dcp_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
> + struct drm_atomic_commit *state)
> +{
> + struct dcp_dsi_bridge *dsi_bridge = to_dcp_dsi_bridge(bridge);
> + int ret;
> +
> + ret = dsi_bridge->session_open ? 0 : -ENODEV;
> + dcp_dsi_bridge_get_state(dsi_bridge)->prepare_error = ret;
> + if (ret)
> + drm_err(bridge->dev, "DSI%u: session prepare failed: %d\n",
> + dsi_bridge->intf_idx, ret);
> +}
> +
> +static void dcp_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
> + struct drm_atomic_commit *state)
> +{
> + struct dcp_dsi_bridge *dsi_bridge = to_dcp_dsi_bridge(bridge);
> + struct dcp_dpu_kms *kms = dsi_bridge->kms;
> + bool scan_start_registered = false;
> + bool scan_complete_registered = false;
> + bool autorefresh_enabled = false;
> + int ret;
> +
> + drm_dbg_driver(kms->dev,
> + "DSI%u: bridge atomic_enable (session_id=%u)\n",
> + dsi_bridge->intf_idx, dsi_bridge->session_id);
> +
> + if (dcp_dsi_bridge_get_state(dsi_bridge)->prepare_error)
> + return;
> + if (!dsi_bridge->session_open)
> + return;
> +
> + ret = dcp_hfi_display_post_enable(kms->hfi, dsi_bridge->session_id);
[ ... ]
> +err_close:
> + if (autorefresh_enabled)
> + dcp_hfi_crtc_set_autorefresh(kms->hfi, dsi_bridge->session_id,
> + false, 0);
> + if (scan_complete_registered)
> + dcp_hfi_display_event_deregister(kms->hfi, dsi_bridge->session_id,
> + HFI_EVENT_FRAME_SCAN_COMPLETE);
> + if (scan_start_registered)
> + dcp_hfi_display_event_deregister(kms->hfi, dsi_bridge->session_id,
> + HFI_EVENT_FRAME_SCAN_START);
> + drm_err(bridge->dev,
> + "DSI%u: bridge enable failed; session closed\n",
> + dsi_bridge->intf_idx);
> + dcp_hfi_display_close(kms->hfi, dsi_bridge->session_id);
> + {
> + guard(mutex)(&dsi_bridge->session_lock);
> + dsi_bridge->session_id = 0;
> + dsi_bridge->session_open = false;
> + }
> + dcp_dsi_bridge_clear_session(dsi_bridge);
> +}
[Severity: Medium]
Should dcp_dsi_bridge_atomic_enable() (and dcp_dsi_bridge_atomic_pre_enable())
hold dsi_bridge->session_lock across the session operations rather than only
around clearing session_id and session_open at the end of err_close?
In addition to mixing goto err_close with guard(mutex), reading
dsi_bridge->session_open and dsi_bridge->session_id and calling
dcp_hfi_display_close() without holding session_lock allows a concurrent
dcp_dsi_host_transfer() call to observe session_open == true and send DCS
commands on a session ID that is actively being closed or has already been
closed in firmware.
[ ... ]
> +struct drm_bridge *dcp_dsi_bridge_init(struct dcp_dpu_kms *kms,
> + struct device_node *np,
> + struct device_node *dcp_np,
> + u32 dcp_port, u32 intf_idx,
> + u32 fw_display_id)
> +{
> + struct dcp_dsi_bridge *dsi_bridge;
> + struct dcp_dsi_hfi_panel_config *cfg;
> + struct device *dev = kms->pm_dev;
> + struct device *dma_dev = kms->hfi->dma_dev;
> + int ret;
> +
> + dsi_bridge = devm_drm_bridge_alloc(dev, struct dcp_dsi_bridge,
> + bridge, &dcp_dsi_bridge_funcs);
> + if (IS_ERR(dsi_bridge))
> + return ERR_CAST(dsi_bridge);
> +
> + dsi_bridge->dcp_np = of_node_get(dcp_np);
[ ... ]
> + device_initialize(&dsi_bridge->dsi_host_dev);
> + dsi_bridge->dsi_host_dev.release = dcp_dsi_host_dev_release;
> + dsi_bridge->dsi_host_dev.parent = dev;
> + dsi_bridge->dsi_host_dev.of_node = of_node_get(np);
> + dev_set_name(&dsi_bridge->dsi_host_dev, "%pOFn", np);
> + dsi_bridge->dsi_host.ops = &dcp_dsi_host_ops;
> + dsi_bridge->dsi_host.dev = &dsi_bridge->dsi_host_dev;
> +
> + ret = device_add(&dsi_bridge->dsi_host_dev);
[Severity: Medium]
Won't dev_set_name(&dsi_bridge->dsi_host_dev, "%pOFn", np) cause a device
name collision in device_add() when two DSI bridges are present?
The %pOFn specifier strips the @unit-address suffix from the node name, so
both dsi@0 and dsi@1 receive the name "dsi" under the same parent device
(kms->pm_dev), causing the second device_add() to fail with -EEXIST.
[ ... ]
> +err_unwind_dma:
> + if (dsi_bridge->dcs_rx_buf) {
> + dma_free_coherent(dma_dev, DCP_DSI_DCS_RX_BUF_SIZE,
> + dsi_bridge->dcs_rx_buf,
> + dsi_bridge->dcs_rx_iova);
> + }
> + if (dsi_bridge->dcs_tx_buf) {
> + dma_free_coherent(dma_dev, DCP_DSI_DCS_TX_BUF_SIZE,
> + dsi_bridge->dcs_tx_buf,
> + dsi_bridge->dcs_tx_iova);
> + }
> + cancel_work_sync(&dsi_bridge->power_control_work);
> + mutex_destroy(&dsi_bridge->session_lock);
> + mutex_destroy(&dsi_bridge->dcs_lock);
> + return ERR_PTR(ret);
> +}
[Severity: Medium]
Does the err_unwind_dma path in dcp_dsi_bridge_init() leak the
dsi_bridge->dcp_np device_node reference acquired via of_node_get(dcp_np) if
dma_alloc_coherent(), device_add(), or mipi_dsi_host_register() fails?
[ ... ]
> +void dcp_dsi_bridge_cleanup(struct dcp_dsi_bridge *dsi_bridge)
> +{
> + struct device *dma_dev = dsi_bridge->kms->hfi->dma_dev;
> +
> + dcp_hfi_clear_power_control_cb(dsi_bridge->kms->hfi, dsi_bridge->kms);
> + cancel_work_sync(&dsi_bridge->power_control_work);
> +
> + drm_bridge_remove(&dsi_bridge->bridge);
> + of_node_put(dsi_bridge->bridge.of_node);
> + of_node_put(dsi_bridge->dcp_np);
> +
> + mipi_dsi_host_unregister(&dsi_bridge->dsi_host);
> + device_del(&dsi_bridge->dsi_host_dev);
> + put_device(&dsi_bridge->dsi_host_dev);
> +
> + dcp_dsi_bridge_unmap_buffers(dsi_bridge);
> + dma_free_coherent(dma_dev, DCP_DSI_DCS_TX_BUF_SIZE,
> + dsi_bridge->dcs_tx_buf, dsi_bridge->dcs_tx_iova);
> +
> + dma_free_coherent(dma_dev, DCP_DSI_DCS_RX_BUF_SIZE,
> + dsi_bridge->dcs_rx_buf, dsi_bridge->dcs_rx_iova);
> +
> + mutex_destroy(&dsi_bridge->session_lock);
> + mutex_destroy(&dsi_bridge->dcs_lock);
> +}
[Severity: High]
Can calling mipi_dsi_host_unregister() from dcp_dsi_bridge_cleanup()
deadlock on component_mutex and trigger use-after-free during teardown?
1. When a DSI device is attached, mipi_dsi_host_unregister() removes the
child device and invokes:
mipi_dsi_remove_device_fn()
-> mipi_dsi_detach()
-> dcp_dsi_host_detach()
-> component_del(&dsi_bridge->dsi_host_dev, &dcp_dsi_component_ops)
component_del() acquires the global component_mutex. When
dcp_dsi_bridge_cleanup() is called from aggregate device bringup failure
or aggregate device takedown (for example via component_master_del() /
take_down_aggregate_device() -> msm_drm_unbind() -> msm_drm_uninit() ->
dcp_dpu_kms_destroy()), component_mutex is already held by the caller,
causing a recursive deadlock.
2. struct dcp_dsi_bridge is allocated with devm_drm_bridge_alloc() on
kms->pm_dev and embeds struct device dsi_host_dev, which is refcounted
independently. Calling device_del() and put_device() on dsi_host_dev
during kms->destroy() happens before component_unbind_all() finishes
using component->dev (&dsi_bridge->dsi_host_dev). In addition,
dcs_tx_buf and dcs_rx_buf are freed without holding session_lock/dcs_lock
or clearing dsi_bridge->dcs_tx_buf to NULL, and session_lock and dcs_lock
are destroyed while the bridge object is still alive.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261026-jshekhar-dcp-hlos-v2-0-7cf014efdee1@oss.qualcomm.com?part=15
next prev parent reply other threads:[~2026-10-26 12:37 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 6:21 [PATCH v2 00/23] drm/msm/dcp: Add Qualcomm DCP display support Jayant Shekhar
2026-10-26 6:21 ` [PATCH v2 01/23] dt-bindings: display: msm: Add Qualcomm DCP Jayant Shekhar
2026-10-26 9:38 ` sashiko-bot
2026-10-26 9:57 ` Dmitry Baryshkov
2026-10-26 19:44 ` Rob Herring (Arm)
2026-10-27 8:36 ` Krzysztof Kozlowski
2026-10-26 6:21 ` [PATCH v2 02/23] drm/msm/dcp: Add HFI packet helpers Jayant Shekhar
2026-10-26 9:48 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 03/23] drm/msm/dcp: Add HFI device definitions Jayant Shekhar
2026-10-26 6:21 ` [PATCH v2 04/23] drm/msm/dcp: Add HFI display definitions Jayant Shekhar
2026-10-26 6:21 ` [PATCH v2 05/23] drm/msm/dcp: Add HFI panel definitions Jayant Shekhar
2026-10-26 6:21 ` [PATCH v2 06/23] drm/msm/dcp: Add HFI VirtIO transport Jayant Shekhar
2026-10-26 10:07 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 07/23] drm/msm/dcp: Handle asynchronous HFI responses Jayant Shekhar
2026-10-26 10:22 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 08/23] drm/msm/dcp: Add IPCC power notifications Jayant Shekhar
2026-10-26 10:36 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 09/23] drm/msm/dcp: Add generic HFI display commands Jayant Shekhar
2026-10-26 10:52 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 10/23] drm/msm/dcp: Add HFI DSI and panel commands Jayant Shekhar
2026-10-26 11:13 ` sashiko-bot
2026-10-27 11:06 ` Dmitry Baryshkov
2026-10-26 6:21 ` [PATCH v2 11/23] drm/msm/dcp: Add DCP CRTCs and shared plane state Jayant Shekhar
2026-10-26 10:49 ` Dmitry Baryshkov
2026-10-26 11:33 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 12/23] drm/msm/dcp: Add DCP planes Jayant Shekhar
2026-10-26 11:57 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 13/23] drm/msm/dcp: Route HFI display events Jayant Shekhar
2026-10-26 12:08 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 14/23] drm/msm/dcp: Add DCP encoder Jayant Shekhar
2026-10-26 6:21 ` [PATCH v2 15/23] drm/msm/dcp: Add DCP DSI host and panel support Jayant Shekhar
2026-10-26 11:08 ` Dmitry Baryshkov
2026-10-26 12:37 ` sashiko-bot [this message]
2026-10-26 6:21 ` [PATCH v2 16/23] drm/msm/dcp: Integrate the DSI bridge with KMS Jayant Shekhar
2026-10-26 13:03 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 17/23] drm/msm/dcp: Register DCP display pipeline Jayant Shekhar
2026-10-26 13:24 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 18/23] virtio: Add Qualcomm Platform Services Firmware Interface ID Jayant Shekhar
2026-10-26 9:59 ` Dmitry Baryshkov
2026-10-26 10:27 ` Michael S. Tsirkin
2026-10-26 6:21 ` [PATCH v2 19/23] drm/msm/dcp: Add Qualcomm VirtIO transport wrapper Jayant Shekhar
2026-10-26 10:07 ` Dmitry Baryshkov
2026-10-26 14:05 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 20/23] drm/msm/dcp: Add DCP VirtIO driver Jayant Shekhar
2026-10-26 10:15 ` Dmitry Baryshkov
2026-10-26 14:31 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 21/23] drm/msm: Support KMS backends without a display IRQ Jayant Shekhar
2026-10-27 11:37 ` Dmitry Baryshkov
2026-10-26 6:21 ` [PATCH v2 22/23] drm/msm: Register the DCP backend Jayant Shekhar
2026-10-26 14:58 ` sashiko-bot
2026-10-27 11:38 ` Dmitry Baryshkov
2026-10-26 6:21 ` [PATCH v2 23/23] arm64: dts: qcom: hawi: Add DCP support Jayant Shekhar
2026-10-26 15:10 ` sashiko-bot
2026-10-27 11:44 ` Dmitry Baryshkov
2026-10-27 11:58 ` [PATCH v2 00/23] drm/msm/dcp: Add Qualcomm DCP display support 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=sashiko-outbox-185222@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=eperezma@redhat.com \
--cc=jayant.shekhar@oss.qualcomm.com \
--cc=media-ci@linuxtv.org \
--cc=mst@redhat.com \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=virtualization@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