From: sashiko-bot@kernel.org
To: "Nihal Kumar Gupta" <nihal.gupta@oss.qualcomm.com>
Cc: devicetree@vger.kernel.org, linux-phy@lists.infradead.org,
robh@kernel.org, conor+dt@kernel.org, media-ci@linuxtv.org,
vkoul@kernel.org, neil.armstrong@linaro.org, olteanv@gmail.com
Subject: Re: [PATCH v3 5/5] media: qcom: camss: Add support for Hawi
Date: Fri, 30 Oct 2026 13:07:50 +0000 [thread overview]
Message-ID: <sashiko-outbox-191048@kernel.org> (raw)
In-Reply-To: <20261030-hawi-maili-camss-v3-5-9742bca8cef2@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] media: qcom: camss: unconditional AUP strobes in csid_configure_stream()
- [High] media: camss: NULL hw_ops deref in msm_csiphy_subdev_init_legacy()
- [Medium] media: qcom: camss: wrong camnoc_rt_axi clock rates in vfe_res_hawi
- [Medium] media: qcom: camss: data race on csid->addr_update and csid->reg_update
- [Low] media: qcom: camss: duplicate CSID 1080 and VFE 1080 code in 1190 files
- [Low] media: qcom: camss: macros in camss-csid-1190.c implicitly capture csid
--
commit 25967aac8ac2c5b636dbbaab24c84dd484d99ab8
Author: Hangxiang Ma <hangxiang.ma@oss.qualcomm.com>
media: qcom: camss: Add support for Hawi
This commit adds CAMSS support for the Hawi SoC, including CSID 1190 and
VFE 1190 hardware operations and Hawi resource definitions.
> diff --git a/drivers/media/platform/qcom/camss/camss-csid-1190.c b/drivers/media/platform/qcom/camss/camss-csid-1190.c
> new file mode 100644
> index 0000000000000..4bd2cce094402
> --- /dev/null
> +++ b/drivers/media/platform/qcom/camss/camss-csid-1190.c
> @@ -0,0 +1,417 @@
[ ... ]
> +#define MSM_CSID_MAX_SRC_STREAMS_1190 (csid_is_lite(csid) ? 4 : 5)
> +
> +/* RDI Configuration */
> +#define CSID_RDI_CFG0(rdi) (csid_is_lite(csid) ?\
> + (0x3080 + 0x200 * (rdi)) :\
> + (0x5480 + 0x200 * (rdi)))
> +#define RDI_CFG0_RETIME_BS BIT(5)
> +#define RDI_CFG0_TIMESTAMP_EN BIT(6)
> +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8)
> +#define RDI_CFG0_DECODE_FORMAT 12
> +#define RDI_CFG0_DT 16
> +#define RDI_CFG0_VC 22
> +#define RDI_CFG0_EN BIT(31)
> +
> +/* RDI Control and Configuration */
> +#define CSID_RDI_CTRL(rdi) (csid_is_lite(csid) ?\
> + (0x3088 + 0x200 * (rdi)) :\
> + (0x5488 + 0x200 * (rdi)))
> +#define RDI_CTRL_START_CMD BIT(0)
> +
> +#define CSID_RDI_CFG1(rdi) (csid_is_lite(csid) ?\
> + (0x3094 + 0x200 * (rdi)) :\
> + (0x5494 + 0x200 * (rdi)))
[Severity: Low]
As reported by Sashiko on v2 [1], this isn't a bug, but
MSM_CSID_MAX_SRC_STREAMS_1190, CSID_RDI_CFG0(rdi), CSID_RDI_CTRL(rdi), and
CSID_RDI_CFG1(rdi) in drivers/media/platform/qcom/camss/camss-csid-1190.c
expand to expressions calling csid_is_lite(csid) without taking csid as a
macro parameter. Should these macros take csid explicitly instead of relying
on a local variable named csid in the caller's scope?
[ ... ]
> +static void __csid_aup_rup_trigger(struct csid_device *csid)
> +{
> + /* trigger SET in combined register */
> + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD);
> +}
> +
> +static void __csid_addr_update(struct csid_device *csid, int port_id)
> +{
> + csid->addr_update |= CSID_RUP_AUP_RDI(port_id);
> + writel(csid->addr_update, csid->base + CSID_AUP_CMD);
> +
> + __csid_aup_rup_trigger(csid);
> +}
> +
> +static void __csid_addr_update_clear(struct csid_device *csid, int port_id)
> +{
> + /* Hardware clears the registers upon consuming the settings */
> + csid->addr_update &= ~CSID_RUP_AUP_RDI(port_id);
> +}
> +
> +static void __csid_reg_update(struct csid_device *csid, int port_id)
> +{
> + csid->reg_update |= CSID_RUP_AUP_RDI(port_id);
> + writel(csid->reg_update, csid->base + CSID_RUP_CMD);
> +
> + __csid_aup_rup_trigger(csid);
> +}
> +
> +static void __csid_reg_update_clear(struct csid_device *csid, int port_id)
> +{
> + /* Hardware clears the registers upon consuming the settings */
> + csid->reg_update &= ~CSID_RUP_AUP_RDI(port_id);
> +}
[Severity: Medium]
As reported by Sashiko on v2 [1], can __csid_addr_update() and
__csid_reg_update() race with __csid_addr_update_clear() and
__csid_reg_update_clear() on csid->addr_update and csid->reg_update?
In drivers/media/platform/qcom/camss/camss-csid-1190.c, __csid_addr_update()
and __csid_reg_update() perform non-atomic read-modify-write operations on
csid->addr_update and csid->reg_update before writing CSID_AUP_CMD and
CSID_RUP_CMD.
Meanwhile, in hardirq context, csid_isr() clears those fields when
INFO_RUP_DONE is set without holding any lock:
drivers/media/platform/qcom/camss/camss-csid-1190.c:csid_isr() {
...
if (val & INFO_RUP_DONE) {
__csid_addr_update_clear(csid, i);
__csid_reg_update_clear(csid, i);
}
...
}
Because vfe_queue_buffer_v2() and vfe_enable_output_v2() only hold
vfe->output_lock (which csid_isr() does not acquire before camss_buf_done())
and csid_configure_stream() holds no spinlock, concurrent updates from process
context (for example during VIDIOC_QBUF or when starting multiple RDI streams
sharing a CSID) and hardirq context can clobber bits in csid->addr_update and
csid->reg_update.
[ ... ]
> +static void csid_configure_stream(struct csid_device *csid, u8 enable)
> +{
> + u8 i, k;
> +
> + __csid_configure_rx(csid, &csid->phy);
> +
> + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_1190; i++) {
> + if (csid->phy.en_vc & BIT(i)) {
> + __csid_configure_rdi_stream(csid, enable, i, 0);
> + __csid_configure_rx_vc(csid, 0);
> +
> + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++)
> + __csid_addr_update(csid, i);
> +
> + __csid_reg_update(csid, i);
> +
> + __csid_ctrl_rdi(csid, enable, i);
> + }
> + }
> +}
[Severity: High]
What happens in csid_configure_stream() if VIDIOC_STREAMON is called with
fewer than CAMSS_INIT_BUF_COUNT (2) buffers queued?
In msm_video_register() in drivers/media/platform/qcom/camss/camss-video.c,
vb2_queue.min_queued_buffers is 0, so vb2_core_streamon() invokes
vb2_start_streaming() -> video_start_streaming() even when 0 or 1 buffer is
queued before VIDIOC_STREAMON.
video_start_streaming() first calls vfe_set_stream() -> vfe_enable_v2() ->
vfe_enable_output_v2(), which dequeues only the available pending buffers (0
or 1) and writes their addresses via ops->vfe_wm_update():
drivers/media/platform/qcom/camss/camss-vfe.c:vfe_enable_output_v2() {
...
for (i = 0; i < CAMSS_INIT_BUF_COUNT; i++) {
output->buf[i] = vfe_buf_get_pending(output);
if (!output->buf[i])
break;
output->gen2.active_num++;
ops->vfe_wm_update(vfe, output->wm_idx[0],
output->buf[i]->addr[0], line);
if (!ops->addr_update)
ops->reg_update(vfe, line->id);
}
...
}
Next, video_start_streaming() calls csid_set_stream() ->
csid_configure_stream(), which unconditionally loops CAMSS_INIT_BUF_COUNT (2)
times calling __csid_addr_update(csid, i) regardless of how many buffers were
queued in vfe_enable_output_v2(). Moreover, vfe_wm_stop() in
drivers/media/platform/qcom/camss/camss-vfe-1190.c only clears
VFE_BUS_WM_CFG(wm) without clearing VFE_BUS_WM_IMAGE_ADDR(wm).
When userspace later queues buffers via VIDIOC_QBUF, vfe_queue_buffer_v2()
sees output->state == VFE_OUTPUT_ON and output->gen2.active_num < 2, and
issues additional ops->addr_update() and ops->reg_update() strobes:
drivers/media/platform/qcom/camss/camss-vfe.c:vfe_queue_buffer_v2() {
...
if (output->state == VFE_OUTPUT_ON &&
output->gen2.active_num < 2) {
output->buf[output->gen2.active_num++] = buf;
ops->vfe_wm_update(vfe, output->wm_idx[0],
buf->addr[0], line);
if (ops->addr_update)
ops->addr_update(vfe, line->id);
ops->reg_update(vfe, line->id);
}
...
}
Doesn't issuing two unconditional __csid_addr_update() strobes in
csid_configure_stream() latch stale or duplicate DMA addresses in the write
master and desynchronize buffer tracking when fewer than two buffers were
queued before streamon?
[ ... ]
> +const struct csid_hw_ops csid_ops_1190 = {
> + .configure_stream = csid_configure_stream,
> + .configure_testgen_pattern = csid_configure_testgen_pattern,
> + .hw_version = csid_hw_version,
> + .isr = csid_isr,
> + .reset = csid_reset,
> + .src_pad_code = csid_src_pad_code,
> + .subdev_init = csid_subdev_init,
> + .reg_update = csid_subdev_reg_update,
> + .addr_update = csid_subdev_addr_update,
> +};
[Severity: Low]
This isn't a bug, but every register offset, bitmask macro, stream count
definition, helper function, interrupt handler, reset routine, and hardware
operation callback in drivers/media/platform/qcom/camss/camss-csid-1190.c
(including the unused lane_cnt local variable in
__csid_configure_rdi_stream()) is identical to
drivers/media/platform/qcom/camss/camss-csid-1080.c.
Similarly, drivers/media/platform/qcom/camss/camss-vfe-1190.c duplicates all
functions and callbacks of drivers/media/platform/qcom/camss/camss-vfe-1080.c
verbatim, differing only in the BUS_REG_BASE and write master register offset
macros.
Could csid_res_hawi reuse csid_ops_1080 directly (just as hawi_resources
reuses csiphy_res_kaanapali and tpg_res_x1e80100), and could the common VFE
1080/1190 helpers be shared?
> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> index df4b4cf30711b..0a67d4f746eeb 100644
> --- a/drivers/media/platform/qcom/camss/camss.c
> +++ b/drivers/media/platform/qcom/camss/camss.c
> @@ -4359,6 +4359,218 @@ static const struct resources_icc icc_res_sa8775p[] = {
> },
> };
>
> +static const struct camss_subdev_resources vfe_res_hawi[] = {
> + /* VFE0 - TFE Full */
> + {
> + .clock = { "vfe0_fast_ahb", "vfe0", "cpas_vfe0",
> + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo",
> + "cpas_mnoc_hf", "cpas_mnoc_sf" },
> + .clock_rate = { { 0 },
> + { 238200000, 397000000, 440000000, 480000000,
> + 630000000, 750000000, 833000000 },
> + { 0 },
> + { 171428571, 240000000, 300000000, 400000000,
> + 480000000, 600000000 },
[Severity: Medium]
Are the camnoc_rt_axi clock rates in vfe_res_hawi (for VFE0 through VFE4)
matching the Hawi CAMCC clock driver?
In drivers/clk/qcom/camcc-hawi.c, ftbl_cam_cc_camnoc_rt_axi_clk_src for
qcom,hawi-camcc defines a maximum rate of 480 MHz:
drivers/clk/qcom/camcc-hawi.c:
static const struct freq_tbl ftbl_cam_cc_camnoc_rt_axi_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(120000000, P_CAM_CC_PLL6_OUT_EVEN, 4, 0, 0),
F(160000000, P_CAM_CC_PLL6_OUT_EVEN, 3, 0, 0),
F(240000000, P_CAM_CC_PLL6_OUT_EVEN, 2, 0, 0),
F(320000000, P_CAM_CC_PLL6_OUT_EVEN, 1.5, 0, 0),
F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
{ }
};
(Whereas the 200/240/300/400/480/600 MHz table
ftbl_cam_cc_camnoc_rt_axi_clk_src_maili is only used for qcom,maili-camcc, and
171428571 Hz is in neither table.)
When vfe_get() -> vfe_set_clock_rates() runs with min_rate between 480 MHz and
600 MHz, it selects 600000000 Hz from vfe_res_hawi instead of rejecting the
rate, and clk_round_rate() on Hawi clamps it down to 480000000 Hz. When the
second pipeline entity calls vfe_get() -> vfe_check_clock_rates(), won't
clk_get_rate(clock->clk) < min_rate cause vfe_check_clock_rates() to fail with
-EBUSY?
[ ... ]
> @@ -6078,6 +6290,22 @@ static const struct camss_resources sm8650_resources = {
> .vfe_num = ARRAY_SIZE(vfe_res_sm8650),
> };
>
> +static const struct camss_resources hawi_resources = {
> + .version = CAMSS_HAWI,
> + .pd_name = "top",
> + .pm_clks = { "cpas_fast_ahb", "cpas_ahb", "gcc_axi_hf" },
> + .csiphy_res = csiphy_res_kaanapali,
[Severity: High]
As reported by Sashiko on v2 [2], can reusing csiphy_res_kaanapali in
hawi_resources lead to a NULL pointer dereference in
msm_csiphy_subdev_init_legacy() during probe?
The entries in csiphy_res_kaanapali do not set .csiphy.hw_ops, leaving hw_ops
as NULL. During camss_probe() -> camss_init_subdevices(),
camss_detect_legacy_phy() defaults camss->legacy_phy to true:
drivers/media/platform/qcom/camss/camss.c:camss_detect_legacy_phy() {
camss->legacy_phy = true;
/* Find first remote-endpoint and determine if its a PHY */
for_each_endpoint_of_node(camss->dev->of_node, ep) {
...
}
If the qcom,hawi-camss node has no endpoints in its ports node (for example,
when enabling CAMSS to use its internal Test Pattern Generators without
external sensors or PHYs), camss->legacy_phy remains true.
camss_init_subdevices() then calls msm_csiphy_subdev_init_legacy(), which
unconditionally dereferences csiphy->res->hw_ops:
drivers/media/platform/qcom/camss/camss-csiphy.c:msm_csiphy_subdev_init_legacy() {
...
ret = csiphy->res->hw_ops->init(csiphy);
...
}
[1] https://lore.kernel.org/r/20261013-hawi-maili-camss-v2-7-fc93222da89c@oss.qualcomm.com
[2] https://lore.kernel.org/r/20261013-hawi-maili-camss-v2-6-fc93222da89c@oss.qualcomm.com
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030-hawi-maili-camss-v3-0-9742bca8cef2@oss.qualcomm.com?part=5
WARNING: multiple messages have this Message-ID (diff)
From: sashiko-bot@kernel.org
To: "Nihal Kumar Gupta" <nihal.gupta@oss.qualcomm.com>
Cc: devicetree@vger.kernel.org, linux-phy@lists.infradead.org,
robh@kernel.org, conor+dt@kernel.org, media-ci@linuxtv.org,
vkoul@kernel.org, neil.armstrong@linaro.org, olteanv@gmail.com
Subject: Re: [PATCH v3 5/5] media: qcom: camss: Add support for Hawi
Date: Fri, 30 Oct 2026 13:07:50 +0000 [thread overview]
Message-ID: <sashiko-outbox-191048@kernel.org> (raw)
In-Reply-To: <20261030-hawi-maili-camss-v3-5-9742bca8cef2@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] media: qcom: camss: unconditional AUP strobes in csid_configure_stream()
- [High] media: camss: NULL hw_ops deref in msm_csiphy_subdev_init_legacy()
- [Medium] media: qcom: camss: wrong camnoc_rt_axi clock rates in vfe_res_hawi
- [Medium] media: qcom: camss: data race on csid->addr_update and csid->reg_update
- [Low] media: qcom: camss: duplicate CSID 1080 and VFE 1080 code in 1190 files
- [Low] media: qcom: camss: macros in camss-csid-1190.c implicitly capture csid
--
commit 25967aac8ac2c5b636dbbaab24c84dd484d99ab8
Author: Hangxiang Ma <hangxiang.ma@oss.qualcomm.com>
media: qcom: camss: Add support for Hawi
This commit adds CAMSS support for the Hawi SoC, including CSID 1190 and
VFE 1190 hardware operations and Hawi resource definitions.
> diff --git a/drivers/media/platform/qcom/camss/camss-csid-1190.c b/drivers/media/platform/qcom/camss/camss-csid-1190.c
> new file mode 100644
> index 0000000000000..4bd2cce094402
> --- /dev/null
> +++ b/drivers/media/platform/qcom/camss/camss-csid-1190.c
> @@ -0,0 +1,417 @@
[ ... ]
> +#define MSM_CSID_MAX_SRC_STREAMS_1190 (csid_is_lite(csid) ? 4 : 5)
> +
> +/* RDI Configuration */
> +#define CSID_RDI_CFG0(rdi) (csid_is_lite(csid) ?\
> + (0x3080 + 0x200 * (rdi)) :\
> + (0x5480 + 0x200 * (rdi)))
> +#define RDI_CFG0_RETIME_BS BIT(5)
> +#define RDI_CFG0_TIMESTAMP_EN BIT(6)
> +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8)
> +#define RDI_CFG0_DECODE_FORMAT 12
> +#define RDI_CFG0_DT 16
> +#define RDI_CFG0_VC 22
> +#define RDI_CFG0_EN BIT(31)
> +
> +/* RDI Control and Configuration */
> +#define CSID_RDI_CTRL(rdi) (csid_is_lite(csid) ?\
> + (0x3088 + 0x200 * (rdi)) :\
> + (0x5488 + 0x200 * (rdi)))
> +#define RDI_CTRL_START_CMD BIT(0)
> +
> +#define CSID_RDI_CFG1(rdi) (csid_is_lite(csid) ?\
> + (0x3094 + 0x200 * (rdi)) :\
> + (0x5494 + 0x200 * (rdi)))
[Severity: Low]
As reported by Sashiko on v2 [1], this isn't a bug, but
MSM_CSID_MAX_SRC_STREAMS_1190, CSID_RDI_CFG0(rdi), CSID_RDI_CTRL(rdi), and
CSID_RDI_CFG1(rdi) in drivers/media/platform/qcom/camss/camss-csid-1190.c
expand to expressions calling csid_is_lite(csid) without taking csid as a
macro parameter. Should these macros take csid explicitly instead of relying
on a local variable named csid in the caller's scope?
[ ... ]
> +static void __csid_aup_rup_trigger(struct csid_device *csid)
> +{
> + /* trigger SET in combined register */
> + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD);
> +}
> +
> +static void __csid_addr_update(struct csid_device *csid, int port_id)
> +{
> + csid->addr_update |= CSID_RUP_AUP_RDI(port_id);
> + writel(csid->addr_update, csid->base + CSID_AUP_CMD);
> +
> + __csid_aup_rup_trigger(csid);
> +}
> +
> +static void __csid_addr_update_clear(struct csid_device *csid, int port_id)
> +{
> + /* Hardware clears the registers upon consuming the settings */
> + csid->addr_update &= ~CSID_RUP_AUP_RDI(port_id);
> +}
> +
> +static void __csid_reg_update(struct csid_device *csid, int port_id)
> +{
> + csid->reg_update |= CSID_RUP_AUP_RDI(port_id);
> + writel(csid->reg_update, csid->base + CSID_RUP_CMD);
> +
> + __csid_aup_rup_trigger(csid);
> +}
> +
> +static void __csid_reg_update_clear(struct csid_device *csid, int port_id)
> +{
> + /* Hardware clears the registers upon consuming the settings */
> + csid->reg_update &= ~CSID_RUP_AUP_RDI(port_id);
> +}
[Severity: Medium]
As reported by Sashiko on v2 [1], can __csid_addr_update() and
__csid_reg_update() race with __csid_addr_update_clear() and
__csid_reg_update_clear() on csid->addr_update and csid->reg_update?
In drivers/media/platform/qcom/camss/camss-csid-1190.c, __csid_addr_update()
and __csid_reg_update() perform non-atomic read-modify-write operations on
csid->addr_update and csid->reg_update before writing CSID_AUP_CMD and
CSID_RUP_CMD.
Meanwhile, in hardirq context, csid_isr() clears those fields when
INFO_RUP_DONE is set without holding any lock:
drivers/media/platform/qcom/camss/camss-csid-1190.c:csid_isr() {
...
if (val & INFO_RUP_DONE) {
__csid_addr_update_clear(csid, i);
__csid_reg_update_clear(csid, i);
}
...
}
Because vfe_queue_buffer_v2() and vfe_enable_output_v2() only hold
vfe->output_lock (which csid_isr() does not acquire before camss_buf_done())
and csid_configure_stream() holds no spinlock, concurrent updates from process
context (for example during VIDIOC_QBUF or when starting multiple RDI streams
sharing a CSID) and hardirq context can clobber bits in csid->addr_update and
csid->reg_update.
[ ... ]
> +static void csid_configure_stream(struct csid_device *csid, u8 enable)
> +{
> + u8 i, k;
> +
> + __csid_configure_rx(csid, &csid->phy);
> +
> + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_1190; i++) {
> + if (csid->phy.en_vc & BIT(i)) {
> + __csid_configure_rdi_stream(csid, enable, i, 0);
> + __csid_configure_rx_vc(csid, 0);
> +
> + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++)
> + __csid_addr_update(csid, i);
> +
> + __csid_reg_update(csid, i);
> +
> + __csid_ctrl_rdi(csid, enable, i);
> + }
> + }
> +}
[Severity: High]
What happens in csid_configure_stream() if VIDIOC_STREAMON is called with
fewer than CAMSS_INIT_BUF_COUNT (2) buffers queued?
In msm_video_register() in drivers/media/platform/qcom/camss/camss-video.c,
vb2_queue.min_queued_buffers is 0, so vb2_core_streamon() invokes
vb2_start_streaming() -> video_start_streaming() even when 0 or 1 buffer is
queued before VIDIOC_STREAMON.
video_start_streaming() first calls vfe_set_stream() -> vfe_enable_v2() ->
vfe_enable_output_v2(), which dequeues only the available pending buffers (0
or 1) and writes their addresses via ops->vfe_wm_update():
drivers/media/platform/qcom/camss/camss-vfe.c:vfe_enable_output_v2() {
...
for (i = 0; i < CAMSS_INIT_BUF_COUNT; i++) {
output->buf[i] = vfe_buf_get_pending(output);
if (!output->buf[i])
break;
output->gen2.active_num++;
ops->vfe_wm_update(vfe, output->wm_idx[0],
output->buf[i]->addr[0], line);
if (!ops->addr_update)
ops->reg_update(vfe, line->id);
}
...
}
Next, video_start_streaming() calls csid_set_stream() ->
csid_configure_stream(), which unconditionally loops CAMSS_INIT_BUF_COUNT (2)
times calling __csid_addr_update(csid, i) regardless of how many buffers were
queued in vfe_enable_output_v2(). Moreover, vfe_wm_stop() in
drivers/media/platform/qcom/camss/camss-vfe-1190.c only clears
VFE_BUS_WM_CFG(wm) without clearing VFE_BUS_WM_IMAGE_ADDR(wm).
When userspace later queues buffers via VIDIOC_QBUF, vfe_queue_buffer_v2()
sees output->state == VFE_OUTPUT_ON and output->gen2.active_num < 2, and
issues additional ops->addr_update() and ops->reg_update() strobes:
drivers/media/platform/qcom/camss/camss-vfe.c:vfe_queue_buffer_v2() {
...
if (output->state == VFE_OUTPUT_ON &&
output->gen2.active_num < 2) {
output->buf[output->gen2.active_num++] = buf;
ops->vfe_wm_update(vfe, output->wm_idx[0],
buf->addr[0], line);
if (ops->addr_update)
ops->addr_update(vfe, line->id);
ops->reg_update(vfe, line->id);
}
...
}
Doesn't issuing two unconditional __csid_addr_update() strobes in
csid_configure_stream() latch stale or duplicate DMA addresses in the write
master and desynchronize buffer tracking when fewer than two buffers were
queued before streamon?
[ ... ]
> +const struct csid_hw_ops csid_ops_1190 = {
> + .configure_stream = csid_configure_stream,
> + .configure_testgen_pattern = csid_configure_testgen_pattern,
> + .hw_version = csid_hw_version,
> + .isr = csid_isr,
> + .reset = csid_reset,
> + .src_pad_code = csid_src_pad_code,
> + .subdev_init = csid_subdev_init,
> + .reg_update = csid_subdev_reg_update,
> + .addr_update = csid_subdev_addr_update,
> +};
[Severity: Low]
This isn't a bug, but every register offset, bitmask macro, stream count
definition, helper function, interrupt handler, reset routine, and hardware
operation callback in drivers/media/platform/qcom/camss/camss-csid-1190.c
(including the unused lane_cnt local variable in
__csid_configure_rdi_stream()) is identical to
drivers/media/platform/qcom/camss/camss-csid-1080.c.
Similarly, drivers/media/platform/qcom/camss/camss-vfe-1190.c duplicates all
functions and callbacks of drivers/media/platform/qcom/camss/camss-vfe-1080.c
verbatim, differing only in the BUS_REG_BASE and write master register offset
macros.
Could csid_res_hawi reuse csid_ops_1080 directly (just as hawi_resources
reuses csiphy_res_kaanapali and tpg_res_x1e80100), and could the common VFE
1080/1190 helpers be shared?
> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> index df4b4cf30711b..0a67d4f746eeb 100644
> --- a/drivers/media/platform/qcom/camss/camss.c
> +++ b/drivers/media/platform/qcom/camss/camss.c
> @@ -4359,6 +4359,218 @@ static const struct resources_icc icc_res_sa8775p[] = {
> },
> };
>
> +static const struct camss_subdev_resources vfe_res_hawi[] = {
> + /* VFE0 - TFE Full */
> + {
> + .clock = { "vfe0_fast_ahb", "vfe0", "cpas_vfe0",
> + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo",
> + "cpas_mnoc_hf", "cpas_mnoc_sf" },
> + .clock_rate = { { 0 },
> + { 238200000, 397000000, 440000000, 480000000,
> + 630000000, 750000000, 833000000 },
> + { 0 },
> + { 171428571, 240000000, 300000000, 400000000,
> + 480000000, 600000000 },
[Severity: Medium]
Are the camnoc_rt_axi clock rates in vfe_res_hawi (for VFE0 through VFE4)
matching the Hawi CAMCC clock driver?
In drivers/clk/qcom/camcc-hawi.c, ftbl_cam_cc_camnoc_rt_axi_clk_src for
qcom,hawi-camcc defines a maximum rate of 480 MHz:
drivers/clk/qcom/camcc-hawi.c:
static const struct freq_tbl ftbl_cam_cc_camnoc_rt_axi_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(120000000, P_CAM_CC_PLL6_OUT_EVEN, 4, 0, 0),
F(160000000, P_CAM_CC_PLL6_OUT_EVEN, 3, 0, 0),
F(240000000, P_CAM_CC_PLL6_OUT_EVEN, 2, 0, 0),
F(320000000, P_CAM_CC_PLL6_OUT_EVEN, 1.5, 0, 0),
F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
{ }
};
(Whereas the 200/240/300/400/480/600 MHz table
ftbl_cam_cc_camnoc_rt_axi_clk_src_maili is only used for qcom,maili-camcc, and
171428571 Hz is in neither table.)
When vfe_get() -> vfe_set_clock_rates() runs with min_rate between 480 MHz and
600 MHz, it selects 600000000 Hz from vfe_res_hawi instead of rejecting the
rate, and clk_round_rate() on Hawi clamps it down to 480000000 Hz. When the
second pipeline entity calls vfe_get() -> vfe_check_clock_rates(), won't
clk_get_rate(clock->clk) < min_rate cause vfe_check_clock_rates() to fail with
-EBUSY?
[ ... ]
> @@ -6078,6 +6290,22 @@ static const struct camss_resources sm8650_resources = {
> .vfe_num = ARRAY_SIZE(vfe_res_sm8650),
> };
>
> +static const struct camss_resources hawi_resources = {
> + .version = CAMSS_HAWI,
> + .pd_name = "top",
> + .pm_clks = { "cpas_fast_ahb", "cpas_ahb", "gcc_axi_hf" },
> + .csiphy_res = csiphy_res_kaanapali,
[Severity: High]
As reported by Sashiko on v2 [2], can reusing csiphy_res_kaanapali in
hawi_resources lead to a NULL pointer dereference in
msm_csiphy_subdev_init_legacy() during probe?
The entries in csiphy_res_kaanapali do not set .csiphy.hw_ops, leaving hw_ops
as NULL. During camss_probe() -> camss_init_subdevices(),
camss_detect_legacy_phy() defaults camss->legacy_phy to true:
drivers/media/platform/qcom/camss/camss.c:camss_detect_legacy_phy() {
camss->legacy_phy = true;
/* Find first remote-endpoint and determine if its a PHY */
for_each_endpoint_of_node(camss->dev->of_node, ep) {
...
}
If the qcom,hawi-camss node has no endpoints in its ports node (for example,
when enabling CAMSS to use its internal Test Pattern Generators without
external sensors or PHYs), camss->legacy_phy remains true.
camss_init_subdevices() then calls msm_csiphy_subdev_init_legacy(), which
unconditionally dereferences csiphy->res->hw_ops:
drivers/media/platform/qcom/camss/camss-csiphy.c:msm_csiphy_subdev_init_legacy() {
...
ret = csiphy->res->hw_ops->init(csiphy);
...
}
[1] https://lore.kernel.org/r/20261013-hawi-maili-camss-v2-7-fc93222da89c@oss.qualcomm.com
[2] https://lore.kernel.org/r/20261013-hawi-maili-camss-v2-6-fc93222da89c@oss.qualcomm.com
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030-hawi-maili-camss-v3-0-9742bca8cef2@oss.qualcomm.com?part=5
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
next prev parent reply other threads:[~2026-10-30 13:07 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 12:43 [PATCH v3 0/5] Add CAMSS support for Qualcomm Hawi and Maili Nihal Kumar Gupta
2026-10-30 12:43 ` Nihal Kumar Gupta
2026-10-30 12:43 ` [PATCH v3 1/5] dt-bindings: i2c: qcom,i2c-cci: Add Hawi compatible Nihal Kumar Gupta
2026-10-30 12:43 ` Nihal Kumar Gupta
2026-10-30 12:51 ` sashiko-bot
2026-10-30 12:51 ` sashiko-bot
2026-10-30 12:43 ` [PATCH v3 2/5] dt-bindings: phy: qcom,x1e80100-csi2-phy: Add Hawi and Maili compatibles Nihal Kumar Gupta
2026-10-30 12:43 ` Nihal Kumar Gupta
2026-10-30 12:43 ` [PATCH v3 3/5] dt-bindings: media: Add CAMSS device for Hawi and Maili Nihal Kumar Gupta
2026-10-30 12:43 ` Nihal Kumar Gupta
2026-10-30 12:55 ` sashiko-bot
2026-10-30 12:55 ` sashiko-bot
2026-10-30 13:38 ` Loic Poulain
2026-10-30 13:38 ` Loic Poulain
2026-10-30 14:05 ` Hangxiang Ma
2026-10-30 14:05 ` Hangxiang Ma
2026-10-30 12:43 ` [PATCH v3 4/5] phy: qcom-mipi-csi2: Add Hawi support Nihal Kumar Gupta
2026-10-30 12:43 ` Nihal Kumar Gupta
2026-10-30 13:39 ` Loic Poulain
2026-10-30 13:39 ` Loic Poulain
2026-10-30 12:43 ` [PATCH v3 5/5] media: qcom: camss: Add support for Hawi Nihal Kumar Gupta
2026-10-30 12:43 ` Nihal Kumar Gupta
2026-10-30 13:05 ` Vladimir Zapolskiy
2026-10-30 13:07 ` sashiko-bot [this message]
2026-10-30 13:07 ` sashiko-bot
2026-10-30 15:04 ` Bryan O'Donoghue
2026-10-30 15:04 ` Bryan O'Donoghue
2026-10-30 15:25 ` Hangxiang Ma
2026-10-30 15:25 ` Hangxiang Ma
2026-10-30 15:05 ` Bryan O'Donoghue
2026-10-30 15:05 ` Bryan O'Donoghue
2026-10-30 15:29 ` Hangxiang Ma
2026-10-30 15:29 ` Hangxiang Ma
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-191048@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=media-ci@linuxtv.org \
--cc=neil.armstrong@linaro.org \
--cc=nihal.gupta@oss.qualcomm.com \
--cc=olteanv@gmail.com \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vkoul@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 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.