Skip to content

Commit 1bbb280

Browse files
Eddie Jamesgroeck
authored andcommitted
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: 5b5513b ("hwmon: Add On-Chip Controller (OCC) hwmon driver") Signed-off-by: Eddie James <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent a111daf commit 1bbb280

File tree

4 files changed

+15
-13
lines changed

4 files changed

+15
-13
lines changed

drivers/hwmon/occ/common.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ static int occ_poll(struct occ *occ)
145145
cmd[6] = 0; /* checksum lsb */
146146

147147
/* mutex should already be locked if necessary */
148-
rc = occ->send_cmd(occ, cmd, sizeof(cmd));
148+
rc = occ->send_cmd(occ, cmd, sizeof(cmd), &occ->resp, sizeof(occ->resp));
149149
if (rc) {
150150
occ->last_error = rc;
151151
if (occ->error_count++ > OCC_ERROR_COUNT_THRESHOLD)
@@ -182,6 +182,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
182182
{
183183
int rc;
184184
u8 cmd[8];
185+
u8 resp[8];
185186
__be16 user_power_cap_be = cpu_to_be16(user_power_cap);
186187

187188
cmd[0] = 0; /* sequence number */
@@ -198,7 +199,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
198199
if (rc)
199200
return rc;
200201

201-
rc = occ->send_cmd(occ, cmd, sizeof(cmd));
202+
rc = occ->send_cmd(occ, cmd, sizeof(cmd), resp, sizeof(resp));
202203

203204
mutex_unlock(&occ->lock);
204205

drivers/hwmon/occ/common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ struct occ {
9696

9797
int powr_sample_time_us; /* average power sample time */
9898
u8 poll_cmd_data; /* to perform OCC poll command */
99-
int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len);
99+
int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len, void *resp,
100+
size_t resp_len);
100101

101102
unsigned long next_update;
102103
struct mutex lock; /* lock OCC access */

drivers/hwmon/occ/p8_i2c.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ static int p8_i2c_occ_putscom_be(struct i2c_client *client, u32 address,
111111
be32_to_cpu(data1));
112112
}
113113

114-
static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
114+
static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
115+
void *resp, size_t resp_len)
115116
{
116117
int i, rc;
117118
unsigned long start;
@@ -120,7 +121,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
120121
const long wait_time = msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
121122
struct p8_i2c_occ *ctx = to_p8_i2c_occ(occ);
122123
struct i2c_client *client = ctx->client;
123-
struct occ_response *resp = &occ->resp;
124+
struct occ_response *or = (struct occ_response *)resp;
124125

125126
start = jiffies;
126127

@@ -151,7 +152,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
151152
return rc;
152153

153154
/* wait for OCC */
154-
if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
155+
if (or->return_status == OCC_RESP_CMD_IN_PRG) {
155156
rc = -EALREADY;
156157

157158
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)
163164
} while (rc);
164165

165166
/* check the OCC response */
166-
switch (resp->return_status) {
167+
switch (or->return_status) {
167168
case OCC_RESP_CMD_IN_PRG:
168169
rc = -ETIMEDOUT;
169170
break;
@@ -192,8 +193,8 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
192193
if (rc < 0)
193194
return rc;
194195

195-
data_length = get_unaligned_be16(&resp->data_length);
196-
if (data_length > OCC_RESP_DATA_BYTES)
196+
data_length = get_unaligned_be16(&or->data_length);
197+
if ((data_length + 7) > resp_len)
197198
return -EMSGSIZE;
198199

199200
/* fetch the rest of the response data */

drivers/hwmon/occ/p9_sbe.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,10 @@ static bool p9_sbe_occ_save_ffdc(struct p9_sbe_occ *ctx, const void *resp,
7878
return notify;
7979
}
8080

81-
static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
81+
static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
82+
void *resp, size_t resp_len)
8283
{
83-
struct occ_response *resp = &occ->resp;
8484
struct p9_sbe_occ *ctx = to_p9_sbe_occ(occ);
85-
size_t resp_len = sizeof(*resp);
8685
int rc;
8786

8887
rc = fsi_occ_submit(ctx->sbe, cmd, len, resp, &resp_len);
@@ -96,7 +95,7 @@ static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
9695
return rc;
9796
}
9897

99-
switch (resp->return_status) {
98+
switch (((struct occ_response *)resp)->return_status) {
10099
case OCC_RESP_CMD_IN_PRG:
101100
rc = -ETIMEDOUT;
102101
break;

0 commit comments

Comments
 (0)