Skip to content

Commit d9a477f

Browse files
qzedjwrdegoede
authored andcommitted
platform/surface: aggregator: Do not check for repeated unsequenced packets
Currently, we check any received packet whether we have already seen it previously, regardless of the packet type (sequenced / unsequenced). We do this by checking the sequence number. This assumes that sequence numbers are valid for both sequenced and unsequenced packets. However, this assumption appears to be incorrect. On some devices, the sequence number field of unsequenced packets (in particular HID input events on the Surface Pro 9) is always zero. As a result, the current retransmission check kicks in and discards all but the first unsequenced packet, breaking (among other things) keyboard and touchpad input. Note that we have, so far, only seen packets being retransmitted in sequenced communication. In particular, this happens when there is an ACK timeout, causing the EC (or us) to re-send the packet waiting for an ACK. Arguably, retransmission / duplication of unsequenced packets should not be an issue as there is no logical condition (such as an ACK timeout) to determine when a packet should be sent again. Therefore, remove the retransmission check for unsequenced packets entirely to resolve the issue. Fixes: c167b9c ("platform/surface: Add Surface Aggregator subsystem") Signed-off-by: Maximilian Luz <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Hans de Goede <[email protected]> Signed-off-by: Hans de Goede <[email protected]>
1 parent 1e817b8 commit d9a477f

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

drivers/platform/surface/aggregator/ssh_packet_layer.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,24 +1596,40 @@ static void ssh_ptl_timeout_reap(struct work_struct *work)
15961596
ssh_ptl_tx_wakeup_packet(ptl);
15971597
}
15981598

1599-
static bool ssh_ptl_rx_retransmit_check(struct ssh_ptl *ptl, u8 seq)
1599+
static bool ssh_ptl_rx_retransmit_check(struct ssh_ptl *ptl, const struct ssh_frame *frame)
16001600
{
16011601
int i;
16021602

1603+
/*
1604+
* Ignore unsequenced packets. On some devices (notably Surface Pro 9),
1605+
* unsequenced events will always be sent with SEQ=0x00. Attempting to
1606+
* detect retransmission would thus just block all events.
1607+
*
1608+
* While sequence numbers would also allow detection of retransmitted
1609+
* packets in unsequenced communication, they have only ever been used
1610+
* to cover edge-cases in sequenced transmission. In particular, the
1611+
* only instance of packets being retransmitted (that we are aware of)
1612+
* is due to an ACK timeout. As this does not happen in unsequenced
1613+
* communication, skip the retransmission check for those packets
1614+
* entirely.
1615+
*/
1616+
if (frame->type == SSH_FRAME_TYPE_DATA_NSQ)
1617+
return false;
1618+
16031619
/*
16041620
* Check if SEQ has been seen recently (i.e. packet was
16051621
* re-transmitted and we should ignore it).
16061622
*/
16071623
for (i = 0; i < ARRAY_SIZE(ptl->rx.blocked.seqs); i++) {
1608-
if (likely(ptl->rx.blocked.seqs[i] != seq))
1624+
if (likely(ptl->rx.blocked.seqs[i] != frame->seq))
16091625
continue;
16101626

16111627
ptl_dbg(ptl, "ptl: ignoring repeated data packet\n");
16121628
return true;
16131629
}
16141630

16151631
/* Update list of blocked sequence IDs. */
1616-
ptl->rx.blocked.seqs[ptl->rx.blocked.offset] = seq;
1632+
ptl->rx.blocked.seqs[ptl->rx.blocked.offset] = frame->seq;
16171633
ptl->rx.blocked.offset = (ptl->rx.blocked.offset + 1)
16181634
% ARRAY_SIZE(ptl->rx.blocked.seqs);
16191635

@@ -1624,7 +1640,7 @@ static void ssh_ptl_rx_dataframe(struct ssh_ptl *ptl,
16241640
const struct ssh_frame *frame,
16251641
const struct ssam_span *payload)
16261642
{
1627-
if (ssh_ptl_rx_retransmit_check(ptl, frame->seq))
1643+
if (ssh_ptl_rx_retransmit_check(ptl, frame))
16281644
return;
16291645

16301646
ptl->ops.data_received(ptl, payload);

0 commit comments

Comments
 (0)