summaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorQiqi Zhang <eddy.zhang@rock-chips.com>2023-04-04 10:27:11 +0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2023-04-23 22:00:04 -0700
commit3c0d41f141c97e516d986f0571b0d7a745a4e2a8 (patch)
tree115ce9d4ff759db3f134a048fd522646ad697af9 /drivers/bluetooth
parent288c90224eec55d13e786844b7954ef060752089 (diff)
downloadlinux-stable-3c0d41f141c97e516d986f0571b0d7a745a4e2a8.tar.gz
linux-stable-3c0d41f141c97e516d986f0571b0d7a745a4e2a8.tar.bz2
linux-stable-3c0d41f141c97e516d986f0571b0d7a745a4e2a8.zip
Bluetooth: hci_h5: Complements reliable packet processing logic
As shown in the schematic diagram below.There may be a critical scenario in the current code. If the device does not receive an pure ack sent by the host due to insufficient receive buffer or other reasons and triggers a retransmission, the host will always be in an 'out-of-order' state.The state machine will get stuck. host device SEQ3,ACK4 ---------> <--------- SEQ4,ACK4 pure ACK ---------> (not received) (out-of-order) <--------- SEQ4,ACK4(retransmission) ........ (out-of-order) <--------- SEQ4,ACK4(retransmission) According to the description in the core specification: "whenever a reliable packet is received, an acknowledgment shall be generated." So set H5_TX_ACK_REQ bit to trigger retransmission of pure ack packet when "out-of-order" occurs. Signed-off-by: Qiqi Zhang <eddy.zhang@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/hci_h5.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index e90670955df2..fefc37b98b4a 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -463,6 +463,8 @@ static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c)
if (H5_HDR_RELIABLE(hdr) && H5_HDR_SEQ(hdr) != h5->tx_ack) {
bt_dev_err(hu->hdev, "Out-of-order packet arrived (%u != %u)",
H5_HDR_SEQ(hdr), h5->tx_ack);
+ set_bit(H5_TX_ACK_REQ, &h5->flags);
+ hci_uart_tx_wakeup(hu);
h5_reset_rx(h5);
return 0;
}