linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Andrea Merello <andrea.merello@gmail.com>
Cc: mchehab+huawei@kernel.org, linux-iio@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	lars@metafoo.de, robh+dt@kernel.org, andy.shevchenko@gmail.com,
	matt.ranostay@konsulko.com, ardeleanalex@gmail.com,
	jacopo@jmondi.org, Andrea Merello <andrea.merello@iit.it>
Subject: Re: [v4 12/14] iio: imu: add BNO055 serdev driver
Date: Fri, 15 Apr 2022 17:48:08 +0100	[thread overview]
Message-ID: <20220415174808.3b81baa4@jic23-huawei> (raw)
In-Reply-To: <20220415130005.85879-13-andrea.merello@gmail.com>

On Fri, 15 Apr 2022 15:00:03 +0200
Andrea Merello <andrea.merello@gmail.com> wrote:

> From: Andrea Merello <andrea.merello@iit.it>
> 
> This path adds a serdev driver for communicating to a BNO055 IMU via
> serial bus, and it enables the BNO055 core driver to work in this
> scenario.
> 
> Signed-off-by: Andrea Merello <andrea.merello@iit.it>
Hi Andrea

A few really trivial things in here from me.

Jonathan

> ---

> diff --git a/drivers/iio/imu/bno055/Makefile b/drivers/iio/imu/bno055/Makefile
> index 56cc4de60a7e..20128b1a1afc 100644
> --- a/drivers/iio/imu/bno055/Makefile
> +++ b/drivers/iio/imu/bno055/Makefile
> @@ -1,3 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0
>  
>  obj-$(CONFIG_BOSCH_BNO055_IIO) += bno055.o
> +obj-$(CONFIG_BOSCH_BNO055_SERIAL) += bno055_ser.o
> +
> +CFLAGS_bno055_ser.o := -I$(src)

Via a bit of grepping I can see other instances of this pattern which point out
that it's to do with allowing the tracing framework to see trace.h.
Perhaps a similar comment here would be good (if nothing else I doubt I'll
remember why this magic is here in a few years time!)

> diff --git a/drivers/iio/imu/bno055/bno055_ser.c b/drivers/iio/imu/bno055/bno055_ser.c
> new file mode 100644
> index 000000000000..360dfb0ee20a
> --- /dev/null
> +++ b/drivers/iio/imu/bno055/bno055_ser.c
> @@ -0,0 +1,556 @@
...

> +
> +struct bno055_ser_priv {
> +	struct serdev_device *serdev;
> +	struct completion cmd_complete;
> +	enum {
> +		CMD_NONE,
> +		CMD_READ,
> +		CMD_WRITE,
> +	} expect_response;
> +	int expected_data_len;
> +	u8 *response_buf;
> +
> +	/**
> +	 * enum cmd_status - represent the status of a command sent to the HW.
> +	 * @STATUS_CRIT: The command failed: the serial communication failed.
> +	 * @STATUS_OK:   The command executed successfully.
> +	 * @STATUS_FAIL: The command failed: HW responded with an error.
> +	 */
> +	enum {
> +		STATUS_CRIT = -1,
> +		STATUS_OK = 0,
> +		STATUS_FAIL = 1,
> +	} cmd_status;

Locks need documentation to say what scope they cover. In this case
I think it is most but not quite all of this structure.
See comment on completion below.

> +	struct mutex lock;
> +
> +	/* Only accessed in RX callback context. No lock needed. */
> +	struct {
> +		enum {
> +			RX_IDLE,
> +			RX_START,
> +			RX_DATA,
> +		} state;
> +		int databuf_count;
> +		int expected_len;
> +		int type;
> +	} rx;
> +
> +	/* Never accessed in behalf of RX callback context. No lock needed */
> +	bool cmd_stale;
> +};




...

> +
> +/*
> + * Handler for received data; this is called from the reicever callback whenever
> + * it got some packet from the serial bus. The status tell us whether the
> + * packet is valid (i.e. header ok && received payload len consistent wrt the
> + * header). It's now our responsability to check whether this is what we
> + * expected, of whether we got some unexpected, yet valid, packet.
> + */
> +static void bno055_ser_handle_rx(struct bno055_ser_priv *priv, int status)
> +{
> +	mutex_lock(&priv->lock);
> +	switch (priv->expect_response) {
> +	case CMD_NONE:
> +		dev_warn(&priv->serdev->dev, "received unexpected, yet valid, data from sensor");
> +		mutex_unlock(&priv->lock);
> +		return;
> +
> +	case CMD_READ:
> +		priv->cmd_status = status;
> +		if (status == STATUS_OK &&
> +		    priv->rx.databuf_count != priv->expected_data_len) {
> +			/*
> +			 * If we got here, then the lower layer serial protocol
> +			 * seems consistent with itself; if we got an unexpected
> +			 * amount of data then signal it as a non critical error
> +			 */
> +			priv->cmd_status = STATUS_FAIL;
> +			dev_warn(&priv->serdev->dev, "received an unexpected amount of, yet valid, data from sensor");

Wrap the line after dev,
Whilst it'll still be a very long line we can make it shorter with no loss
of readability, whilst still not breaking the string (which would make it hard
to grep for).

> +		}
> +		break;
> +
> +	case CMD_WRITE:
> +		priv->cmd_status = status;
> +		break;
> +	}
> +
> +	priv->expect_response = CMD_NONE;
> +	complete(&priv->cmd_complete);

I argued with myself a bit on whether the complete() should be inside the lock
or not - but then concluded it doesn't really matter and moving it out is
probably premature optimisation... Maybe it's worth moving it out simply
so that it's clear the lock isn't needed to protect it, or am I missing something?

> +	mutex_unlock(&priv->lock);
> +}
> +
> +/*
> + * Serdev receiver FSM. This tracks the serial communication and parse the
> + * header. It pushes packets to bno055_ser_handle_rx(), eventually communicating
> + * failures (i.e. malformed packets).
> + * Ideally it doesn't know anything about upper layer (i.e. if this is the
> + * packet we were really expecting), but since we copies the payload into the
> + * receiver buffer (that is not valid when i.e. we don't expect data), we
> + * snoop a bit in the upper layer..
> + * Also, we assume to RX one pkt per time (i.e. the HW doesn't send anything
> + * unless we require to AND we don't queue more than one request per time).
> + */
> +static int bno055_ser_receive_buf(struct serdev_device *serdev,
> +				  const unsigned char *buf, size_t size)
> +{
> +	int status;
> +	struct bno055_ser_priv *priv = serdev_device_get_drvdata(serdev);
> +	int remaining = size;
> +
> +	if (size == 0)
> +		return 0;
> +
> +	trace_recv(size, buf);
> +	switch (priv->rx.state) {
> +	case RX_IDLE:
> +		/*
> +		 * New packet.
> +		 * Check for its 1st byte, that identifies the pkt type.
> +		 */
> +		if (buf[0] != 0xEE && buf[0] != 0xBB) {
> +			dev_err(&priv->serdev->dev,
> +				"Invalid packet start %x", buf[0]);
> +			bno055_ser_handle_rx(priv, STATUS_CRIT);
> +			break;
> +		}
> +		priv->rx.type = buf[0];
> +		priv->rx.state = RX_START;
> +		remaining--;
> +		buf++;
> +		priv->rx.databuf_count = 0;
> +		fallthrough;
> +
> +	case RX_START:
> +		/*
> +		 * Packet RX in progress, we expect either 1-byte len or 1-byte
> +		 * status depending by the packet type.
> +		 */
> +		if (remaining == 0)
> +			break;
> +
> +		if (priv->rx.type == 0xEE) {
> +			if (remaining > 1) {
> +				dev_err(&priv->serdev->dev, "EE pkt. Extra data received");
> +				status = STATUS_CRIT;

Trivial, but this blank line doesn't add anything so drop it.

> +
> +			} else {
> +				status = (buf[0] == 1) ? STATUS_OK : STATUS_FAIL;
> +			}
> +			bno055_ser_handle_rx(priv, status);
> +			priv->rx.state = RX_IDLE;
> +			break;
> +
> +		} else {
> +			/*priv->rx.type == 0xBB */
> +			priv->rx.state = RX_DATA;
> +			priv->rx.expected_len = buf[0];
> +			remaining--;
> +			buf++;
> +		}
> +		fallthrough;
> +
> +	case RX_DATA:
> +		/* Header parsed; now receiving packet data payload */
> +		if (remaining == 0)
> +			break;
> +
> +		if (priv->rx.databuf_count + remaining > priv->rx.expected_len) {
> +			/*
> +			 * This is a inconsistency in serial protocol, we lost

an inconsistency

> +			 * sync and we don't know how to handle further data
> +			 */
> +			dev_err(&priv->serdev->dev, "BB pkt. Extra data received");
> +			bno055_ser_handle_rx(priv, STATUS_CRIT);
> +			priv->rx.state = RX_IDLE;
> +			break;
> +		}
> +
> +		mutex_lock(&priv->lock);
> +		/*
> +		 * NULL e.g. when read cmd is stale or when no read cmd is
> +		 * actually pending.
> +		 */
> +		if (priv->response_buf &&
> +		    /*
> +		     * Snoop on the upper layer protocol stuff to make sure not
> +		     * to write to an invalid memory. Apart for this, let's the
> +		     * upper layer manage any inconsistency wrt expected data
> +		     * len (as long as the serial protocol is consistent wrt
> +		     * itself (i.e. response header is consistent with received
> +		     * response len.
> +		     */
> +		    (priv->rx.databuf_count + remaining <= priv->expected_data_len))
> +			memcpy(priv->response_buf + priv->rx.databuf_count,
> +			       buf, remaining);
> +		mutex_unlock(&priv->lock);
> +
> +		priv->rx.databuf_count += remaining;
> +
> +		/*
> +		 * Reached expected len advertised by the IMU for the current
> +		 * packet. Pass it to the upper layer (for us it is just valid).
> +		 */
> +		if (priv->rx.databuf_count == priv->rx.expected_len) {
> +			bno055_ser_handle_rx(priv, STATUS_OK);
> +			priv->rx.state = RX_IDLE;
> +		}
> +		break;
> +	}
> +
> +	return size;
> +}

  reply	other threads:[~2022-04-15 16:40 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-15 12:59 [v4 00/14] Add support for Bosch BNO055 IMU Andrea Merello
2022-04-15 12:59 ` [v4 01/14] iio: add modifiers for linear acceleration Andrea Merello
2022-04-15 12:59 ` [v4 02/14] iio: document linear acceleration modifiers Andrea Merello
2022-04-15 12:59 ` [v4 03/14] iio: event_monitor: add " Andrea Merello
2022-04-16  8:37   ` Andy Shevchenko
2022-04-15 12:59 ` [v4 04/14] iio: add modifers for pitch, yaw, roll Andrea Merello
2022-04-16  8:38   ` Andy Shevchenko
2022-04-15 12:59 ` [v4 05/14] iio: document pitch, yaw, roll modifiers Andrea Merello
2022-04-15 12:59 ` [v4 06/14] iio: event_monitor: add pitch, yaw and " Andrea Merello
2022-04-15 12:59 ` [v4 07/14] iio: add support for binary attributes Andrea Merello
2022-04-15 12:59 ` [v4 08/14] iio: imu: add Bosch Sensortec BNO055 core driver Andrea Merello
2022-04-15 17:43   ` Jonathan Cameron
2022-04-19  7:10     ` Andrea Merello
2022-04-24 17:45       ` Jonathan Cameron
2022-04-26  9:28         ` Andrea Merello
2022-04-28 18:45           ` Jonathan Cameron
2022-04-15 13:00 ` [v4 09/14] iio: document bno055 private sysfs attributes Andrea Merello
2022-04-15 13:00 ` [v4 10/14] iio: document "serial_number" sysfs attribute Andrea Merello
2022-04-19  7:41   ` Lars-Peter Clausen
2022-04-24 17:46     ` Jonathan Cameron
2022-04-15 13:00 ` [v4 11/14] dt-bindings: iio: imu: add documentation for Bosch BNO055 bindings Andrea Merello
2022-04-25 22:08   ` Rob Herring
2022-04-15 13:00 ` [v4 12/14] iio: imu: add BNO055 serdev driver Andrea Merello
2022-04-15 16:48   ` Jonathan Cameron [this message]
2022-04-16  8:44     ` Andy Shevchenko
2022-04-19  7:48       ` Andrea Merello
2022-04-19  8:29         ` Andy Shevchenko
2022-04-20  7:22     ` Andrea Merello
2022-04-15 13:00 ` [v4 13/14] iio: imu: add BNO055 I2C driver Andrea Merello
2022-04-15 16:49   ` Jonathan Cameron
2022-04-15 13:00 ` [v4 14/14] docs: iio: add documentation for BNO055 driver Andrea Merello
2022-04-16  8:40 ` [v4 00/14] Add support for Bosch BNO055 IMU Andy Shevchenko

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=20220415174808.3b81baa4@jic23-huawei \
    --to=jic23@kernel.org \
    --cc=andrea.merello@gmail.com \
    --cc=andrea.merello@iit.it \
    --cc=andy.shevchenko@gmail.com \
    --cc=ardeleanalex@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=jacopo@jmondi.org \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=matt.ranostay@konsulko.com \
    --cc=mchehab+huawei@kernel.org \
    --cc=robh+dt@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).