Skip to content

Commit 68dbac0

Browse files
walshbTzung-Bi Shih
authored andcommitted
platform/chrome: cros_ec_lpc: MEC access can return error code
cros_ec_lpc_io_bytes_mec was returning a u8 checksum of all bytes read/written, which didn't leave room to indicate errors. Change this u8 to an int where negative values indicate an error, and non-negative values are the checksum as before. Tested-by: Dustin L. Howett <[email protected]> Signed-off-by: Ben Walsh <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Tzung-Bi Shih <[email protected]>
1 parent 106d673 commit 68dbac0

File tree

4 files changed

+112
-56
lines changed

4 files changed

+112
-56
lines changed

drivers/platform/chrome/cros_ec_lpc.c

Lines changed: 89 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,16 @@ struct cros_ec_lpc {
6262

6363
/**
6464
* struct lpc_driver_ops - LPC driver operations
65-
* @read: Copy length bytes from EC address offset into buffer dest. Returns
66-
* the 8-bit checksum of all bytes read.
67-
* @write: Copy length bytes from buffer msg into EC address offset. Returns
68-
* the 8-bit checksum of all bytes written.
65+
* @read: Copy length bytes from EC address offset into buffer dest.
66+
* Returns a negative error code on error, or the 8-bit checksum
67+
* of all bytes read.
68+
* @write: Copy length bytes from buffer msg into EC address offset.
69+
* Returns a negative error code on error, or the 8-bit checksum
70+
* of all bytes written.
6971
*/
7072
struct lpc_driver_ops {
71-
u8 (*read)(unsigned int offset, unsigned int length, u8 *dest);
72-
u8 (*write)(unsigned int offset, unsigned int length, const u8 *msg);
73+
int (*read)(unsigned int offset, unsigned int length, u8 *dest);
74+
int (*write)(unsigned int offset, unsigned int length, const u8 *msg);
7375
};
7476

7577
static struct lpc_driver_ops cros_ec_lpc_ops = { };
@@ -78,10 +80,10 @@ static struct lpc_driver_ops cros_ec_lpc_ops = { };
7880
* A generic instance of the read function of struct lpc_driver_ops, used for
7981
* the LPC EC.
8082
*/
81-
static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
82-
u8 *dest)
83+
static int cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
84+
u8 *dest)
8385
{
84-
int sum = 0;
86+
u8 sum = 0;
8587
int i;
8688

8789
for (i = 0; i < length; ++i) {
@@ -97,10 +99,10 @@ static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
9799
* A generic instance of the write function of struct lpc_driver_ops, used for
98100
* the LPC EC.
99101
*/
100-
static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
101-
const u8 *msg)
102+
static int cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
103+
const u8 *msg)
102104
{
103-
int sum = 0;
105+
u8 sum = 0;
104106
int i;
105107

106108
for (i = 0; i < length; ++i) {
@@ -116,8 +118,8 @@ static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
116118
* An instance of the read function of struct lpc_driver_ops, used for the
117119
* MEC variant of LPC EC.
118120
*/
119-
static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
120-
u8 *dest)
121+
static int cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
122+
u8 *dest)
121123
{
122124
int in_range = cros_ec_lpc_mec_in_range(offset, length);
123125

@@ -135,8 +137,8 @@ static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
135137
* An instance of the write function of struct lpc_driver_ops, used for the
136138
* MEC variant of LPC EC.
137139
*/
138-
static u8 cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
139-
const u8 *msg)
140+
static int cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
141+
const u8 *msg)
140142
{
141143
int in_range = cros_ec_lpc_mec_in_range(offset, length);
142144

@@ -154,11 +156,14 @@ static int ec_response_timed_out(void)
154156
{
155157
unsigned long one_second = jiffies + HZ;
156158
u8 data;
159+
int ret;
157160

158161
usleep_range(200, 300);
159162
do {
160-
if (!(cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data) &
161-
EC_LPC_STATUS_BUSY_MASK))
163+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data);
164+
if (ret < 0)
165+
return ret;
166+
if (!(data & EC_LPC_STATUS_BUSY_MASK))
162167
return 0;
163168
usleep_range(100, 200);
164169
} while (time_before(jiffies, one_second));
@@ -179,28 +184,41 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
179184
goto done;
180185

181186
/* Write buffer */
182-
cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
187+
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
188+
if (ret < 0)
189+
goto done;
183190

184191
/* Here we go */
185192
sum = EC_COMMAND_PROTOCOL_3;
186-
cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
193+
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
194+
if (ret < 0)
195+
goto done;
187196

188-
if (ec_response_timed_out()) {
197+
ret = ec_response_timed_out();
198+
if (ret < 0)
199+
goto done;
200+
if (ret) {
189201
dev_warn(ec->dev, "EC response timed out\n");
190202
ret = -EIO;
191203
goto done;
192204
}
193205

194206
/* Check result */
195-
msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
207+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
208+
if (ret < 0)
209+
goto done;
210+
msg->result = ret;
196211
ret = cros_ec_check_result(ec, msg);
197212
if (ret)
198213
goto done;
199214

200215
/* Read back response */
201216
dout = (u8 *)&response;
202-
sum = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
217+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
203218
dout);
219+
if (ret < 0)
220+
goto done;
221+
sum = ret;
204222

205223
msg->result = response.result;
206224

@@ -213,9 +231,12 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
213231
}
214232

215233
/* Read response and process checksum */
216-
sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
217-
sizeof(response), response.data_len,
218-
msg->data);
234+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
235+
sizeof(response), response.data_len,
236+
msg->data);
237+
if (ret < 0)
238+
goto done;
239+
sum += ret;
219240

220241
if (sum) {
221242
dev_err(ec->dev,
@@ -255,32 +276,47 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
255276
sum = msg->command + args.flags + args.command_version + args.data_size;
256277

257278
/* Copy data and update checksum */
258-
sum += cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
259-
msg->data);
279+
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
280+
msg->data);
281+
if (ret < 0)
282+
goto done;
283+
sum += ret;
260284

261285
/* Finalize checksum and write args */
262286
args.checksum = sum;
263-
cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
264-
(u8 *)&args);
287+
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
288+
(u8 *)&args);
289+
if (ret < 0)
290+
goto done;
265291

266292
/* Here we go */
267293
sum = msg->command;
268-
cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
294+
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
295+
if (ret < 0)
296+
goto done;
269297

270-
if (ec_response_timed_out()) {
298+
ret = ec_response_timed_out();
299+
if (ret < 0)
300+
goto done;
301+
if (ret) {
271302
dev_warn(ec->dev, "EC response timed out\n");
272303
ret = -EIO;
273304
goto done;
274305
}
275306

276307
/* Check result */
277-
msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
308+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
309+
if (ret < 0)
310+
goto done;
311+
msg->result = ret;
278312
ret = cros_ec_check_result(ec, msg);
279313
if (ret)
280314
goto done;
281315

282316
/* Read back args */
283-
cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
317+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
318+
if (ret < 0)
319+
goto done;
284320

285321
if (args.data_size > msg->insize) {
286322
dev_err(ec->dev,
@@ -294,8 +330,11 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
294330
sum = msg->command + args.flags + args.command_version + args.data_size;
295331

296332
/* Read response and update checksum */
297-
sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
298-
msg->data);
333+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
334+
msg->data);
335+
if (ret < 0)
336+
goto done;
337+
sum += ret;
299338

300339
/* Verify checksum */
301340
if (args.checksum != sum) {
@@ -320,19 +359,24 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
320359
int i = offset;
321360
char *s = dest;
322361
int cnt = 0;
362+
int ret;
323363

324364
if (offset >= EC_MEMMAP_SIZE - bytes)
325365
return -EINVAL;
326366

327367
/* fixed length */
328368
if (bytes) {
329-
cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + offset, bytes, s);
369+
ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + offset, bytes, s);
370+
if (ret < 0)
371+
return ret;
330372
return bytes;
331373
}
332374

333375
/* string */
334376
for (; i < EC_MEMMAP_SIZE; i++, s++) {
335-
cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + i, 1, s);
377+
ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + i, 1, s);
378+
if (ret < 0)
379+
return ret;
336380
cnt++;
337381
if (!*s)
338382
break;
@@ -425,7 +469,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
425469
*/
426470
cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes;
427471
cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes;
428-
cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
472+
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
473+
if (ret < 0)
474+
return ret;
429475
if (buf[0] != 'E' || buf[1] != 'C') {
430476
if (!devm_request_region(dev, ec_lpc->mmio_memory_base, EC_MEMMAP_SIZE,
431477
dev_name(dev))) {
@@ -436,8 +482,10 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
436482
/* Re-assign read/write operations for the non MEC variant */
437483
cros_ec_lpc_ops.read = cros_ec_lpc_read_bytes;
438484
cros_ec_lpc_ops.write = cros_ec_lpc_write_bytes;
439-
cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2,
440-
buf);
485+
ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2,
486+
buf);
487+
if (ret < 0)
488+
return ret;
441489
if (buf[0] != 'E' || buf[1] != 'C') {
442490
dev_err(dev, "EC ID not detected\n");
443491
return -ENODEV;

drivers/platform/chrome/cros_ec_lpc_mec.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,12 @@ int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length)
6767
* @length: Number of bytes to read / write
6868
* @buf: Destination / source buffer
6969
*
70-
* Return: 8-bit checksum of all bytes read / written
70+
* @return: A negative error code on error, or 8-bit checksum of all
71+
* bytes read / written
7172
*/
72-
u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
73-
unsigned int offset, unsigned int length,
74-
u8 *buf)
73+
int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
74+
unsigned int offset, unsigned int length,
75+
u8 *buf)
7576
{
7677
int i = 0;
7778
int io_addr;

drivers/platform/chrome/cros_ec_lpc_mec.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length);
6464
* @length: Number of bytes to read / write
6565
* @buf: Destination / source buffer
6666
*
67-
* @return 8-bit checksum of all bytes read / written
67+
* @return: A negative error code on error, or 8-bit checksum of all
68+
* bytes read / written
6869
*/
69-
u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
70-
unsigned int offset, unsigned int length, u8 *buf);
70+
int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
71+
unsigned int offset, unsigned int length, u8 *buf);
7172

7273
#endif /* __CROS_EC_LPC_MEC_H */

drivers/platform/chrome/wilco_ec/mailbox.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,17 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec,
117117
struct wilco_ec_request *rq)
118118
{
119119
struct wilco_ec_response *rs;
120-
u8 checksum;
120+
int ret;
121121
u8 flag;
122122

123123
/* Write request header, then data */
124-
cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq);
125-
cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size,
126-
msg->request_data);
124+
ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq);
125+
if (ret < 0)
126+
return ret;
127+
ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size,
128+
msg->request_data);
129+
if (ret < 0)
130+
return ret;
127131

128132
/* Start the command */
129133
outb(EC_MAILBOX_START_COMMAND, ec->io_command->start);
@@ -149,10 +153,12 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec,
149153

150154
/* Read back response */
151155
rs = ec->data_buffer;
152-
checksum = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0,
153-
sizeof(*rs) + EC_MAILBOX_DATA_SIZE,
154-
(u8 *)rs);
155-
if (checksum) {
156+
ret = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0,
157+
sizeof(*rs) + EC_MAILBOX_DATA_SIZE,
158+
(u8 *)rs);
159+
if (ret < 0)
160+
return ret;
161+
if (ret) {
156162
dev_dbg(ec->dev, "bad packet checksum 0x%02x\n", rs->checksum);
157163
return -EBADMSG;
158164
}

0 commit comments

Comments
 (0)