summaryrefslogtreecommitdiff
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authormark-yw.chen <mark-yw.chen@mediatek.com>2021-08-04 12:03:15 +0300
committerMarcel Holtmann <marcel@holtmann.org>2021-08-04 17:48:08 +0300
commit0b10c8c84c0c78ba4456bdbeb8a5b6ee58f47e39 (patch)
tree5b3f4a9c04483c96fee9ccbe12dc2ab7e3572bee /drivers/bluetooth
parent67cbdd74c4cba378a715003923fc418a10349fae (diff)
downloadlinux-0b10c8c84c0c78ba4456bdbeb8a5b6ee58f47e39.tar.xz
Bluetooth: btusb: Record debug log for Mediatek Chip.
Mediatek Bluetooth controller sends the FW log and FW dump via EP2. This patch creates an MTK specified callback(btusb_recv_acl_mtk) to replace the original one (hci_recv_frame) when an MTK controller is detected. The new callback will separate the firmware dump traffics from the ACL data to have them process separately. 1. Add a new field (recv_acl) to the btusb_data struct to store vendor-specific ACL callback handler. 2. Add the MTK-specific ACL callback handler (btusb_recv_acl_mtk) to process ACL data, debug log, and firmware dump. 3. The debug log traces LMP/LL events and connection quality reports. 4. The upper layer can use hci_channel_monitor to receive these packets. Example btmon: firmware debug log. 1. Enable firmware debug log. < HCI Command: Vendor (0x3f|0x005d) plen 4 00 00 02 02 .... > HCI Event: Command Complete (0x0e) plen 8 Vendor (0x3f|0x005d) ncmd 1 Status: Success (0x00) 00 00 02 02 .... 2. Diagnostic packet from controller = Vendor Diagnostic (len 500) ff 05 f0 01 fd ff 02 0e 08 01 5d fc 00 00 00 02 02 aa aa aa cb e3 f0 15 b0 0c 5f 01 00 d1 0f 33 01 7f 00 08 57 61 0c 00 00 00 00 00 23 37 17 00 fd ff 00 00 29 60 ff ff b1 56 e8 00 57 40 0a 40 39 95 f2 00 47 40 43 00 fc f0 16 00 57 61 0c 00 00 00 00 00 23 37 17 00 fd ff 00 00 29 60 ff ff 65 95 f2 00 57 40 0a 40 ec d3 fc 00 47 40 3b 00 2c f1 17 00 57 61 0c 00 00 00 00 00 23 37 17 00 fd ff 00 00 29 60 ff ff 19 d4 fc 00 57 40 76 1c b2 61 01 01 47 40 b3 04 0b 63 18 00 fe ff 02 01 04 05 33 8b 9e 08 00 aa aa aa aa aa 27 38 01 02 01 00 00 00 02 e0 10 00 20 00 20 00 2a 08 40 00 20 00 20 08 2a 08 02 00 40 00 00 01 2e 08 40 00 01 67 b0 c2 2e 08 3e 07 ff ff ff ff 40 08 01 00 02 00 00 00 34 08 a3 00 00 00 00 00 34 08 a3 00 00 00 00 00 35 08 45 01 00 00 00 00 2e 08 40 00 01 67 b0 c2 30 35 01 02 00 00 00 00 2c 31 01 00 02 00 00 40 2d 19 03 00 00 40 00 00 fd ff 02 0f 04 00 01 01 04 aa aa aa aa aa aa aa 57 61 0c 00 00 00 00 00 23 46 32 00 01 00 00 00 2f 35 00 02 00 00 00 00 29 35 ff 02 00 22 00 00 2d 31 a6 02 02 00 00 00 31 6c 40 00 14 63 18 1b 31 6c 40 00 14 63 18 23 51 08 53 00 12 63 18 00 2c 35 12 01 fe 00 00 00 2b 35 fe 02 02 00 00 00 2f 31 21 00 00 00 02 00 75 61 01 00 4c 1b 93 00 79 61 01 00 00 00 00 00 12 e3 63 18 20 31 86 01 74 61 68 03 00 00 04 00 a1 73 ff 00 b9 01 00 00 a1 73 04 00 00 00 00 00 a1 73 00 00 00 00 00 00 a1 73 00 00 02 00 00 00 31 6c 40 00 16 63 18 0c 31 6c 40 00 16 63 18 1c 77 61 40 00 48 33 40 00 14 e3 63 18 40 31 86 01 00 d1 02 c5 07 23 a1 34 73 61 37 02 02 00 00 a1 Signed-off-by: mark-yw.chen <mark-yw.chen@mediatek.com> Reviewed-by: Michael Sun <michaelfsun@google.com> Reviewed-by: Archie Pusaka <apusaka@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/btusb.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index b1a05bb9f4bf..115c01150c02 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -585,6 +585,7 @@ struct btusb_data {
int suspend_count;
int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
+ int (*recv_acl)(struct hci_dev *hdev, struct sk_buff *skb);
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
int (*setup_on_usb)(struct hci_dev *hdev);
@@ -792,7 +793,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
if (!hci_skb_expect(skb)) {
/* Complete frame */
- hci_recv_frame(data->hdev, skb);
+ data->recv_acl(data->hdev, skb);
skb = NULL;
}
}
@@ -3887,6 +3888,25 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)
return 0;
}
+static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
+
+ switch (handle) {
+ case 0xfc6f: /* Firmware dump from device */
+ /* When the firmware hangs, the device can no longer
+ * suspend and thus disable auto-suspend.
+ */
+ usb_disable_autosuspend(data->udev);
+ case 0x05ff: /* Firmware debug logging 1 */
+ case 0x05fe: /* Firmware debug logging 2 */
+ return hci_recv_diag(hdev, skb);
+ }
+
+ return hci_recv_frame(hdev, skb);
+}
+
MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668);
@@ -4590,6 +4610,8 @@ static int btusb_probe(struct usb_interface *intf,
data->recv_bulk = btusb_recv_bulk;
}
+ data->recv_acl = hci_recv_frame;
+
hdev = hci_alloc_dev();
if (!hdev)
return -ENOMEM;
@@ -4717,6 +4739,7 @@ static int btusb_probe(struct usb_interface *intf,
hdev->shutdown = btusb_mtk_shutdown;
hdev->manufacturer = 70;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
+ data->recv_acl = btusb_recv_acl_mtk;
}
if (id->driver_info & BTUSB_SWAVE) {