From: Gwendal Grignou Date: Wed, 23 Apr 2025 22:05:06 +0000 (-0700) Subject: iio: cros_ec_sensors: Flush when changing the FIFO timeout X-Git-Tag: v6.16-rc1~30^2~4^2~56 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=e50cf7e2e6e0e1fe106384eab938faf712e6230f;p=linux-block.git iio: cros_ec_sensors: Flush when changing the FIFO timeout |hwfifo_timeout| is used by the EC firmware only when new samples are available. When the timeout changes, espcially when the new timeout is shorter than the current one, send the samples waiting in the FIFO to the host. Inline the call to transmit |hwfifo_timeout| value to the firmware. Now flush when a sensor is suspended (ODR set to 0) as well. Signed-off-by: Gwendal Grignou Link: https://patch.msgid.link/20250423220506.2061021-1-gwendal@chromium.org Signed-off-by: Jonathan Cameron --- diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 576d7b451767..700ebcd68ff4 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -91,22 +91,6 @@ static void get_default_min_max_freq(enum motionsensor_type type, } } -static int cros_ec_sensor_set_ec_rate(struct cros_ec_sensors_core_state *st, - int rate) -{ - int ret; - - if (rate > U16_MAX) - rate = U16_MAX; - - mutex_lock(&st->cmd_lock); - st->param.cmd = MOTIONSENSE_CMD_EC_RATE; - st->param.ec_rate.data = rate; - ret = cros_ec_motion_send_host_cmd(st, 0); - mutex_unlock(&st->cmd_lock); - return ret; -} - static ssize_t cros_ec_sensor_set_report_latency(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -122,7 +106,25 @@ static ssize_t cros_ec_sensor_set_report_latency(struct device *dev, /* EC rate is in ms. */ latency = integer * 1000 + fract / 1000; - ret = cros_ec_sensor_set_ec_rate(st, latency); + + mutex_lock(&st->cmd_lock); + st->param.cmd = MOTIONSENSE_CMD_EC_RATE; + st->param.ec_rate.data = min(U16_MAX, latency); + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret < 0) { + mutex_unlock(&st->cmd_lock); + return ret; + } + + /* + * Flush samples currently in the FIFO, especially when the new latency + * is shorter than the old one: new timeout value is only considered when + * there is a new sample available. It can take a while for a slow + * sensor. + */ + st->param.cmd = MOTIONSENSE_CMD_FIFO_FLUSH; + ret = cros_ec_motion_send_host_cmd(st, 0); + mutex_unlock(&st->cmd_lock); if (ret < 0) return ret; @@ -832,6 +834,18 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, st->param.sensor_odr.roundup = 1; ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + /* Flush the FIFO when a sensor is stopped. + * If the FIFO has just been emptied, pending samples will be + * stuck until new samples are available. It will not happen + * when all the sensors are stopped. + */ + if (frequency == 0) { + st->param.cmd = MOTIONSENSE_CMD_FIFO_FLUSH; + ret = cros_ec_motion_send_host_cmd(st, 0); + } break; default: ret = -EINVAL;