diff options
| author | Tzung-Bi Shih <tzungbi@kernel.org> | 2026-04-07 13:26:15 +0300 |
|---|---|---|
| committer | Tzung-Bi Shih <tzungbi@kernel.org> | 2026-05-11 06:09:30 +0300 |
| commit | c40f5f9927b5bf6062daa1e293ae32d83afc963e (patch) | |
| tree | eda7f3ffeced4a9e6e9b6e91e742c44bdf592d74 | |
| parent | 5d6919055dec134de3c40167a490f33c74c12581 (diff) | |
| download | linux-c40f5f9927b5bf6062daa1e293ae32d83afc963e.tar.xz | |
platform/chrome: Resolve kb_wake_angle visibility race
A race condition exists between the probe of cros-ec-sysfs and
cros-ec-sensorhub.
The `kb_wake_angle` attribute should only be visible if the sensor hub
detects two or more accelerometers. If cros_ec_sysfs_probe() runs
before cros_ec_sensorhub_register() completes sensor enumeration, the
sysfs attributes are created while `has_kb_wake_angle` is still false,
hiding `kb_wake_angle` incorrectly.
Store the created attribute group pointer in `ec_dev->group`. When
the sensor hub completes sensor enumeration, it checks for this group
and calls sysfs_update_group() to notify the sysfs core to re-evaluate
attribute visibility. This ensures the `kb_wake_angle` attribute
visibility is correctly updated regardless of the driver probe order.
Co-developed-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Link: https://lore.kernel.org/r/20260407102615.1605317-1-tzungbi@kernel.org
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
| -rw-r--r-- | drivers/platform/chrome/cros_ec_sensorhub.c | 6 | ||||
| -rw-r--r-- | drivers/platform/chrome/cros_ec_sysfs.c | 5 | ||||
| -rw-r--r-- | include/linux/platform_data/cros_ec_proto.h | 2 |
3 files changed, 10 insertions, 3 deletions
diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c b/drivers/platform/chrome/cros_ec_sensorhub.c index 9bad8f72680e..f938c3fc84e4 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub.c +++ b/drivers/platform/chrome/cros_ec_sensorhub.c @@ -122,8 +122,12 @@ static int cros_ec_sensorhub_register(struct device *dev, sensor_type[sensorhub->resp->info.type]++; } - if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) + if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) { ec->has_kb_wake_angle = true; + if (ec->group && sysfs_update_group(&ec->class_dev.kobj, + ec->group)) + dev_warn(dev, "Unable to update sysfs"); + } if (cros_ec_check_features(ec, EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) { diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index f22e9523da3e..9d3767ab1548 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -405,7 +405,8 @@ static int cros_ec_sysfs_probe(struct platform_device *pd) struct device *dev = &pd->dev; int ret; - ret = sysfs_create_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group); + ec_dev->group = &cros_ec_attr_group; + ret = sysfs_create_group(&ec_dev->class_dev.kobj, ec_dev->group); if (ret < 0) dev_err(dev, "failed to create attributes. err=%d\n", ret); @@ -416,7 +417,7 @@ static void cros_ec_sysfs_remove(struct platform_device *pd) { struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent); - sysfs_remove_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group); + sysfs_remove_group(&ec_dev->class_dev.kobj, ec_dev->group); } static const struct platform_device_id cros_ec_sysfs_id[] = { diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index de14923720a5..6ed1c4c5ce2e 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -228,6 +228,7 @@ struct cros_ec_platform { /** * struct cros_ec_dev - ChromeOS EC device entry point. * @class_dev: Device structure used in sysfs. + * @group: sysfs attributes groups for this EC. * @ec_dev: cros_ec_device structure to talk to the physical device. * @dev: Pointer to the platform device. * @debug_info: cros_ec_debugfs structure for debugging information. @@ -237,6 +238,7 @@ struct cros_ec_platform { */ struct cros_ec_dev { struct device class_dev; + const struct attribute_group *group; struct cros_ec_device *ec_dev; struct device *dev; struct cros_ec_debugfs *debug_info; |
