diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-23 11:20:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-23 11:20:49 -0400 |
commit | bee797529d7c1ea4e2803fda067d20edbc00bc3d (patch) | |
tree | 9a19b34411360d1299e0f9a270b779e746a959bd | |
parent | 9ce8654323d69273b4977f76f11c9e2d345ab130 (diff) | |
parent | 11799564fc7eedff50801950090773928f867996 (diff) |
Merge tag 'mfd-fixes-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD fix from Lee Jones:
"A single cros_ec_spi fix correcting the handling for long-running
commands"
* tag 'mfd-fixes-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd:
mfd: cros_ec: Retry commands when EC is known to be busy
-rw-r--r-- | drivers/mfd/cros_ec_spi.c | 24 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_proto.c | 2 |
2 files changed, 22 insertions, 4 deletions
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c index 1b52b8557034..2060d1483043 100644 --- a/drivers/mfd/cros_ec_spi.c +++ b/drivers/mfd/cros_ec_spi.c | |||
@@ -419,10 +419,25 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, | |||
419 | /* Verify that EC can process command */ | 419 | /* Verify that EC can process command */ |
420 | for (i = 0; i < len; i++) { | 420 | for (i = 0; i < len; i++) { |
421 | rx_byte = rx_buf[i]; | 421 | rx_byte = rx_buf[i]; |
422 | /* | ||
423 | * Seeing the PAST_END, RX_BAD_DATA, or NOT_READY | ||
424 | * markers are all signs that the EC didn't fully | ||
425 | * receive our command. e.g., if the EC is flashing | ||
426 | * itself, it can't respond to any commands and instead | ||
427 | * clocks out EC_SPI_PAST_END from its SPI hardware | ||
428 | * buffer. Similar occurrences can happen if the AP is | ||
429 | * too slow to clock out data after asserting CS -- the | ||
430 | * EC will abort and fill its buffer with | ||
431 | * EC_SPI_RX_BAD_DATA. | ||
432 | * | ||
433 | * In all cases, these errors should be safe to retry. | ||
434 | * Report -EAGAIN and let the caller decide what to do | ||
435 | * about that. | ||
436 | */ | ||
422 | if (rx_byte == EC_SPI_PAST_END || | 437 | if (rx_byte == EC_SPI_PAST_END || |
423 | rx_byte == EC_SPI_RX_BAD_DATA || | 438 | rx_byte == EC_SPI_RX_BAD_DATA || |
424 | rx_byte == EC_SPI_NOT_READY) { | 439 | rx_byte == EC_SPI_NOT_READY) { |
425 | ret = -EREMOTEIO; | 440 | ret = -EAGAIN; |
426 | break; | 441 | break; |
427 | } | 442 | } |
428 | } | 443 | } |
@@ -431,7 +446,7 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, | |||
431 | if (!ret) | 446 | if (!ret) |
432 | ret = cros_ec_spi_receive_packet(ec_dev, | 447 | ret = cros_ec_spi_receive_packet(ec_dev, |
433 | ec_msg->insize + sizeof(*response)); | 448 | ec_msg->insize + sizeof(*response)); |
434 | else | 449 | else if (ret != -EAGAIN) |
435 | dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); | 450 | dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); |
436 | 451 | ||
437 | final_ret = terminate_request(ec_dev); | 452 | final_ret = terminate_request(ec_dev); |
@@ -537,10 +552,11 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, | |||
537 | /* Verify that EC can process command */ | 552 | /* Verify that EC can process command */ |
538 | for (i = 0; i < len; i++) { | 553 | for (i = 0; i < len; i++) { |
539 | rx_byte = rx_buf[i]; | 554 | rx_byte = rx_buf[i]; |
555 | /* See comments in cros_ec_pkt_xfer_spi() */ | ||
540 | if (rx_byte == EC_SPI_PAST_END || | 556 | if (rx_byte == EC_SPI_PAST_END || |
541 | rx_byte == EC_SPI_RX_BAD_DATA || | 557 | rx_byte == EC_SPI_RX_BAD_DATA || |
542 | rx_byte == EC_SPI_NOT_READY) { | 558 | rx_byte == EC_SPI_NOT_READY) { |
543 | ret = -EREMOTEIO; | 559 | ret = -EAGAIN; |
544 | break; | 560 | break; |
545 | } | 561 | } |
546 | } | 562 | } |
@@ -549,7 +565,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, | |||
549 | if (!ret) | 565 | if (!ret) |
550 | ret = cros_ec_spi_receive_response(ec_dev, | 566 | ret = cros_ec_spi_receive_response(ec_dev, |
551 | ec_msg->insize + EC_MSG_TX_PROTO_BYTES); | 567 | ec_msg->insize + EC_MSG_TX_PROTO_BYTES); |
552 | else | 568 | else if (ret != -EAGAIN) |
553 | dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); | 569 | dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); |
554 | 570 | ||
555 | final_ret = terminate_request(ec_dev); | 571 | final_ret = terminate_request(ec_dev); |
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index e7bbdf947bbc..8350ca2311c7 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c | |||
@@ -91,6 +91,8 @@ static int send_command(struct cros_ec_device *ec_dev, | |||
91 | usleep_range(10000, 11000); | 91 | usleep_range(10000, 11000); |
92 | 92 | ||
93 | ret = (*xfer_fxn)(ec_dev, status_msg); | 93 | ret = (*xfer_fxn)(ec_dev, status_msg); |
94 | if (ret == -EAGAIN) | ||
95 | continue; | ||
94 | if (ret < 0) | 96 | if (ret < 0) |
95 | break; | 97 | break; |
96 | 98 | ||