iio: cros: Register FIFO callback after sensor is registered
authorGwendal Grignou <gwendal@chromium.org>
Mon, 11 Jul 2022 14:47:16 +0000 (07:47 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:23:55 +0000 (14:23 +0200)
[ Upstream commit 0b4ae3f6d1210c11f9baf159009c7227eacf90f2 ]

Instead of registering callback to process sensor events right at
initialization time, wait for the sensor to be register in the iio
subsystem.

Events can come at probe time (in case the kernel rebooted abruptly
without switching the sensor off for  instance), and be sent to IIO core
before the sensor is fully registered.

Fixes: aa984f1ba4a4 ("iio: cros_ec: Register to cros_ec_sensorhub when EC supports FIFO")
Reported-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/r/20220711144716.642617-1-gwendal@chromium.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/iio/accel/cros_ec_accel_legacy.c
drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
drivers/iio/light/cros_ec_light_prox.c
drivers/iio/pressure/cros_ec_baro.c
include/linux/iio/common/cros_ec_sensors_core.h

index b6f3471b62dcf478b2e6cbdc6245f16fac955649..3b77fded2dc072b0f5fb28a84016c4a24914da70 100644 (file)
@@ -215,7 +215,7 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
-                                       cros_ec_sensors_capture, NULL);
+                                       cros_ec_sensors_capture);
        if (ret)
                return ret;
 
@@ -235,7 +235,7 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
                state->sign[CROS_EC_SENSOR_Z] = -1;
        }
 
-       return devm_iio_device_register(dev, indio_dev);
+       return cros_ec_sensors_core_register(dev, indio_dev, NULL);
 }
 
 static struct platform_driver cros_ec_accel_platform_driver = {
index af801e203623e37b00188b4c96985c1165d2c35d..02d3cf36acb0cfb346365d6e35944f2aed6b4520 100644 (file)
@@ -97,7 +97,7 @@ static int cros_ec_lid_angle_probe(struct platform_device *pdev)
        if (!indio_dev)
                return -ENOMEM;
 
-       ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, NULL);
+       ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL);
        if (ret)
                return ret;
 
@@ -113,7 +113,7 @@ static int cros_ec_lid_angle_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       return devm_iio_device_register(dev, indio_dev);
+       return cros_ec_sensors_core_register(dev, indio_dev, NULL);
 }
 
 static const struct platform_device_id cros_ec_lid_angle_ids[] = {
index 376a5b30010aeaaefcf06910287214131190a1ed..5cce34fdff022fa4101c918f14236a92c7b5a51b 100644 (file)
@@ -235,8 +235,7 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
-                                       cros_ec_sensors_capture,
-                                       cros_ec_sensors_push_data);
+                                       cros_ec_sensors_capture);
        if (ret)
                return ret;
 
@@ -297,7 +296,8 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
        else
                state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
 
-       return devm_iio_device_register(dev, indio_dev);
+       return cros_ec_sensors_core_register(dev, indio_dev,
+                       cros_ec_sensors_push_data);
 }
 
 static const struct platform_device_id cros_ec_sensors_ids[] = {
index 28bde13003b74427fb6e72c7b8dc5dbe57ba9404..b0c1dc8cc4c52304f882499467931d042c4a97a6 100644 (file)
@@ -234,21 +234,18 @@ static void cros_ec_sensors_core_clean(void *arg)
 
 /**
  * cros_ec_sensors_core_init() - basic initialization of the core structure
- * @pdev:              platform device created for the sensors
+ * @pdev:              platform device created for the sensor
  * @indio_dev:         iio device structure of the device
  * @physical_device:   true if the device refers to a physical device
  * @trigger_capture:    function pointer to call buffer is triggered,
  *    for backward compatibility.
- * @push_data:          function to call when cros_ec_sensorhub receives
- *    a sample for that sensor.
  *
  * Return: 0 on success, -errno on failure.
  */
 int cros_ec_sensors_core_init(struct platform_device *pdev,
                              struct iio_dev *indio_dev,
                              bool physical_device,
-                             cros_ec_sensors_capture_t trigger_capture,
-                             cros_ec_sensorhub_push_data_cb_t push_data)
+                             cros_ec_sensors_capture_t trigger_capture)
 {
        struct device *dev = &pdev->dev;
        struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
@@ -339,17 +336,6 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
                        if (ret)
                                return ret;
 
-                       ret = cros_ec_sensorhub_register_push_data(
-                                       sensor_hub, sensor_platform->sensor_num,
-                                       indio_dev, push_data);
-                       if (ret)
-                               return ret;
-
-                       ret = devm_add_action_or_reset(
-                                       dev, cros_ec_sensors_core_clean, pdev);
-                       if (ret)
-                               return ret;
-
                        /* Timestamp coming from FIFO are in ns since boot. */
                        ret = iio_device_set_clock(indio_dev, CLOCK_BOOTTIME);
                        if (ret)
@@ -371,6 +357,46 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
 
+/**
+ * cros_ec_sensors_core_register() - Register callback to FIFO and IIO when
+ * sensor is ready.
+ * It must be called at the end of the sensor probe routine.
+ * @dev:               device created for the sensor
+ * @indio_dev:         iio device structure of the device
+ * @push_data:          function to call when cros_ec_sensorhub receives
+ *    a sample for that sensor.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_sensors_core_register(struct device *dev,
+                                 struct iio_dev *indio_dev,
+                                 cros_ec_sensorhub_push_data_cb_t push_data)
+{
+       struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
+       struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct cros_ec_dev *ec = sensor_hub->ec;
+       int ret;
+
+       ret = devm_iio_device_register(dev, indio_dev);
+       if (ret)
+               return ret;
+
+       if (!push_data ||
+           !cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO))
+               return 0;
+
+       ret = cros_ec_sensorhub_register_push_data(
+                       sensor_hub, sensor_platform->sensor_num,
+                       indio_dev, push_data);
+       if (ret)
+               return ret;
+
+       return devm_add_action_or_reset(
+                       dev, cros_ec_sensors_core_clean, pdev);
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_register);
+
 /**
  * cros_ec_motion_send_host_cmd() - send motion sense host command
  * @state:             pointer to state information for device
index de472f23d1cbab563bfabdca5f05293c007274fa..16b893bae38816ab37dc56ec6df1ba6e5e86e731 100644 (file)
@@ -181,8 +181,7 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
-                                       cros_ec_sensors_capture,
-                                       cros_ec_sensors_push_data);
+                                       cros_ec_sensors_capture);
        if (ret)
                return ret;
 
@@ -240,7 +239,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
 
        state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
 
-       return devm_iio_device_register(dev, indio_dev);
+       return cros_ec_sensors_core_register(dev, indio_dev,
+                                            cros_ec_sensors_push_data);
 }
 
 static const struct platform_device_id cros_ec_light_prox_ids[] = {
index 2f882e1094232e939c2119861e93eb0d82cb7edc..0511edbf868d7060a4cb897df4f107b5496ef1b5 100644 (file)
@@ -138,8 +138,7 @@ static int cros_ec_baro_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
-                                       cros_ec_sensors_capture,
-                                       cros_ec_sensors_push_data);
+                                       cros_ec_sensors_capture);
        if (ret)
                return ret;
 
@@ -186,7 +185,8 @@ static int cros_ec_baro_probe(struct platform_device *pdev)
 
        state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
 
-       return devm_iio_device_register(dev, indio_dev);
+       return cros_ec_sensors_core_register(dev, indio_dev,
+                                            cros_ec_sensors_push_data);
 }
 
 static const struct platform_device_id cros_ec_baro_ids[] = {
index c582e1a142320f452d43ec2f413691252edcadd8..7b5dbd7499957531f1d1b400d761f42d9a2a2e15 100644 (file)
@@ -95,8 +95,11 @@ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
 struct platform_device;
 int cros_ec_sensors_core_init(struct platform_device *pdev,
                              struct iio_dev *indio_dev, bool physical_device,
-                             cros_ec_sensors_capture_t trigger_capture,
-                             cros_ec_sensorhub_push_data_cb_t push_data);
+                             cros_ec_sensors_capture_t trigger_capture);
+
+int cros_ec_sensors_core_register(struct device *dev,
+                                 struct iio_dev *indio_dev,
+                                 cros_ec_sensorhub_push_data_cb_t push_data);
 
 irqreturn_t cros_ec_sensors_capture(int irq, void *p);
 int cros_ec_sensors_push_data(struct iio_dev *indio_dev,