platform/chrome: cros_ec_sensorhub: Allocate sensorhub resource before claiming sensors

Allocate callbacks array before enumerating the sensors: The probe routine
for these sensors (for instance cros_ec_sensors_probe) can be called
within the sensorhub probe routine (cros_ec_sensors_probe())

Fixes: 145d59baff ("platform/chrome: cros_ec_sensorhub: Add FIFO support")
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reported-by: Douglas Anderson <dianders@chromium.org>
Tested-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
This commit is contained in:
Gwendal Grignou 2020-04-27 15:59:02 -07:00 committed by Enric Balletbo i Serra
parent 538b8471fe
commit b31d1d2b1c
3 changed files with 94 additions and 62 deletions

View File

@ -52,28 +52,15 @@ static int cros_ec_sensorhub_register(struct device *dev,
int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
struct cros_ec_command *msg = sensorhub->msg;
struct cros_ec_dev *ec = sensorhub->ec;
int ret, i, sensor_num;
int ret, i;
char *name;
sensor_num = cros_ec_get_sensor_count(ec);
if (sensor_num < 0) {
dev_err(dev,
"Unable to retrieve sensor information (err:%d)\n",
sensor_num);
return sensor_num;
}
sensorhub->sensor_num = sensor_num;
if (sensor_num == 0) {
dev_err(dev, "Zero sensors reported.\n");
return -EINVAL;
}
msg->version = 1;
msg->insize = sizeof(struct ec_response_motion_sense);
msg->outsize = sizeof(struct ec_params_motion_sense);
for (i = 0; i < sensor_num; i++) {
for (i = 0; i < sensorhub->sensor_num; i++) {
sensorhub->params->cmd = MOTIONSENSE_CMD_INFO;
sensorhub->params->info.sensor_num = i;
@ -140,8 +127,7 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
struct cros_ec_dev *ec = dev_get_drvdata(dev->parent);
struct cros_ec_sensorhub *data;
struct cros_ec_command *msg;
int ret;
int i;
int ret, i, sensor_num;
msg = devm_kzalloc(dev, sizeof(struct cros_ec_command) +
max((u16)sizeof(struct ec_params_motion_sense),
@ -166,10 +152,52 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
dev_set_drvdata(dev, data);
/* Check whether this EC is a sensor hub. */
if (cros_ec_check_features(data->ec, EC_FEATURE_MOTION_SENSE)) {
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) {
sensor_num = cros_ec_get_sensor_count(ec);
if (sensor_num < 0) {
dev_err(dev,
"Unable to retrieve sensor information (err:%d)\n",
sensor_num);
return sensor_num;
}
if (sensor_num == 0) {
dev_err(dev, "Zero sensors reported.\n");
return -EINVAL;
}
data->sensor_num = sensor_num;
/*
* Prepare the ring handler before enumering the
* sensors.
*/
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
ret = cros_ec_sensorhub_ring_allocate(data);
if (ret)
return ret;
}
/* Enumerate the sensors.*/
ret = cros_ec_sensorhub_register(dev, data);
if (ret)
return ret;
/*
* When the EC does not have a FIFO, the sensors will query
* their data themselves via sysfs or a software trigger.
*/
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
ret = cros_ec_sensorhub_ring_add(data);
if (ret)
return ret;
/*
* The msg and its data is not under the control of the
* ring handler.
*/
return devm_add_action_or_reset(dev,
cros_ec_sensorhub_ring_remove,
data);
}
} else {
/*
* If the device has sensors but does not claim to
@ -184,22 +212,6 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
}
}
/*
* If the EC does not have a FIFO, the sensors will query their data
* themselves via sysfs or a software trigger.
*/
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
ret = cros_ec_sensorhub_ring_add(data);
if (ret)
return ret;
/*
* The msg and its data is not under the control of the ring
* handler.
*/
return devm_add_action_or_reset(dev,
cros_ec_sensorhub_ring_remove,
data);
}
return 0;
}

View File

@ -956,6 +956,53 @@ static int cros_ec_sensorhub_event(struct notifier_block *nb,
return NOTIFY_OK;
}
/**
* cros_ec_sensorhub_ring_allocate() - Prepare the FIFO functionality if the EC
* supports it.
*
* @sensorhub : Sensor Hub object.
*
* Return: 0 on success.
*/
int cros_ec_sensorhub_ring_allocate(struct cros_ec_sensorhub *sensorhub)
{
int fifo_info_length =
sizeof(struct ec_response_motion_sense_fifo_info) +
sizeof(u16) * sensorhub->sensor_num;
/* Allocate the array for lost events. */
sensorhub->fifo_info = devm_kzalloc(sensorhub->dev, fifo_info_length,
GFP_KERNEL);
if (!sensorhub->fifo_info)
return -ENOMEM;
/*
* Allocate the callback area based on the number of sensors.
* Add one for the sensor ring.
*/
sensorhub->push_data = devm_kcalloc(sensorhub->dev,
sensorhub->sensor_num,
sizeof(*sensorhub->push_data),
GFP_KERNEL);
if (!sensorhub->push_data)
return -ENOMEM;
sensorhub->tight_timestamps = cros_ec_check_features(
sensorhub->ec,
EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS);
if (sensorhub->tight_timestamps) {
sensorhub->batch_state = devm_kcalloc(sensorhub->dev,
sensorhub->sensor_num,
sizeof(*sensorhub->batch_state),
GFP_KERNEL);
if (!sensorhub->batch_state)
return -ENOMEM;
}
return 0;
}
/**
* cros_ec_sensorhub_ring_add() - Add the FIFO functionality if the EC
* supports it.
@ -972,12 +1019,6 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
sizeof(struct ec_response_motion_sense_fifo_info) +
sizeof(u16) * sensorhub->sensor_num;
/* Allocate the array for lost events. */
sensorhub->fifo_info = devm_kzalloc(sensorhub->dev, fifo_info_length,
GFP_KERNEL);
if (!sensorhub->fifo_info)
return -ENOMEM;
/* Retrieve FIFO information */
sensorhub->msg->version = 2;
sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INFO;
@ -998,31 +1039,9 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
if (!sensorhub->ring)
return -ENOMEM;
/*
* Allocate the callback area based on the number of sensors.
*/
sensorhub->push_data = devm_kcalloc(
sensorhub->dev, sensorhub->sensor_num,
sizeof(*sensorhub->push_data),
GFP_KERNEL);
if (!sensorhub->push_data)
return -ENOMEM;
sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] =
cros_ec_get_time_ns();
sensorhub->tight_timestamps = cros_ec_check_features(
ec, EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS);
if (sensorhub->tight_timestamps) {
sensorhub->batch_state = devm_kcalloc(sensorhub->dev,
sensorhub->sensor_num,
sizeof(*sensorhub->batch_state),
GFP_KERNEL);
if (!sensorhub->batch_state)
return -ENOMEM;
}
/* Register the notifier that will act as a top half interrupt. */
sensorhub->notifier.notifier_call = cros_ec_sensorhub_event;
ret = blocking_notifier_chain_register(&ec->ec_dev->event_notifier,

View File

@ -185,6 +185,7 @@ int cros_ec_sensorhub_register_push_data(struct cros_ec_sensorhub *sensorhub,
void cros_ec_sensorhub_unregister_push_data(struct cros_ec_sensorhub *sensorhub,
u8 sensor_num);
int cros_ec_sensorhub_ring_allocate(struct cros_ec_sensorhub *sensorhub);
int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub);
void cros_ec_sensorhub_ring_remove(void *arg);
int cros_ec_sensorhub_ring_fifo_enable(struct cros_ec_sensorhub *sensorhub,