Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: hci_core: Detect if an ISO link has stalled

This attempts to detect if an ISO link has been waiting for an ISO
buffer for longer than the maximum allowed transport latency then
proceed to use hci_link_tx_to which prints an error and disconnects.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

+28 -8
+1
include/net/bluetooth/hci.h
··· 488 488 #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ 489 489 #define HCI_ACL_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */ 490 490 #define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */ 491 + #define HCI_ISO_TX_TIMEOUT usecs_to_jiffies(0x7fffff) /* 8388607 usecs */ 491 492 492 493 /* HCI data types */ 493 494 #define HCI_COMMAND_PKT 0x01
+1
include/net/bluetooth/hci_core.h
··· 487 487 488 488 unsigned long acl_last_tx; 489 489 unsigned long le_last_tx; 490 + unsigned long iso_last_tx; 490 491 491 492 __u8 le_tx_def_phys; 492 493 __u8 le_rx_def_phys;
+26 -8
net/bluetooth/hci_core.c
··· 3585 3585 3586 3586 static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type) 3587 3587 { 3588 - unsigned long last_tx; 3588 + unsigned long timeout; 3589 3589 3590 3590 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 3591 3591 return; 3592 3592 3593 3593 switch (type) { 3594 + case ACL_LINK: 3595 + /* tx timeout must be longer than maximum link supervision 3596 + * timeout (40.9 seconds) 3597 + */ 3598 + timeout = hdev->acl_last_tx + HCI_ACL_TX_TIMEOUT; 3599 + break; 3594 3600 case LE_LINK: 3595 - last_tx = hdev->le_last_tx; 3601 + /* tx timeout must be longer than maximum link supervision 3602 + * timeout (40.9 seconds) 3603 + */ 3604 + timeout = hdev->le_last_tx + HCI_ACL_TX_TIMEOUT; 3605 + break; 3606 + case CIS_LINK: 3607 + case BIS_LINK: 3608 + case PA_LINK: 3609 + /* tx timeout must be longer than the maximum transport latency 3610 + * (8.388607 seconds) 3611 + */ 3612 + timeout = hdev->iso_last_tx + HCI_ISO_TX_TIMEOUT; 3596 3613 break; 3597 3614 default: 3598 - last_tx = hdev->acl_last_tx; 3599 - break; 3615 + return; 3600 3616 } 3601 3617 3602 - /* tx timeout must be longer than maximum link supervision timeout 3603 - * (40.9 seconds) 3604 - */ 3605 - if (!cnt && time_after(jiffies, last_tx + HCI_ACL_TX_TIMEOUT)) 3618 + if (!cnt && time_after(jiffies, timeout)) 3606 3619 hci_link_tx_to(hdev, type); 3607 3620 } 3608 3621 ··· 3772 3759 return; 3773 3760 3774 3761 cnt = &hdev->iso_cnt; 3762 + 3763 + __check_timeout(hdev, *cnt, type); 3764 + 3775 3765 while (*cnt && (conn = hci_low_sent(hdev, type, &quote))) { 3776 3766 while (quote-- && (skb = skb_dequeue(&conn->data_q))) { 3777 3767 BT_DBG("skb %p len %d", skb, skb->len); 3768 + 3778 3769 hci_send_conn_frame(hdev, conn, skb); 3770 + hdev->iso_last_tx = jiffies; 3779 3771 3780 3772 conn->sent++; 3781 3773 if (conn->sent == ~0)