diff mbox series

[v2,4/4] platform/chrome: cros_ec_proto: Convert EC error codes to Linux error codes

Message ID 20200720202243.180230-5-linux@roeck-us.net (mailing list archive)
State New, archived
Headers show
Series platform/chrome: cros_ec_proto: Convert EC error codes to Linux error codes | expand

Commit Message

Guenter Roeck July 20, 2020, 8:22 p.m. UTC
The EC reports a variety of error codes. Most of those, with the exception
of EC_RES_INVALID_VERSION, are converted to -EPROTO. As result, the actual
error code gets lost. In cros_ec_cmd_xfer_status(), convert all EC errors
to Linux error codes to report a more meaningful error to the caller to aid
debugging.

Cc: Yu-Hsuan Hsu <yuhsuan@chromium.org>
Cc: Prashant Malani <pmalani@chromium.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
v2: No change

Notes:
    I would welcome feedback on the error code translations.
    Can we do better ?

    -ENOTSUPP is not a recommended error code, and checkpatch complains
    about it. It is used in existing code, so I did not change it, but it
    might be worthwhile exploring if we can find a better error code to
    report "version not supported". Possible candidates might be EPROTOTYPE,
    ENOPROTOOPT, EPROTONOSUPPORT, EPFNOSUPPORT, or EAFNOSUPPORT. I don't
    see a direct match, but NFS reports -EPROTONOSUPPORT for unsupported
    protocol versions.

 drivers/platform/chrome/cros_ec_proto.c | 37 +++++++++++++++++++------
 1 file changed, 29 insertions(+), 8 deletions(-)

Comments

Enric Balletbo i Serra July 21, 2020, 11:29 a.m. UTC | #1
Hi Guenter,

Thank you for work on this. Cc'ing Gwendal as he has a deep knowledge of the EC
and their errors.

On 20/7/20 22:22, Guenter Roeck wrote:
> The EC reports a variety of error codes. Most of those, with the exception
> of EC_RES_INVALID_VERSION, are converted to -EPROTO. As result, the actual
> error code gets lost. In cros_ec_cmd_xfer_status(), convert all EC errors
> to Linux error codes to report a more meaningful error to the caller to aid
> debugging.
> 
> Cc: Yu-Hsuan Hsu <yuhsuan@chromium.org>
> Cc: Prashant Malani <pmalani@chromium.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> ---
> v2: No change
> 
> Notes:
>     I would welcome feedback on the error code translations.
>     Can we do better ?
> 
>     -ENOTSUPP is not a recommended error code, and checkpatch complains
>     about it. It is used in existing code, so I did not change it, but it
>     might be worthwhile exploring if we can find a better error code to
>     report "version not supported". Possible candidates might be EPROTOTYPE,
>     ENOPROTOOPT, EPROTONOSUPPORT, EPFNOSUPPORT, or EAFNOSUPPORT. I don't
>     see a direct match, but NFS reports -EPROTONOSUPPORT for unsupported
>     protocol versions.
> 
>  drivers/platform/chrome/cros_ec_proto.c | 37 +++++++++++++++++++------
>  1 file changed, 29 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
> index 3e745e0fe092..10aa9e483d35 100644
> --- a/drivers/platform/chrome/cros_ec_proto.c
> +++ b/drivers/platform/chrome/cros_ec_proto.c
> @@ -543,6 +543,29 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
>  }
>  EXPORT_SYMBOL(cros_ec_cmd_xfer);
>  
> +static const int cros_ec_error_map[] = {
> +	[EC_RES_INVALID_COMMAND] = -EOPNOTSUPP,
> +	[EC_RES_ERROR] = -EIO,

nit -EREMOTEIO? To make explicit that the error is "remote" from the host.
Although -EIO seems to be more generic.

> +	[EC_RES_INVALID_PARAM] = -EINVAL,
> +	[EC_RES_ACCESS_DENIED] = -EACCES,
> +	[EC_RES_INVALID_RESPONSE] = -EPROTO,
> +	[EC_RES_INVALID_VERSION] = -ENOTSUPP,

+1 for EPROTONOSUPPORT to match with EC_RES_INVALID_VERSION

> +	[EC_RES_INVALID_CHECKSUM] = -EBADMSG,
> +	[EC_RES_IN_PROGRESS] = -EINPROGRESS,
> +	[EC_RES_UNAVAILABLE] = -ENODATA,
> +	[EC_RES_TIMEOUT] = -ETIMEDOUT,
> +	[EC_RES_OVERFLOW] = -EOVERFLOW,
> +	[EC_RES_INVALID_HEADER] = -EBADR,
> +	[EC_RES_REQUEST_TRUNCATED] = -EBADR,
> +	[EC_RES_RESPONSE_TOO_BIG] = -EFBIG,
> +	[EC_RES_BUS_ERROR] = -EFAULT,
> +	[EC_RES_BUSY] = -EBUSY,

Although the name matches, I'm wondering if we should use -EAGAIN instead as per
EC documentation:

  EC_RES_BUSY - Up but too busy. Should retry.

hmm, however, for the audio codec, for example, this seems to have a slightly
different meaning and retry is not what we want, so let's do direct translation
and stay with -EBUSY.

> +	[EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,
> +	[EC_RES_INVALID_HEADER_CRC] = -EBADMSG,
> +	[EC_RES_INVALID_DATA_CRC] = -EBADMSG,
> +	[EC_RES_DUP_UNAVAILABLE] = -ENODATA,
> +};
> +
>  /**
>   * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
>   * @ec_dev: EC device.
> @@ -555,8 +578,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer);
>   *
>   * Return:
>   * >=0 - The number of bytes transferred
> - * -ENOTSUPP - Operation not supported
> - * -EPROTO - Protocol error
> + * <0 - Linux error code
>   */
>  int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
>  			    struct cros_ec_command *msg)
> @@ -566,13 +588,12 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
>  	ret = cros_ec_cmd_xfer(ec_dev, msg);
>  	if (ret < 0) {
>  		dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
> -	} else if (msg->result == EC_RES_INVALID_VERSION) {
> -		dev_dbg(ec_dev->dev, "Command invalid version (err:%d)\n",
> -			msg->result);
> -		return -ENOTSUPP;
>  	} else if (msg->result != EC_RES_SUCCESS) {
> -		dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
> -		return -EPROTO;
> +		if (msg->result < ARRAY_SIZE(cros_ec_error_map) && cros_ec_error_map[msg->result])
> +			ret = cros_ec_error_map[msg->result];
> +		else
> +			ret = -EPROTO;
> +		dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n", msg->result, ret);
>  	}
>  
>  	return ret;
>
Guenter Roeck July 21, 2020, 2:11 p.m. UTC | #2
Hi Enric,

On Tue, Jul 21, 2020 at 01:29:01PM +0200, Enric Balletbo i Serra wrote:
> Hi Guenter,
> 
> Thank you for work on this. Cc'ing Gwendal as he has a deep knowledge of the EC
> and their errors.

The series is now also available in Gerrit at
	https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2306731/3
for integration/testing into ChromeOS.

Thanks,
Guenter

> 
> On 20/7/20 22:22, Guenter Roeck wrote:
> > The EC reports a variety of error codes. Most of those, with the exception
> > of EC_RES_INVALID_VERSION, are converted to -EPROTO. As result, the actual
> > error code gets lost. In cros_ec_cmd_xfer_status(), convert all EC errors
> > to Linux error codes to report a more meaningful error to the caller to aid
> > debugging.
> > 
> > Cc: Yu-Hsuan Hsu <yuhsuan@chromium.org>
> > Cc: Prashant Malani <pmalani@chromium.org>
> > Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> > ---
> > v2: No change
> > 
> > Notes:
> >     I would welcome feedback on the error code translations.
> >     Can we do better ?
> > 
> >     -ENOTSUPP is not a recommended error code, and checkpatch complains
> >     about it. It is used in existing code, so I did not change it, but it
> >     might be worthwhile exploring if we can find a better error code to
> >     report "version not supported". Possible candidates might be EPROTOTYPE,
> >     ENOPROTOOPT, EPROTONOSUPPORT, EPFNOSUPPORT, or EAFNOSUPPORT. I don't
> >     see a direct match, but NFS reports -EPROTONOSUPPORT for unsupported
> >     protocol versions.
> > 
> >  drivers/platform/chrome/cros_ec_proto.c | 37 +++++++++++++++++++------
> >  1 file changed, 29 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
> > index 3e745e0fe092..10aa9e483d35 100644
> > --- a/drivers/platform/chrome/cros_ec_proto.c
> > +++ b/drivers/platform/chrome/cros_ec_proto.c
> > @@ -543,6 +543,29 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
> >  }
> >  EXPORT_SYMBOL(cros_ec_cmd_xfer);
> >  
> > +static const int cros_ec_error_map[] = {
> > +	[EC_RES_INVALID_COMMAND] = -EOPNOTSUPP,
> > +	[EC_RES_ERROR] = -EIO,
> 
> nit -EREMOTEIO? To make explicit that the error is "remote" from the host.
> Although -EIO seems to be more generic.
> 
> > +	[EC_RES_INVALID_PARAM] = -EINVAL,
> > +	[EC_RES_ACCESS_DENIED] = -EACCES,
> > +	[EC_RES_INVALID_RESPONSE] = -EPROTO,
> > +	[EC_RES_INVALID_VERSION] = -ENOTSUPP,
> 
> +1 for EPROTONOSUPPORT to match with EC_RES_INVALID_VERSION
> 
> > +	[EC_RES_INVALID_CHECKSUM] = -EBADMSG,
> > +	[EC_RES_IN_PROGRESS] = -EINPROGRESS,
> > +	[EC_RES_UNAVAILABLE] = -ENODATA,
> > +	[EC_RES_TIMEOUT] = -ETIMEDOUT,
> > +	[EC_RES_OVERFLOW] = -EOVERFLOW,
> > +	[EC_RES_INVALID_HEADER] = -EBADR,
> > +	[EC_RES_REQUEST_TRUNCATED] = -EBADR,
> > +	[EC_RES_RESPONSE_TOO_BIG] = -EFBIG,
> > +	[EC_RES_BUS_ERROR] = -EFAULT,
> > +	[EC_RES_BUSY] = -EBUSY,
> 
> Although the name matches, I'm wondering if we should use -EAGAIN instead as per
> EC documentation:
> 
>   EC_RES_BUSY - Up but too busy. Should retry.
> 
> hmm, however, for the audio codec, for example, this seems to have a slightly
> different meaning and retry is not what we want, so let's do direct translation
> and stay with -EBUSY.
> 
> > +	[EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,
> > +	[EC_RES_INVALID_HEADER_CRC] = -EBADMSG,
> > +	[EC_RES_INVALID_DATA_CRC] = -EBADMSG,
> > +	[EC_RES_DUP_UNAVAILABLE] = -ENODATA,
> > +};
> > +
> >  /**
> >   * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
> >   * @ec_dev: EC device.
> > @@ -555,8 +578,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer);
> >   *
> >   * Return:
> >   * >=0 - The number of bytes transferred
> > - * -ENOTSUPP - Operation not supported
> > - * -EPROTO - Protocol error
> > + * <0 - Linux error code
> >   */
> >  int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
> >  			    struct cros_ec_command *msg)
> > @@ -566,13 +588,12 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
> >  	ret = cros_ec_cmd_xfer(ec_dev, msg);
> >  	if (ret < 0) {
> >  		dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
> > -	} else if (msg->result == EC_RES_INVALID_VERSION) {
> > -		dev_dbg(ec_dev->dev, "Command invalid version (err:%d)\n",
> > -			msg->result);
> > -		return -ENOTSUPP;
> >  	} else if (msg->result != EC_RES_SUCCESS) {
> > -		dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
> > -		return -EPROTO;
> > +		if (msg->result < ARRAY_SIZE(cros_ec_error_map) && cros_ec_error_map[msg->result])
> > +			ret = cros_ec_error_map[msg->result];
> > +		else
> > +			ret = -EPROTO;
> > +		dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n", msg->result, ret);
> >  	}
> >  
> >  	return ret;
> >
Guenter Roeck July 21, 2020, 2:23 p.m. UTC | #3
On Tue, Jul 21, 2020 at 01:29:01PM +0200, Enric Balletbo i Serra wrote:
> Hi Guenter,
> 
> Thank you for work on this. Cc'ing Gwendal as he has a deep knowledge of the EC
> and their errors.
> 
> On 20/7/20 22:22, Guenter Roeck wrote:
> > The EC reports a variety of error codes. Most of those, with the exception
> > of EC_RES_INVALID_VERSION, are converted to -EPROTO. As result, the actual
> > error code gets lost. In cros_ec_cmd_xfer_status(), convert all EC errors
> > to Linux error codes to report a more meaningful error to the caller to aid
> > debugging.
> > 
> > Cc: Yu-Hsuan Hsu <yuhsuan@chromium.org>
> > Cc: Prashant Malani <pmalani@chromium.org>
> > Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> > ---
> > v2: No change
> > 
> > Notes:
> >     I would welcome feedback on the error code translations.
> >     Can we do better ?
> > 
> >     -ENOTSUPP is not a recommended error code, and checkpatch complains
> >     about it. It is used in existing code, so I did not change it, but it
> >     might be worthwhile exploring if we can find a better error code to
> >     report "version not supported". Possible candidates might be EPROTOTYPE,
> >     ENOPROTOOPT, EPROTONOSUPPORT, EPFNOSUPPORT, or EAFNOSUPPORT. I don't
> >     see a direct match, but NFS reports -EPROTONOSUPPORT for unsupported
> >     protocol versions.
> > 
> >  drivers/platform/chrome/cros_ec_proto.c | 37 +++++++++++++++++++------
> >  1 file changed, 29 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
> > index 3e745e0fe092..10aa9e483d35 100644
> > --- a/drivers/platform/chrome/cros_ec_proto.c
> > +++ b/drivers/platform/chrome/cros_ec_proto.c
> > @@ -543,6 +543,29 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
> >  }
> >  EXPORT_SYMBOL(cros_ec_cmd_xfer);
> >  
> > +static const int cros_ec_error_map[] = {
> > +	[EC_RES_INVALID_COMMAND] = -EOPNOTSUPP,
> > +	[EC_RES_ERROR] = -EIO,
> 
> nit -EREMOTEIO? To make explicit that the error is "remote" from the host.
> Although -EIO seems to be more generic.
> 
I think using -EREMOTEIO is a good idea; some SPI/I2C controller error
might return -EIO.

> > +	[EC_RES_INVALID_PARAM] = -EINVAL,
> > +	[EC_RES_ACCESS_DENIED] = -EACCES,
> > +	[EC_RES_INVALID_RESPONSE] = -EPROTO,
> > +	[EC_RES_INVALID_VERSION] = -ENOTSUPP,
> 
> +1 for EPROTONOSUPPORT to match with EC_RES_INVALID_VERSION
> 
Ok. I'll do that with a separate patch.

> > +	[EC_RES_INVALID_CHECKSUM] = -EBADMSG,
> > +	[EC_RES_IN_PROGRESS] = -EINPROGRESS,
> > +	[EC_RES_UNAVAILABLE] = -ENODATA,
> > +	[EC_RES_TIMEOUT] = -ETIMEDOUT,
> > +	[EC_RES_OVERFLOW] = -EOVERFLOW,
> > +	[EC_RES_INVALID_HEADER] = -EBADR,
> > +	[EC_RES_REQUEST_TRUNCATED] = -EBADR,
> > +	[EC_RES_RESPONSE_TOO_BIG] = -EFBIG,
> > +	[EC_RES_BUS_ERROR] = -EFAULT,
> > +	[EC_RES_BUSY] = -EBUSY,
> 
> Although the name matches, I'm wondering if we should use -EAGAIN instead as per
> EC documentation:
> 
>   EC_RES_BUSY - Up but too busy. Should retry.
> 
> hmm, however, for the audio codec, for example, this seems to have a slightly
> different meaning and retry is not what we want, so let's do direct translation
> and stay with -EBUSY.
> 
> > +	[EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,

Any idea for EC_RES_INVALID_HEADER_VERSION ? I am not entirely happy
with -EBADMSG: the error is distinctly different to CRC errors.
EPROTONOSUPPORT as well, maybe, or something else ?

Thanks,
Guenter

> > +	[EC_RES_INVALID_HEADER_CRC] = -EBADMSG,
> > +	[EC_RES_INVALID_DATA_CRC] = -EBADMSG,
> > +	[EC_RES_DUP_UNAVAILABLE] = -ENODATA,
> > +};
> > +
> >  /**
> >   * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
> >   * @ec_dev: EC device.
> > @@ -555,8 +578,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer);
> >   *
> >   * Return:
> >   * >=0 - The number of bytes transferred
> > - * -ENOTSUPP - Operation not supported
> > - * -EPROTO - Protocol error
> > + * <0 - Linux error code
> >   */
> >  int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
> >  			    struct cros_ec_command *msg)
> > @@ -566,13 +588,12 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
> >  	ret = cros_ec_cmd_xfer(ec_dev, msg);
> >  	if (ret < 0) {
> >  		dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
> > -	} else if (msg->result == EC_RES_INVALID_VERSION) {
> > -		dev_dbg(ec_dev->dev, "Command invalid version (err:%d)\n",
> > -			msg->result);
> > -		return -ENOTSUPP;
> >  	} else if (msg->result != EC_RES_SUCCESS) {
> > -		dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
> > -		return -EPROTO;
> > +		if (msg->result < ARRAY_SIZE(cros_ec_error_map) && cros_ec_error_map[msg->result])
> > +			ret = cros_ec_error_map[msg->result];
> > +		else
> > +			ret = -EPROTO;
> > +		dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n", msg->result, ret);
> >  	}
> >  
> >  	return ret;
> >
Brian Norris July 22, 2020, 9:52 p.m. UTC | #4
+ drinkcat, aseda

On Tue, Jul 21, 2020 at 07:23:20AM -0700, Guenter Roeck wrote:
> On Tue, Jul 21, 2020 at 01:29:01PM +0200, Enric Balletbo i Serra wrote:
> > On 20/7/20 22:22, Guenter Roeck wrote:
> > > +	[EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,
> 
> Any idea for EC_RES_INVALID_HEADER_VERSION ? I am not entirely happy
> with -EBADMSG: the error is distinctly different to CRC errors.
> EPROTONOSUPPORT as well, maybe, or something else ?

FWIW, these (INVALID_HEADER_VERSION, INVALID_HEADER_CRC,
INVALID_DATA_CRC) aren't actually used on any firmware yet. This has
been open forever:
https://crbug.com/787159
Added here:
https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/780452/

Unfortunately, the linked design doc (still in draft) is not public.

My understanding is that while they're not all exactly the same (CRC is
different than the others), they are all still supposed to represent
"corrupt request [from the Application Processor]". EBADMSG seems good
enough to me.

Brian

P.S. for those added late -- you can grab the whole thread from here:
https://lore.kernel.org/lkml/20200720202243.180230-1-linux@roeck-us.net/
or in mbox form:
https://lore.kernel.org/lkml/20200720202243.180230-1-linux@roeck-us.net/t.mbox.gz
Guenter Roeck July 22, 2020, 10:01 p.m. UTC | #5
On 7/22/20 2:52 PM, Brian Norris wrote:
> + drinkcat, aseda
> 
> On Tue, Jul 21, 2020 at 07:23:20AM -0700, Guenter Roeck wrote:
>> On Tue, Jul 21, 2020 at 01:29:01PM +0200, Enric Balletbo i Serra wrote:
>>> On 20/7/20 22:22, Guenter Roeck wrote:
>>>> +	[EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,
>>
>> Any idea for EC_RES_INVALID_HEADER_VERSION ? I am not entirely happy
>> with -EBADMSG: the error is distinctly different to CRC errors.
>> EPROTONOSUPPORT as well, maybe, or something else ?
> 
> FWIW, these (INVALID_HEADER_VERSION, INVALID_HEADER_CRC,
> INVALID_DATA_CRC) aren't actually used on any firmware yet. This has
> been open forever:
> https://crbug.com/787159
> Added here:
> https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/780452/
> 
> Unfortunately, the linked design doc (still in draft) is not public.
> 
> My understanding is that while they're not all exactly the same (CRC is
> different than the others), they are all still supposed to represent
> "corrupt request [from the Application Processor]". EBADMSG seems good
> enough to me.
> 

SGTM, and make sense.

Thanks,
Guenter

> Brian
> 
> P.S. for those added late -- you can grab the whole thread from here:
> https://lore.kernel.org/lkml/20200720202243.180230-1-linux@roeck-us.net/
> or in mbox form:
> https://lore.kernel.org/lkml/20200720202243.180230-1-linux@roeck-us.net/t.mbox.gz
>
diff mbox series

Patch

diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index 3e745e0fe092..10aa9e483d35 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -543,6 +543,29 @@  int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer);
 
+static const int cros_ec_error_map[] = {
+	[EC_RES_INVALID_COMMAND] = -EOPNOTSUPP,
+	[EC_RES_ERROR] = -EIO,
+	[EC_RES_INVALID_PARAM] = -EINVAL,
+	[EC_RES_ACCESS_DENIED] = -EACCES,
+	[EC_RES_INVALID_RESPONSE] = -EPROTO,
+	[EC_RES_INVALID_VERSION] = -ENOTSUPP,
+	[EC_RES_INVALID_CHECKSUM] = -EBADMSG,
+	[EC_RES_IN_PROGRESS] = -EINPROGRESS,
+	[EC_RES_UNAVAILABLE] = -ENODATA,
+	[EC_RES_TIMEOUT] = -ETIMEDOUT,
+	[EC_RES_OVERFLOW] = -EOVERFLOW,
+	[EC_RES_INVALID_HEADER] = -EBADR,
+	[EC_RES_REQUEST_TRUNCATED] = -EBADR,
+	[EC_RES_RESPONSE_TOO_BIG] = -EFBIG,
+	[EC_RES_BUS_ERROR] = -EFAULT,
+	[EC_RES_BUSY] = -EBUSY,
+	[EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,
+	[EC_RES_INVALID_HEADER_CRC] = -EBADMSG,
+	[EC_RES_INVALID_DATA_CRC] = -EBADMSG,
+	[EC_RES_DUP_UNAVAILABLE] = -ENODATA,
+};
+
 /**
  * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
  * @ec_dev: EC device.
@@ -555,8 +578,7 @@  EXPORT_SYMBOL(cros_ec_cmd_xfer);
  *
  * Return:
  * >=0 - The number of bytes transferred
- * -ENOTSUPP - Operation not supported
- * -EPROTO - Protocol error
+ * <0 - Linux error code
  */
 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
 			    struct cros_ec_command *msg)
@@ -566,13 +588,12 @@  int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
 	ret = cros_ec_cmd_xfer(ec_dev, msg);
 	if (ret < 0) {
 		dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
-	} else if (msg->result == EC_RES_INVALID_VERSION) {
-		dev_dbg(ec_dev->dev, "Command invalid version (err:%d)\n",
-			msg->result);
-		return -ENOTSUPP;
 	} else if (msg->result != EC_RES_SUCCESS) {
-		dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
-		return -EPROTO;
+		if (msg->result < ARRAY_SIZE(cros_ec_error_map) && cros_ec_error_map[msg->result])
+			ret = cros_ec_error_map[msg->result];
+		else
+			ret = -EPROTO;
+		dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n", msg->result, ret);
 	}
 
 	return ret;