From: "Vadillo, Miguel" <miguel.vadillo@intel.com>
To: Mehdi Djait <mehdi.djait@linux.intel.com>
Cc: <linux-media@vger.kernel.org>, <wei.a.xu@intel.com>,
<atul.raut@intel.com>, <sakari.ailus@linux.intel.com>,
<antti.laakso@linux.intel.com>, <kieran.bingham@ideasonboard.com>
Subject: Re: [PATCH v3 1/3] media: i2c: cvs: Add driver of Intel Computer Vision Sensing Controller(CVS)
Date: Sat, 23 May 2026 16:33:56 -0700 [thread overview]
Message-ID: <0ecb5cb8-1772-4b9e-a9dc-580b48f071f5@intel.com> (raw)
In-Reply-To: <ahBmGsv67RcYAvsc@mdjait-mobl>
Hi Mehdi,
Thanks for reviewing.
On 5/22/26 7:41 AM, Mehdi Djait wrote:
> Hi Miguel,
>
> Thank you for the patch!
>
> A couple of comments below.
>
> On Thu, May 21, 2026 at 03:23:57PM -0700, Miguel Vadillo wrote:
>
> [..]
>
>> +
>> +/* I2C transport helpers */
>> +
>> +/**
>> + * cvs_read_i2c - Issue a read-type command and fetch device response
>> + * @ctx: CVS device context
>> + * @cmd_id: Command identifier (big endian)
>> + * @resp: Destination buffer for response payload
>> + * @size: Size of payload to read into @resp (without prefix)
>> + *
>> + * Sends @cmd_id and reads back the response in a single I2C transaction.
>> + * When the device prepends a 4-byte protocol prefix, the combined
>> + * prefix+payload is read into a temporary buffer and only the payload is
>> + * copied to @resp, avoiding any dependency on the layout of the caller's
>> + * buffer.
>> + *
>> + * Return: 0 on success or negative errno.
>> + */
>> +static int cvs_read_i2c(struct icvs *ctx, __be16 cmd_id, void *resp,
>> + size_t size)
>> +{
>> + size_t prefix_size = ctx->prefix ? sizeof(u32) : 0;
>> + size_t read_size = size + prefix_size;
>> + struct i2c_client *i2c = ctx->i2c_client;
>> + u8 *buf;
>
> use this instead:
> u8 *buf __free(kfree) = NULL;
>
> and then remove the two calls to kfree() below.
This makes sense, ack.
>
>> + int cnt;
>> +
>> + if (!resp || !size)
>> + return -EINVAL;
>> +
>> + cnt = i2c_master_send(i2c, (const char *)&cmd_id, sizeof(cmd_id));
>> + if (cnt != sizeof(cmd_id))
>> + return cnt < 0 ? cnt : -EIO;
>> +
>> + buf = kmalloc(read_size, GFP_KERNEL);
>> + if (!buf)
>> + return -ENOMEM;
>> +
>> + cnt = i2c_master_recv(i2c, buf, read_size);
>> + if (cnt != read_size) {
>> + dev_dbg(cvs_dev(ctx), "recv cmd 0x%04x short read (%d/%zu)\n",
>> + be16_to_cpu(cmd_id), cnt, read_size);
>> + kfree(buf);
>> + return cnt < 0 ? cnt : -EIO;
>> + }
>> +
>> + memcpy(resp, buf + prefix_size, size);
>> + kfree(buf);
>> +
>> + return 0;
>> +}
>
> [..]
>
>> +/**
>> + * cvs_send - Common command submission path
>> + * @ctx: CVS device context
>> + * @cmd: Command buffer (icvs_cmd) with cmd_id and param populated
>> + * @len: Buffer length
>> + *
>> + * Dispatches a set of supported commands:
>> + * - ICVS_SET_DEV_HOST_ID,
>> + * - ICVS_HOST_SENSOR_OWNER,
>> + * - ICVS_HOST_SET_MIPI_CONFIG
>> + * - ICVS_FW_LOADER_*
>> + *
>> + * For I2C based commands it sets big-endian cmd ids, writes to the device
>> + * and waits (via delayed work) for completion or timeout.
>> + * GPIO based ownership toggles are handled locally.
>> + *
>> + * Caller must hold ctx->lock when invoking this function and check for i2c
>> + * bus availability.
>> + *
>> + * Return: 0 on success, negative errno, -EINVAL for unsupported command
>> + * or status from device in ctx->wq_resp.
>> + */
>> +int cvs_send(struct icvs *ctx, struct icvs_cmd *cmd, size_t len)
>> +{
>> + int ret, status = 0;
>> +
>> + dev_dbg(cvs_dev(ctx), "send cmd = 0x%04x", be16_to_cpu(cmd->cmd_id));
>
> From where I see this function being called, it needs to hold the
> ctx->lock. It is also mentioned in the documentation of function
>
> Let's add a lockdep_assert_held() to make sure of it at the beginning of
> cvs_send()
Agree and ack'ed
>
>> +
>> + reinit_completion(&ctx->cmd_completion);
>> +
>> + switch (be16_to_cpu(cmd->cmd_id)) {
>> + case ICVS_SET_DEV_HOST_ID:
>> + cmd->cmd_id = cpu_to_be16(ICVS_SET_DEV_HOST_ID);
>> + ret = cvs_write_i2c(ctx, cmd, len);
>> + if (ret < 0)
>> + break;
>> +
>> + ret = cvs_schedule_and_wait(ctx, FW_READY_DELAY_MS,
>> + CMD_TIMEOUT);
>> + if (ret < 0)
>> + break;
>> +
>> + status = ctx->wq_resp.resp.state &
>> + ICVS_DEV_STATE_ERROR ? -EINVAL : 0;
>> + break;
>> + case ICVS_HOST_SENSOR_OWNER:
>> + gpiod_set_value_cansleep(ctx->req, cmd->param.param);
>> + fsleep(FW_READY_DELAY_MS * USEC_PER_MSEC);
>> + ret = gpiod_get_value_cansleep(ctx->resp);
>> + status = cmd->param.param == ret ? 0 : -EINVAL;
>> + ret = 0; /* success */
>> + break;
>> + case ICVS_HOST_SET_MIPI_CONFIG:
>> + cmd->cmd_id = cpu_to_be16(ICVS_HOST_SET_MIPI_CONFIG);
>> + ret = cvs_config_mipi(ctx, cmd, len);
>> + if (ret < 0)
>> + break;
>> +
>> + ret = cvs_schedule_and_wait(ctx, FW_READY_DELAY_MS,
>> + CMD_TIMEOUT);
>> + status = (ctx->wq_resp.resp.state &
>> + ICVS_DEV_STATE_ERROR) ? -EINVAL : 0;
>> + break;
>> + case ICVS_FW_LOADER_START:
>> + cmd->cmd_id = cpu_to_be16(ICVS_FW_LOADER_START);
>> + ret = cvs_write_i2c(ctx, cmd, len);
>> + if (ret < 0)
>> + break;
>> +
>> + ret = cvs_wait_wake_or_sleep(ctx, CMD_TIMEOUT,
>> + FW_READY_DELAY_MS);
>> + if (ret)
>> + break;
>> +
>> + ret = cvs_schedule_and_wait(ctx, FW_READY_DELAY_MS,
>> + CMD_TIMEOUT);
>> + status = (ctx->wq_resp.resp.state &
>> + ICVS_DEV_STATE_DOWNLOAD) ? 0 : -EINVAL;
>> + break;
>> + case ICVS_FW_LOADER_DATA:
>> + /* Quirk for older protocols */
>> + if (ctx->caps.protocol_version_major >= 2 &&
>> + ctx->caps.protocol_version_minor >= 2) {
>> + cmd->cmd_id = cpu_to_be16(ICVS_FW_LOADER_DATA);
>> + ret = cvs_write_i2c(ctx, cmd, len);
>> + } else {
>> + ret = cvs_write_i2c(ctx, &cmd->param,
>> + len - sizeof(cmd->cmd_id));
>> + }
>> +
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = cvs_wait_wake_or_sleep(ctx, FW_READY_DELAY_MS,
>> + FW_READY_DELAY_MS);
>> + if (ret)
>> + break;
>> +
>> + ret = cvs_schedule_and_wait(ctx, FW_READY_DELAY_MS,
>> + CMD_TIMEOUT);
>> + status = ctx->wq_resp.resp.state &
>> + ICVS_DEV_STATE_ERROR ? -EINVAL : 0;
>> + break;
>> + case ICVS_FW_LOADER_END:
>> + cmd->cmd_id = cpu_to_be16(ICVS_FW_LOADER_END);
>> + ret = cvs_write_i2c(ctx, cmd, len);
>> + if (ret < 0)
>> + break;
>> +
>> + ret = cvs_wait_wake_or_sleep(ctx, CMD_TIMEOUT,
>> + FW_READY_DELAY_MS);
>> + if (ret)
>> + break;
>> +
>> + ret = cvs_schedule_and_wait(ctx, FW_READY_DELAY_MS,
>> + CMD_TIMEOUT);
>> + status = !(ctx->wq_resp.resp.state &
>> + ICVS_DEV_STATE_DOWNLOAD) ? 0 : -EINVAL;
>> + break;
>> + default:
>> + ret = -EINVAL;
>> + break;
>> + }
>> +
>> + if (ret < 0)
>> + return ret;
>> +
>> + return ctx->wq_resp.status = status;
>> +}
>
> [..]
>
>> + * cvs_core_remove - Shared remove logic
>> + * @dev: Device
>> + */
>> +static void cvs_core_remove(struct device *dev)
>> +{
>> + struct icvs *ctx = dev_get_drvdata(dev);
>> +
>> + cvs_csi_remove(ctx);
>
> Shouldn't we cancel ctx work first ? And then do the CSI2 v4l2 cleanup ?
Good catch I think this was leaving a window for race condition, ack'ed
--
regards,
Miguel
>
>> + cancel_delayed_work_sync(&ctx->work);
>> +
>> + if (ctx->ipu_link)
>> + device_link_del(ctx->ipu_link);
>> +
>> + pm_runtime_put_noidle(dev);
>> + pm_runtime_disable(dev);
>> + pm_runtime_set_suspended(dev);
>> +
>> + cvs_reset(ctx);
>> +}
>> +
>> +/**
>> + * cvs_remove - I2C driver remove
>> + * @client: I2C client
>> + */
>> +static void cvs_remove(struct i2c_client *client)
>> +{
>> + cvs_core_remove(&client->dev);
>
> [..]
>
> --
> Kind Regards
> Mehdi Djait
next prev parent reply other threads:[~2026-05-23 23:34 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-21 22:23 [PATCH v3 0/3] media: i2c: cvs: Add Intel CVS driver Miguel Vadillo
2026-05-21 22:23 ` [PATCH v3 1/3] media: i2c: cvs: Add driver of Intel Computer Vision Sensing Controller(CVS) Miguel Vadillo
2026-05-22 8:39 ` Mehdi Djait
2026-05-23 23:37 ` Vadillo, Miguel
2026-05-25 8:36 ` Mehdi Djait
2026-05-22 14:41 ` Mehdi Djait
2026-05-23 23:33 ` Vadillo, Miguel [this message]
2026-05-21 22:23 ` [PATCH v3 2/3] media: pci: intel: Add CVS support for IPU bridge driver Miguel Vadillo
2026-05-21 22:23 ` [PATCH v3 3/3] ACPI: scan: Honor _DEP for Intel CVS devices Miguel Vadillo
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=0ecb5cb8-1772-4b9e-a9dc-580b48f071f5@intel.com \
--to=miguel.vadillo@intel.com \
--cc=antti.laakso@linux.intel.com \
--cc=atul.raut@intel.com \
--cc=kieran.bingham@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=mehdi.djait@linux.intel.com \
--cc=sakari.ailus@linux.intel.com \
--cc=wei.a.xu@intel.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