iio: cros_ec_sensors: Flush when changing the FIFO timeout
authorGwendal Grignou <gwendal@chromium.org>
Wed, 23 Apr 2025 22:05:06 +0000 (15:05 -0700)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Wed, 21 May 2025 13:20:28 +0000 (14:20 +0100)
|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 <gwendal@chromium.org>
Link: https://patch.msgid.link/20250423220506.2061021-1-gwendal@chromium.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c

index 576d7b4..700ebcd 100644 (file)
@@ -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;