Skip to content

Commit 2840143

Browse files
Christian A. Ehrhardtgregkh
authored andcommitted
usb: ucsi_acpi: Fix command completion handling
In case of a spurious or otherwise delayed notification it is possible that CCI still reports the previous completion. The UCSI spec is aware of this and provides two completion bits in CCI, one for normal commands and one for acks. As acks and commands alternate the notification handler can determine if the completion bit is from the current command. The initial UCSI code correctly handled this but the distinction between the two completion bits was lost with the introduction of the new API. To fix this revive the ACK_PENDING bit for ucsi_acpi and only complete commands if the completion bit matches. Fixes: f56de27 ("usb: typec: ucsi: acpi: Move to the new API") Cc: stable@vger.kernel.org Signed-off-by: "Christian A. Ehrhardt" <lk@c--e.de> Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20240121204123.275441-3-lk@c--e.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c9aed03 commit 2840143

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

drivers/usb/typec/ucsi/ucsi_acpi.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,13 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
7373
const void *val, size_t val_len)
7474
{
7575
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
76+
bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI;
7677
int ret;
7778

78-
set_bit(COMMAND_PENDING, &ua->flags);
79+
if (ack)
80+
set_bit(ACK_PENDING, &ua->flags);
81+
else
82+
set_bit(COMMAND_PENDING, &ua->flags);
7983

8084
ret = ucsi_acpi_async_write(ucsi, offset, val, val_len);
8185
if (ret)
@@ -85,7 +89,10 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
8589
ret = -ETIMEDOUT;
8690

8791
out_clear_bit:
88-
clear_bit(COMMAND_PENDING, &ua->flags);
92+
if (ack)
93+
clear_bit(ACK_PENDING, &ua->flags);
94+
else
95+
clear_bit(COMMAND_PENDING, &ua->flags);
8996

9097
return ret;
9198
}
@@ -142,8 +149,10 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
142149
if (UCSI_CCI_CONNECTOR(cci))
143150
ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci));
144151

145-
if (test_bit(COMMAND_PENDING, &ua->flags) &&
146-
cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
152+
if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags))
153+
complete(&ua->complete);
154+
if (cci & UCSI_CCI_COMMAND_COMPLETE &&
155+
test_bit(COMMAND_PENDING, &ua->flags))
147156
complete(&ua->complete);
148157
}
149158

0 commit comments

Comments
 (0)