OSDN Git Service

Bluetooth: btusb: Record debug log for Mediatek Chip.
authormark-yw.chen <mark-yw.chen@mediatek.com>
Wed, 4 Aug 2021 09:03:15 +0000 (17:03 +0800)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 4 Aug 2021 14:48:08 +0000 (16:48 +0200)
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>
drivers/bluetooth/btusb.c

index b1a05bb..115c011 100644 (file)
@@ -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) {