2023-05-12 21:26:18

by Sean Wang

[permalink] [raw]
Subject: [PATCH v6 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding

From: Sean Wang <[email protected]>

Use readx_poll_timeout instead of open coding to poll the hardware reset
status until it is done.

Signed-off-by: Sean Wang <[email protected]>
---
v2: use 20ms as the unit to poll according to the requirement of
readx_poll_timeout
v3: refine btusb_mtk_reset_done and drop the necessary error check
in btusb_mtk_cmd_timeout
v4, v5, v6: rebase onto the latest codebase
---
drivers/bluetooth/btusb.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2a8e2bb038f5..275e0666503d 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2566,8 +2566,6 @@ static int btusb_setup_realtek(struct hci_dev *hdev)
#define MTK_EP_RST_OPT 0x74011890
#define MTK_EP_RST_IN_OUT_OPT 0x00010001
#define MTK_BT_RST_DONE 0x00000100
-#define MTK_BT_RESET_WAIT_MS 100
-#define MTK_BT_RESET_NUM_TRIES 10

static void btusb_mtk_wmt_recv(struct urb *urb)
{
@@ -2938,6 +2936,16 @@ static int btusb_mtk_id_get(struct btusb_data *data, u32 reg, u32 *id)
return btusb_mtk_reg_read(data, reg, id);
}

+static u32 btusb_mtk_reset_done(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ u32 val = 0;
+
+ btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
+
+ return val & MTK_BT_RST_DONE;
+}
+
static int btusb_mtk_setup(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -3127,7 +3135,7 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
u32 val;
- int err, retry = 0;
+ int err;

/* It's MediaTek specific bluetooth reset mechanism via USB */
if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
@@ -3158,18 +3166,10 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);

- /* Poll the register until reset is completed */
- do {
- btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
- if (val & MTK_BT_RST_DONE) {
- bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
- break;
- }
-
- bt_dev_dbg(hdev, "Polling Bluetooth Reset CR");
- retry++;
- msleep(MTK_BT_RESET_WAIT_MS);
- } while (retry < MTK_BT_RESET_NUM_TRIES);
+ err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
+ val & MTK_BT_RST_DONE, 20000, 1000000);
+ if (err < 0)
+ bt_dev_err(hdev, "Reset timeout");

btusb_mtk_id_get(data, 0x70010200, &val);
if (!val)
--
2.25.1



2023-05-12 21:26:20

by Sean Wang

[permalink] [raw]
Subject: [PATCH v6 2/3] Bluetooth: btmtk: introduce btmtk reset work

From: Jing Cai <[email protected]>

Introduce btmtk_reset_work which can be called whenever the firmware abort,
HCI command timeout, other fatal error happen.

Co-developed-by: Chris Lu <[email protected]>
Signed-off-by: Chris Lu <[email protected]>
Co-developed-by: Sean Wang <[email protected]>
Signed-off-by: Sean Wang <[email protected]>
Signed-off-by: Jing Cai <[email protected]>
---
v2, v3, v4: rebase onto the latest codebase
v5: reset the device on hdev basis and use hci_cmd_sync_queue to
schedule reset work
v6: rebase onto the latest codebase
---
drivers/bluetooth/btmtk.c | 15 ++++++
drivers/bluetooth/btmtk.h | 11 ++++
drivers/bluetooth/btusb.c | 108 ++++++++++++++++++++------------------
3 files changed, 84 insertions(+), 50 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 809762d64fc6..ac2fac7e3c5f 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -280,6 +280,21 @@ int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);

+void btmtk_reset_sync(struct hci_dev *hdev)
+{
+ struct btmtk_data *reset_work = hci_get_priv(hdev);
+ int err;
+
+ hci_dev_lock(hdev);
+
+ err = hci_cmd_sync_queue(hdev, reset_work->reset_sync, NULL, NULL);
+ if (err)
+ bt_dev_err(hdev, "failed to reset (%d)", err);
+
+ hci_dev_unlock(hdev);
+}
+EXPORT_SYMBOL_GPL(btmtk_reset_sync);
+
MODULE_AUTHOR("Sean Wang <[email protected]>");
MODULE_AUTHOR("Mark Chen <[email protected]>");
MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index 2a88ea8e475e..6245662f6ccb 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -122,6 +122,12 @@ struct btmtk_hci_wmt_params {
typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
struct btmtk_hci_wmt_params *);

+typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
+
+struct btmtk_data {
+ btmtk_reset_sync_func_t reset_sync;
+};
+
#if IS_ENABLED(CONFIG_BT_MTK)

int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
@@ -131,6 +137,8 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,

int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
wmt_cmd_sync_func_t wmt_cmd_sync);
+
+void btmtk_reset_sync(struct hci_dev *hdev);
#else

static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -151,4 +159,7 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
return -EOPNOTSUPP;
}

+static void btmtk_reset_sync(struct hci_dev *hdev)
+{
+}
#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 275e0666503d..034edd8ad777 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2946,8 +2946,60 @@ static u32 btusb_mtk_reset_done(struct hci_dev *hdev)
return val & MTK_BT_RST_DONE;
}

+static int btusb_mtk_reset_work(struct hci_dev *hdev, void *rst_data)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ u32 val;
+ int err;
+
+ /* It's MediaTek specific bluetooth reset mechanism via USB */
+ if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
+ bt_dev_err(hdev, "last reset failed? Not resetting again");
+ return -EBUSY;
+ }
+
+ err = usb_autopm_get_interface(data->intf);
+ if (err < 0)
+ return err;
+
+ btusb_stop_traffic(data);
+ usb_kill_anchored_urbs(&data->tx_anchor);
+
+ /* It's Device EndPoint Reset Option Register */
+ bt_dev_dbg(hdev, "Initiating reset mechanism via uhw");
+ btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
+ btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val);
+
+ /* Reset the bluetooth chip via USB interface. */
+ btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1);
+ btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
+ btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
+ btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
+ btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
+ /* MT7921 need to delay 20ms between toggle reset bit */
+ msleep(20);
+ btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
+ btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
+
+ err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
+ val & MTK_BT_RST_DONE, 20000, 1000000);
+ if (err < 0)
+ bt_dev_err(hdev, "Reset timeout");
+
+ btusb_mtk_id_get(data, 0x70010200, &val);
+ if (!val)
+ bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
+
+ usb_queue_reset_device(data->intf);
+
+ clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
+
+ return err;
+}
+
static int btusb_mtk_setup(struct hci_dev *hdev)
{
+ struct btmtk_data *btmtk_data = hci_get_priv(hdev);
struct btusb_data *data = hci_get_drvdata(hdev);
struct btmtk_hci_wmt_params wmt_params;
ktime_t calltime, delta, rettime;
@@ -2982,6 +3034,8 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
}
}

+ btmtk_data->reset_sync = btusb_mtk_reset_work;
+
switch (dev_id) {
case 0x7663:
fwname = FIRMWARE_MT7663;
@@ -3131,55 +3185,6 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)
return 0;
}

-static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
-{
- struct btusb_data *data = hci_get_drvdata(hdev);
- u32 val;
- int err;
-
- /* It's MediaTek specific bluetooth reset mechanism via USB */
- if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
- bt_dev_err(hdev, "last reset failed? Not resetting again");
- return;
- }
-
- err = usb_autopm_get_interface(data->intf);
- if (err < 0)
- return;
-
- btusb_stop_traffic(data);
- usb_kill_anchored_urbs(&data->tx_anchor);
-
- /* It's Device EndPoint Reset Option Register */
- bt_dev_dbg(hdev, "Initiating reset mechanism via uhw");
- btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
- btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val);
-
- /* Reset the bluetooth chip via USB interface. */
- btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1);
- btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
- btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
- btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
- btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
- /* MT7921 need to delay 20ms between toggle reset bit */
- msleep(20);
- btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
- btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
-
- err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
- val & MTK_BT_RST_DONE, 20000, 1000000);
- if (err < 0)
- bt_dev_err(hdev, "Reset timeout");
-
- btusb_mtk_id_get(data, 0x70010200, &val);
- if (!val)
- bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
-
- usb_queue_reset_device(data->intf);
-
- clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
-}
-
static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -4195,6 +4200,9 @@ static int btusb_probe(struct usb_interface *intf,
} else if (id->driver_info & BTUSB_REALTEK) {
/* Allocate extra space for Realtek device */
priv_size += sizeof(struct btrealtek_data);
+ } else if (id->driver_info & BTUSB_MEDIATEK) {
+ /* Allocate extra space for Mediatek device */
+ priv_size += sizeof(struct btmtk_data);
}

data->recv_acl = hci_recv_frame;
@@ -4301,7 +4309,7 @@ static int btusb_probe(struct usb_interface *intf,
hdev->setup = btusb_mtk_setup;
hdev->shutdown = btusb_mtk_shutdown;
hdev->manufacturer = 70;
- hdev->cmd_timeout = btusb_mtk_cmd_timeout;
+ hdev->cmd_timeout = btmtk_reset_sync;
hdev->set_bdaddr = btmtk_set_bdaddr;
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
--
2.25.1


2023-05-12 21:26:32

by Sean Wang

[permalink] [raw]
Subject: [PATCH v6 3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support

From: Jing Cai <[email protected]>

This patch implement function .coredump() and dmp_hdr() in btusb
driver for MediaTek controller. FW core dump was triggered by FW
specific event to show something unexpected happened in the controller.

The driver would be responsible for collecting and uploading the device
core dump pieces in hci driver using core dump API. Once we finished
the whole process, the driver would reset the controller to recover the
kind of fatal error.

Co-developed-by: Chris Lu <[email protected]>
Signed-off-by: Chris Lu <[email protected]>
Co-developed-by: Sean Wang <[email protected]>
Signed-off-by: Sean Wang <[email protected]>
Signed-off-by: Jing Cai <[email protected]>
---
v2, v3: rebase onto the latest codebase
v4: update the newest API usage for the coredump which was already
into the upstream
v5: support devcoredump on hdev basis
v6: reuse the coredump state HCI_DEVCOREDUMP_* in driver
and drop the driver name copying
---
drivers/bluetooth/btmtk.c | 106 ++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/btmtk.h | 27 ++++++++++
drivers/bluetooth/btusb.c | 14 +++++
3 files changed, 147 insertions(+)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index ac2fac7e3c5f..60233afc0a9c 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -53,6 +53,56 @@ struct btmtk_section_map {
};
} __packed;

+static void btmtk_coredump(struct hci_dev *hdev)
+{
+ int err;
+
+ err = __hci_cmd_send(hdev, 0xfd5b, 0, NULL);
+ if (err < 0)
+ bt_dev_err(hdev, "Coredump failed (%d)", err);
+}
+
+static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct btmtk_data *data = hci_get_priv(hdev);
+ char buf[80];
+
+ snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
+ data->cd_info.dev_id);
+ skb_put_data(skb, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
+ data->cd_info.fw_version);
+ skb_put_data(skb, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "Driver: %s\n",
+ data->cd_info.driver_name);
+ skb_put_data(skb, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "Vendor: MediaTek\n");
+ skb_put_data(skb, buf, strlen(buf));
+}
+
+static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
+{
+ struct btmtk_data *data = hci_get_priv(hdev);
+
+ switch (state) {
+ case HCI_DEVCOREDUMP_IDLE:
+ data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
+ break;
+ case HCI_DEVCOREDUMP_ACTIVE:
+ data->cd_info.state = HCI_DEVCOREDUMP_ACTIVE;
+ break;
+ case HCI_DEVCOREDUMP_TIMEOUT:
+ case HCI_DEVCOREDUMP_ABORT:
+ case HCI_DEVCOREDUMP_DONE:
+ data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
+ btmtk_reset_sync(hdev);
+ break;
+ }
+}
+
int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
wmt_cmd_sync_func_t wmt_cmd_sync)
{
@@ -295,6 +345,62 @@ void btmtk_reset_sync(struct hci_dev *hdev)
}
EXPORT_SYMBOL_GPL(btmtk_reset_sync);

+int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id,
+ const char *name, u32 fw_version)
+{
+ struct btmtk_data *data = hci_get_priv(hdev);
+
+ if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
+ return -EOPNOTSUPP;
+
+ data->cd_info.dev_id = dev_id;
+ data->cd_info.fw_version = fw_version;
+ data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
+ data->cd_info.driver_name = name;
+
+ return hci_devcd_register(hdev, btmtk_coredump, btmtk_coredump_hdr,
+ btmtk_coredump_notify);
+}
+EXPORT_SYMBOL_GPL(btmtk_register_coredump);
+
+int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct btmtk_data *data = hci_get_priv(hdev);
+ int err;
+
+ if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
+ return 0;
+
+ switch (data->cd_info.state) {
+ case HCI_DEVCOREDUMP_IDLE:
+ err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
+ if (err < 0)
+ break;
+ /* It is supposed coredump can be done within 5 seconds */
+ schedule_delayed_work(&hdev->dump.dump_timeout,
+ msecs_to_jiffies(5000));
+ fallthrough;
+ case HCI_DEVCOREDUMP_ACTIVE:
+ default:
+ err = hci_devcd_append(hdev, skb);
+ if (err < 0)
+ break;
+
+ if (skb->len > 12 &&
+ !strncmp((char *)&skb->data[skb->len - 13],
+ MTK_COREDUMP_END, 12))
+ hci_devcd_complete(hdev);
+
+ break;
+ }
+
+ if (err < 0)
+ kfree_skb(skb);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(btmtk_process_coredump);
+
MODULE_AUTHOR("Sean Wang <[email protected]>");
MODULE_AUTHOR("Mark Chen <[email protected]>");
MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index 6245662f6ccb..852a67db8f80 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -21,6 +21,9 @@
#define MT7921_DLSTATUS 0x7c053c10
#define BT_DL_STATE BIT(1)

+#define MTK_COREDUMP_SIZE (1024 * 1000)
+#define MTK_COREDUMP_END "coredump end"
+
enum {
BTMTK_WMT_PATCH_DWNLD = 0x1,
BTMTK_WMT_TEST = 0x2,
@@ -119,12 +122,20 @@ struct btmtk_hci_wmt_params {
u32 *status;
};

+struct btmtk_coredump_info {
+ const char *driver_name;
+ u32 dev_id;
+ u32 fw_version;
+ int state;
+};
+
typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
struct btmtk_hci_wmt_params *);

typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);

struct btmtk_data {
+ struct btmtk_coredump_info cd_info;
btmtk_reset_sync_func_t reset_sync;
};

@@ -139,6 +150,11 @@ int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
wmt_cmd_sync_func_t wmt_cmd_sync);

void btmtk_reset_sync(struct hci_dev *hdev);
+
+int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id, const char *name,
+ u32 fw_version);
+
+int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);
#else

static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -162,4 +178,15 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
static void btmtk_reset_sync(struct hci_dev *hdev)
{
}
+
+static int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id, const char *name,
+ u32 fw_version)
+{
+ return -EOPNOTSUPP;
+}
+
+static int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ return -EOPNOTSUPP;
+}
#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 034edd8ad777..1c2a0cbcf62e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -3035,6 +3035,10 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
}

btmtk_data->reset_sync = btusb_mtk_reset_work;
+ err = btmtk_register_coredump(hdev, dev_id, btusb_driver.name,
+ fw_version);
+ if (err < 0)
+ bt_dev_err(hdev, "Failed to register coredump (%d)", err);

switch (dev_id) {
case 0x7663:
@@ -3189,6 +3193,7 @@ 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);
+ struct sk_buff *skb_cd;

switch (handle) {
case 0xfc6f: /* Firmware dump from device */
@@ -3196,6 +3201,15 @@ static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
* suspend and thus disable auto-suspend.
*/
usb_disable_autosuspend(data->udev);
+
+ /* We need to forward the diagnostic packet to userspace daemon
+ * for backward compatibility, so we have to clone the packet
+ * extraly for the in-kernel coredump support.
+ */
+ skb_cd = skb_clone(skb, GFP_ATOMIC);
+ if (skb_cd)
+ btmtk_process_coredump(hdev, skb_cd);
+
fallthrough;
case 0x05ff: /* Firmware debug logging 1 */
case 0x05fe: /* Firmware debug logging 2 */
--
2.25.1


2023-05-12 22:03:53

by bluez.test.bot

[permalink] [raw]
Subject: RE: [v6,1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=747196

---Test result---

Test Summary:
CheckPatch PASS 2.88 seconds
GitLint FAIL 1.28 seconds
SubjectPrefix PASS 0.40 seconds
BuildKernel PASS 31.29 seconds
CheckAllWarning PASS 34.79 seconds
CheckSparse PASS 39.03 seconds
CheckSmatch PASS 109.66 seconds
BuildKernel32 PASS 30.30 seconds
TestRunnerSetup PASS 435.28 seconds
TestRunner_l2cap-tester PASS 16.53 seconds
TestRunner_iso-tester PASS 20.11 seconds
TestRunner_bnep-tester PASS 5.27 seconds
TestRunner_mgmt-tester PASS 111.35 seconds
TestRunner_rfcomm-tester PASS 8.45 seconds
TestRunner_sco-tester PASS 7.84 seconds
TestRunner_ioctl-tester PASS 9.04 seconds
TestRunner_mesh-tester PASS 6.68 seconds
TestRunner_smp-tester PASS 7.75 seconds
TestRunner_userchan-tester PASS 5.53 seconds
IncrementalBuild PASS 40.26 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v6,1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
1: T1 Title exceeds max length (82>80): "[v6,1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding"


---
Regards,
Linux Bluetooth

2023-05-15 19:08:12

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH v6 3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support

Hi Sean,

On Fri, May 12, 2023 at 2:20 PM <[email protected]> wrote:
>
> From: Jing Cai <[email protected]>
>
> This patch implement function .coredump() and dmp_hdr() in btusb
> driver for MediaTek controller. FW core dump was triggered by FW
> specific event to show something unexpected happened in the controller.
>
> The driver would be responsible for collecting and uploading the device
> core dump pieces in hci driver using core dump API. Once we finished
> the whole process, the driver would reset the controller to recover the
> kind of fatal error.
>
> Co-developed-by: Chris Lu <[email protected]>
> Signed-off-by: Chris Lu <[email protected]>
> Co-developed-by: Sean Wang <[email protected]>
> Signed-off-by: Sean Wang <[email protected]>
> Signed-off-by: Jing Cai <[email protected]>
> ---
> v2, v3: rebase onto the latest codebase
> v4: update the newest API usage for the coredump which was already
> into the upstream
> v5: support devcoredump on hdev basis
> v6: reuse the coredump state HCI_DEVCOREDUMP_* in driver
> and drop the driver name copying
> ---
> drivers/bluetooth/btmtk.c | 106 ++++++++++++++++++++++++++++++++++++++
> drivers/bluetooth/btmtk.h | 27 ++++++++++
> drivers/bluetooth/btusb.c | 14 +++++
> 3 files changed, 147 insertions(+)
>
> diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
> index ac2fac7e3c5f..60233afc0a9c 100644
> --- a/drivers/bluetooth/btmtk.c
> +++ b/drivers/bluetooth/btmtk.c
> @@ -53,6 +53,56 @@ struct btmtk_section_map {
> };
> } __packed;
>
> +static void btmtk_coredump(struct hci_dev *hdev)
> +{
> + int err;
> +
> + err = __hci_cmd_send(hdev, 0xfd5b, 0, NULL);
> + if (err < 0)
> + bt_dev_err(hdev, "Coredump failed (%d)", err);
> +}
> +
> +static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> + struct btmtk_data *data = hci_get_priv(hdev);
> + char buf[80];
> +
> + snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
> + data->cd_info.dev_id);
> + skb_put_data(skb, buf, strlen(buf));
> +
> + snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
> + data->cd_info.fw_version);
> + skb_put_data(skb, buf, strlen(buf));
> +
> + snprintf(buf, sizeof(buf), "Driver: %s\n",
> + data->cd_info.driver_name);
> + skb_put_data(skb, buf, strlen(buf));
> +
> + snprintf(buf, sizeof(buf), "Vendor: MediaTek\n");
> + skb_put_data(skb, buf, strlen(buf));
> +}
> +
> +static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
> +{
> + struct btmtk_data *data = hci_get_priv(hdev);
> +
> + switch (state) {
> + case HCI_DEVCOREDUMP_IDLE:
> + data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
> + break;
> + case HCI_DEVCOREDUMP_ACTIVE:
> + data->cd_info.state = HCI_DEVCOREDUMP_ACTIVE;
> + break;
> + case HCI_DEVCOREDUMP_TIMEOUT:
> + case HCI_DEVCOREDUMP_ABORT:
> + case HCI_DEVCOREDUMP_DONE:
> + data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
> + btmtk_reset_sync(hdev);
> + break;
> + }
> +}
> +
> int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
> wmt_cmd_sync_func_t wmt_cmd_sync)
> {
> @@ -295,6 +345,62 @@ void btmtk_reset_sync(struct hci_dev *hdev)
> }
> EXPORT_SYMBOL_GPL(btmtk_reset_sync);
>
> +int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id,
> + const char *name, u32 fw_version)
> +{
> + struct btmtk_data *data = hci_get_priv(hdev);
> +
> + if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
> + return -EOPNOTSUPP;
> +
> + data->cd_info.dev_id = dev_id;
> + data->cd_info.fw_version = fw_version;
> + data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
> + data->cd_info.driver_name = name;
> +
> + return hci_devcd_register(hdev, btmtk_coredump, btmtk_coredump_hdr,
> + btmtk_coredump_notify);
> +}
> +EXPORT_SYMBOL_GPL(btmtk_register_coredump);
> +
> +int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> + struct btmtk_data *data = hci_get_priv(hdev);
> + int err;
> +
> + if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
> + return 0;
> +
> + switch (data->cd_info.state) {
> + case HCI_DEVCOREDUMP_IDLE:
> + err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
> + if (err < 0)
> + break;
> + /* It is supposed coredump can be done within 5 seconds */
> + schedule_delayed_work(&hdev->dump.dump_timeout,
> + msecs_to_jiffies(5000));
> + fallthrough;
> + case HCI_DEVCOREDUMP_ACTIVE:
> + default:
> + err = hci_devcd_append(hdev, skb);
> + if (err < 0)
> + break;
> +
> + if (skb->len > 12 &&
> + !strncmp((char *)&skb->data[skb->len - 13],
> + MTK_COREDUMP_END, 12))
> + hci_devcd_complete(hdev);

This is a bad idea, not only it is inefficient since you have to
compare the end after each append but it also assumes the size of
MTK_COREDUMP_END to be 12, so Id scrap this code and probably use the
return of hci_devcd_append or have the code in hci_devcd_append detect
it has reached the end.

> +
> + break;
> + }
> +
> + if (err < 0)
> + kfree_skb(skb);
> +
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(btmtk_process_coredump);
> +
> MODULE_AUTHOR("Sean Wang <[email protected]>");
> MODULE_AUTHOR("Mark Chen <[email protected]>");
> MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
> diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
> index 6245662f6ccb..852a67db8f80 100644
> --- a/drivers/bluetooth/btmtk.h
> +++ b/drivers/bluetooth/btmtk.h
> @@ -21,6 +21,9 @@
> #define MT7921_DLSTATUS 0x7c053c10
> #define BT_DL_STATE BIT(1)
>
> +#define MTK_COREDUMP_SIZE (1024 * 1000)
> +#define MTK_COREDUMP_END "coredump end"
> +
> enum {
> BTMTK_WMT_PATCH_DWNLD = 0x1,
> BTMTK_WMT_TEST = 0x2,
> @@ -119,12 +122,20 @@ struct btmtk_hci_wmt_params {
> u32 *status;
> };
>
> +struct btmtk_coredump_info {
> + const char *driver_name;
> + u32 dev_id;
> + u32 fw_version;
> + int state;
> +};
> +
> typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
> struct btmtk_hci_wmt_params *);
>
> typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
>
> struct btmtk_data {
> + struct btmtk_coredump_info cd_info;
> btmtk_reset_sync_func_t reset_sync;
> };
>
> @@ -139,6 +150,11 @@ int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
> wmt_cmd_sync_func_t wmt_cmd_sync);
>
> void btmtk_reset_sync(struct hci_dev *hdev);
> +
> +int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id, const char *name,
> + u32 fw_version);
> +
> +int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);
> #else
>
> static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
> @@ -162,4 +178,15 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
> static void btmtk_reset_sync(struct hci_dev *hdev)
> {
> }
> +
> +static int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id, const char *name,
> + u32 fw_version)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> +static int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> + return -EOPNOTSUPP;
> +}
> #endif
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 034edd8ad777..1c2a0cbcf62e 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -3035,6 +3035,10 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
> }
>
> btmtk_data->reset_sync = btusb_mtk_reset_work;
> + err = btmtk_register_coredump(hdev, dev_id, btusb_driver.name,
> + fw_version);
> + if (err < 0)
> + bt_dev_err(hdev, "Failed to register coredump (%d)", err);
>
> switch (dev_id) {
> case 0x7663:
> @@ -3189,6 +3193,7 @@ 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);
> + struct sk_buff *skb_cd;
>
> switch (handle) {
> case 0xfc6f: /* Firmware dump from device */
> @@ -3196,6 +3201,15 @@ static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
> * suspend and thus disable auto-suspend.
> */
> usb_disable_autosuspend(data->udev);
> +
> + /* We need to forward the diagnostic packet to userspace daemon
> + * for backward compatibility, so we have to clone the packet
> + * extraly for the in-kernel coredump support.
> + */
> + skb_cd = skb_clone(skb, GFP_ATOMIC);
> + if (skb_cd)
> + btmtk_process_coredump(hdev, skb_cd);
> +
> fallthrough;
> case 0x05ff: /* Firmware debug logging 1 */
> case 0x05fe: /* Firmware debug logging 2 */
> --
> 2.25.1
>


--
Luiz Augusto von Dentz

2023-05-16 20:29:57

by Sean Wang

[permalink] [raw]
Subject: Re: [PATCH v6 3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support

Hi Luiz,

On Mon, May 15, 2023 at 12:08 PM Luiz Augusto von Dentz
<[email protected]> wrote:
>
> Hi Sean,
>
> On Fri, May 12, 2023 at 2:20 PM <[email protected]> wrote:
> >
> > From: Jing Cai <[email protected]>
> >
> > This patch implement function .coredump() and dmp_hdr() in btusb
> > driver for MediaTek controller. FW core dump was triggered by FW
> > specific event to show something unexpected happened in the controller.
> >
> > The driver would be responsible for collecting and uploading the device
> > core dump pieces in hci driver using core dump API. Once we finished
> > the whole process, the driver would reset the controller to recover the
> > kind of fatal error.
> >
> > Co-developed-by: Chris Lu <[email protected]>
> > Signed-off-by: Chris Lu <[email protected]>
> > Co-developed-by: Sean Wang <[email protected]>
> > Signed-off-by: Sean Wang <[email protected]>
> > Signed-off-by: Jing Cai <[email protected]>
> > ---
> > v2, v3: rebase onto the latest codebase
> > v4: update the newest API usage for the coredump which was already
> > into the upstream
> > v5: support devcoredump on hdev basis
> > v6: reuse the coredump state HCI_DEVCOREDUMP_* in driver
> > and drop the driver name copying
> > ---
> > drivers/bluetooth/btmtk.c | 106 ++++++++++++++++++++++++++++++++++++++
> > drivers/bluetooth/btmtk.h | 27 ++++++++++
> > drivers/bluetooth/btusb.c | 14 +++++
> > 3 files changed, 147 insertions(+)
> >
> > diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
> > index ac2fac7e3c5f..60233afc0a9c 100644
> > --- a/drivers/bluetooth/btmtk.c
> > +++ b/drivers/bluetooth/btmtk.c
> > @@ -53,6 +53,56 @@ struct btmtk_section_map {
> > };
> > } __packed;
> >
> > +static void btmtk_coredump(struct hci_dev *hdev)
> > +{
> > + int err;
> > +
> > + err = __hci_cmd_send(hdev, 0xfd5b, 0, NULL);
> > + if (err < 0)
> > + bt_dev_err(hdev, "Coredump failed (%d)", err);
> > +}
> > +
> > +static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
> > +{
> > + struct btmtk_data *data = hci_get_priv(hdev);
> > + char buf[80];
> > +
> > + snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
> > + data->cd_info.dev_id);
> > + skb_put_data(skb, buf, strlen(buf));
> > +
> > + snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
> > + data->cd_info.fw_version);
> > + skb_put_data(skb, buf, strlen(buf));
> > +
> > + snprintf(buf, sizeof(buf), "Driver: %s\n",
> > + data->cd_info.driver_name);
> > + skb_put_data(skb, buf, strlen(buf));
> > +
> > + snprintf(buf, sizeof(buf), "Vendor: MediaTek\n");
> > + skb_put_data(skb, buf, strlen(buf));
> > +}
> > +
> > +static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
> > +{
> > + struct btmtk_data *data = hci_get_priv(hdev);
> > +
> > + switch (state) {
> > + case HCI_DEVCOREDUMP_IDLE:
> > + data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
> > + break;
> > + case HCI_DEVCOREDUMP_ACTIVE:
> > + data->cd_info.state = HCI_DEVCOREDUMP_ACTIVE;
> > + break;
> > + case HCI_DEVCOREDUMP_TIMEOUT:
> > + case HCI_DEVCOREDUMP_ABORT:
> > + case HCI_DEVCOREDUMP_DONE:
> > + data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
> > + btmtk_reset_sync(hdev);
> > + break;
> > + }
> > +}
> > +
> > int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
> > wmt_cmd_sync_func_t wmt_cmd_sync)
> > {
> > @@ -295,6 +345,62 @@ void btmtk_reset_sync(struct hci_dev *hdev)
> > }
> > EXPORT_SYMBOL_GPL(btmtk_reset_sync);
> >
> > +int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id,
> > + const char *name, u32 fw_version)
> > +{
> > + struct btmtk_data *data = hci_get_priv(hdev);
> > +
> > + if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
> > + return -EOPNOTSUPP;
> > +
> > + data->cd_info.dev_id = dev_id;
> > + data->cd_info.fw_version = fw_version;
> > + data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
> > + data->cd_info.driver_name = name;
> > +
> > + return hci_devcd_register(hdev, btmtk_coredump, btmtk_coredump_hdr,
> > + btmtk_coredump_notify);
> > +}
> > +EXPORT_SYMBOL_GPL(btmtk_register_coredump);
> > +
> > +int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
> > +{
> > + struct btmtk_data *data = hci_get_priv(hdev);
> > + int err;
> > +
> > + if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
> > + return 0;
> > +
> > + switch (data->cd_info.state) {
> > + case HCI_DEVCOREDUMP_IDLE:
> > + err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
> > + if (err < 0)
> > + break;
> > + /* It is supposed coredump can be done within 5 seconds */
> > + schedule_delayed_work(&hdev->dump.dump_timeout,
> > + msecs_to_jiffies(5000));
> > + fallthrough;
> > + case HCI_DEVCOREDUMP_ACTIVE:
> > + default:
> > + err = hci_devcd_append(hdev, skb);
> > + if (err < 0)
> > + break;
> > +
> > + if (skb->len > 12 &&
> > + !strncmp((char *)&skb->data[skb->len - 13],
> > + MTK_COREDUMP_END, 12))
> > + hci_devcd_complete(hdev);
>
> This is a bad idea, not only it is inefficient since you have to
> compare the end after each append but it also assumes the size of
> MTK_COREDUMP_END to be 12, so Id scrap this code and probably use the
> return of hci_devcd_append or have the code in hci_devcd_append detect
> it has reached the end.

MTK_COREDUMP_END is a unique string of exactly 12 characters. It acts
as a critical marker, signifying the end of the MTK core dump. This
flag is guaranteed to be present in every instance of an MTK core
dump. Also, MTK_COREDUMP_END must take the last position in the core
dump, emphasizing its importance. While this method might be a bit
inefficient, which doesn't happen usually but also it provides an only
accurate way to determine the conclusion of an MTK core dump.
>
> > +
> > + break;
> > + }
> > +
> > + if (err < 0)
> > + kfree_skb(skb);
> > +
> > + return err;
> > +}
> > +EXPORT_SYMBOL_GPL(btmtk_process_coredump);
> > +
> > MODULE_AUTHOR("Sean Wang <[email protected]>");
> > MODULE_AUTHOR("Mark Chen <[email protected]>");
> > MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
> > diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
> > index 6245662f6ccb..852a67db8f80 100644
> > --- a/drivers/bluetooth/btmtk.h
> > +++ b/drivers/bluetooth/btmtk.h
> > @@ -21,6 +21,9 @@
> > #define MT7921_DLSTATUS 0x7c053c10
> > #define BT_DL_STATE BIT(1)
> >
> > +#define MTK_COREDUMP_SIZE (1024 * 1000)
> > +#define MTK_COREDUMP_END "coredump end"
> > +
> > enum {
> > BTMTK_WMT_PATCH_DWNLD = 0x1,
> > BTMTK_WMT_TEST = 0x2,
> > @@ -119,12 +122,20 @@ struct btmtk_hci_wmt_params {
> > u32 *status;
> > };
> >
> > +struct btmtk_coredump_info {
> > + const char *driver_name;
> > + u32 dev_id;
> > + u32 fw_version;
> > + int state;
> > +};
> > +
> > typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
> > struct btmtk_hci_wmt_params *);
> >
> > typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
> >
> > struct btmtk_data {
> > + struct btmtk_coredump_info cd_info;
> > btmtk_reset_sync_func_t reset_sync;
> > };
> >
> > @@ -139,6 +150,11 @@ int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
> > wmt_cmd_sync_func_t wmt_cmd_sync);
> >
> > void btmtk_reset_sync(struct hci_dev *hdev);
> > +
> > +int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id, const char *name,
> > + u32 fw_version);
> > +
> > +int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);
> > #else
> >
> > static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
> > @@ -162,4 +178,15 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
> > static void btmtk_reset_sync(struct hci_dev *hdev)
> > {
> > }
> > +
> > +static int btmtk_register_coredump(struct hci_dev *hdev, u32 dev_id, const char *name,
> > + u32 fw_version)
> > +{
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +static int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
> > +{
> > + return -EOPNOTSUPP;
> > +}
> > #endif
> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> > index 034edd8ad777..1c2a0cbcf62e 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
> > @@ -3035,6 +3035,10 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
> > }
> >
> > btmtk_data->reset_sync = btusb_mtk_reset_work;
> > + err = btmtk_register_coredump(hdev, dev_id, btusb_driver.name,
> > + fw_version);
> > + if (err < 0)
> > + bt_dev_err(hdev, "Failed to register coredump (%d)", err);
> >
> > switch (dev_id) {
> > case 0x7663:
> > @@ -3189,6 +3193,7 @@ 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);
> > + struct sk_buff *skb_cd;
> >
> > switch (handle) {
> > case 0xfc6f: /* Firmware dump from device */
> > @@ -3196,6 +3201,15 @@ static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
> > * suspend and thus disable auto-suspend.
> > */
> > usb_disable_autosuspend(data->udev);
> > +
> > + /* We need to forward the diagnostic packet to userspace daemon
> > + * for backward compatibility, so we have to clone the packet
> > + * extraly for the in-kernel coredump support.
> > + */
> > + skb_cd = skb_clone(skb, GFP_ATOMIC);
> > + if (skb_cd)
> > + btmtk_process_coredump(hdev, skb_cd);
> > +
> > fallthrough;
> > case 0x05ff: /* Firmware debug logging 1 */
> > case 0x05fe: /* Firmware debug logging 2 */
> > --
> > 2.25.1
> >
>
>
> --
> Luiz Augusto von Dentz