summaryrefslogtreecommitdiff
path: root/drivers/hwmon/occ/p8_i2c.c
diff options
context:
space:
mode:
authorEddie James <eajames@linux.ibm.com>2022-06-28 23:30:29 +0300
committerGuenter Roeck <linux@roeck-us.net>2022-06-29 23:59:23 +0300
commit1bbb2809040a1f9c7c53c9f06c21aa83275ed27b (patch)
tree8891dc3129bf5cc7ee668c62526c6ff1de0866ba /drivers/hwmon/occ/p8_i2c.c
parenta111daf0c53ae91e71fd2bfe7497862d14132e3e (diff)
downloadlinux-1bbb2809040a1f9c7c53c9f06c21aa83275ed27b.tar.xz
hwmon: (occ) Prevent power cap command overwriting poll response
Currently, the response to the power cap command overwrites the first eight bytes of the poll response, since the commands use the same buffer. This means that user's get the wrong data between the time of sending the power cap and the next poll response update. Fix this by specifying a different buffer for the power cap command response. Fixes: 5b5513b88002 ("hwmon: Add On-Chip Controller (OCC) hwmon driver") Signed-off-by: Eddie James <eajames@linux.ibm.com> Link: https://lore.kernel.org/r/20220628203029.51747-1-eajames@linux.ibm.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/occ/p8_i2c.c')
-rw-r--r--drivers/hwmon/occ/p8_i2c.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c
index da39ea28df31..b221be1f35f3 100644
--- a/drivers/hwmon/occ/p8_i2c.c
+++ b/drivers/hwmon/occ/p8_i2c.c
@@ -111,7 +111,8 @@ static int p8_i2c_occ_putscom_be(struct i2c_client *client, u32 address,
be32_to_cpu(data1));
}
-static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
+static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+ void *resp, size_t resp_len)
{
int i, rc;
unsigned long start;
@@ -120,7 +121,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
const long wait_time = msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
struct p8_i2c_occ *ctx = to_p8_i2c_occ(occ);
struct i2c_client *client = ctx->client;
- struct occ_response *resp = &occ->resp;
+ struct occ_response *or = (struct occ_response *)resp;
start = jiffies;
@@ -151,7 +152,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
return rc;
/* wait for OCC */
- if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
+ if (or->return_status == OCC_RESP_CMD_IN_PRG) {
rc = -EALREADY;
if (time_after(jiffies, start + timeout))
@@ -163,7 +164,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
} while (rc);
/* check the OCC response */
- switch (resp->return_status) {
+ switch (or->return_status) {
case OCC_RESP_CMD_IN_PRG:
rc = -ETIMEDOUT;
break;
@@ -192,8 +193,8 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
if (rc < 0)
return rc;
- data_length = get_unaligned_be16(&resp->data_length);
- if (data_length > OCC_RESP_DATA_BYTES)
+ data_length = get_unaligned_be16(&or->data_length);
+ if ((data_length + 7) > resp_len)
return -EMSGSIZE;
/* fetch the rest of the response data */