diff options
author | Dmitry Baryshkov <dmitry.baryshkov@linaro.org> | 2024-06-27 17:44:46 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-07-03 16:04:50 +0200 |
commit | 6cbb7fc91085b39f681aa94ab1a9ce566a93f27b (patch) | |
tree | 7fb110be6a353f7b37ce99350793e5b8e0bab4b4 /drivers/usb | |
parent | 584e8df58942338602c70686b451b5c3093543a1 (diff) | |
download | lwn-6cbb7fc91085b39f681aa94ab1a9ce566a93f27b.tar.gz lwn-6cbb7fc91085b39f681aa94ab1a9ce566a93f27b.zip |
usb: typec: ucsi: reorder operations in ucsi_run_command()
Streamline control stream of ucsi_run_command(). Reorder operations so
that there is only one call to ucsi_acknowledge(), making sure that all
complete commands are acknowledged. This also makes sure that the
command is acknowledged even if reading MESSAGE_IN data returns an
error.
Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20240627-ucsi-rework-interface-v4-7-289ddc6874c7@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/typec/ucsi/ucsi.c | 34 |
1 files changed, 14 insertions, 20 deletions
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 25d2ee5ee8bb..dcd3765cc1f5 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -95,7 +95,7 @@ static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack) static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, void *data, size_t size, bool conn_ack) { - int ret; + int ret, err; *cci = 0; @@ -120,30 +120,24 @@ static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, if (!(*cci & UCSI_CCI_COMMAND_COMPLETE)) return -EIO; - if (*cci & UCSI_CCI_NOT_SUPPORTED) { - if (ucsi_acknowledge(ucsi, false) < 0) - dev_err(ucsi->dev, - "ACK of unsupported command failed\n"); - return -EOPNOTSUPP; - } - - if (*cci & UCSI_CCI_ERROR) { - /* Acknowledge the command that failed */ - ret = ucsi_acknowledge(ucsi, false); - return ret ? ret : -EIO; - } + if (*cci & UCSI_CCI_NOT_SUPPORTED) + err = -EOPNOTSUPP; + else if (*cci & UCSI_CCI_ERROR) + err = -EIO; + else + err = 0; - if (data) { - ret = ucsi->ops->read_message_in(ucsi, data, size); - if (ret) - return ret; - } + if (!err && data && UCSI_CCI_LENGTH(*cci)) + err = ucsi->ops->read_message_in(ucsi, data, size); - ret = ucsi_acknowledge(ucsi, conn_ack); + /* + * Don't ACK connection change if there was an error. + */ + ret = ucsi_acknowledge(ucsi, err ? false : conn_ack); if (ret) return ret; - return 0; + return err; } static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num) |