From 51e6fc138f42275ec5429e875ca47aab37aca443 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 26 Jun 2024 15:04:35 -0400 Subject: [PATCH] Fixes for 6.9 Signed-off-by: Sasha Levin --- queue-6.9/series | 2 + ...i-ack-also-failed-get-error-commands.patch | 48 ++++++ ...ever-send-a-lone-connector-change-ac.patch | 159 ++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 queue-6.9/usb-typec-ucsi-ack-also-failed-get-error-commands.patch create mode 100644 queue-6.9/usb-typec-ucsi-never-send-a-lone-connector-change-ac.patch diff --git a/queue-6.9/series b/queue-6.9/series index 901efefb4da..548b0d29e53 100644 --- a/queue-6.9/series +++ b/queue-6.9/series @@ -247,3 +247,5 @@ net-sched-unregister-lockdep-keys-in-qdisc_create-qdisc_alloc-error-path.patch kprobe-ftrace-fix-build-error-due-to-bad-function-definition.patch hid-asus-asus_report_fixup-fix-potential-read-out-of-bounds.patch revert-mm-mmap-allow-for-the-maximum-number-of-bits-for-randomizing-mmap_base-by-default.patch +usb-typec-ucsi-never-send-a-lone-connector-change-ac.patch +usb-typec-ucsi-ack-also-failed-get-error-commands.patch diff --git a/queue-6.9/usb-typec-ucsi-ack-also-failed-get-error-commands.patch b/queue-6.9/usb-typec-ucsi-ack-also-failed-get-error-commands.patch new file mode 100644 index 00000000000..ef5a644f455 --- /dev/null +++ b/queue-6.9/usb-typec-ucsi-ack-also-failed-get-error-commands.patch @@ -0,0 +1,48 @@ +From 2b5011497f01fd8669e274435bb1f536e1091f2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 May 2024 13:46:52 +0300 +Subject: usb: typec: ucsi: Ack also failed Get Error commands + +From: Heikki Krogerus + +[ Upstream commit 8bdf8a42bca4f47646fd105a387ab6926948c7f1 ] + +It is possible that also the GET_ERROR command fails. If +that happens, the command completion still needs to be +acknowledged. Otherwise the interface will be stuck until +it's reset. + +Reported-by: Ammy Yi +Fixes: bdc62f2bae8f ("usb: typec: ucsi: Simplified registration and I/O API") +Cc: stable@vger.kernel.org +Signed-off-by: Heikki Krogerus +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20240531104653.1303519-1-heikki.krogerus@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/ucsi/ucsi.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index 144e47ed6fae3..911d774c9805a 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -153,8 +153,13 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) + } + + if (cci & UCSI_CCI_ERROR) { +- if (cmd == UCSI_GET_ERROR_STATUS) ++ if (cmd == UCSI_GET_ERROR_STATUS) { ++ ret = ucsi_acknowledge(ucsi, false); ++ if (ret) ++ return ret; ++ + return -EIO; ++ } + return ucsi_read_error(ucsi); + } + +-- +2.43.0 + diff --git a/queue-6.9/usb-typec-ucsi-never-send-a-lone-connector-change-ac.patch b/queue-6.9/usb-typec-ucsi-never-send-a-lone-connector-change-ac.patch new file mode 100644 index 00000000000..2609c532954 --- /dev/null +++ b/queue-6.9/usb-typec-ucsi-never-send-a-lone-connector-change-ac.patch @@ -0,0 +1,159 @@ +From 86348adc92e8fde07a5eb41ed30a048bae529bf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Mar 2024 23:45:53 +0100 +Subject: usb: typec: ucsi: Never send a lone connector change ack + +From: Christian A. Ehrhardt + +[ Upstream commit de52aca4d9d56c3b2f00b638d457075914b1a227 ] + +Some PPM implementation do not like UCSI_ACK_CONNECTOR_CHANGE +without UCSI_ACK_COMMAND_COMPLETE. Moreover, doing this is racy +as it requires sending two UCSI_ACK_CC_CI commands in a row and +the second one will be started with UCSI_CCI_ACK_COMPLETE already +set in CCI. + +Bundle the UCSI_ACK_CONNECTOR_CHANGE with the UCSI_ACK_COMMAND_COMPLETE +for the UCSI_GET_CONNECTOR_STATUS command that is sent while +handling a connector change event. + +Signed-off-by: Christian A. Ehrhardt +Reviewed-by: Heikki Krogerus +Tested-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20240327224554.1772525-3-lk@c--e.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 8bdf8a42bca4 ("usb: typec: ucsi: Ack also failed Get Error commands") +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/ucsi/ucsi.c | 48 +++++++++++++++-------------------- + 1 file changed, 21 insertions(+), 27 deletions(-) + +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index 7801501837b69..144e47ed6fae3 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -49,22 +49,16 @@ static int ucsi_read_message_in(struct ucsi *ucsi, void *buf, + return ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, buf, buf_size); + } + +-static int ucsi_acknowledge_command(struct ucsi *ucsi) ++static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack) + { + u64 ctrl; + + ctrl = UCSI_ACK_CC_CI; + ctrl |= UCSI_ACK_COMMAND_COMPLETE; +- +- return ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &ctrl, sizeof(ctrl)); +-} +- +-static int ucsi_acknowledge_connector_change(struct ucsi *ucsi) +-{ +- u64 ctrl; +- +- ctrl = UCSI_ACK_CC_CI; +- ctrl |= UCSI_ACK_CONNECTOR_CHANGE; ++ if (conn_ack) { ++ clear_bit(EVENT_PENDING, &ucsi->flags); ++ ctrl |= UCSI_ACK_CONNECTOR_CHANGE; ++ } + + return ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &ctrl, sizeof(ctrl)); + } +@@ -77,7 +71,7 @@ static int ucsi_read_error(struct ucsi *ucsi) + int ret; + + /* Acknowledge the command that failed */ +- ret = ucsi_acknowledge_command(ucsi); ++ ret = ucsi_acknowledge(ucsi, false); + if (ret) + return ret; + +@@ -89,7 +83,7 @@ static int ucsi_read_error(struct ucsi *ucsi) + if (ret) + return ret; + +- ret = ucsi_acknowledge_command(ucsi); ++ ret = ucsi_acknowledge(ucsi, false); + if (ret) + return ret; + +@@ -152,7 +146,7 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) + return -EIO; + + if (cci & UCSI_CCI_NOT_SUPPORTED) { +- if (ucsi_acknowledge_command(ucsi) < 0) ++ if (ucsi_acknowledge(ucsi, false) < 0) + dev_err(ucsi->dev, + "ACK of unsupported command failed\n"); + return -EOPNOTSUPP; +@@ -165,15 +159,15 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) + } + + if (cmd == UCSI_CANCEL && cci & UCSI_CCI_CANCEL_COMPLETE) { +- ret = ucsi_acknowledge_command(ucsi); ++ ret = ucsi_acknowledge(ucsi, false); + return ret ? ret : -EBUSY; + } + + return UCSI_CCI_LENGTH(cci); + } + +-int ucsi_send_command(struct ucsi *ucsi, u64 command, +- void *data, size_t size) ++static int ucsi_send_command_common(struct ucsi *ucsi, u64 command, ++ void *data, size_t size, bool conn_ack) + { + u8 length; + int ret; +@@ -192,7 +186,7 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command, + goto out; + } + +- ret = ucsi_acknowledge_command(ucsi); ++ ret = ucsi_acknowledge(ucsi, conn_ack); + if (ret) + goto out; + +@@ -201,6 +195,12 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command, + mutex_unlock(&ucsi->ppm_lock); + return ret; + } ++ ++int ucsi_send_command(struct ucsi *ucsi, u64 command, ++ void *data, size_t size) ++{ ++ return ucsi_send_command_common(ucsi, command, data, size, false); ++} + EXPORT_SYMBOL_GPL(ucsi_send_command); + + /* -------------------------------------------------------------------------- */ +@@ -1157,7 +1157,9 @@ static void ucsi_handle_connector_change(struct work_struct *work) + mutex_lock(&con->lock); + + command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); +- ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status)); ++ ++ ret = ucsi_send_command_common(ucsi, command, &con->status, ++ sizeof(con->status), true); + if (ret < 0) { + dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", + __func__, ret); +@@ -1214,14 +1216,6 @@ static void ucsi_handle_connector_change(struct work_struct *work) + if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) + ucsi_partner_task(con, ucsi_check_altmodes, 1, 0); + +- mutex_lock(&ucsi->ppm_lock); +- clear_bit(EVENT_PENDING, &con->ucsi->flags); +- ret = ucsi_acknowledge_connector_change(ucsi); +- mutex_unlock(&ucsi->ppm_lock); +- +- if (ret) +- dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); +- + out_unlock: + mutex_unlock(&con->lock); + } +-- +2.43.0 + -- 2.47.3