Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: cros: Register FIFO callback after sensor is registered

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>

authored by

Gwendal Grignou and committed by
Jonathan Cameron
0b4ae3f6 0565d238

+60 -31
+2 -2
drivers/iio/accel/cros_ec_accel_legacy.c
··· 215 215 return -ENOMEM; 216 216 217 217 ret = cros_ec_sensors_core_init(pdev, indio_dev, true, 218 - cros_ec_sensors_capture, NULL); 218 + cros_ec_sensors_capture); 219 219 if (ret) 220 220 return ret; 221 221 ··· 235 235 state->sign[CROS_EC_SENSOR_Z] = -1; 236 236 } 237 237 238 - return devm_iio_device_register(dev, indio_dev); 238 + return cros_ec_sensors_core_register(dev, indio_dev, NULL); 239 239 } 240 240 241 241 static struct platform_driver cros_ec_accel_platform_driver = {
+2 -2
drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
··· 98 98 if (!indio_dev) 99 99 return -ENOMEM; 100 100 101 - ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, NULL); 101 + ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL); 102 102 if (ret) 103 103 return ret; 104 104 ··· 114 114 if (ret) 115 115 return ret; 116 116 117 - return devm_iio_device_register(dev, indio_dev); 117 + return cros_ec_sensors_core_register(dev, indio_dev, NULL); 118 118 } 119 119 120 120 static const struct platform_device_id cros_ec_lid_angle_ids[] = {
+3 -3
drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
··· 236 236 return -ENOMEM; 237 237 238 238 ret = cros_ec_sensors_core_init(pdev, indio_dev, true, 239 - cros_ec_sensors_capture, 240 - cros_ec_sensors_push_data); 239 + cros_ec_sensors_capture); 241 240 if (ret) 242 241 return ret; 243 242 ··· 297 298 else 298 299 state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; 299 300 300 - return devm_iio_device_register(dev, indio_dev); 301 + return cros_ec_sensors_core_register(dev, indio_dev, 302 + cros_ec_sensors_push_data); 301 303 } 302 304 303 305 static const struct platform_device_id cros_ec_sensors_ids[] = {
+42 -16
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
··· 228 228 229 229 /** 230 230 * cros_ec_sensors_core_init() - basic initialization of the core structure 231 - * @pdev: platform device created for the sensors 231 + * @pdev: platform device created for the sensor 232 232 * @indio_dev: iio device structure of the device 233 233 * @physical_device: true if the device refers to a physical device 234 234 * @trigger_capture: function pointer to call buffer is triggered, 235 235 * for backward compatibility. 236 - * @push_data: function to call when cros_ec_sensorhub receives 237 - * a sample for that sensor. 238 236 * 239 237 * Return: 0 on success, -errno on failure. 240 238 */ 241 239 int cros_ec_sensors_core_init(struct platform_device *pdev, 242 240 struct iio_dev *indio_dev, 243 241 bool physical_device, 244 - cros_ec_sensors_capture_t trigger_capture, 245 - cros_ec_sensorhub_push_data_cb_t push_data) 242 + cros_ec_sensors_capture_t trigger_capture) 246 243 { 247 244 struct device *dev = &pdev->dev; 248 245 struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); ··· 337 340 if (ret) 338 341 return ret; 339 342 340 - ret = cros_ec_sensorhub_register_push_data( 341 - sensor_hub, sensor_platform->sensor_num, 342 - indio_dev, push_data); 343 - if (ret) 344 - return ret; 345 - 346 - ret = devm_add_action_or_reset( 347 - dev, cros_ec_sensors_core_clean, pdev); 348 - if (ret) 349 - return ret; 350 - 351 343 /* Timestamp coming from FIFO are in ns since boot. */ 352 344 ret = iio_device_set_clock(indio_dev, CLOCK_BOOTTIME); 353 345 if (ret) ··· 357 371 return 0; 358 372 } 359 373 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init); 374 + 375 + /** 376 + * cros_ec_sensors_core_register() - Register callback to FIFO and IIO when 377 + * sensor is ready. 378 + * It must be called at the end of the sensor probe routine. 379 + * @dev: device created for the sensor 380 + * @indio_dev: iio device structure of the device 381 + * @push_data: function to call when cros_ec_sensorhub receives 382 + * a sample for that sensor. 383 + * 384 + * Return: 0 on success, -errno on failure. 385 + */ 386 + int cros_ec_sensors_core_register(struct device *dev, 387 + struct iio_dev *indio_dev, 388 + cros_ec_sensorhub_push_data_cb_t push_data) 389 + { 390 + struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); 391 + struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent); 392 + struct platform_device *pdev = to_platform_device(dev); 393 + struct cros_ec_dev *ec = sensor_hub->ec; 394 + int ret; 395 + 396 + ret = devm_iio_device_register(dev, indio_dev); 397 + if (ret) 398 + return ret; 399 + 400 + if (!push_data || 401 + !cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) 402 + return 0; 403 + 404 + ret = cros_ec_sensorhub_register_push_data( 405 + sensor_hub, sensor_platform->sensor_num, 406 + indio_dev, push_data); 407 + if (ret) 408 + return ret; 409 + 410 + return devm_add_action_or_reset( 411 + dev, cros_ec_sensors_core_clean, pdev); 412 + } 413 + EXPORT_SYMBOL_GPL(cros_ec_sensors_core_register); 360 414 361 415 /** 362 416 * cros_ec_motion_send_host_cmd() - send motion sense host command
+3 -3
drivers/iio/light/cros_ec_light_prox.c
··· 182 182 return -ENOMEM; 183 183 184 184 ret = cros_ec_sensors_core_init(pdev, indio_dev, true, 185 - cros_ec_sensors_capture, 186 - cros_ec_sensors_push_data); 185 + cros_ec_sensors_capture); 187 186 if (ret) 188 187 return ret; 189 188 ··· 238 239 239 240 state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; 240 241 241 - return devm_iio_device_register(dev, indio_dev); 242 + return cros_ec_sensors_core_register(dev, indio_dev, 243 + cros_ec_sensors_push_data); 242 244 } 243 245 244 246 static const struct platform_device_id cros_ec_light_prox_ids[] = {
+3 -3
drivers/iio/pressure/cros_ec_baro.c
··· 139 139 return -ENOMEM; 140 140 141 141 ret = cros_ec_sensors_core_init(pdev, indio_dev, true, 142 - cros_ec_sensors_capture, 143 - cros_ec_sensors_push_data); 142 + cros_ec_sensors_capture); 144 143 if (ret) 145 144 return ret; 146 145 ··· 184 185 185 186 state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; 186 187 187 - return devm_iio_device_register(dev, indio_dev); 188 + return cros_ec_sensors_core_register(dev, indio_dev, 189 + cros_ec_sensors_push_data); 188 190 } 189 191 190 192 static const struct platform_device_id cros_ec_baro_ids[] = {
+5 -2
include/linux/iio/common/cros_ec_sensors_core.h
··· 93 93 struct platform_device; 94 94 int cros_ec_sensors_core_init(struct platform_device *pdev, 95 95 struct iio_dev *indio_dev, bool physical_device, 96 - cros_ec_sensors_capture_t trigger_capture, 97 - cros_ec_sensorhub_push_data_cb_t push_data); 96 + cros_ec_sensors_capture_t trigger_capture); 97 + 98 + int cros_ec_sensors_core_register(struct device *dev, 99 + struct iio_dev *indio_dev, 100 + cros_ec_sensorhub_push_data_cb_t push_data); 98 101 99 102 irqreturn_t cros_ec_sensors_capture(int irq, void *p); 100 103 int cros_ec_sensors_push_data(struct iio_dev *indio_dev,