Linux Media Controller development
 help / color / mirror / Atom feed
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


  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