From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE6604F649D for ; Fri, 4 Sep 2026 15:58:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537532; cv=none; b=N3eUeAT1N+iNJdlwkZ1dLMIhkszj/yjHrRaHyGDnJb5n+kfU8zIIxVUt1SZG8nevlko4QvYIiRtdQBuKARuzS6ykgsaaRJ9p7i1FR997QdCMoGgYGy9JDOLmZQh4numrellMjgJcUe6uZmWv1IvKZZJp999fOM4qUl6uehDbmtc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788537532; c=relaxed/simple; bh=Z61w2I2DdC48qJyfK63dtXKiXKlMoY85oaI+keItCAc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fAqe0DclTHoJKrpFe0txFWw/Eyk6A0dVsYidoM9KshP8hBhL+YVU6LTZEYkhXDaA6eWAcZEhUFrERwM4RbJgIk9iFovOP2J/VGWz+JkdKh2WR8YpShORUk1h2+/KFpdE46rasxX0VLtTAKAQcAYo9O5SCfGLmkfy5EDfCBa6074= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kGhT9juf; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kGhT9juf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F026D1F00ADB; Fri, 4 Sep 2026 15:58:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788537530; bh=5QeP+znc6+nGCXMfQbz9uWcHQDSan7ITWqXAqZLUbdE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kGhT9jufS24LY35zeiaRZrg/a1eXWQ3lnndkZL9XF7ec8J+s35+y0oFXVQLZxgIsc e2MYlC3n/iHKwIiDF8L9D44CfK4rp3u6i8lVLcvBs+WSBzAZLvtB20IqslnxPib68E LB2vwJpJZgBF5LgqO1VjndFyOo9QgvB0/M3vVgvbf1CtSHfWVCFqd0Ee3IJyUjladi RIAIpzOqcq0Uj6tfGxJuyg8w0uyd4ItN60v+azX+GNMQomlHxHVCAgBBE/NOmEtsuF Bvx945537ByoRwUi8346t+g+rdFwjNIMk3BzRStGDLr2dRMRQFKXdj+64qVEtQ3lGC Q+XAU5oS16QJw== From: Sasha Levin To: stable@vger.kernel.org Cc: Dmitry Baryshkov , Heikki Krogerus , Greg Kroah-Hartman , Sasha Levin Subject: [PATCH 6.6.y 3/7] usb: typec: ucsi: split read operation Date: Fri, 4 Sep 2026 11:58:42 -0400 Message-ID: <20260904155846.1071149-3-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260904155846.1071149-1-sashal@kernel.org> References: <2026090307-cannot-posh-1230@gregkh> <20260904155846.1071149-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Dmitry Baryshkov [ 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(). Tested-by: Heikki Krogerus Reviewed-by: Heikki Krogerus Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240627-ucsi-rework-interface-v4-3-289ddc6874c7@linaro.org Signed-off-by: Greg Kroah-Hartman [ 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") Signed-off-by: Sasha Levin --- 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(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index f94ccf830cbd2..56ddedb6a44aa 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -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; diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index ef3ad1401070b..386b06bc7a1a0 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -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, diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index ef18611282de5..c0c5746117343 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -46,8 +46,7 @@ static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) return 0; } -static int ucsi_acpi_read(struct ucsi *ucsi, unsigned int offset, - void *val, size_t val_len) +static int ucsi_acpi_read_version(struct ucsi *ucsi, u16 *version) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); int ret; @@ -56,7 +55,35 @@ static int ucsi_acpi_read(struct ucsi *ucsi, unsigned int offset, if (ret) return ret; - memcpy(val, ua->base + offset, val_len); + memcpy(version, ua->base + UCSI_VERSION, sizeof(*version)); + + return 0; +} + +static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + int ret; + + ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); + if (ret) + return ret; + + memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci)); + + return 0; +} + +static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + int ret; + + ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); + if (ret) + return ret; + + memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len); return 0; } @@ -99,30 +126,45 @@ static int ucsi_acpi_sync_control(struct ucsi *ucsi, u64 command) } static const struct ucsi_operations ucsi_acpi_ops = { - .read = ucsi_acpi_read, + .read_version = ucsi_acpi_read_version, + .read_cci = ucsi_acpi_read_cci, + .read_message_in = ucsi_acpi_read_message_in, .sync_control = ucsi_acpi_sync_control, .async_control = ucsi_acpi_async_control }; static int -ucsi_zenbook_read(struct ucsi *ucsi, unsigned int offset, void *val, size_t val_len) +ucsi_zenbook_read_cci(struct ucsi *ucsi, u32 *cci) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); int ret; - if (offset == UCSI_VERSION || UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) { + if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) { ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); if (ret) return ret; } - memcpy(val, ua->base + offset, val_len); + memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci)); + + return 0; +} + +static int +ucsi_zenbook_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + + /* UCSI_MESSAGE_IN is never read for PPM_RESET, return stored data */ + memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len); return 0; } static const struct ucsi_operations ucsi_zenbook_ops = { - .read = ucsi_zenbook_read, + .read_version = ucsi_acpi_read_version, + .read_cci = ucsi_zenbook_read_cci, + .read_message_in = ucsi_zenbook_read_message_in, .sync_control = ucsi_acpi_sync_control, .async_control = ucsi_acpi_async_control }; @@ -163,7 +205,9 @@ ucsi_dell_sync_control(struct ucsi *ucsi, u64 command) } static const struct ucsi_operations ucsi_dell_ops = { - .read = ucsi_acpi_read, + .read_version = ucsi_acpi_read_version, + .read_cci = ucsi_acpi_read_cci, + .read_message_in = ucsi_acpi_read_message_in, .sync_control = ucsi_dell_sync_control, .async_control = ucsi_acpi_async_control }; @@ -191,7 +235,7 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) u32 cci; int ret; - ret = ua->ucsi->ops->read(ua->ucsi, UCSI_CCI, &cci, sizeof(cci)); + ret = ua->ucsi->ops->read_cci(ua->ucsi, &cci); if (ret) return; diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 17e94f98fff25..185d67745a540 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -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 diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index 56214527fe8e2..9427693b9593c 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -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, diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c index 4454d60b9a680..e39a3ef662268 100644 --- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c +++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c @@ -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, }; -- 2.53.0