FAILED: patch "[PATCH] usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command" failed to apply to 6.6-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x eb4573cf2fd860b20adfae050c3f6ec6ddc3abdb
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090307-cannot-posh-1230@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From eb4573cf2fd860b20adfae050c3f6ec6ddc3abdb Mon Sep 17 00:00:00 2001
From: Huang Wei <[email protected]>
Date: Wed, 5 Aug 2026 16:57:25 +0800
Subject: [PATCH] usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command
completion
The synchronous command completion path in ucsi_sync_control_common() hardcodes a 5 second (5 * HZ) timeout when waiting for the PPM to signal command completion via ACPI notification. This value matched UCSI_TIMEOUT_MS when it was still 5000 ms, but it was not updated when that macro was later raised to 10000 ms to fix PPM reset timeouts.
As a result, the two PPM communication paths are now inconsistent: the polling path in ucsi_reset_ppm() respects the 10 second timeout, while the event-driven completion path still uses 5 seconds. On machines where the firmware is slow to respond during boot (e.g. some Lenovo ThinkPad models such as the E14 Gen 7), commands sent after the PPM reset, such as SET_NOTIFICATION_ENABLE and GET_CAPABILITY, can exceed 5 seconds and cause UCSI initialization to fail with:
ucsi_acpi USBC000:00: error -ETIMEDOUT: PPM init failed
Once UCSI init aborts, USB-C PD negotiation never completes, which in turn blocks USB-C dock enumeration since the dock depends on a successful PD contract.
Replace the hardcoded 5 * HZ with msecs_to_jiffies(UCSI_TIMEOUT_MS) so that both communication paths share a single, consistent timeout value, and future adjustments to UCSI_TIMEOUT_MS are picked up automatically.
drivers/usb/typec/ucsi/ucsi.c +2 -1
@@ -91,7 +91,8 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci,if (ret) goto out_clear_bit; -if (!wait_for_completion_timeout (&ucsi->complete,5 *HZ )) +if (!wait_for_completion_timeout (&ucsi->complete, +msecs_to_jiffies (UCSI_TIMEOUT_MS ))) ret = -ETIMEDOUT ; out_clear_bit:
Sasha Levin
maintainerPATCH 1/7 usb: typec: ucsi: move ucsi_acknowledge() from ucsi_read_error()
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit a7d2fa776976294d39d4cf36b25ca43be8325c3f ]
As a preparation for reworking UCSI command handling, move ucsi_acknowledge() for the failed command from ucsi_read_error() to ucsi_exec_command().
Stable-dep-of: eb4573cf2fd8 ("usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion")
--- drivers/usb/typec/ucsi/ucsi.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +6 -10
@@ -70,11 +70,6 @@ static int ucsi_read_error(struct ucsi *ucsi)u16 error;int ret; -/* Acknowledge the command that failed */ - ret =ucsi_acknowledge (ucsi, false); -if (ret) -return ret; - ret =ucsi_exec_command (ucsi,UCSI_GET_ERROR_STATUS );if (ret <0 )return ret;
@@ -153,13 +148,14 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) }if (cci &UCSI_CCI_ERROR ) { -if (cmd ==UCSI_GET_ERROR_STATUS ) { - ret =ucsi_acknowledge (ucsi, false); -if (ret) -return ret; +/* Acknowledge the command that failed */ + ret =ucsi_acknowledge (ucsi, false); +if (ret) +return ret; +if (cmd ==UCSI_GET_ERROR_STATUS )return -EIO ; - } +return ucsi_read_error (ucsi); }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/7 usb: typec: ucsi: simplify command sending API
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 13f2ec3115c845d7f2cd5525316ef4a3fbe908e3 ]
The sync_write and async_write are used only for writing UCSI commands to the UCSI_CONTROL offsets. Rename sync_write and async_write operations to sync_control and async_control accordingly. Drop the offset and length fields and pass u64 command instead.
[ sashal: Reduced backport -- upstream 13f2ec3115c84 touches 7 file(s), this
backport carries 6. Not backported here:
drivers/usb/typec/ucsi/ucsi_yoga_c630.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: eb4573cf2fd8 ("usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion")
--- drivers/usb/typec/ucsi/ucsi.c | 18 +++++------- drivers/usb/typec/ucsi/ucsi.h | 10 +++---- drivers/usb/typec/ucsi/ucsi_acpi.c | 36 +++++++++++------------- drivers/usb/typec/ucsi/ucsi_ccg.c | 40 ++++++++++++--------------- drivers/usb/typec/ucsi/ucsi_glink.c | 14 ++++------ drivers/usb/typec/ucsi/ucsi_stm32g0.c | 24 ++++++++-------- 6 files changed, 62 insertions(+), 80 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +7 -11
@@ -60,7 +60,7 @@ static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack) ctrl |=UCSI_ACK_CONNECTOR_CHANGE ; } -return ucsi->ops->sync_write (ucsi,UCSI_CONTROL , &ctrl,sizeof (ctrl)); +return ucsi->ops->sync_control (ucsi, ctrl); }static int ucsi_exec_command (struct ucsi *ucsi,u64 command);
@@ -126,7 +126,7 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd)u32 cci;int ret; - ret = ucsi->ops->sync_write (ucsi,UCSI_CONTROL , &cmd,sizeof (cmd)); + ret = ucsi->ops->sync_control (ucsi, cmd);if (ret)return ret;
@@ -1017,8 +1017,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)*/ if (cci &UCSI_CCI_RESET_COMPLETE ) { command =UCSI_SET_NOTIFICATION_ENABLE ; - ret = ucsi->ops->async_write (ucsi,UCSI_CONTROL , &command, -sizeof (command)); + ret = ucsi->ops->async_control (ucsi, command);if (ret <0 ) goto out;
@@ -1039,8 +1038,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) } command =UCSI_PPM_RESET ; - ret = ucsi->ops->async_write (ucsi,UCSI_CONTROL , &command, -sizeof (command)); + ret = ucsi->ops->async_control (ucsi, command);if (ret <0 ) goto out;
@@ -1058,9 +1056,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)/* If the PPM is still doing something else, reset it again. */ if (cci & ~UCSI_CCI_RESET_COMPLETE ) { - ret = ucsi->ops->async_write (ucsi,UCSI_CONTROL , - &command, -sizeof (command)); + ret = ucsi->ops->async_control (ucsi, command);if (ret <0 ) goto out; }
@@ -1691,7 +1687,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) {struct ucsi *ucsi; -if (!ops || !ops->read || !ops->sync_write || !ops->async_write) +if (!ops || !ops->read || !ops->sync_control || !ops->async_control)return ERR_PTR (-EINVAL ); ucsi =kzalloc (sizeof (*ucsi),GFP_KERNEL );
@@ -1767,7 +1763,7 @@ void ucsi_unregister(struct ucsi *ucsi)cancel_work_sync (&ucsi->resume_work);/* Disable notifications */ - ucsi->ops->async_write (ucsi,UCSI_CONTROL , &cmd,sizeof (cmd)); + ucsi->ops->async_control (ucsi, cmd);if (!ucsi->connector)return ;
drivers/usb/typec/ucsi/ucsi.h +4 -6
@@ -50,8 +50,8 @@ struct dentry;/** * struct ucsi_operations - UCSI I/O operations * @read: Read operation -* @sync_write: Blocking write operation -* @async_write: Non-blocking write operation +* @sync_control: Blocking control operation +* @async_control: Non-blocking control operation * @update_altmodes: Squashes duplicate DP altmodes * @update_connector: Update connector capabilities before registering * @connector_status: Updates connector status, called holding connector lock
@@ -63,10 +63,8 @@ struct dentry;struct ucsi_operations {int (*read)(struct ucsi *ucsi,unsigned int offset,void *val,size_t val_len); -int (*sync_write)(struct ucsi *ucsi,unsigned int offset, -const void *val,size_t val_len); -int (*async_write)(struct ucsi *ucsi,unsigned int offset, -const void *val,size_t val_len); +int (*sync_control)(struct ucsi *ucsi,u64 command); +int (*async_control)(struct ucsi *ucsi,u64 command);bool (*update_altmodes)(struct ucsi *ucsi,struct ucsi_altmode *orig,struct ucsi_altmode *updated);void (*update_connector)(struct ucsi_connector *con);
drivers/usb/typec/ucsi/ucsi_acpi.c +16 -20
@@ -61,22 +61,20 @@ static int ucsi_acpi_read(struct ucsi *ucsi, unsigned int offset,return 0 ; } -static int ucsi_acpi_async_write (struct ucsi *ucsi,unsigned int offset, -const void *val,size_t val_len) +static int ucsi_acpi_async_control (struct ucsi *ucsi,u64 command) {struct ucsi_acpi *ua =ucsi_get_drvdata (ucsi); -memcpy (ua->base + offset, val, val_len); - ua->cmd = *(u64 *)val; +memcpy (ua->base +UCSI_CONTROL , &command,sizeof (command)); + ua->cmd = command;return ucsi_acpi_dsm (ua,UCSI_DSM_FUNC_WRITE ); } -static int ucsi_acpi_sync_write (struct ucsi *ucsi,unsigned int offset, -const void *val,size_t val_len) +static int ucsi_acpi_sync_control (struct ucsi *ucsi,u64 command) {struct ucsi_acpi *ua =ucsi_get_drvdata (ucsi); -bool ack =UCSI_COMMAND (*(u64 *)val) ==UCSI_ACK_CC_CI ; +bool ack =UCSI_COMMAND (command) ==UCSI_ACK_CC_CI ;int ret;if (ack)
@@ -84,7 +82,7 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,else set_bit (UCSI_ACPI_COMMAND_PENDING , &ua->flags); - ret =ucsi_acpi_async_write (ucsi, offset, val, val_len); + ret =ucsi_acpi_async_control (ucsi, command);if (ret) goto out_clear_bit;
@@ -102,8 +100,8 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,static const struct ucsi_operations ucsi_acpi_ops = { .read = ucsi_acpi_read, - .sync_write = ucsi_acpi_sync_write, - .async_write = ucsi_acpi_async_write + .sync_control = ucsi_acpi_sync_control, + .async_control = ucsi_acpi_async_control }; static int
@@ -125,8 +123,8 @@ ucsi_zenbook_read(struct ucsi *ucsi, unsigned int offset, void *val, size_t val_static const struct ucsi_operations ucsi_zenbook_ops = { .read = ucsi_zenbook_read, - .sync_write = ucsi_acpi_sync_write, - .async_write = ucsi_acpi_async_write + .sync_control = ucsi_acpi_sync_control, + .async_control = ucsi_acpi_async_control };/*
@@ -137,11 +135,10 @@ static const struct ucsi_operations ucsi_zenbook_ops = {* for the dummy command. */ static int -ucsi_dell_sync_write (struct ucsi *ucsi,unsigned int offset, -const void *val,size_t val_len) +ucsi_dell_sync_control (struct ucsi *ucsi,u64 command) {struct ucsi_acpi *ua =ucsi_get_drvdata (ucsi); -u64 cmd = *(u64 *)val; +u64 cmd = command;u64 dummycmd =UCSI_GET_CAPABILITY ;int ret;
@@ -155,21 +152,20 @@ ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset,* still report the very event that the core is trying to clear. */ set_bit (UCSI_ACPI_SUPPRESS_EVENT , &ua->flags); - ret =ucsi_acpi_sync_write (ucsi,UCSI_CONTROL , &dummycmd, -sizeof (dummycmd)); + ret =ucsi_acpi_sync_control (ucsi, dummycmd);clear_bit (UCSI_ACPI_SUPPRESS_EVENT , &ua->flags);if (ret <0 )return ret; } -return ucsi_acpi_sync_write (ucsi,UCSI_CONTROL , &cmd,sizeof (cmd)); +return ucsi_acpi_sync_control (ucsi, cmd); }static const struct ucsi_operations ucsi_dell_ops = { .read = ucsi_acpi_read, - .sync_write = ucsi_dell_sync_write, - .async_write = ucsi_acpi_async_write + .sync_control = ucsi_dell_sync_control, + .async_control = ucsi_acpi_async_control };static const struct dmi_system_id ucsi_acpi_quirks[] = {
drivers/usb/typec/ucsi/ucsi_ccg.c +18 -22
@@ -558,16 +558,15 @@ static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,return ret; } -static int ucsi_ccg_async_write (struct ucsi *ucsi,unsigned int offset, -const void *val,size_t val_len) +static int ucsi_ccg_async_control (struct ucsi *ucsi,u64 command) { -u16 reg =CCGX_RAB_UCSI_DATA_BLOCK (offset); +u16 reg =CCGX_RAB_UCSI_DATA_BLOCK (UCSI_CONTROL ); -return ccg_write (ucsi_get_drvdata (ucsi), reg, val, val_len); +return ccg_write (ucsi_get_drvdata (ucsi), reg, (u8 *)&command, +sizeof (command)); } -static int ucsi_ccg_sync_write (struct ucsi *ucsi,unsigned int offset, -const void *val,size_t val_len) +static int ucsi_ccg_sync_control (struct ucsi *ucsi,u64 command) {struct ucsi_ccg *uc =ucsi_get_drvdata (ucsi);struct ucsi_connector *con;
@@ -578,23 +577,20 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,pm_runtime_get_sync (uc->dev);set_bit (DEV_CMD_PENDING , &uc->flags); -if (offset ==UCSI_CONTROL && val_len ==sizeof (uc->last_cmd_sent)) { - uc->last_cmd_sent = *(u64 *)val; - -if (UCSI_COMMAND (uc->last_cmd_sent) ==UCSI_SET_NEW_CAM && - uc->has_multiple_dp) { - con_index = (uc->last_cmd_sent >>16 ) & -UCSI_CMD_CONNECTOR_MASK ; -if (con_index ==0 ) { - ret = -EINVAL ; - goto err_put; - } - con = &uc->ucsi->connector[con_index -1 ]; -ucsi_ccg_update_set_new_cam_cmd (uc, con, (u64 *)val); + uc->last_cmd_sent = command; +if (UCSI_COMMAND (uc->last_cmd_sent) ==UCSI_SET_NEW_CAM && + uc->has_multiple_dp) { + con_index = (uc->last_cmd_sent >>16 ) & +UCSI_CMD_CONNECTOR_MASK ; +if (con_index ==0 ) { + ret = -EINVAL ; + goto err_put; } + con = &uc->ucsi->connector[con_index -1 ]; +ucsi_ccg_update_set_new_cam_cmd (uc, con, &command); } - ret =ucsi_ccg_async_write (ucsi, offset, val, val_len); + ret =ucsi_ccg_async_control (ucsi, command);if (ret) goto err_clear_bit;
@@ -612,8 +608,8 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,static const struct ucsi_operations ucsi_ccg_ops = { .read = ucsi_ccg_read, - .sync_write = ucsi_ccg_sync_write, - .async_write = ucsi_ccg_async_write, + .sync_control = ucsi_ccg_sync_control, + .async_control = ucsi_ccg_async_control, .update_altmodes = ucsi_ccg_update_altmodes };
drivers/usb/typec/ucsi/ucsi_glink.c +6 -8
@@ -146,21 +146,19 @@ static int pmic_glink_ucsi_locked_write(struct pmic_glink_ucsi *ucsi, unsigned ireturn 0 ; } -static int pmic_glink_ucsi_async_write (struct ucsi *__ucsi,unsigned int offset, -const void *val,size_t val_len) +static int pmic_glink_ucsi_async_control (struct ucsi *__ucsi,u64 command) {struct pmic_glink_ucsi *ucsi =ucsi_get_drvdata (__ucsi);int ret;mutex_lock (&ucsi->lock); - ret =pmic_glink_ucsi_locked_write (ucsi, offset, val, val_len); + ret =pmic_glink_ucsi_locked_write (ucsi,UCSI_CONTROL , &command,sizeof (command));mutex_unlock (&ucsi->lock);return ret; } -static int pmic_glink_ucsi_sync_write (struct ucsi *__ucsi,unsigned int offset, -const void *val,size_t val_len) +static int pmic_glink_ucsi_sync_control (struct ucsi *__ucsi,u64 command) {struct pmic_glink_ucsi *ucsi =ucsi_get_drvdata (__ucsi);unsigned long left;
@@ -172,7 +170,7 @@ static int pmic_glink_ucsi_sync_write(struct ucsi *__ucsi, unsigned int offset, ucsi->sync_val =0 ;reinit_completion (&ucsi->sync_ack); ucsi->sync_pending = true; - ret =pmic_glink_ucsi_locked_write (ucsi, offset, val, val_len); + ret =pmic_glink_ucsi_locked_write (ucsi,UCSI_CONTROL , &command,sizeof (command));mutex_unlock (&ucsi->lock); left =wait_for_completion_timeout (&ucsi->sync_ack,5 *HZ );
@@ -219,8 +217,8 @@ static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)static const struct ucsi_operations pmic_glink_ucsi_ops = { .read = pmic_glink_ucsi_read, - .sync_write = pmic_glink_ucsi_sync_write, - .async_write = pmic_glink_ucsi_async_write, + .sync_control = pmic_glink_ucsi_sync_control, + .async_control = pmic_glink_ucsi_async_control, .update_connector = pmic_glink_ucsi_update_connector, .connector_status = pmic_glink_ucsi_connector_status, };
drivers/usb/typec/ucsi/ucsi_stm32g0.c +11 -13
@@ -358,8 +358,7 @@ static int ucsi_stm32g0_read(struct ucsi *ucsi, unsigned int offset, void *val,return 0 ; } -static int ucsi_stm32g0_async_write (struct ucsi *ucsi,unsigned int offset,const void *val, -size_t len) +static int ucsi_stm32g0_async_control (struct ucsi *ucsi,u64 command) {struct ucsi_stm32g0 *g0 =ucsi_get_drvdata (ucsi);struct i2c_client *client = g0->client;
@@ -372,19 +371,19 @@ static int ucsi_stm32g0_async_write(struct ucsi *ucsi, unsigned int offset, consunsigned char *buf;int ret; - buf =kmalloc (len +1 ,GFP_KERNEL ); + buf =kmalloc (sizeof (command) +1 ,GFP_KERNEL );if (!buf)return -ENOMEM ; - buf[0 ] = offset; -memcpy (&buf[1 ], val, len); - msg[0 ].len = len +1 ; + buf[0 ] =UCSI_CONTROL ; +memcpy (&buf[1 ], &command,sizeof (command)); + msg[0 ].len =sizeof (command) +1 ; msg[0 ].buf = buf; ret =i2c_transfer (client->adapter, msg,ARRAY_SIZE (msg));kfree (buf);if (ret !=ARRAY_SIZE (msg)) { -dev_err (g0->dev,"i2c write %02x, %02x error: %d\n" , client->addr, offset, ret); +dev_err (g0->dev,"i2c write %02x, %02x error: %d\n" , client->addr,UCSI_CONTROL , ret);return ret <0 ? ret : -EIO ; }
@@ -392,11 +391,10 @@ static int ucsi_stm32g0_async_write(struct ucsi *ucsi, unsigned int offset, consreturn 0 ; } -static int ucsi_stm32g0_sync_write (struct ucsi *ucsi,unsigned int offset,const void *val, -size_t len) +static int ucsi_stm32g0_sync_control (struct ucsi *ucsi,u64 command) {struct ucsi_stm32g0 *g0 =ucsi_get_drvdata (ucsi); -bool ack =UCSI_COMMAND (*(u64 *)val) ==UCSI_ACK_CC_CI ; +bool ack =UCSI_COMMAND (command) ==UCSI_ACK_CC_CI ;int ret;if (ack)
@@ -404,7 +402,7 @@ static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, constelse set_bit (COMMAND_PENDING , &g0->flags); - ret =ucsi_stm32g0_async_write (ucsi, offset, val, len); + ret =ucsi_stm32g0_async_control (ucsi, command);if (ret) goto out_clear_bit;
@@ -448,8 +446,8 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data)static const struct ucsi_operations ucsi_stm32g0_ops = { .read = ucsi_stm32g0_read, - .sync_write = ucsi_stm32g0_sync_write, - .async_write = ucsi_stm32g0_async_write, + .sync_control = ucsi_stm32g0_sync_control, + .async_control = ucsi_stm32g0_async_control, };static int ucsi_stm32g0_register (struct ucsi *ucsi)
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/7 usb: typec: ucsi: split read operation
In reply to Sasha LevinFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 467399d989d799433ec7dd8da2ebbfbc70207d03 ]
The read operation is only used to read fixed data at fixed offsets (UCSI_VERSION, UCSI_CCI, UCSI_MESSAGE_IN). In some cases drivers apply offset-specific overrides. Split the read() operation into three operations, read_version(), read_cci(), read_message_in().
[ sashal: Reduced backport -- upstream 467399d989d79 touches 7 file(s), this
backport carries 6. Not backported here:
drivers/usb/typec/ucsi/ucsi_yoga_c630.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: eb4573cf2fd8 ("usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion")
--- drivers/usb/typec/ucsi/ucsi.c | 20 ++++----- drivers/usb/typec/ucsi/ucsi.h | 9 ++-- drivers/usb/typec/ucsi/ucsi_acpi.c | 64 ++++++++++++++++++++++----- drivers/usb/typec/ucsi/ucsi_ccg.c | 28 +++++++++--- drivers/usb/typec/ucsi/ucsi_glink.c | 19 +++++++- drivers/usb/typec/ucsi/ucsi_stm32g0.c | 19 +++++++- 6 files changed, 127 insertions(+), 32 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +10 -10
@@ -46,7 +46,7 @@ static int ucsi_read_message_in(struct ucsi *ucsi, void *buf,if (ucsi->version <=UCSI_VERSION_1_2 ) buf_size =clamp (buf_size,0 ,16 ); -return ucsi->ops->read (ucsi,UCSI_MESSAGE_IN , buf, buf_size); +return ucsi->ops->read_message_in (ucsi, buf, buf_size); }static int ucsi_acknowledge (struct ucsi *ucsi,bool conn_ack)
@@ -130,7 +130,7 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd)if (ret)return ret; - ret = ucsi->ops->read (ucsi,UCSI_CCI , &cci,sizeof (cci)); + ret = ucsi->ops->read_cci (ucsi, &cci);if (ret)return ret;
@@ -1005,7 +1005,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)mutex_lock (&ucsi->ppm_lock); - ret = ucsi->ops->read (ucsi,UCSI_CCI , &cci,sizeof (cci)); + ret = ucsi->ops->read_cci (ucsi, &cci);if (ret <0 ) goto out;
@@ -1023,8 +1023,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) tmo = jiffies +msecs_to_jiffies (UCSI_TIMEOUT_MS ); do { - ret = ucsi->ops->read(ucsi, UCSI_CCI, - &cci, sizeof(cci)); + ret = ucsi->ops->read_cci(ucsi, &cci); if (ret < 0) goto out; if (cci & UCSI_CCI_COMMAND_COMPLETE)
@@ -1050,7 +1049,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) goto out; } - ret = ucsi->ops->read (ucsi,UCSI_CCI , &cci,sizeof (cci)); + ret = ucsi->ops->read_cci (ucsi, &cci);if (ret) goto out;
@@ -1530,7 +1529,7 @@ static int ucsi_init(struct ucsi *ucsi) ucsi->ntfy = ntfy;mutex_lock (&ucsi->ppm_lock); - ret = ucsi->ops->read (ucsi,UCSI_CCI , &cci,sizeof (cci)); + ret = ucsi->ops->read_cci (ucsi, &cci);mutex_unlock (&ucsi->ppm_lock);if (ret)return ret;
@@ -1687,7 +1686,9 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) {struct ucsi *ucsi; -if (!ops || !ops->read || !ops->sync_control || !ops->async_control) +if (!ops || + !ops->read_version || !ops->read_cci || !ops->read_message_in || + !ops->sync_control || !ops->async_control)return ERR_PTR (-EINVAL ); ucsi =kzalloc (sizeof (*ucsi),GFP_KERNEL );
@@ -1723,8 +1724,7 @@ int ucsi_register(struct ucsi *ucsi) {int ret; - ret = ucsi->ops->read (ucsi,UCSI_VERSION , &ucsi->version, -sizeof (ucsi->version)); + ret = ucsi->ops->read_version (ucsi, &ucsi->version);if (ret)return ret;
drivers/usb/typec/ucsi/ucsi.h +6 -3
@@ -49,7 +49,9 @@ struct dentry;/** * struct ucsi_operations - UCSI I/O operations -* @read: Read operation +* @read_version: Read implemented UCSI version +* @read_cci: Read CCI register +* @read_message_in: Read message data from UCSI * @sync_control: Blocking control operation * @async_control: Non-blocking control operation * @update_altmodes: Squashes duplicate DP altmodes
@@ -61,8 +63,9 @@ struct dentry;* return immediately after sending the data to the PPM. */ struct ucsi_operations { -int (*read)(struct ucsi *ucsi,unsigned int offset, -void *val,size_t val_len); +int (*read_version)(struct ucsi *ucsi,u16 *version); +int (*read_cci)(struct ucsi *ucsi,u32 *cci); +int (*read_message_in)(struct ucsi *ucsi,void *val,size_t val_len);int (*sync_control)(struct ucsi *ucsi,u64 command);int (*async_control)(struct ucsi *ucsi,u64 command); bool (*update_altmodes)(struct ucsi *ucsi, struct ucsi_altmode *orig,
drivers/usb/typec/ucsi/ucsi_acpi.c +54 -10
113 lines not on this page · raw message
drivers/usb/typec/ucsi/ucsi_ccg.c +21 -7
@@ -515,11 +515,26 @@ static void ucsi_ccg_nvidia_altmode(struct ucsi_ccg *uc, } } -static int ucsi_ccg_read (struct ucsi *ucsi,unsigned int offset, -void *val,size_t val_len) +static int ucsi_ccg_read_version (struct ucsi *ucsi,u16 *version) {struct ucsi_ccg *uc =ucsi_get_drvdata (ucsi); -u16 reg =CCGX_RAB_UCSI_DATA_BLOCK (offset); +u16 reg =CCGX_RAB_UCSI_DATA_BLOCK (UCSI_VERSION ); + +return ccg_read (uc, reg, (u8 *)version,sizeof (*version)); +} + +static int ucsi_ccg_read_cci (struct ucsi *ucsi,u32 *cci) +{ +struct ucsi_ccg *uc =ucsi_get_drvdata (ucsi); +u16 reg =CCGX_RAB_UCSI_DATA_BLOCK (UCSI_CCI ); + +return ccg_read (uc, reg, (u8 *)cci,sizeof (*cci)); +} + +static int ucsi_ccg_read_message_in (struct ucsi *ucsi,void *val,size_t val_len) +{ +struct ucsi_ccg *uc =ucsi_get_drvdata (ucsi); +u16 reg =CCGX_RAB_UCSI_DATA_BLOCK (UCSI_MESSAGE_IN );struct ucsi_capability *cap;struct ucsi_altmode *alt;int ret;
@@ -528,9 +543,6 @@ static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,if (ret)return ret; -if (offset !=UCSI_MESSAGE_IN ) -return ret; -switch (UCSI_COMMAND (uc->last_cmd_sent)) {case UCSI_GET_CURRENT_CAM :if (uc->has_multiple_dp)
@@ -607,7 +619,9 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) }static const struct ucsi_operations ucsi_ccg_ops = { - .read = ucsi_ccg_read, + .read_version = ucsi_ccg_read_version, + .read_cci = ucsi_ccg_read_cci, + .read_message_in = ucsi_ccg_read_message_in, .sync_control = ucsi_ccg_sync_control, .async_control = ucsi_ccg_async_control, .update_altmodes = ucsi_ccg_update_altmodes
drivers/usb/typec/ucsi/ucsi_glink.c +18 -1
@@ -117,6 +117,21 @@ static int pmic_glink_ucsi_read(struct ucsi *__ucsi, unsigned int offset,return ret; } +static int pmic_glink_ucsi_read_version (struct ucsi *ucsi,u16 *version) +{ +return pmic_glink_ucsi_read (ucsi,UCSI_VERSION , version,sizeof (*version)); +} + +static int pmic_glink_ucsi_read_cci (struct ucsi *ucsi,u32 *cci) +{ +return pmic_glink_ucsi_read (ucsi,UCSI_CCI , cci,sizeof (*cci)); +} + +static int pmic_glink_ucsi_read_message_in (struct ucsi *ucsi,void *val,size_t val_len) +{ +return pmic_glink_ucsi_read (ucsi,UCSI_MESSAGE_IN , val, val_len); +} +static int pmic_glink_ucsi_locked_write (struct pmic_glink_ucsi *ucsi,unsigned int offset,const void *val,size_t val_len) {
@@ -216,7 +231,9 @@ static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con) }static const struct ucsi_operations pmic_glink_ucsi_ops = { - .read = pmic_glink_ucsi_read, + .read_version = pmic_glink_ucsi_read_version, + .read_cci = pmic_glink_ucsi_read_cci, + .read_message_in = pmic_glink_ucsi_read_message_in, .sync_control = pmic_glink_ucsi_sync_control, .async_control = pmic_glink_ucsi_async_control, .update_connector = pmic_glink_ucsi_update_connector,
drivers/usb/typec/ucsi/ucsi_stm32g0.c +18 -1
@@ -358,6 +358,21 @@ static int ucsi_stm32g0_read(struct ucsi *ucsi, unsigned int offset, void *val,return 0 ; } +static int ucsi_stm32g0_read_version (struct ucsi *ucsi,u16 *version) +{ +return ucsi_stm32g0_read (ucsi,UCSI_VERSION , version,sizeof (*version)); +} + +static int ucsi_stm32g0_read_cci (struct ucsi *ucsi,u32 *cci) +{ +return ucsi_stm32g0_read (ucsi,UCSI_CCI , cci,sizeof (*cci)); +} + +static int ucsi_stm32g0_read_message_in (struct ucsi *ucsi,void *val,size_t len) +{ +return ucsi_stm32g0_read (ucsi,UCSI_MESSAGE_IN , val, len); +} +static int ucsi_stm32g0_async_control (struct ucsi *ucsi,u64 command) {struct ucsi_stm32g0 *g0 =ucsi_get_drvdata (ucsi);
@@ -445,7 +460,9 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) }static const struct ucsi_operations ucsi_stm32g0_ops = { - .read = ucsi_stm32g0_read, + .read_version = ucsi_stm32g0_read_version, + .read_cci = ucsi_stm32g0_read_cci, + .read_message_in = ucsi_stm32g0_read_message_in, .sync_control = ucsi_stm32g0_sync_control, .async_control = ucsi_stm32g0_async_control, };
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/7 usb: typec: ucsi: rework command execution functions
In reply to Sasha LevinFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 5e9c1662a89b1d5dc3042d8a2f1614bd8124ded5 ]
Rework command execution code to remove recursive calls of ucsi_exec_command. This also streamlines the sync_control / read(CCI) read (MESSAGE_IN) sequence, allowing further rework of the command code.
Stable-dep-of: eb4573cf2fd8 ("usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion")
--- drivers/usb/typec/ucsi/ucsi.c | 137 ++++++++++++++++------------------ 1 file changed, 64 insertions(+), 73 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +64 -73
@@ -63,25 +63,74 @@ static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack)return ucsi->ops->sync_control (ucsi, ctrl); } -static int ucsi_exec_command (struct ucsi *ucsi,u64 command); - -static int ucsi_read_error (struct ucsi *ucsi) +static int ucsi_run_command (struct ucsi *ucsi,u64 command,u32 *cci, +void *data,size_t size,bool conn_ack) { -u16 error;int ret; - ret =ucsi_exec_command (ucsi,UCSI_GET_ERROR_STATUS ); -if (ret <0 ) + *cci =0 ; + + ret = ucsi->ops->sync_control (ucsi, command); +if (ret)return ret; - ret =ucsi_read_message_in (ucsi, &error,sizeof (error)); + ret = ucsi->ops->read_cci (ucsi, cci);if (ret)return ret; - ret =ucsi_acknowledge (ucsi, false); +if (*cci &UCSI_CCI_BUSY ) +return -EBUSY ; + +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 (data) { + ret =ucsi_read_message_in (ucsi, data, size); +if (ret) +return ret; + } + + ret =ucsi_acknowledge (ucsi, conn_ack);if (ret)return ret; +return UCSI_CCI_LENGTH (*cci); +} + +static int ucsi_read_error (struct ucsi *ucsi) +{ +u16 error; +u32 cci; +int ret; + + ret =ucsi_run_command (ucsi,UCSI_GET_ERROR_STATUS , &cci, + &error,sizeof (error), false); + +if (cci &UCSI_CCI_BUSY ) { + ret =ucsi_run_command (ucsi,UCSI_CANCEL , &cci,NULL ,0 , false); + +return ret ? ret : -EBUSY ; + } + +if (ret <0 ) +return ret; + +if (cci &UCSI_CCI_ERROR ) +return -EIO ; +switch (error) {case UCSI_ERROR_INCOMPATIBLE_PARTNER :return -EOPNOTSUPP ;
@@ -121,78 +170,20 @@ static int ucsi_read_error(struct ucsi *ucsi)return -EIO ; } -static int ucsi_exec_command (struct ucsi *ucsi,u64 cmd) -{ -u32 cci; -int ret; - - ret = ucsi->ops->sync_control (ucsi, cmd); -if (ret) -return ret; - - ret = ucsi->ops->read_cci (ucsi, &cci); -if (ret) -return ret; - -if (cmd !=UCSI_CANCEL && cci &UCSI_CCI_BUSY ) -return ucsi_exec_command (ucsi,UCSI_CANCEL ); - -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); -if (ret) -return ret; - -if (cmd ==UCSI_GET_ERROR_STATUS ) -return -EIO ; - -return ucsi_read_error (ucsi); - } - -if (cmd ==UCSI_CANCEL && cci &UCSI_CCI_CANCEL_COMPLETE ) { - ret =ucsi_acknowledge (ucsi, false); -return ret ? ret : -EBUSY ; - } - -return UCSI_CCI_LENGTH (cci); -} - -static int ucsi_send_command_common (struct ucsi *ucsi,u64 command, +static int ucsi_send_command_common (struct ucsi *ucsi,u64 cmd,void *data,size_t size,bool conn_ack) { -u8 length; +u32 cci;int ret;mutex_lock (&ucsi->ppm_lock); - ret =ucsi_exec_command (ucsi, command); -if (ret <0 ) - goto out; - - length = ret; + ret =ucsi_run_command (ucsi, cmd, &cci, data, size, conn_ack); +if (cci &UCSI_CCI_BUSY ) + ret =ucsi_run_command (ucsi,UCSI_CANCEL , &cci,NULL ,0 , false) ?: -EBUSY ; +else if (cci &UCSI_CCI_ERROR ) + ret =ucsi_read_error (ucsi); -if (data) { - ret =ucsi_read_message_in (ucsi, data, size); -if (ret) - goto out; - } - - ret =ucsi_acknowledge (ucsi, conn_ack); -if (ret) - goto out; - - ret = length; -out:mutex_unlock (&ucsi->ppm_lock);return ret; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 5/7 usb: typec: ucsi: inline ucsi_read_message_in
In reply to Sasha LevinFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit e1870c17e550b7a114833e392f2e340117941b7f ]
There is no need to have a separate wrapper for reading MESSAGE_IN data, inline it to ucsi_run_command().
Stable-dep-of: eb4573cf2fd8 ("usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion")
--- drivers/usb/typec/ucsi/ucsi.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +8 -14
@@ -36,19 +36,6 @@*/ #define UCSI_SWAP_TIMEOUT_MS 5000 -static int ucsi_read_message_in (struct ucsi *ucsi,void *buf, -size_t buf_size) -{ -/* -* Below UCSI 2.0, MESSAGE_IN was limited to 16 bytes. Truncate the -* reads here. -*/ -if (ucsi->version <=UCSI_VERSION_1_2 ) - buf_size =clamp (buf_size,0 ,16 ); - -return ucsi->ops->read_message_in (ucsi, buf, buf_size); -} -static int ucsi_acknowledge (struct ucsi *ucsi,bool conn_ack) {u64 ctrl;
@@ -70,6 +57,13 @@ static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, *cci =0 ; +/* +* Below UCSI 2.0, MESSAGE_IN was limited to 16 bytes. Truncate the +* reads here. +*/ +if (ucsi->version <=UCSI_VERSION_1_2 ) + size =clamp (size,0 ,16 ); + ret = ucsi->ops->sync_control (ucsi, command);if (ret)return ret;
@@ -98,7 +92,7 @@ static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, }if (data) { - ret =ucsi_read_message_in (ucsi, data, size); + ret = ucsi->ops->read_message_in (ucsi, data, size);if (ret)return ret; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 6/7 usb: typec: ucsi: extract common code for command handling
In reply to Sasha LevinFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 584e8df58942338602c70686b451b5c3093543a1 ]
Extract common functions to handle command sending and to handle events from UCSI. This ensures that all UCSI glue drivers handle the ACKs in the same way.
The CCG driver used DEV_CMD_PENDING both for internal firmware-related commands and for UCSI control handling. Leave the former use case intact.
[ sashal: Reduced backport -- upstream 584e8df589423 touches 7 file(s), this
backport carries 6. Not backported here:
drivers/usb/typec/ucsi/ucsi_yoga_c630.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: eb4573cf2fd8 ("usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion")
--- drivers/usb/typec/ucsi/ucsi.c | 43 +++++++++++++++++++++++ drivers/usb/typec/ucsi/ucsi.h | 5 +++ drivers/usb/typec/ucsi/ucsi_acpi.c | 50 ++++----------------------- drivers/usb/typec/ucsi/ucsi_ccg.c | 20 ++--------- drivers/usb/typec/ucsi/ucsi_glink.c | 47 ++----------------------- drivers/usb/typec/ucsi/ucsi_stm32g0.c | 43 ++--------------------- 6 files changed, 61 insertions(+), 147 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +43 -0
@@ -36,6 +36,48 @@*/ #define UCSI_SWAP_TIMEOUT_MS 5000 +void ucsi_notify_common (struct ucsi *ucsi,u32 cci) +{ +if (UCSI_CCI_CONNECTOR (cci)) +ucsi_connector_change (ucsi,UCSI_CCI_CONNECTOR (cci)); + +if (cci &UCSI_CCI_ACK_COMPLETE && +test_bit (ACK_PENDING , &ucsi->flags)) +complete (&ucsi->complete); + +if (cci &UCSI_CCI_COMMAND_COMPLETE && +test_bit (COMMAND_PENDING , &ucsi->flags)) +complete (&ucsi->complete); +} +EXPORT_SYMBOL_GPL (ucsi_notify_common); + +int ucsi_sync_control_common (struct ucsi *ucsi,u64 command) +{ +bool ack =UCSI_COMMAND (command) ==UCSI_ACK_CC_CI ; +int ret; + +if (ack) +set_bit (ACK_PENDING , &ucsi->flags); +else +set_bit (COMMAND_PENDING , &ucsi->flags); + + ret = ucsi->ops->async_control (ucsi, command); +if (ret) + goto out_clear_bit; + +if (!wait_for_completion_timeout (&ucsi->complete,5 *HZ )) + ret = -ETIMEDOUT ; + +out_clear_bit: +if (ack) +clear_bit (ACK_PENDING , &ucsi->flags); +else +clear_bit (COMMAND_PENDING , &ucsi->flags); + +return ret; +} +EXPORT_SYMBOL_GPL (ucsi_sync_control_common); +static int ucsi_acknowledge (struct ucsi *ucsi,bool conn_ack) {u64 ctrl;
@@ -1683,6 +1725,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops)INIT_WORK (&ucsi->resume_work, ucsi_resume_work);INIT_DELAYED_WORK (&ucsi->work, ucsi_init_work);mutex_init (&ucsi->ppm_lock); +init_completion (&ucsi->complete); ucsi->dev = dev; ucsi->ops = ops;
drivers/usb/typec/ucsi/ucsi.h +5 -0
@@ -4,6 +4,7 @@#define __DRIVER_USB_TYPEC_UCSI_H#include <linux/bitops.h> +#include <linux/completion.h> #include <linux/device.h> #include <linux/power_supply.h> #include <linux/types.h>
@@ -336,6 +337,7 @@ struct ucsi {#define EVENT_PENDING 0#define COMMAND_PENDING 1#define ACK_PENDING 2 +struct completion complete; };#define UCSI_MAX_SVID 5
@@ -391,6 +393,9 @@ void ucsi_altmode_update_active(struct ucsi_connector *con);int ucsi_suspend (struct ucsi *ucsi);int ucsi_resume (struct ucsi *ucsi); +void ucsi_notify_common (struct ucsi *ucsi,u32 cci); +int ucsi_sync_control_common (struct ucsi *ucsi,u64 command); +#if IS_ENABLED (CONFIG_POWER_SUPPLY )int ucsi_register_port_psy (struct ucsi_connector *con);void ucsi_unregister_port_psy (struct ucsi_connector *con);
drivers/usb/typec/ucsi/ucsi_acpi.c +7 -43
99 lines not on this page · raw message
drivers/usb/typec/ucsi/ucsi_ccg.c +2 -18
@@ -216,8 +216,6 @@ struct ucsi_ccg {u16 fw_build;struct work_struct pm_work; -struct completion complete; -u64 last_cmd_sent;bool has_multiple_dp;struct ucsi_ccg_altmode orig[UCSI_MAX_ALTMODES ];
@@ -587,7 +585,6 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command)mutex_lock (&uc->lock);pm_runtime_get_sync (uc->dev); -set_bit (DEV_CMD_PENDING , &uc->flags); uc->last_cmd_sent = command; if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_SET_NEW_CAM &&
@@ -602,15 +599,8 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command)ucsi_ccg_update_set_new_cam_cmd (uc, con, &command); } - ret =ucsi_ccg_async_control (ucsi, command); -if (ret) - goto err_clear_bit; - -if (!wait_for_completion_timeout (&uc->complete,msecs_to_jiffies (5000 ))) - ret = -ETIMEDOUT ; + ret =ucsi_sync_control_common (ucsi, command); -err_clear_bit: -clear_bit (DEV_CMD_PENDING , &uc->flags); err_put:pm_runtime_put_sync (uc->dev);mutex_unlock (&uc->lock);
@@ -643,12 +633,7 @@ static irqreturn_t ccg_irq_handler(int irq, void *data)if (ret) goto err_clear_irq; -if (UCSI_CCI_CONNECTOR (cci)) -ucsi_connector_change (uc->ucsi,UCSI_CCI_CONNECTOR (cci)); - -if (test_bit (DEV_CMD_PENDING , &uc->flags) && - cci & (UCSI_CCI_ACK_COMPLETE |UCSI_CCI_COMMAND_COMPLETE )) -complete (&uc->complete); +ucsi_notify_common (uc->ucsi, cci); err_clear_irq:ccg_write (uc,CCGX_RAB_INTR_REG , &intr_reg,sizeof (intr_reg));
@@ -1375,7 +1360,6 @@ static int ucsi_ccg_probe(struct i2c_client *client) uc->client = client; uc->irq = client->irq;mutex_init (&uc->lock); -init_completion (&uc->complete);INIT_WORK (&uc->work, ccg_update_firmware);INIT_WORK (&uc->pm_work, ccg_pm_workaround_work);
drivers/usb/typec/ucsi/ucsi_glink.c +2 -45
91 lines not on this page · raw message
drivers/usb/typec/ucsi/ucsi_stm32g0.c +2 -41
74 lines not on this page · raw message
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 7/7 usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion
In reply to Sasha LevinFrom: Huang Wei <[email protected]>
[ Upstream commit eb4573cf2fd860b20adfae050c3f6ec6ddc3abdb ]
The synchronous command completion path in ucsi_sync_control_common() hardcodes a 5 second (5 * HZ) timeout when waiting for the PPM to signal command completion via ACPI notification. This value matched UCSI_TIMEOUT_MS when it was still 5000 ms, but it was not updated when that macro was later raised to 10000 ms to fix PPM reset timeouts.
As a result, the two PPM communication paths are now inconsistent: the polling path in ucsi_reset_ppm() respects the 10 second timeout, while the event-driven completion path still uses 5 seconds. On machines where the firmware is slow to respond during boot (e.g. some Lenovo ThinkPad models such as the E14 Gen 7), commands sent after the PPM reset, such as SET_NOTIFICATION_ENABLE and GET_CAPABILITY, can exceed 5 seconds and cause UCSI initialization to fail with:
ucsi_acpi USBC000:00: error -ETIMEDOUT: PPM init failed
Once UCSI init aborts, USB-C PD negotiation never completes, which in turn blocks USB-C dock enumeration since the dock depends on a successful PD contract.
Replace the hardcoded 5 * HZ with msecs_to_jiffies(UCSI_TIMEOUT_MS) so that both communication paths share a single, consistent timeout value, and future adjustments to UCSI_TIMEOUT_MS are picked up automatically.
--- drivers/usb/typec/ucsi/ucsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/typec/ucsi/ucsi.c +2 -1
@@ -65,7 +65,8 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command)if (ret) goto out_clear_bit; -if (!wait_for_completion_timeout (&ucsi->complete,5 *HZ )) +if (!wait_for_completion_timeout (&ucsi->complete, +msecs_to_jiffies (UCSI_TIMEOUT_MS ))) ret = -ETIMEDOUT ; out_clear_bit:
Signature · 1 line
2.53.0
PATCH 1/1 usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion
In reply to [email protected]commit eb4573cf2fd860b20adfae050c3f6ec6ddc3abdb upstream.
The synchronous command completion path in ucsi_acpi_sync_write() hardcodes a 5 second (5 * HZ) timeout when waiting for the PPM to signal command completion via ACPI notification. This value matched UCSI_TIMEOUT_MS when it was still 5000 ms, but it was not updated when that macro was later raised to 10000 ms to fix PPM reset timeouts.
As a result, the two PPM communication paths are now inconsistent: the polling path in ucsi_reset_ppm() respects the 10 second timeout, while the event-driven completion path still uses 5 seconds. On machines where the firmware is slow to respond during boot (e.g. some Lenovo ThinkPad models such as the E14 Gen 7), commands sent after the PPM reset, such as SET_NOTIFICATION_ENABLE and GET_CAPABILITY, can exceed 5 seconds and cause UCSI initialization to fail with:
ucsi_acpi USBC000:00: error -ETIMEDOUT: PPM init failed
Once UCSI init aborts, USB-C PD negotiation never completes, which in turn blocks USB-C dock enumeration since the dock depends on a successful PD contract.
Replace the hardcoded 5 * HZ with msecs_to_jiffies(UCSI_TIMEOUT_MS) so that both communication paths share a single, consistent timeout value. Move the UCSI_TIMEOUT_MS definition to ucsi.h so the ACPI backend can use it.
---
drivers/usb/typec/ucsi/ucsi.h +3 -0
@@ -26,6 +26,9 @@#define UCSI_MESSAGE_OUT 32#define UCSIv2_MESSAGE_OUT 272 +/* PPM communication timeout in milliseconds */ +#define UCSI_TIMEOUT_MS 10000 +/* UCSI versions */ #define UCSI_VERSION_1_2 0x0120#define UCSI_VERSION_2_0 0x0200
drivers/usb/typec/ucsi/ucsi.c +0 -10
@@ -18,16 +18,6 @@#include "trace.h" /* -* UCSI_TIMEOUT_MS - PPM communication timeout -* -* Ideally we could use MIN_TIME_TO_RESPOND_WITH_BUSY (which is defined in UCSI -* specification) here as reference, but unfortunately we can't. It is very -* difficult to estimate the time it takes for the system to process the command -* before it is actually passed to the PPM. -*/ -#define UCSI_TIMEOUT_MS 10000 - -/* * UCSI_SWAP_TIMEOUT_MS - Timeout for role swap requests * * 5 seconds is close to the time it takes for CapsCounter to reach 0, so even
drivers/usb/typec/ucsi/ucsi_acpi.c +2 -1
@@ -88,7 +88,8 @@if (ret) goto out_clear_bit; -if (!wait_for_completion_timeout (&ua->complete,5 *HZ )) +if (!wait_for_completion_timeout (&ua->complete, +msecs_to_jiffies (UCSI_TIMEOUT_MS ))) ret = -ETIMEDOUT ; out_clear_bit:
Re: [PATCH 6.6.y] usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion
Quoted 5 lines
commit
eb4573cf2fd860b20adfae050c3f6ec6ddc3abdbupstream.The synchronous command completion path in
ucsi_acpi_sync_write()hardcodes a 5 second (5 * HZ) timeout when waiting for the PPM to signal command completion via ACPI notification.
Queued for 6.6, thanks.
Signature · 2 lines
Thanks, Sasha