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: 61+ 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 9:50 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 04/23] drm/msm/dcp: Add HFI display definitions Jayant Shekhar
2026-10-26 9:52 ` sashiko-bot
2026-10-26 6:21 ` [PATCH v2 05/23] drm/msm/dcp: Add HFI panel definitions Jayant Shekhar
2026-10-26 9:54 ` sashiko-bot
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 12:11 ` sashiko-bot
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 13:48 ` sashiko-bot
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-26 14:40 ` sashiko-bot
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.