linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Gwendal Grignou <gwendal@chromium.org>
Cc: briannorris@chromium.org, knaack.h@gmx.de, lars@metafoo.de,
	pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org,
	enric.balletbo@collabora.com, dianders@chromium.org,
	groeck@chromium.org, fabien.lahoudere@collabora.com,
	linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org,
	Enrico Granata <egranata@chromium.org>
Subject: Re: [PATCH v2 07/18] platform: chrome: cros_ec: handle MKBP more events flag
Date: Mon, 21 Oct 2019 17:07:19 +0100	[thread overview]
Message-ID: <20191021170719.09f1e5c2@archlinux> (raw)
In-Reply-To: <20191021055403.67849-8-gwendal@chromium.org>

On Sun, 20 Oct 2019 22:53:52 -0700
Gwendal Grignou <gwendal@chromium.org> wrote:

> From: Enrico Granata <egranata@chromium.org>
> 
> The ChromeOS EC has support for signaling to the host that
> a single IRQ can serve multiple MKBP (Matrix KeyBoard Protocol)
> events.
> 
> Doing this serves an optimization purpose, as it minimizes the
> number of round-trips into the interrupt handling machinery, and
> it proves beneficial to sensor timestamping as it keeps the desired
> synchronization of event times between the two processors.
> 
> This patch adds kernel support for this EC feature, allowing the
> ec_irq to loop until all events have been served.
> 
> Signed-off-by: Enrico Granata <egranata@chromium.org>
> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
A few superficial bits inline.

Jonathan
> ---
> Changes in v2:
>   Process flag inside cros_ec_get_next_event, clean flag from event.
>   Introduce public function cros_ec_handle_event(), use it in rpmsg and
>     ishtp transport layer.
>   Remplace dev_info with dev_dbg, call only once.
> 
>  drivers/platform/chrome/cros_ec.c           | 35 +++++++--
>  drivers/platform/chrome/cros_ec_ishtp.c     |  8 +-
>  drivers/platform/chrome/cros_ec_lpc.c       | 15 +++-
>  drivers/platform/chrome/cros_ec_proto.c     | 81 +++++++++++++--------
>  drivers/platform/chrome/cros_ec_rpmsg.c     | 23 ++----
>  include/linux/platform_data/cros_ec_proto.h | 12 ++-
>  6 files changed, 110 insertions(+), 64 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c
> index 9b19f50572313..eb7f60140e2c1 100644
> --- a/drivers/platform/chrome/cros_ec.c
> +++ b/drivers/platform/chrome/cros_ec.c
> @@ -40,13 +40,24 @@ static irqreturn_t ec_irq_handler(int irq, void *data)
>  	return IRQ_WAKE_THREAD;
>  }
>  
> -static irqreturn_t ec_irq_thread(int irq, void *data)
> +/**
> + * cros_ec_handle_event - process and forward pending events on EC
run kernel-doc generation over the files after adding kernel doc.

It needs to be a complete and this one doesn't document the parameter.

> + *
> + * Call this function in a loop when the kernel is notified that the EC has
> + * pending events.
> + *
> + * Returns true if more events are still pending and this function should be
> + * called again.
> + */
> +bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
>  {
> -	struct cros_ec_device *ec_dev = data;
> -	bool wake_event = true;
> +	bool wake_event;
> +	bool ec_has_more_events;
>  	int ret;
>  
> -	ret = cros_ec_get_next_event(ec_dev, &wake_event);
> +	ret = cros_ec_get_next_event(ec_dev,
> +			&wake_event,
> +			&ec_has_more_events);

	ret = cros_ec_get_next_event(ec_dev, &wake_event, &ec_has_more_events);

Seems to be under 80 chars (just!)
>  
>  	/*
>  	 * Signal only if wake host events or any interrupt if
> @@ -59,6 +70,20 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
>  	if (ret > 0)
>  		blocking_notifier_call_chain(&ec_dev->event_notifier,
>  					     0, ec_dev);
> +
> +	return ec_has_more_events;
> +}
> +EXPORT_SYMBOL(cros_ec_handle_event);
> +
> +static irqreturn_t ec_irq_thread(int irq, void *data)
> +{
> +	struct cros_ec_device *ec_dev = data;
> +	bool ec_has_more_events;
> +
> +	do {
> +		ec_has_more_events = cros_ec_handle_event(ec_dev);
> +	} while (ec_has_more_events);
> +
>  	return IRQ_HANDLED;
>  }
>  
> @@ -273,7 +298,7 @@ EXPORT_SYMBOL(cros_ec_suspend);
>  static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev)
>  {
>  	while (ec_dev->mkbp_event_supported &&
> -	       cros_ec_get_next_event(ec_dev, NULL) > 0)
> +	       cros_ec_get_next_event(ec_dev, NULL, NULL) > 0)
>  		blocking_notifier_call_chain(&ec_dev->event_notifier,
>  					     1, ec_dev);
>  }
> diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c
> index 5c848f22b44b4..e5996821d08b3 100644
> --- a/drivers/platform/chrome/cros_ec_ishtp.c
> +++ b/drivers/platform/chrome/cros_ec_ishtp.c
> @@ -136,11 +136,11 @@ static void ish_evt_handler(struct work_struct *work)
>  	struct ishtp_cl_data *client_data =
>  		container_of(work, struct ishtp_cl_data, work_ec_evt);
>  	struct cros_ec_device *ec_dev = client_data->ec_dev;
> +	bool ec_has_more_events;
>  
> -	if (cros_ec_get_next_event(ec_dev, NULL) > 0) {
> -		blocking_notifier_call_chain(&ec_dev->event_notifier,
> -					     0, ec_dev);
> -	}
> +	do {
> +		ec_has_more_events = cros_ec_handle_event(ec_dev);
> +	} while (ec_has_more_events);
>  }
>  
>  /**
> diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
> index 3c77496e164da..7d2db3d2b094a 100644
> --- a/drivers/platform/chrome/cros_ec_lpc.c
> +++ b/drivers/platform/chrome/cros_ec_lpc.c
> @@ -312,13 +312,20 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
>  static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
>  {
>  	struct cros_ec_device *ec_dev = data;
> +	bool ec_has_more_events;
> +	int ret;
>  
>  	ec_dev->last_event_time = cros_ec_get_time_ns();
>  
> -	if (ec_dev->mkbp_event_supported &&
> -	    cros_ec_get_next_event(ec_dev, NULL) > 0)
> -		blocking_notifier_call_chain(&ec_dev->event_notifier, 0,
> -					     ec_dev);
> +	if (ec_dev->mkbp_event_supported)
> +		do {
> +			ret = cros_ec_get_next_event(ec_dev, NULL,
> +					&ec_has_more_events);
> +			if (ret > 0)
> +				blocking_notifier_call_chain(
> +						&ec_dev->event_notifier, 0,
> +						ec_dev);
> +		} while (ec_has_more_events);
>  
>  	if (value == ACPI_NOTIFY_DEVICE_WAKE)
>  		pm_system_wakeup();
> diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
> index 2357c717399ad..17d6f36a576d1 100644
> --- a/drivers/platform/chrome/cros_ec_proto.c
> +++ b/drivers/platform/chrome/cros_ec_proto.c
> @@ -456,7 +456,10 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
>  	if (ret < 0 || ver_mask == 0)
>  		ec_dev->mkbp_event_supported = 0;
>  	else
> -		ec_dev->mkbp_event_supported = 1;
> +		ec_dev->mkbp_event_supported = fls(ver_mask);
> +
> +	dev_dbg(ec_dev->dev, "MKBP support version %u\n",
> +		ec_dev->mkbp_event_supported - 1);
>  
>  	/* Probe if host sleep v1 is supported for S0ix failure detection. */
>  	ret = cros_ec_get_host_command_version_mask(ec_dev,
> @@ -569,6 +572,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
>  
>  static int get_next_event_xfer(struct cros_ec_device *ec_dev,
>  			       struct cros_ec_command *msg,
> +			       struct ec_response_get_next_event_v1 *event,
>  			       int version, uint32_t size)
>  {
>  	int ret;
> @@ -581,7 +585,7 @@ static int get_next_event_xfer(struct cros_ec_device *ec_dev,
>  	ret = cros_ec_cmd_xfer(ec_dev, msg);
>  	if (ret > 0) {
>  		ec_dev->event_size = ret - 1;
> -		memcpy(&ec_dev->event_data, msg->data, ret);
> +		ec_dev->event_data = *event;
>  	}
>  
>  	return ret;
> @@ -589,30 +593,26 @@ static int get_next_event_xfer(struct cros_ec_device *ec_dev,
>  
>  static int get_next_event(struct cros_ec_device *ec_dev)
>  {
> -	u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
> -	struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
> -	static int cmd_version = 1;
> -	int ret;
> +	struct {
> +		struct cros_ec_command msg;
> +		struct ec_response_get_next_event_v1 event;
> +	} __packed buf;
> +	struct cros_ec_command *msg = &buf.msg;
> +	struct ec_response_get_next_event_v1 *event = &buf.event;
> +	const int cmd_version = ec_dev->mkbp_event_supported - 1;
>  
> +	memset(msg, 0, sizeof(*msg));
>  	if (ec_dev->suspended) {
>  		dev_dbg(ec_dev->dev, "Device suspended.\n");
>  		return -EHOSTDOWN;
>  	}
>  
> -	if (cmd_version == 1) {
> -		ret = get_next_event_xfer(ec_dev, msg, cmd_version,
> -				sizeof(struct ec_response_get_next_event_v1));
> -		if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
> -			return ret;
> -
> -		/* Fallback to version 0 for future send attempts */
> -		cmd_version = 0;
> -	}
> -
> -	ret = get_next_event_xfer(ec_dev, msg, cmd_version,
> +	if (cmd_version == 0)
> +		return get_next_event_xfer(ec_dev, msg, event, 0,
>  				  sizeof(struct ec_response_get_next_event));
>  
> -	return ret;
> +	return get_next_event_xfer(ec_dev, msg, event, cmd_version,
> +				sizeof(struct ec_response_get_next_event_v1));
>  }
>  
>  static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
> @@ -639,32 +639,55 @@ static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
>   * @ec_dev: Device to fetch event from.
>   * @wake_event: Pointer to a bool set to true upon return if the event might be
>   *              treated as a wake event. Ignored if null.
> + * @has_more_events: Pointer to bool set to true if more than one event is
> + *              pending.
> + *              Some EC will set this flag to indicate cros_ec_get_next_event()
> + *              can be called multiple times in a row.
> + *              It is an optimization to prevent issuing a EC command for
> + *              nothing or wait for another interrupt from the EC to process
> + *              the next message.
> + *              Ignored if null.
>   *
>   * Return: negative error code on errors; 0 for no data; or else number of
>   * bytes received (i.e., an event was retrieved successfully). Event types are
>   * written out to @ec_dev->event_data.event_type on success.
>   */
> -int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event)
> +int cros_ec_get_next_event(struct cros_ec_device *ec_dev,
> +			   bool *wake_event,
> +			   bool *has_more_events)
>  {
>  	u8 event_type;
>  	u32 host_event;
>  	int ret;
>  
> -	if (!ec_dev->mkbp_event_supported) {
> -		ret = get_keyboard_state_event(ec_dev);
> -		if (ret <= 0)
> -			return ret;
> +	/*
> +	 * Default value for wake_event.
> +	 * Wake up on keyboard event, wake up for spurious interrupt or link
> +	 * error to the EC.
> +	 */
> +	if (wake_event)
> +		*wake_event = true;
>  
> -		if (wake_event)
> -			*wake_event = true;
> +	/*
> +	 * Default value for has_more_events.
> +	 * EC will raise another interrupt if AP does not process all events
> +	 * anyway.
> +	 */
> +	if (has_more_events)
> +		*has_more_events = false;
>  
> -		return ret;
> -	}
> +	if (!ec_dev->mkbp_event_supported)
> +		return get_keyboard_state_event(ec_dev);
>  
>  	ret = get_next_event(ec_dev);
>  	if (ret <= 0)
>  		return ret;
>  
> +	if (has_more_events)
> +		*has_more_events = ec_dev->event_data.event_type &
> +			EC_MKBP_HAS_MORE_EVENTS;
> +	ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK;
> +
>  	if (wake_event) {
>  		event_type = ec_dev->event_data.event_type;
>  		host_event = cros_ec_get_host_event(ec_dev);
> @@ -679,11 +702,7 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event)
>  		else if (host_event &&
>  			 !(host_event & ec_dev->host_event_wake_mask))
>  			*wake_event = false;
> -		/* Consider all other events as wake events. */
> -		else
> -			*wake_event = true;
>  	}
> -
>  	return ret;
>  }
>  EXPORT_SYMBOL(cros_ec_get_next_event);
> diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c
> index 0c3738c3244d8..7aa3be42d8e3f 100644
> --- a/drivers/platform/chrome/cros_ec_rpmsg.c
> +++ b/drivers/platform/chrome/cros_ec_rpmsg.c
> @@ -140,25 +140,14 @@ static void
>  cros_ec_rpmsg_host_event_function(struct work_struct *host_event_work)
>  {
>  	struct cros_ec_rpmsg *ec_rpmsg = container_of(host_event_work,
> -						      struct cros_ec_rpmsg,
> -						      host_event_work);
> +			struct cros_ec_rpmsg,
> +			host_event_work);

Why?  Should be aligned with opening brackets where possible and it was.

>  	struct cros_ec_device *ec_dev = dev_get_drvdata(&ec_rpmsg->rpdev->dev);
> -	bool wake_event = true;
> -	int ret;
> -
> -	ret = cros_ec_get_next_event(ec_dev, &wake_event);
> -
> -	/*
> -	 * Signal only if wake host events or any interrupt if
> -	 * cros_ec_get_next_event() returned an error (default value for
> -	 * wake_event is true)
> -	 */
> -	if (wake_event && device_may_wakeup(ec_dev->dev))
> -		pm_wakeup_event(ec_dev->dev, 0);
> +	bool ec_has_more_events;
>  
> -	if (ret > 0)
> -		blocking_notifier_call_chain(&ec_dev->event_notifier,
> -					     0, ec_dev);
> +	do {
> +		ec_has_more_events = cros_ec_handle_event(ec_dev);
> +	} while (ec_has_more_events);
>  }
>  
>  static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
> diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h
> index b183024fef1f6..e238930ae9670 100644
> --- a/include/linux/platform_data/cros_ec_proto.h
> +++ b/include/linux/platform_data/cros_ec_proto.h
> @@ -116,7 +116,9 @@ struct cros_ec_command {
>   *            code.
>   * @pkt_xfer: Send packet to EC and get response.
>   * @lock: One transaction at a time.
> - * @mkbp_event_supported: True if this EC supports the MKBP event protocol.
> + * @mkbp_event_supported: 0 if MKBP not supported. Otherwise its value is
> + *                        the maximum supported version of the MKBP host event
> + *                        command + 1.
>   * @host_sleep_v1: True if this EC supports the sleep v1 command.
>   * @event_notifier: Interrupt event notifier for transport devices.
>   * @event_data: Raw payload transferred with the MKBP event.
> @@ -156,7 +158,7 @@ struct cros_ec_device {
>  	int (*pkt_xfer)(struct cros_ec_device *ec,
>  			struct cros_ec_command *msg);
>  	struct mutex lock;
> -	bool mkbp_event_supported;
> +	u8 mkbp_event_supported;
>  	bool host_sleep_v1;
>  	struct blocking_notifier_head event_notifier;
>  
> @@ -205,7 +207,9 @@ int cros_ec_unregister(struct cros_ec_device *ec_dev);
>  
>  int cros_ec_query_all(struct cros_ec_device *ec_dev);
>  
> -int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
> +int cros_ec_get_next_event(struct cros_ec_device *ec_dev,
> +			   bool *wake_event,
> +			   bool *has_more_events);
>  
>  u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
>  
> @@ -213,6 +217,8 @@ int cros_ec_check_features(struct cros_ec_dev *ec, int feature);
>  
>  int cros_ec_get_sensor_count(struct cros_ec_dev *ec);
>  
> +bool cros_ec_handle_event(struct cros_ec_device *ec_dev);
> +
>  /**
>   * cros_ec_get_time_ns - Return time in ns.
>   *


  reply	other threads:[~2019-10-21 16:07 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-21  5:53 [PATCH v2 00/18] cros_ec: Add sensorhub driver and FIFO processing*** SUBJECT HERE Gwendal Grignou
2019-10-21  5:53 ` [PATCH v2 01/18] platform: chrome: Put docs with the code Gwendal Grignou
2019-10-21 15:31   ` Jonathan Cameron
2019-10-24 17:03     ` Enric Balletbo i Serra
2019-10-21  5:53 ` [PATCH v2 02/18] mfd: cros_ec: Add sensor_count and make check_features public Gwendal Grignou
2019-10-21 15:12   ` Enric Balletbo i Serra
2019-10-21 15:49   ` Jonathan Cameron
2019-11-01  9:00   ` Lee Jones
2019-10-21  5:53 ` [PATCH v2 03/18] platform: cros_ec: Add cros_ec_sensor_hub driver Gwendal Grignou
2019-10-21 15:59   ` Jonathan Cameron
2019-10-22  8:32     ` Enric Balletbo i Serra
2019-10-21  5:53 ` [PATCH v2 04/18] platform/mfd:iio: cros_ec: Register sensor through sensorhub Gwendal Grignou
2019-10-21 16:00   ` Jonathan Cameron
2019-10-22  9:39     ` Enric Balletbo i Serra
2019-10-21  5:53 ` [PATCH v2 05/18] platform: chrome: cros-ec: record event timestamp in the hard irq Gwendal Grignou
2019-10-22 10:03   ` Enric Balletbo i Serra
2019-10-21  5:53 ` [PATCH v2 06/18] platform: chrome: cros_ec: Do not attempt to register a non-positive IRQ number Gwendal Grignou
2019-10-22 10:05   ` Enric Balletbo i Serra
2019-10-21  5:53 ` [PATCH v2 07/18] platform: chrome: cros_ec: handle MKBP more events flag Gwendal Grignou
2019-10-21 16:07   ` Jonathan Cameron [this message]
2019-10-21  5:53 ` [PATCH v2 08/18] Revert "Input: cros_ec_keyb - add back missing mask for event_type" Gwendal Grignou
2019-10-21  5:53 ` [PATCH v2 09/18] Revert "Input: cros_ec_keyb: mask out extra flags in event_type" Gwendal Grignou
2019-10-21  5:53 ` [PATCH v2 10/18] platform: chrome: sensorhub: Add FIFO support Gwendal Grignou
2019-10-21 16:27   ` Jonathan Cameron
2019-10-21 22:09     ` Gwendal Grignou
2019-10-22 10:42       ` Jonathan Cameron
2019-10-21  5:53 ` [PATCH v2 11/18] platform: chrome: sensorhub: Add code to spread timestmap Gwendal Grignou
2019-10-21  5:53 ` [PATCH v2 12/18] platform: chrome: sensorhub: Add median filter Gwendal Grignou
2019-10-21  5:53 ` [PATCH v2 13/18] iio: cros_ec: Move function description to .c file Gwendal Grignou
2019-10-21 16:33   ` Jonathan Cameron
2019-10-21  5:53 ` [PATCH v2 14/18] iio: cros_ec: Register to cros_ec_sensorhub when EC supports FIFO Gwendal Grignou
2019-10-21 16:38   ` Jonathan Cameron
2019-10-21  5:54 ` [PATCH v2 15/18] iio: cros_ec: Remove pm function Gwendal Grignou
2019-10-21 16:39   ` Jonathan Cameron
2019-10-21  5:54 ` [PATCH v2 16/18] iio: cros_ec: Expose hwfifo_timeout Gwendal Grignou
2019-10-21 16:42   ` Jonathan Cameron
2019-10-21  5:54 ` [PATCH v2 17/18] iio: cros_ec: Report hwfifo_watermark_max Gwendal Grignou
2019-10-21 16:42   ` Jonathan Cameron
2019-10-21  5:54 ` [PATCH v2 18/18] iio: cros_ec: Use Hertz as unit for sampling frequency Gwendal Grignou
2019-10-21 16:45   ` Jonathan Cameron
2019-10-22 19:11     ` Gwendal Grignou
2019-10-21 15:29 ` [PATCH v2 00/18] cros_ec: Add sensorhub driver and FIFO processing*** SUBJECT HERE Jonathan Cameron

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=20191021170719.09f1e5c2@archlinux \
    --to=jic23@kernel.org \
    --cc=bleung@chromium.org \
    --cc=briannorris@chromium.org \
    --cc=dianders@chromium.org \
    --cc=egranata@chromium.org \
    --cc=enric.balletbo@collabora.com \
    --cc=fabien.lahoudere@collabora.com \
    --cc=groeck@chromium.org \
    --cc=gwendal@chromium.org \
    --cc=knaack.h@gmx.de \
    --cc=lars@metafoo.de \
    --cc=lee.jones@linaro.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pmeerw@pmeerw.net \
    /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).