From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>,
Heikki Krogerus <heikki.krogerus@linux.intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.6.y 2/7] usb: typec: ucsi: simplify command sending API
Date: Fri, 4 Sep 2026 11:58:41 -0400 [thread overview]
Message-ID: <20260904155846.1071149-2-sashal@kernel.org> (raw)
In-Reply-To: <20260904155846.1071149-1-sashal@kernel.org>
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
[ 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.
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-2-289ddc6874c7@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ 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")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
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(-)
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 37c6d7d7c46ae..f94ccf830cbd2 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -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;
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 9ac5ad87f4015..ef3ad1401070b 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -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);
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index e40f3bf650ad8..ef18611282de5 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -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[] = {
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index 7d436dfdc028f..17e94f98fff25 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -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
};
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
index cddbeae914198..56214527fe8e2 100644
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -146,21 +146,19 @@ static int pmic_glink_ucsi_locked_write(struct pmic_glink_ucsi *ucsi, unsigned i
return 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,
};
diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
index 1d7ee833eb4fd..4454d60b9a680 100644
--- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c
+++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
@@ -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, cons
unsigned 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, cons
return 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, const
else
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)
--
2.53.0
next prev parent reply other threads:[~2026-09-04 15:58 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 12:40 FAILED: patch "[PATCH] usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command" failed to apply to 6.6-stable tree gregkh
2026-09-04 15:58 ` [PATCH 6.6.y 1/7] usb: typec: ucsi: move ucsi_acknowledge() from ucsi_read_error() Sasha Levin
2026-09-04 15:58 ` Sasha Levin [this message]
2026-09-04 15:58 ` [PATCH 6.6.y 3/7] usb: typec: ucsi: split read operation Sasha Levin
2026-09-04 15:58 ` [PATCH 6.6.y 4/7] usb: typec: ucsi: rework command execution functions Sasha Levin
2026-09-04 15:58 ` [PATCH 6.6.y 5/7] usb: typec: ucsi: inline ucsi_read_message_in Sasha Levin
2026-09-04 15:58 ` [PATCH 6.6.y 6/7] usb: typec: ucsi: extract common code for command handling Sasha Levin
2026-09-04 15:58 ` [PATCH 6.6.y 7/7] usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion Sasha Levin
2026-09-10 1:36 ` [PATCH 6.6.y] " Huang Wei
2026-09-11 11:21 ` Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260904155846.1071149-2-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=dmitry.baryshkov@linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=heikki.krogerus@linux.intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.