summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorJavier Martinez Canillas <javier.martinez@collabora.co.uk>2015-06-09 14:04:42 +0300
committerLee Jones <lee.jones@linaro.org>2015-06-15 15:18:19 +0300
commita841178445bb72a3d566b4e6ab9d19e9b002eb47 (patch)
treebdc857e82c9c9e8b49bd5471efa5a954673d58f0 /drivers/mfd
parentbb03ffb96c72418d06e75c7b74ea62e04c78d322 (diff)
downloadlinux-a841178445bb72a3d566b4e6ab9d19e9b002eb47.tar.xz
mfd: cros_ec: Use a zero-length array for command data
Commit 1b84f2a4cd4a ("mfd: cros_ec: Use fixed size arrays to transfer data with the EC") modified the struct cros_ec_command fields to not use pointers for the input and output buffers and use fixed length arrays instead. This change was made because the cros_ec ioctl API uses that struct cros_ec_command to allow user-space to send commands to the EC and to get data from the EC. So using pointers made the API not 64-bit safe. Unfortunately this approach was not flexible enough for all the use-cases since there may be a need to send larger commands on newer versions of the EC command protocol. So to avoid to choose a constant length that it may be too big for most commands and thus wasting memory and CPU cycles on copy from and to user-space or having a size that is too small for some big commands, use a zero-length array that is both 64-bit safe and flexible. The same buffer is used for both output and input data so the maximum of these values should be used to allocate it. Suggested-by: Gwendal Grignou <gwendal@chromium.org> Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Tested-by: Heiko Stuebner <heiko@sntech.de> Acked-by: Lee Jones <lee.jones@linaro.org> Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/cros_ec.c28
-rw-r--r--drivers/mfd/cros_ec_i2c.c4
-rw-r--r--drivers/mfd/cros_ec_spi.c2
3 files changed, 23 insertions, 11 deletions
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 1574a9352a6d..4a0f6dfcd376 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -41,7 +41,7 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
out[2] = msg->outsize;
csum = out[0] + out[1] + out[2];
for (i = 0; i < msg->outsize; i++)
- csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->outdata[i];
+ csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->data[i];
out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff);
return EC_MSG_TX_PROTO_BYTES + msg->outsize;
@@ -75,11 +75,20 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
ret = ec_dev->cmd_xfer(ec_dev, msg);
if (msg->result == EC_RES_IN_PROGRESS) {
int i;
- struct cros_ec_command status_msg = { };
+ struct cros_ec_command *status_msg;
struct ec_response_get_comms_status *status;
- status_msg.command = EC_CMD_GET_COMMS_STATUS;
- status_msg.insize = sizeof(*status);
+ status_msg = kmalloc(sizeof(*status_msg) + sizeof(*status),
+ GFP_KERNEL);
+ if (!status_msg) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ status_msg->version = 0;
+ status_msg->command = EC_CMD_GET_COMMS_STATUS;
+ status_msg->insize = sizeof(*status);
+ status_msg->outsize = 0;
/*
* Query the EC's status until it's no longer busy or
@@ -88,20 +97,23 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
for (i = 0; i < EC_COMMAND_RETRIES; i++) {
usleep_range(10000, 11000);
- ret = ec_dev->cmd_xfer(ec_dev, &status_msg);
+ ret = ec_dev->cmd_xfer(ec_dev, status_msg);
if (ret < 0)
break;
- msg->result = status_msg.result;
- if (status_msg.result != EC_RES_SUCCESS)
+ msg->result = status_msg->result;
+ if (status_msg->result != EC_RES_SUCCESS)
break;
status = (struct ec_response_get_comms_status *)
- status_msg.indata;
+ status_msg->data;
if (!(status->flags & EC_COMMS_STATUS_PROCESSING))
break;
}
+
+ kfree(status_msg);
}
+exit:
mutex_unlock(&ec_dev->lock);
return ret;
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 82b4d6148698..fbf7819f5de5 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -76,7 +76,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
/* copy message payload and compute checksum */
sum = out_buf[0] + out_buf[1] + out_buf[2];
for (i = 0; i < msg->outsize; i++) {
- out_buf[3 + i] = msg->outdata[i];
+ out_buf[3 + i] = msg->data[i];
sum += out_buf[3 + i];
}
out_buf[3 + msg->outsize] = sum;
@@ -109,7 +109,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
/* copy response packet payload and compute checksum */
sum = in_buf[0] + in_buf[1];
for (i = 0; i < len; i++) {
- msg->indata[i] = in_buf[2 + i];
+ msg->data[i] = in_buf[2 + i];
sum += in_buf[2 + i];
}
dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 27bd52e5e8b7..573730fec947 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -299,7 +299,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
for (i = 0; i < len; i++) {
sum += ptr[i + 2];
if (ec_msg->insize)
- ec_msg->indata[i] = ptr[i + 2];
+ ec_msg->data[i] = ptr[i + 2];
}
sum &= 0xff;