From dd9a1d69ba90be7fe742c6234e6bd09706b7aaea Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 29 Jan 2016 13:35:44 +0000 Subject: firmware: arm_scpi: fix send_message and sensor_get_value for big-endian scpi_process_cmd converts the status word from little endian to cpu endianness. However scpi_send_message again does the conversion which is wrong and shows up as a bug only when running in big-endian kernel. Similarly scpi_sensor_get_value passes the sensor index in the cpu endianness to SCP which results in SCPI_ERR_RANGE in big-endian mode. This patch fixes the above mentioned issue for big-endian kernel. Acked-by: Punit Agrawal Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 6174db8..3cb591e 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -373,7 +373,7 @@ static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len, ret = -ETIMEDOUT; else /* first status word */ - ret = le32_to_cpu(msg->status); + ret = msg->status; out: if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */ scpi_process_cmd(scpi_chan, msg->cmd); @@ -527,10 +527,11 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info) int scpi_sensor_get_value(u16 sensor, u32 *val) { + __le16 id = cpu_to_le16(sensor); struct sensor_value buf; int ret; - ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &sensor, sizeof(sensor), + ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id), &buf, sizeof(buf)); if (!ret) *val = le32_to_cpu(buf.val); -- cgit v1.1 From 3bdd884371b6fe68bb144aa4661d6a774a5417f1 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 15 Jan 2016 11:57:38 +0000 Subject: firmware: arm_scpi: decrease Tx timeout to 20ms Currently we have Tx timeout of 50ms while Rx timeout of 20 ms. Tx state machine is maintained by the mailbox framework and Rx by SCPI driver. It is possible that before msg_submit call tx_prepare(because of other message in the queue and the channel being active), wait for completion in scpi_send_message times out and the buffers are freed. In that case when Tx state machine timer goes off later, poll_txdone calls scpi_tx_prepare on that message, which adds it to the rx_pending list, corrupting link pointers. This patch reduces the Tx timeout to 20ms and increases Rx timeout to 30ms to avoid the above mentioned issue. Reported-by: Jon Medhurst (Tixy) Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 3cb591e..c32ac6e 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -80,7 +80,7 @@ #define FW_REV_MINOR(x) (((x) & FW_REV_MINOR_MASK) >> FW_REV_MINOR_BITS) #define FW_REV_PATCH(x) ((x) & FW_REV_PATCH_MASK) -#define MAX_RX_TIMEOUT (msecs_to_jiffies(20)) +#define MAX_RX_TIMEOUT (msecs_to_jiffies(30)) enum scpi_error_codes { SCPI_SUCCESS = 0, /* Success */ @@ -700,7 +700,7 @@ static int scpi_probe(struct platform_device *pdev) cl->rx_callback = scpi_handle_remote_msg; cl->tx_prepare = scpi_tx_prepare; cl->tx_block = true; - cl->tx_tout = 50; + cl->tx_tout = 20; cl->knows_txdone = false; /* controller can't ack */ INIT_LIST_HEAD(&pchan->rx_pending); -- cgit v1.1 From 2e8741599cf128ea27674d9ae93b46e847f820b4 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 14 Jan 2016 17:58:02 +0000 Subject: firmware: arm_scpi: add support for 64-bit sensor values SCPI specification version 1.1 extended the sensor from 32-bit to 64-bit values in order to accommodate new sensor class with 64-bit requirements Since the SCPI driver sets the higher 32-bit for older protocol version to zeros, there's no need to explicitly check the SCPI protocol version and the backward compatibility is maintainted. Acked-by: Guenter Roeck Reviewed-by: Punit Agrawal Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index c32ac6e..7e3e595 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -231,7 +231,8 @@ struct _scpi_sensor_info { }; struct sensor_value { - __le32 val; + __le32 lo_val; + __le32 hi_val; } __packed; static struct scpi_drvinfo *scpi_info; @@ -525,7 +526,7 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info) return ret; } -int scpi_sensor_get_value(u16 sensor, u32 *val) +int scpi_sensor_get_value(u16 sensor, u64 *val) { __le16 id = cpu_to_le16(sensor); struct sensor_value buf; @@ -534,7 +535,8 @@ int scpi_sensor_get_value(u16 sensor, u32 *val) ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id), &buf, sizeof(buf)); if (!ret) - *val = le32_to_cpu(buf.val); + *val = (u64)le32_to_cpu(buf.hi_val) << 32 | + le32_to_cpu(buf.lo_val); return ret; } -- cgit v1.1