Commit b9388959 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tag-chrome-platform-fixes-for-v5.7-rc5' of...

Merge tag 'tag-chrome-platform-fixes-for-v5.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux

Pull chrome platform fix from Benson Leung:
 "Fix a resource allocation issue in cros_ec_sensorhub.c"

* tag 'tag-chrome-platform-fixes-for-v5.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux:
  platform/chrome: cros_ec_sensorhub: Allocate sensorhub resource before claiming sensors
parents 3c40cdb0 b31d1d2b
...@@ -52,28 +52,15 @@ static int cros_ec_sensorhub_register(struct device *dev, ...@@ -52,28 +52,15 @@ static int cros_ec_sensorhub_register(struct device *dev,
int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 }; int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
struct cros_ec_command *msg = sensorhub->msg; struct cros_ec_command *msg = sensorhub->msg;
struct cros_ec_dev *ec = sensorhub->ec; struct cros_ec_dev *ec = sensorhub->ec;
int ret, i, sensor_num; int ret, i;
char *name; 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->version = 1;
msg->insize = sizeof(struct ec_response_motion_sense); msg->insize = sizeof(struct ec_response_motion_sense);
msg->outsize = sizeof(struct ec_params_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->cmd = MOTIONSENSE_CMD_INFO;
sensorhub->params->info.sensor_num = i; sensorhub->params->info.sensor_num = i;
...@@ -140,8 +127,7 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev) ...@@ -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_dev *ec = dev_get_drvdata(dev->parent);
struct cros_ec_sensorhub *data; struct cros_ec_sensorhub *data;
struct cros_ec_command *msg; struct cros_ec_command *msg;
int ret; int ret, i, sensor_num;
int i;
msg = devm_kzalloc(dev, sizeof(struct cros_ec_command) + msg = devm_kzalloc(dev, sizeof(struct cros_ec_command) +
max((u16)sizeof(struct ec_params_motion_sense), max((u16)sizeof(struct ec_params_motion_sense),
...@@ -166,10 +152,52 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev) ...@@ -166,10 +152,52 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
dev_set_drvdata(dev, data); dev_set_drvdata(dev, data);
/* Check whether this EC is a sensor hub. */ /* 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); ret = cros_ec_sensorhub_register(dev, data);
if (ret) if (ret)
return 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 { } else {
/* /*
* If the device has sensors but does not claim to * If the device has sensors but does not claim to
...@@ -184,22 +212,6 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev) ...@@ -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; return 0;
} }
......
...@@ -957,17 +957,15 @@ static int cros_ec_sensorhub_event(struct notifier_block *nb, ...@@ -957,17 +957,15 @@ static int cros_ec_sensorhub_event(struct notifier_block *nb,
} }
/** /**
* cros_ec_sensorhub_ring_add() - Add the FIFO functionality if the EC * cros_ec_sensorhub_ring_allocate() - Prepare the FIFO functionality if the EC
* supports it. * supports it.
* *
* @sensorhub : Sensor Hub object. * @sensorhub : Sensor Hub object.
* *
* Return: 0 on success. * Return: 0 on success.
*/ */
int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) int cros_ec_sensorhub_ring_allocate(struct cros_ec_sensorhub *sensorhub)
{ {
struct cros_ec_dev *ec = sensorhub->ec;
int ret;
int fifo_info_length = int fifo_info_length =
sizeof(struct ec_response_motion_sense_fifo_info) + sizeof(struct ec_response_motion_sense_fifo_info) +
sizeof(u16) * sensorhub->sensor_num; sizeof(u16) * sensorhub->sensor_num;
...@@ -978,6 +976,49 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) ...@@ -978,6 +976,49 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
if (!sensorhub->fifo_info) if (!sensorhub->fifo_info)
return -ENOMEM; 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.
*
* @sensorhub : Sensor Hub object.
*
* Return: 0 on success.
*/
int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
{
struct cros_ec_dev *ec = sensorhub->ec;
int ret;
int fifo_info_length =
sizeof(struct ec_response_motion_sense_fifo_info) +
sizeof(u16) * sensorhub->sensor_num;
/* Retrieve FIFO information */ /* Retrieve FIFO information */
sensorhub->msg->version = 2; sensorhub->msg->version = 2;
sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INFO; sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INFO;
...@@ -998,31 +1039,9 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) ...@@ -998,31 +1039,9 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub)
if (!sensorhub->ring) if (!sensorhub->ring)
return -ENOMEM; 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] = sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] =
cros_ec_get_time_ns(); 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. */ /* Register the notifier that will act as a top half interrupt. */
sensorhub->notifier.notifier_call = cros_ec_sensorhub_event; sensorhub->notifier.notifier_call = cros_ec_sensorhub_event;
ret = blocking_notifier_chain_register(&ec->ec_dev->event_notifier, ret = blocking_notifier_chain_register(&ec->ec_dev->event_notifier,
......
...@@ -185,6 +185,7 @@ int cros_ec_sensorhub_register_push_data(struct cros_ec_sensorhub *sensorhub, ...@@ -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, void cros_ec_sensorhub_unregister_push_data(struct cros_ec_sensorhub *sensorhub,
u8 sensor_num); 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); int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub);
void cros_ec_sensorhub_ring_remove(void *arg); void cros_ec_sensorhub_ring_remove(void *arg);
int cros_ec_sensorhub_ring_fifo_enable(struct cros_ec_sensorhub *sensorhub, int cros_ec_sensorhub_ring_fifo_enable(struct cros_ec_sensorhub *sensorhub,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment