From: "Du, Bin" <bin.du@amd.com>
To: Sultan Alsawaf <sultan@kerneltoast.com>,
Sakari Ailus <sakari.ailus@linux.intel.com>
Cc: mchehab@kernel.org, hverkuil@xs4all.nl,
laurent.pinchart+renesas@ideasonboard.com,
bryan.odonoghue@linaro.org,
prabhakar.mahadev-lad.rj@bp.renesas.com,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
pratap.nirujogi@amd.com, benjamin.chan@amd.com, king.li@amd.com,
gjorgji.rosikopulos@amd.com, Phil.Jawich@amd.com,
Dominic.Antony@amd.com, mario.limonciello@amd.com,
richard.gong@amd.com, anson.tsao@amd.com,
Alexey Zagorodnikov <xglooom@gmail.com>
Subject: Re: [PATCH v7 4/7] media: platform: amd: isp4 subdev and firmware loading handling added
Date: Tue, 20 Jan 2026 17:29:55 +0800 [thread overview]
Message-ID: <24c3bcfb-5338-4cf7-a0f3-a32428e91144@amd.com> (raw)
In-Reply-To: <aWiVfyz49P7oWTsn@sultan-box>
Hi Skari, since this is a mature product, the ISP driver/FW interface is
fixed and should not change. The only remaining question is how to
initialize them—by declaration or with memset. Would you please share
your preference?
On 1/15/2026 3:21 PM, Sultan Alsawaf wrote:
> On Wed, Jan 14, 2026 at 11:03:49PM +0200, Sakari Ailus wrote:
>> Hi Sultan,
>>
>> On Tue, Jan 06, 2026 at 11:33:53PM -0800, Sultan Alsawaf wrote:
>>> Hi Sakari,
>>>
>>> On Mon, Dec 22, 2025 at 12:11:11PM +0200, Sakari Ailus wrote:
>>>> Hi Bin,
>>>>
>>>> On Tue, Dec 16, 2025 at 05:13:23PM +0800, Bin Du wrote:
>>>>> +static int isp4sd_set_stream_path(struct isp4_subdev *isp_subdev)
>>>>> +{
>>>>> + struct isp4_interface *ispif = &isp_subdev->ispif;
>>>>> + struct isp4fw_cmd_set_stream_cfg cmd;
>>>>> + struct device *dev = isp_subdev->dev;
>>>>> +
>>>>> + /*
>>>>> + * The struct will be shared with ISP FW, use memset() to guarantee padding bits are
>>>>> + * zeroed, since this is not guaranteed on all compilers.
>>>>> + */
>>>>> + memset(&cmd, 0, sizeof(cmd));
>>>>
>>>> You could assign assign all these in the declaration and avoid zeroing the
>>>> memory explicitly at the same time. I presume possibly leaking some
>>>> information from memory to the firmware in case there are holes in the
>>>> struct isn't an issue.
>>>
>>> Leaking kernel memory is bad. Also, there is no guarantee that the firmware will
>>> behave as expected with varying values for the padding bytes.
>>>
>>> Please see my arguments from v4 on why these structs should be memset [1].
>>
>> There should be no host CPU related ABI introduced padding in structs defining
>> firmware interfaces. Just use reserved fields in that case instead. In
>> other words, the above memset() is equivalent to zeroing the memory using
>> an assignment.
>
> I understand that, but I don't work for AMD and don't have firmware source. :)
>
> My personal preference is to pack firmware interface structs since relying on
> reserved fields is subject to human error, especially for future changes to the
> firmware interface.
>
> That being said, please see what Bin said about the firmware interface [1]:
> "Quoted below is Sultan's reply regarding this, does that make sense? On
> the other hand, these definitions are shared between the ISP driver and
> firmware and have been verified. I prefer not to add extra padding
> fields to the driver as it would affect consistency. Is it acceptable to
> leave the definitions as they are?"
>
>>>
>>>>> + cmd.stream_cfg.mipi_pipe_path_cfg.isp4fw_sensor_id = SENSOR_ID_ON_MIPI0;
>>>>> + cmd.stream_cfg.mipi_pipe_path_cfg.b_enable = true;
>>>>> + cmd.stream_cfg.isp_pipe_path_cfg.isp_pipe_id = MIPI0_ISP_PIPELINE_ID;
>>>>> +
>>>>> + cmd.stream_cfg.b_enable_tnr = true;
>>>>> + dev_dbg(dev, "isp4fw_sensor_id %d, pipeId 0x%x EnableTnr %u\n",
>>>>> + cmd.stream_cfg.mipi_pipe_path_cfg.isp4fw_sensor_id,
>>>>> + cmd.stream_cfg.isp_pipe_path_cfg.isp_pipe_id,
>>>>> + cmd.stream_cfg.b_enable_tnr);
>>>>> +
>>>>> + return isp4if_send_command(ispif, CMD_ID_SET_STREAM_CONFIG,
>>>>> + &cmd, sizeof(cmd));
>>>>> +}
>>>>> +
>>>>> +static int isp4sd_send_meta_buf(struct isp4_subdev *isp_subdev)
>>>>> +{
>>>>> + struct isp4_interface *ispif = &isp_subdev->ispif;
>>>>> + struct isp4fw_cmd_send_buffer buf_type;
>>>>> + struct device *dev = isp_subdev->dev;
>>>>> + int i;
>>>>
>>>> unsigned int, please. You can also declare this within the loop as you do
>>>> elsewhere. Consistency is nice.
>>>
>>> Why does this need to be unsigned?
>>
>> Do you need negative numbers there?
>
> No, but we don't need to make the variable explicitly unsigned either. It's more
> common to see `int i;` than `unsigned int i;` too:
>
> $ rg 'unsigned int i;' drivers/media/ | wc -l
> 904
> $ rg 'int i;' drivers/media/ | rg -v unsigned | wc -l
> 1208
>
> Making trivial loop iterators unsigned without reason inflates the code and adds
> some confusion to future readers trying to understand if the 'unsigned' was
> added because it was *required*, IMO.
>
>>>
>>>>> +
>>>>> + /*
>>>>> + * The struct will be shared with ISP FW, use memset() to guarantee padding bits are
>>>>> + * zeroed, since this is not guaranteed on all compilers.
>>>>> + */
>>>>> + memset(&buf_type, 0, sizeof(buf_type));
>>>>> + for (i = 0; i < ISP4IF_MAX_STREAM_BUF_COUNT; i++) {
>>>>> + struct isp4if_gpu_mem_info *meta_info_buf =
>>>>> + isp_subdev->ispif.meta_info_buf[i];
>>>>> + int ret;
>>>>> +
>>>>> + if (!meta_info_buf) {
>>>>> + dev_err(dev, "fail for no meta info buf(%u)\n", i);
>>>>> + return -ENOMEM;
>>>>> + }
>>>>> +
>>>>> + buf_type.buffer_type = BUFFER_TYPE_META_INFO;
>>>>> + buf_type.buffer.vmid_space.bit.space = ADDR_SPACE_TYPE_GPU_VA;
>>>>> + isp4if_split_addr64(meta_info_buf->gpu_mc_addr,
>>>>> + &buf_type.buffer.buf_base_a_lo,
>>>>> + &buf_type.buffer.buf_base_a_hi);
>>>>> + buf_type.buffer.buf_size_a = meta_info_buf->mem_size;
>>>>> + ret = isp4if_send_command(ispif, CMD_ID_SEND_BUFFER,
>>>>> + &buf_type, sizeof(buf_type));
>>>>> + if (ret) {
>>>>> + dev_err(dev, "send meta info(%u) fail\n", i);
>>>>> + return ret;
>>>>> + }
>>>>> + }
>>>>> +
>>>>> + dev_dbg(dev, "send meta info suc\n");
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +static bool isp4sd_get_str_out_prop(struct isp4_subdev *isp_subdev,
>>>>> + struct isp4fw_image_prop *out_prop,
>>>>> + struct v4l2_subdev_state *state, u32 pad)
>>>>> +{
>>>>> + struct device *dev = isp_subdev->dev;
>>>>> + struct v4l2_mbus_framefmt *format;
>>>>> +
>>>>> + format = v4l2_subdev_state_get_format(state, pad, 0);
>>>>> + if (!format) {
>>>>> + dev_err(dev, "fail get subdev state format\n");
>>>>> + return false;
>>>>> + }
>>>>> +
>>>>> + switch (format->code) {
>>>>> + case MEDIA_BUS_FMT_YUYV8_1_5X8:
>>>>> + out_prop->image_format = IMAGE_FORMAT_NV12;
>>>>> + out_prop->width = format->width;
>>>>> + out_prop->height = format->height;
>>>>> + out_prop->luma_pitch = format->width;
>>>>> + out_prop->chroma_pitch = out_prop->width;
>>>>> + break;
>>>>> + case MEDIA_BUS_FMT_YUYV8_1X16:
>>>>> + out_prop->image_format = IMAGE_FORMAT_YUV422INTERLEAVED;
>>>>> + out_prop->width = format->width;
>>>>> + out_prop->height = format->height;
>>>>> + out_prop->luma_pitch = format->width * 2;
>>>>> + out_prop->chroma_pitch = 0;
>>>>> + break;
>>>>> + default:
>>>>> + dev_err(dev, "fail for bad image format:0x%x\n",
>>>>> + format->code);
>>>>> + return false;
>>>>> + }
>>>>> +
>>>>> + if (!out_prop->width || !out_prop->height)
>>>>> + return false;
>>>>> +
>>>>> + return true;
>>>>> +}
>>>>> +
>>>>> +static int isp4sd_kickoff_stream(struct isp4_subdev *isp_subdev, u32 w, u32 h)
>>>>> +{
>>>>> + struct isp4sd_sensor_info *sensor_info = &isp_subdev->sensor_info;
>>>>> + struct isp4_interface *ispif = &isp_subdev->ispif;
>>>>> + struct device *dev = isp_subdev->dev;
>>>>> +
>>>>> + if (sensor_info->status == ISP4SD_START_STATUS_STARTED)
>>>>> + return 0;
>>>>> +
>>>>> + if (sensor_info->status == ISP4SD_START_STATUS_START_FAIL) {
>>>>> + dev_err(dev, "fail for previous start fail\n");
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + dev_dbg(dev, "w:%u,h:%u\n", w, h);
>>>>> +
>>>>> + if (isp4sd_send_meta_buf(isp_subdev)) {
>>>>> + dev_err(dev, "fail to send meta buf\n");
>>>>> + sensor_info->status = ISP4SD_START_STATUS_START_FAIL;
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + sensor_info->status = ISP4SD_START_STATUS_OFF;
>>>>> +
>>>>> + if (!sensor_info->start_stream_cmd_sent &&
>>>>> + sensor_info->buf_sent_cnt >= ISP4SD_MIN_BUF_CNT_BEF_START_STREAM) {
>>>>> + int ret = isp4if_send_command(ispif, CMD_ID_START_STREAM,
>>>>> + NULL, 0);
>>>>> + if (ret) {
>>>>> + dev_err(dev, "fail to start stream\n");
>>>>> + return ret;
>>>>> + }
>>>>> +
>>>>> + sensor_info->start_stream_cmd_sent = true;
>>>>> + } else {
>>>>> + dev_dbg(dev,
>>>>> + "no send START_STREAM, start_sent %u, buf_sent %u\n",
>>>>> + sensor_info->start_stream_cmd_sent,
>>>>> + sensor_info->buf_sent_cnt);
>>>>> + }
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +static int isp4sd_setup_output(struct isp4_subdev *isp_subdev,
>>>>> + struct v4l2_subdev_state *state, u32 pad)
>>>>> +{
>>>>> + struct isp4sd_output_info *output_info = &isp_subdev->sensor_info.output_info;
>>>>> + struct isp4sd_sensor_info *sensor_info = &isp_subdev->sensor_info;
>>>>> + struct isp4_interface *ispif = &isp_subdev->ispif;
>>>>> + struct isp4fw_cmd_set_out_ch_prop cmd_ch_prop;
>>>>> + struct isp4fw_cmd_enable_out_ch cmd_ch_en;
>>>>> + struct device *dev = isp_subdev->dev;
>>>>> + int ret;
>>>>> +
>>>>> + if (output_info->start_status == ISP4SD_START_STATUS_STARTED)
>>>>> + return 0;
>>>>> +
>>>>> + if (output_info->start_status == ISP4SD_START_STATUS_START_FAIL) {
>>>>> + dev_err(dev, "fail for previous start fail\n");
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + /*
>>>>> + * The struct will be shared with ISP FW, use memset() to guarantee padding bits are
>>>>> + * zeroed, since this is not guaranteed on all compilers.
>>>>> + */
>>>>> + memset(&cmd_ch_prop, 0, sizeof(cmd_ch_prop));
>>>>> + cmd_ch_prop.ch = ISP_PIPE_OUT_CH_PREVIEW;
>>>>> +
>>>>> + if (!isp4sd_get_str_out_prop(isp_subdev, &cmd_ch_prop.image_prop, state, pad)) {
>>>>> + dev_err(dev, "fail to get out prop\n");
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + dev_dbg(dev, "channel:%d,fmt %d,w:h=%u:%u,lp:%u,cp%u\n",
>>>>> + cmd_ch_prop.ch,
>>>>> + cmd_ch_prop.image_prop.image_format,
>>>>> + cmd_ch_prop.image_prop.width, cmd_ch_prop.image_prop.height,
>>>>> + cmd_ch_prop.image_prop.luma_pitch,
>>>>> + cmd_ch_prop.image_prop.chroma_pitch);
>>>>> +
>>>>> + ret = isp4if_send_command(ispif, CMD_ID_SET_OUT_CHAN_PROP,
>>>>> + &cmd_ch_prop, sizeof(cmd_ch_prop));
>>>>> + if (ret) {
>>>>> + output_info->start_status = ISP4SD_START_STATUS_START_FAIL;
>>>>> + dev_err(dev, "fail to set out prop\n");
>>>>> + return ret;
>>>>> + }
>>>>> +
>>>>> + /*
>>>>> + * The struct will be shared with ISP FW, use memset() to guarantee padding bits are
>>>>> + * zeroed, since this is not guaranteed on all compilers.
>>>>
>>>> You should have explicit padding fields in any case and not rely on ABI in
>>>> this case.
>>>
>>> It is error-prone for a human to make sure that all padding bytes have
>>> explicit struct members. And what about future changes to the firmware
>>> API where explicit padding might be forgotten?
>>
>> Just don't do that. Use pahole to verify the result when making changes to
>> the structs.
>
> Humans are fallible. Someone will undoubtedly make this mistake in the future
> without some way in place to either automatically run pahole and scrape the
> output for holes in firmware API structs or memset the whole struct at runtime
> so it never matters. OR slap __packed onto all those structs.
>
>>>
>>> Unless the firmware API structs are all __packed in a future firmware update, I
>>> think the memsets should remain.
>>
>> If you want to be certain of the size of the structs, use BUILD_BUG_ON().
>
> This won't help for the addition of new structs and still requires a human to
> "do the right thing" and make sure there aren't any holes when they hardcode the
> struct size into a compile-time assert.
>
>> --
>> Kind regards,
>>
>> Sakari Ailus
>
> [1] https://lore.kernel.org/all/62bd8248-dd8a-4d51-8a85-ad13d3a03180@amd.com/
>
> Sultan
--
Regards,
Bin
next prev parent reply other threads:[~2026-01-20 9:30 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-16 9:13 [PATCH v7 0/7] Add AMD ISP4 driver Bin Du
2025-12-16 9:13 ` [PATCH v7 1/7] media: platform: amd: Introduce amd isp4 capture driver Bin Du
2025-12-22 9:23 ` Sakari Ailus
2026-01-06 8:30 ` Du, Bin
2025-12-16 9:13 ` [PATCH v7 2/7] media: platform: amd: low level support for isp4 firmware Bin Du
2025-12-16 9:13 ` [PATCH v7 3/7] media: platform: amd: Add isp4 fw and hw interface Bin Du
2025-12-22 9:37 ` Sakari Ailus
2026-01-07 8:44 ` Du, Bin
2026-01-14 20:55 ` Sakari Ailus
2026-01-15 2:24 ` Du, Bin
2026-01-20 9:22 ` Du, Bin
2026-01-27 8:38 ` Du, Bin
2026-02-02 9:10 ` Sakari Ailus
2026-02-03 6:37 ` Du, Bin
2025-12-16 9:13 ` [PATCH v7 4/7] media: platform: amd: isp4 subdev and firmware loading handling added Bin Du
2025-12-22 10:11 ` Sakari Ailus
2026-01-07 7:33 ` Sultan Alsawaf
2026-01-14 21:03 ` Sakari Ailus
2026-01-14 21:08 ` Mario Limonciello
2026-01-15 5:56 ` Du, Bin
2026-01-15 7:21 ` Sultan Alsawaf
2026-01-20 9:29 ` Du, Bin [this message]
2026-01-27 8:39 ` Du, Bin
2026-01-15 10:36 ` Du, Bin
2026-01-14 10:34 ` Du, Bin
2026-01-14 21:07 ` Sakari Ailus
2026-01-15 7:51 ` Du, Bin
2026-01-14 9:45 ` Markus Elfring
2025-12-16 9:13 ` [PATCH v7 5/7] media: platform: amd: isp4 video node and buffers " Bin Du
2025-12-22 17:07 ` Sakari Ailus
2026-01-09 10:08 ` Du, Bin
2026-01-29 21:17 ` Sakari Ailus
2026-02-03 6:32 ` Du, Bin
2025-12-16 9:13 ` [PATCH v7 6/7] media: platform: amd: isp4 debug fs logging and more descriptive errors Bin Du
2025-12-16 9:13 ` [PATCH v7 7/7] Documentation: add documentation of AMD isp 4 driver Bin Du
2025-12-17 7:36 ` [PATCH v7 0/7] Add AMD ISP4 driver Sultan Alsawaf
2025-12-17 7:47 ` Du, Bin
2025-12-17 10:29 ` Du, Bin
2025-12-17 11:04 ` Sakari Ailus
2025-12-31 9:03 ` Kate Hsuan
2026-01-06 5:49 ` Kate Hsuan
2026-01-06 8:35 ` Du, Bin
2026-01-13 14:11 ` Kate Hsuan
2026-01-13 17:14 ` Nirujogi, Pratap
2026-01-14 8:59 ` Kate Hsuan
2026-01-15 6:47 ` Du, Bin
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=24c3bcfb-5338-4cf7-a0f3-a32428e91144@amd.com \
--to=bin.du@amd.com \
--cc=Dominic.Antony@amd.com \
--cc=Phil.Jawich@amd.com \
--cc=anson.tsao@amd.com \
--cc=benjamin.chan@amd.com \
--cc=bryan.odonoghue@linaro.org \
--cc=gjorgji.rosikopulos@amd.com \
--cc=hverkuil@xs4all.nl \
--cc=king.li@amd.com \
--cc=laurent.pinchart+renesas@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mario.limonciello@amd.com \
--cc=mchehab@kernel.org \
--cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
--cc=pratap.nirujogi@amd.com \
--cc=richard.gong@amd.com \
--cc=sakari.ailus@linux.intel.com \
--cc=sultan@kerneltoast.com \
--cc=xglooom@gmail.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
all inboxes | Powered by JetHome®