Commit bee79752 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 9ce86543 11799564
...@@ -419,10 +419,25 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, ...@@ -419,10 +419,25 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev,
/* Verify that EC can process command */ /* Verify that EC can process command */
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
rx_byte = rx_buf[i]; rx_byte = rx_buf[i];
/*
* Seeing the PAST_END, RX_BAD_DATA, or NOT_READY
* markers are all signs that the EC didn't fully
* receive our command. e.g., if the EC is flashing
* itself, it can't respond to any commands and instead
* clocks out EC_SPI_PAST_END from its SPI hardware
* buffer. Similar occurrences can happen if the AP is
* too slow to clock out data after asserting CS -- the
* EC will abort and fill its buffer with
* EC_SPI_RX_BAD_DATA.
*
* In all cases, these errors should be safe to retry.
* Report -EAGAIN and let the caller decide what to do
* about that.
*/
if (rx_byte == EC_SPI_PAST_END || if (rx_byte == EC_SPI_PAST_END ||
rx_byte == EC_SPI_RX_BAD_DATA || rx_byte == EC_SPI_RX_BAD_DATA ||
rx_byte == EC_SPI_NOT_READY) { rx_byte == EC_SPI_NOT_READY) {
ret = -EREMOTEIO; ret = -EAGAIN;
break; break;
} }
} }
...@@ -431,7 +446,7 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, ...@@ -431,7 +446,7 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev,
if (!ret) if (!ret)
ret = cros_ec_spi_receive_packet(ec_dev, ret = cros_ec_spi_receive_packet(ec_dev,
ec_msg->insize + sizeof(*response)); ec_msg->insize + sizeof(*response));
else else if (ret != -EAGAIN)
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
final_ret = terminate_request(ec_dev); final_ret = terminate_request(ec_dev);
...@@ -537,10 +552,11 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, ...@@ -537,10 +552,11 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
/* Verify that EC can process command */ /* Verify that EC can process command */
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
rx_byte = rx_buf[i]; rx_byte = rx_buf[i];
/* See comments in cros_ec_pkt_xfer_spi() */
if (rx_byte == EC_SPI_PAST_END || if (rx_byte == EC_SPI_PAST_END ||
rx_byte == EC_SPI_RX_BAD_DATA || rx_byte == EC_SPI_RX_BAD_DATA ||
rx_byte == EC_SPI_NOT_READY) { rx_byte == EC_SPI_NOT_READY) {
ret = -EREMOTEIO; ret = -EAGAIN;
break; break;
} }
} }
...@@ -549,7 +565,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, ...@@ -549,7 +565,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
if (!ret) if (!ret)
ret = cros_ec_spi_receive_response(ec_dev, ret = cros_ec_spi_receive_response(ec_dev,
ec_msg->insize + EC_MSG_TX_PROTO_BYTES); ec_msg->insize + EC_MSG_TX_PROTO_BYTES);
else else if (ret != -EAGAIN)
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
final_ret = terminate_request(ec_dev); final_ret = terminate_request(ec_dev);
......
...@@ -91,6 +91,8 @@ static int send_command(struct cros_ec_device *ec_dev, ...@@ -91,6 +91,8 @@ static int send_command(struct cros_ec_device *ec_dev,
usleep_range(10000, 11000); usleep_range(10000, 11000);
ret = (*xfer_fxn)(ec_dev, status_msg); ret = (*xfer_fxn)(ec_dev, status_msg);
if (ret == -EAGAIN)
continue;
if (ret < 0) if (ret < 0)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment