Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 7c5c987

Browse files
Christian A. EhrhardtCarlos Llamas
authored andcommitted
UPSTREAM: acpi: typec: ucsi: Introduce a ->poll_cci method
commit 976e7e9 upstream. For the ACPI backend of UCSI the UCSI "registers" are just a memory copy of the register values in an opregion. The ACPI implementation in the BIOS ensures that the opregion contents are synced to the embedded controller and it ensures that the registers (in particular CCI) are synced back to the opregion on notifications. While there is an ACPI call that syncs the actual registers to the opregion there is rarely a need to do this and on some ACPI implementations it actually breaks in various interesting ways. The only reason to force a sync from the embedded controller is to poll CCI while notifications are disabled. Only the ucsi core knows if this is the case and guessing based on the current command is suboptimal, i.e. leading to the following spurious assertion splat: WARNING: CPU: 3 PID: 76 at drivers/usb/typec/ucsi/ucsi.c:1388 ucsi_reset_ppm+0x1b4/0x1c0 [typec_ucsi] CPU: 3 UID: 0 PID: 76 Comm: kworker/3:0 Not tainted 6.12.11-200.fc41.x86_64 #1 Hardware name: LENOVO 21D0/LNVNB161216, BIOS J6CN45WW 03/17/2023 Workqueue: events_long ucsi_init_work [typec_ucsi] RIP: 0010:ucsi_reset_ppm+0x1b4/0x1c0 [typec_ucsi] Call Trace: <TASK> ucsi_init_work+0x3c/0xac0 [typec_ucsi] process_one_work+0x179/0x330 worker_thread+0x252/0x390 kthread+0xd2/0x100 ret_from_fork+0x34/0x50 ret_from_fork_asm+0x1a/0x30 </TASK> Thus introduce a ->poll_cci() method that works like ->read_cci() with an additional forced sync and document that this should be used when polling with notifications disabled. For all other backends that presumably don't have this issue use the same implementation for both methods. Fixes: fa48d7e ("usb: typec: ucsi: Do not call ACPI _DSM method for UCSI read operations") Cc: stable <stable@kernel.org> Change-Id: I449bd10cdc230843cef3f4b3056725181910ce5b Signed-off-by: Christian A. Ehrhardt <lk@c--e.de> Tested-by: Fedor Pchelkin <boddah8794@gmail.com> Signed-off-by: Fedor Pchelkin <boddah8794@gmail.com> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20250217105442.113486-2-boddah8794@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 012b98c) Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
1 parent cf4c97d commit 7c5c987

File tree

7 files changed

+25
-12
lines changed

7 files changed

+25
-12
lines changed

drivers/usb/typec/ucsi/ucsi.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,7 +1330,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)
13301330

13311331
mutex_lock(&ucsi->ppm_lock);
13321332

1333-
ret = ucsi->ops->read_cci(ucsi, &cci);
1333+
ret = ucsi->ops->poll_cci(ucsi, &cci);
13341334
if (ret < 0)
13351335
goto out;
13361336

@@ -1348,7 +1348,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)
13481348

13491349
tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS);
13501350
do {
1351-
ret = ucsi->ops->read_cci(ucsi, &cci);
1351+
ret = ucsi->ops->poll_cci(ucsi, &cci);
13521352
if (ret < 0)
13531353
goto out;
13541354
if (cci & UCSI_CCI_COMMAND_COMPLETE)
@@ -1377,7 +1377,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)
13771377
/* Give the PPM time to process a reset before reading CCI */
13781378
msleep(20);
13791379

1380-
ret = ucsi->ops->read_cci(ucsi, &cci);
1380+
ret = ucsi->ops->poll_cci(ucsi, &cci);
13811381
if (ret)
13821382
goto out;
13831383

@@ -1913,8 +1913,8 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops)
19131913
struct ucsi *ucsi;
19141914

19151915
if (!ops ||
1916-
!ops->read_version || !ops->read_cci || !ops->read_message_in ||
1917-
!ops->sync_control || !ops->async_control)
1916+
!ops->read_version || !ops->read_cci || !ops->poll_cci ||
1917+
!ops->read_message_in || !ops->sync_control || !ops->async_control)
19181918
return ERR_PTR(-EINVAL);
19191919

19201920
ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL);

drivers/usb/typec/ucsi/ucsi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct dentry;
6060
* struct ucsi_operations - UCSI I/O operations
6161
* @read_version: Read implemented UCSI version
6262
* @read_cci: Read CCI register
63+
* @poll_cci: Read CCI register while polling with notifications disabled
6364
* @read_message_in: Read message data from UCSI
6465
* @sync_control: Blocking control operation
6566
* @async_control: Non-blocking control operation
@@ -74,6 +75,7 @@ struct dentry;
7475
struct ucsi_operations {
7576
int (*read_version)(struct ucsi *ucsi, u16 *version);
7677
int (*read_cci)(struct ucsi *ucsi, u32 *cci);
78+
int (*poll_cci)(struct ucsi *ucsi, u32 *cci);
7779
int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len);
7880
int (*sync_control)(struct ucsi *ucsi, u64 command);
7981
int (*async_control)(struct ucsi *ucsi, u64 command);

drivers/usb/typec/ucsi/ucsi_acpi.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,24 @@ static int ucsi_acpi_read_version(struct ucsi *ucsi, u16 *version)
5959
static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci)
6060
{
6161
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
62-
int ret;
63-
64-
if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) {
65-
ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
66-
if (ret)
67-
return ret;
68-
}
6962

7063
memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci));
7164

7265
return 0;
7366
}
7467

68+
static int ucsi_acpi_poll_cci(struct ucsi *ucsi, u32 *cci)
69+
{
70+
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
71+
int ret;
72+
73+
ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
74+
if (ret)
75+
return ret;
76+
77+
return ucsi_acpi_read_cci(ucsi, cci);
78+
}
79+
7580
static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
7681
{
7782
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
@@ -94,6 +99,7 @@ static int ucsi_acpi_async_control(struct ucsi *ucsi, u64 command)
9499
static const struct ucsi_operations ucsi_acpi_ops = {
95100
.read_version = ucsi_acpi_read_version,
96101
.read_cci = ucsi_acpi_read_cci,
102+
.poll_cci = ucsi_acpi_poll_cci,
97103
.read_message_in = ucsi_acpi_read_message_in,
98104
.sync_control = ucsi_sync_control_common,
99105
.async_control = ucsi_acpi_async_control
@@ -145,6 +151,7 @@ static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command)
145151
static const struct ucsi_operations ucsi_gram_ops = {
146152
.read_version = ucsi_acpi_read_version,
147153
.read_cci = ucsi_acpi_read_cci,
154+
.poll_cci = ucsi_acpi_poll_cci,
148155
.read_message_in = ucsi_gram_read_message_in,
149156
.sync_control = ucsi_gram_sync_control,
150157
.async_control = ucsi_acpi_async_control

drivers/usb/typec/ucsi/ucsi_ccg.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command)
664664
static const struct ucsi_operations ucsi_ccg_ops = {
665665
.read_version = ucsi_ccg_read_version,
666666
.read_cci = ucsi_ccg_read_cci,
667+
.poll_cci = ucsi_ccg_read_cci,
667668
.read_message_in = ucsi_ccg_read_message_in,
668669
.sync_control = ucsi_ccg_sync_control,
669670
.async_control = ucsi_ccg_async_control,

drivers/usb/typec/ucsi/ucsi_glink.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
201201
static const struct ucsi_operations pmic_glink_ucsi_ops = {
202202
.read_version = pmic_glink_ucsi_read_version,
203203
.read_cci = pmic_glink_ucsi_read_cci,
204+
.poll_cci = pmic_glink_ucsi_read_cci,
204205
.read_message_in = pmic_glink_ucsi_read_message_in,
205206
.sync_control = ucsi_sync_control_common,
206207
.async_control = pmic_glink_ucsi_async_control,

drivers/usb/typec/ucsi/ucsi_stm32g0.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data)
424424
static const struct ucsi_operations ucsi_stm32g0_ops = {
425425
.read_version = ucsi_stm32g0_read_version,
426426
.read_cci = ucsi_stm32g0_read_cci,
427+
.poll_cci = ucsi_stm32g0_read_cci,
427428
.read_message_in = ucsi_stm32g0_read_message_in,
428429
.sync_control = ucsi_sync_control_common,
429430
.async_control = ucsi_stm32g0_async_control,

drivers/usb/typec/ucsi/ucsi_yoga_c630.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ static int yoga_c630_ucsi_async_control(struct ucsi *ucsi, u64 command)
7474
const struct ucsi_operations yoga_c630_ucsi_ops = {
7575
.read_version = yoga_c630_ucsi_read_version,
7676
.read_cci = yoga_c630_ucsi_read_cci,
77+
.poll_cci = yoga_c630_ucsi_read_cci,
7778
.read_message_in = yoga_c630_ucsi_read_message_in,
7879
.sync_control = ucsi_sync_control_common,
7980
.async_control = yoga_c630_ucsi_async_control,

0 commit comments

Comments
 (0)