From nobody Sat Feb 7 23:23:06 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 924A2C77B73 for ; Mon, 22 May 2023 06:02:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230262AbjEVGCa convert rfc822-to-8bit (ORCPT ); Mon, 22 May 2023 02:02:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229571AbjEVGC2 (ORCPT ); Mon, 22 May 2023 02:02:28 -0400 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B1AFCF; Sun, 21 May 2023 23:02:24 -0700 (PDT) Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.77 with qID 34M61uncE007202, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexh36505.realtek.com.tw[172.21.6.25]) by rtits2.realtek.com.tw (8.15.2/2.81/5.90) with ESMTPS id 34M61uncE007202 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK); Mon, 22 May 2023 14:01:56 +0800 Received: from RTEXMBS06.realtek.com.tw (172.21.6.99) by RTEXH36505.realtek.com.tw (172.21.6.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.32; Mon, 22 May 2023 14:02:06 +0800 Received: from RTEXMBS04.realtek.com.tw (172.21.6.97) by RTEXMBS06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Mon, 22 May 2023 14:02:06 +0800 Received: from RTEXMBS04.realtek.com.tw ([fe80::e138:e7f1:4709:ff4d]) by RTEXMBS04.realtek.com.tw ([fe80::e138:e7f1:4709:ff4d%5]) with mapi id 15.01.2375.007; Mon, 22 May 2023 14:02:06 +0800 From: Hilda Wu To: "marcel@holtmann.org" CC: "johan.hedberg@gmail.com" , "luiz.dentz@gmail.com" , "linux-bluetooth@vger.kernel.org" , "linux-kernel@vger.kernel.org" , "mmandlik@google.com" , "apusaka@chromium.org" , "yinghsu@chromium.org" , "alex_lu@realsil.com.cn" , Max Chou , KidmanLee Subject: RE: [PATCH v4] Bluetooth: btrtl: Add Realtek devcoredump support Thread-Topic: [PATCH v4] Bluetooth: btrtl: Add Realtek devcoredump support Thread-Index: AQHZeLhFt1hIfTKg4E+SKRXN39RX2a9lyOWg Date: Mon, 22 May 2023 06:02:05 +0000 Message-ID: <6e2b544469034ca694f4cc2388f81832@realtek.com> References: <20230427032755.28519-1-hildawu@realtek.com> In-Reply-To: <20230427032755.28519-1-hildawu@realtek.com> Accept-Language: zh-TW, en-US Content-Language: zh-TW X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.21.132.182] x-kse-serverinfo: RTEXMBS06.realtek.com.tw, 9 x-kse-antispam-interceptor-info: fallback x-kse-antivirus-interceptor-info: fallback Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-ServerInfo: RTEXH36505.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Hi Marcel, Johan, Luiz, and Maintainers, Friendly ping, we are waiting for a maintainer review. If you have any suggestions, please let us know. Thank you for your help and your time. Regards, Hilda -----Original Message----- From: Hilda Wu =20 Sent: Thursday, April 27, 2023 11:28 AM To: marcel@holtmann.org Cc: johan.hedberg@gmail.com; luiz.dentz@gmail.com; linux-bluetooth@vger.ker= nel.org; linux-kernel@vger.kernel.org; mmandlik@google.com; apusaka@chromiu= m.org; yinghsu@chromium.org; alex_lu@realsil.com.cn; Max Chou ; KidmanLee Subject: [PATCH v4] Bluetooth: btrtl: Add Realtek devcoredump support From: Hilda Wu Catch debug exception from controller and driver, and trigger a devcoredump= using hci devcoredump APIs. The debug exception data will be parsed in use= rspace. Signed-off-by: Alex Lu Signed-off-by: Hilda Wu --- Changes in v4: - Adjust coredump_info stored on a per hdev basis. - Adjust message level. Changes in v3: - Rebase, fixed merge confilt Changes in v2: - According to devcoredump API revision, modified related part. --- --- drivers/bluetooth/btrtl.c | 145 +++++++++++++++++++++++++++++++------- drivers/bluetooth/btrtl.h | 13 ++++ drivers/bluetooth/btusb.c | 74 +++++++++++++++++++ 3 files changed, 205 insertions(+), 27 deletions(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 29= 15c82d719d..3a1abd8fad60 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -32,6 +32,8 @@ #define RTL_ROM_LMP_8851B 0x8851 #define RTL_CONFIG_MAGIC 0x8723ab55 =20 +#define RTL_VSC_OP_COREDUMP 0xfcff + #define IC_MATCH_FL_LMPSUBV (1 << 0) #define IC_MATCH_FL_HCIREV (1 << 1) #define IC_MATCH_FL_HCIVER (1 << 2) @@ -81,6 +83,7 @@ struct id_table { bool has_msft_ext; char *fw_name; char *cfg_name; + char *hw_info; }; =20 struct btrtl_device_info { @@ -102,21 +105,24 @@ static const struct id_table ic_id_table[] =3D { .config_needed =3D false, .has_rom_version =3D false, .fw_name =3D "rtl_bt/rtl8723a_fw.bin", - .cfg_name =3D NULL }, + .cfg_name =3D NULL, + .hw_info =3D "rtl8723au" }, =20 /* 8723BS */ { IC_INFO(RTL_ROM_LMP_8723B, 0xb, 0x6, HCI_UART), .config_needed =3D true, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8723bs_fw.bin", - .cfg_name =3D "rtl_bt/rtl8723bs_config" }, + .cfg_name =3D "rtl_bt/rtl8723bs_config", + .hw_info =3D "rtl8723bs" }, =20 /* 8723B */ { IC_INFO(RTL_ROM_LMP_8723B, 0xb, 0x6, HCI_USB), .config_needed =3D false, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8723b_fw.bin", - .cfg_name =3D "rtl_bt/rtl8723b_config" }, + .cfg_name =3D "rtl_bt/rtl8723b_config", + .hw_info =3D "rtl8723bu" }, =20 /* 8723CS-CG */ { .match_flags =3D IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE | @@ -127,= 7 +133,8 @@ static const struct id_table ic_id_table[] =3D { .config_needed =3D true, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8723cs_cg_fw.bin", - .cfg_name =3D "rtl_bt/rtl8723cs_cg_config" }, + .cfg_name =3D "rtl_bt/rtl8723cs_cg_config", + .hw_info =3D "rtl8723cs-cg" }, =20 /* 8723CS-VF */ { .match_flags =3D IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE | @@ -138,= 7 +145,8 @@ static const struct id_table ic_id_table[] =3D { .config_needed =3D true, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8723cs_vf_fw.bin", - .cfg_name =3D "rtl_bt/rtl8723cs_vf_config" }, + .cfg_name =3D "rtl_bt/rtl8723cs_vf_config", + .hw_info =3D "rtl8723cs-vf" }, =20 /* 8723CS-XX */ { .match_flags =3D IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE | @@ -149,= 28 +157,32 @@ static const struct id_table ic_id_table[] =3D { .config_needed =3D true, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8723cs_xx_fw.bin", - .cfg_name =3D "rtl_bt/rtl8723cs_xx_config" }, + .cfg_name =3D "rtl_bt/rtl8723cs_xx_config", + .hw_info =3D "rtl8723cs" }, =20 /* 8723D */ { IC_INFO(RTL_ROM_LMP_8723B, 0xd, 0x8, HCI_USB), .config_needed =3D true, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8723d_fw.bin", - .cfg_name =3D "rtl_bt/rtl8723d_config" }, + .cfg_name =3D "rtl_bt/rtl8723d_config", + .hw_info =3D "rtl8723du" }, =20 /* 8723DS */ { IC_INFO(RTL_ROM_LMP_8723B, 0xd, 0x8, HCI_UART), .config_needed =3D true, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8723ds_fw.bin", - .cfg_name =3D "rtl_bt/rtl8723ds_config" }, + .cfg_name =3D "rtl_bt/rtl8723ds_config", + .hw_info =3D "rtl8723ds" }, =20 /* 8821A */ { IC_INFO(RTL_ROM_LMP_8821A, 0xa, 0x6, HCI_USB), .config_needed =3D false, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8821a_fw.bin", - .cfg_name =3D "rtl_bt/rtl8821a_config" }, + .cfg_name =3D "rtl_bt/rtl8821a_config", + .hw_info =3D "rtl8821au" }, =20 /* 8821C */ { IC_INFO(RTL_ROM_LMP_8821A, 0xc, 0x8, HCI_USB), @@ -178,7 +190,8 @@ stat= ic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8821c_fw.bin", - .cfg_name =3D "rtl_bt/rtl8821c_config" }, + .cfg_name =3D "rtl_bt/rtl8821c_config", + .hw_info =3D "rtl8821cu" }, =20 /* 8821CS */ { IC_INFO(RTL_ROM_LMP_8821A, 0xc, 0x8, HCI_UART), @@ -186,14 +199,16 @@ s= tatic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8821cs_fw.bin", - .cfg_name =3D "rtl_bt/rtl8821cs_config" }, + .cfg_name =3D "rtl_bt/rtl8821cs_config", + .hw_info =3D "rtl8821cs" }, =20 /* 8761A */ { IC_INFO(RTL_ROM_LMP_8761A, 0xa, 0x6, HCI_USB), .config_needed =3D false, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8761a_fw.bin", - .cfg_name =3D "rtl_bt/rtl8761a_config" }, + .cfg_name =3D "rtl_bt/rtl8761a_config", + .hw_info =3D "rtl8761au" }, =20 /* 8761B */ { IC_INFO(RTL_ROM_LMP_8761A, 0xb, 0xa, HCI_UART), @@ -201,14 +216,16 @@ s= tatic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8761b_fw.bin", - .cfg_name =3D "rtl_bt/rtl8761b_config" }, + .cfg_name =3D "rtl_bt/rtl8761b_config", + .hw_info =3D "rtl8761btv" }, =20 /* 8761BU */ { IC_INFO(RTL_ROM_LMP_8761A, 0xb, 0xa, HCI_USB), .config_needed =3D false, .has_rom_version =3D true, .fw_name =3D "rtl_bt/rtl8761bu_fw.bin", - .cfg_name =3D "rtl_bt/rtl8761bu_config" }, + .cfg_name =3D "rtl_bt/rtl8761bu_config", + .hw_info =3D "rtl8761bu" }, =20 /* 8822C with UART interface */ { IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0x8, HCI_UART), @@ -216,7 +233,8 @@ sta= tic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8822cs_fw.bin", - .cfg_name =3D "rtl_bt/rtl8822cs_config" }, + .cfg_name =3D "rtl_bt/rtl8822cs_config", + .hw_info =3D "rtl8822cs" }, =20 /* 8822C with UART interface */ { IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_UART), @@ -224,7 +242,8 @@ sta= tic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8822cs_fw.bin", - .cfg_name =3D "rtl_bt/rtl8822cs_config" }, + .cfg_name =3D "rtl_bt/rtl8822cs_config", + .hw_info =3D "rtl8822cs" }, =20 /* 8822C with USB interface */ { IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_USB), @@ -232,7 +251,8 @@ stat= ic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8822cu_fw.bin", - .cfg_name =3D "rtl_bt/rtl8822cu_config" }, + .cfg_name =3D "rtl_bt/rtl8822cu_config", + .hw_info =3D "rtl8822cu" }, =20 /* 8822B */ { IC_INFO(RTL_ROM_LMP_8822B, 0xb, 0x7, HCI_USB), @@ -240,7 +260,8 @@ stat= ic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8822b_fw.bin", - .cfg_name =3D "rtl_bt/rtl8822b_config" }, + .cfg_name =3D "rtl_bt/rtl8822b_config", + .hw_info =3D "rtl8822bu" }, =20 /* 8852A */ { IC_INFO(RTL_ROM_LMP_8852A, 0xa, 0xb, HCI_USB), @@ -248,7 +269,8 @@ stat= ic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8852au_fw.bin", - .cfg_name =3D "rtl_bt/rtl8852au_config" }, + .cfg_name =3D "rtl_bt/rtl8852au_config", + .hw_info =3D "rtl8852au" }, =20 /* 8852B with UART interface */ { IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_UART), @@ -256,7 +278,8 @@ sta= tic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8852bs_fw.bin", - .cfg_name =3D "rtl_bt/rtl8852bs_config" }, + .cfg_name =3D "rtl_bt/rtl8852bs_config", + .hw_info =3D "rtl8852bs" }, =20 /* 8852B */ { IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_USB), @@ -264,7 +287,8 @@ stat= ic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8852bu_fw.bin", - .cfg_name =3D "rtl_bt/rtl8852bu_config" }, + .cfg_name =3D "rtl_bt/rtl8852bu_config", + .hw_info =3D "rtl8852bu" }, =20 /* 8852C */ { IC_INFO(RTL_ROM_LMP_8852A, 0xc, 0xc, HCI_USB), @@ -272,7 +296,8 @@ stat= ic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D true, .fw_name =3D "rtl_bt/rtl8852cu_fw.bin", - .cfg_name =3D "rtl_bt/rtl8852cu_config" }, + .cfg_name =3D "rtl_bt/rtl8852cu_config", + .hw_info =3D "rtl8852cu" }, =20 /* 8851B */ { IC_INFO(RTL_ROM_LMP_8851B, 0xb, 0xc, HCI_USB), @@ -280,7 +305,8 @@ stat= ic const struct id_table ic_id_table[] =3D { .has_rom_version =3D true, .has_msft_ext =3D false, .fw_name =3D "rtl_bt/rtl8851bu_fw.bin", - .cfg_name =3D "rtl_bt/rtl8851bu_config" }, + .cfg_name =3D "rtl_bt/rtl8851bu_config", + .hw_info =3D "rtl8851bu" }, }; =20 static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev, = @@ -590,6 +616,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, unsigned char **_buf) { static const u8 extension_sig[] =3D { 0x51, 0x04, 0xfd, 0x77 }; + struct btrealtek_data *coredump_info =3D hci_get_priv(hdev); struct rtl_epatch_header *epatch_info; unsigned char *buf; int i, len; @@ -705,8 +732,10 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, =20 epatch_info =3D (struct rtl_epatch_header *)btrtl_dev->fw_data; num_patches =3D le16_to_cpu(epatch_info->num_patches); + BT_DBG("fw_version=3D%x, num_patches=3D%d", le32_to_cpu(epatch_info->fw_version), num_patches); + coredump_info->rtl_dump.fw_version =3D=20 +le32_to_cpu(epatch_info->fw_version); =20 /* After the rtl_epatch_header there is a funky patch metadata section. * Assuming 2 patches, the layout is: @@ -903,6 +932,53 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, return ret; } =20 +static void btrtl_coredump(struct hci_dev *hdev) { + static const u8 param[] =3D { 0x00, 0x00 }; + + __hci_cmd_send(hdev, RTL_VSC_OP_COREDUMP, sizeof(param), param); } + +static void btrtl_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb) { + struct btrealtek_data *coredump_info =3D hci_get_priv(hdev); + char buf[80]; + + if (coredump_info->rtl_dump.controller) + snprintf(buf, sizeof(buf), "Controller Name: %s\n", + coredump_info->rtl_dump.controller); + else + snprintf(buf, sizeof(buf), "Controller Name: Unknown\n"); + skb_put_data(skb, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n", + coredump_info->rtl_dump.fw_version); + skb_put_data(skb, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Driver: %s\n", coredump_info->rtl_dump.driver= _name); + skb_put_data(skb, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Vendor: Realtek\n"); + skb_put_data(skb, buf, strlen(buf)); +} + +static int btrtl_register_devcoredump_support(struct hci_dev *hdev) { + int err; + + err =3D hci_devcd_register(hdev, btrtl_coredump, btrtl_dmp_hdr, NULL); + + return err; +} + +void btrtl_set_driver_name(struct hci_dev *hdev, const char=20 +*driver_name) { + struct btrealtek_data *coredump_info =3D hci_get_priv(hdev); + + coredump_info->rtl_dump.driver_name =3D driver_name; }=20 +EXPORT_SYMBOL_GPL(btrtl_set_driver_name); + static bool rtl_has_chip_type(u16 lmp_subver) { switch (lmp_subver) { @@ -964,6 +1040,7 @@ EXPORT_SYMBOL_GPL(btrtl_free); struct btrtl_device_in= fo *btrtl_initialize(struct hci_dev *hdev, const char *postfix) { + struct btrealtek_data *coredump_info =3D hci_get_priv(hdev); struct btrtl_device_info *btrtl_dev; struct sk_buff *skb; struct hci_rp_read_local_version *resp; @@ -1113,6 +1190,9 @@ struct btrt= l_device_info *btrtl_initialize(struct hci_dev *hdev, if (btrtl_dev->ic_info->has_msft_ext) hci_set_msft_opcode(hdev, 0xFCF0); =20 + if (btrtl_dev->ic_info) + coredump_info->rtl_dump.controller =3D btrtl_dev->ic_info->hw_info; + return btrtl_dev; =20 err_free: @@ -1125,6 +1205,8 @@ EXPORT_SYMBOL_GPL(btrtl_initialize); int btrtl_download_firmware(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) { + int err =3D 0; + /* Match a set of subver values that correspond to stock firmware, * which is not compatible with standard btusb. * If matched, upload an alternative firmware that does conform to @@ -11= 33,12 +1215,14 @@ int btrtl_download_firmware(struct hci_dev *hdev, */ if (!btrtl_dev->ic_info) { rtl_dev_info(hdev, "assuming no firmware upload needed"); - return 0; + err =3D 0; + goto done; } =20 switch (btrtl_dev->ic_info->lmp_subver) { case RTL_ROM_LMP_8723A: - return btrtl_setup_rtl8723a(hdev, btrtl_dev); + err =3D btrtl_setup_rtl8723a(hdev, btrtl_dev); + break; case RTL_ROM_LMP_8723B: case RTL_ROM_LMP_8821A: case RTL_ROM_LMP_8761A: @@ -1146,11 +1230,18 @@ int btrtl_download_firmware(struct hci_dev *hdev, case RTL_ROM_LMP_8852A: case RTL_ROM_LMP_8703B: case RTL_ROM_LMP_8851B: - return btrtl_setup_rtl8723b(hdev, btrtl_dev); + err =3D btrtl_setup_rtl8723b(hdev, btrtl_dev); + break; default: rtl_dev_info(hdev, "assuming no firmware upload needed"); - return 0; + break; } + +done: + if (!err) + err =3D btrtl_register_devcoredump_support(hdev); + + return err; } EXPORT_SYMBOL_GPL(btrtl_download_firmware); =20 diff --git a/drivers/bluetooth/btrtl.h b/drivers/bluetooth/btrtl.h index ad= b4c2c9abc5..a2d9d34f9fb0 100644 --- a/drivers/bluetooth/btrtl.h +++ b/drivers/bluetooth/btrtl.h @@ -109,8 +109,16 @@ enum { __REALTEK_NUM_FLAGS, }; =20 +struct rtl_dump_info { + const char *driver_name; + char *controller; + u32 fw_version; +}; + struct btrealtek_data { DECLARE_BITMAP(flags, __REALTEK_NUM_FLAGS); + + struct rtl_dump_info rtl_dump; }; =20 #define btrealtek_set_flag(hdev, nr) \ @@ -139,6 +147,7 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev, unsigned int *controller_baudrate, u32 *device_baudrate, bool *flow_control); +void btrtl_set_driver_name(struct hci_dev *hdev, const char=20 +*driver_name); =20 #else =20 @@ -182,4 +191,8 @@ static inline int btrtl_get_uart_settings(struct hci_de= v *hdev, return -ENOENT; } =20 +static inline void btrtl_set_driver_name(struct hci_dev *hdev, const=20 +char *driver_name) { } + #endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 3a= a189b1986d..23059e3463eb 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -869,10 +869,49 @@ static void btusb_intel_cmd_timeout(struct hci_dev *h= dev) gpiod_set_value_cansleep(reset_gpio, 0); } =20 +#define RTK_DEVCOREDUMP_CODE_MEMDUMP 0x01 +#define RTK_DEVCOREDUMP_CODE_HW_ERR 0x02 +#define RTK_DEVCOREDUMP_CODE_CMD_TIMEOUT 0x03 + +#define RTK_SUB_EVENT_CODE_COREDUMP 0x34 + +struct rtk_dev_coredump_hdr { + u8 type; + u8 code; + u8 reserved[2]; +} __packed; + +static inline void btusb_rtl_alloc_devcoredump(struct hci_dev *hdev, + struct rtk_dev_coredump_hdr *hdr, u8 *buf, u32 len) { + struct sk_buff *skb; + + skb =3D alloc_skb(len + sizeof(*hdr), GFP_ATOMIC); + if (!skb) + return; + + skb_put_data(skb, hdr, sizeof(*hdr)); + if (len) + skb_put_data(skb, buf, len); + + if (!hci_devcd_init(hdev, skb->len)) { + hci_devcd_append(hdev, skb); + hci_devcd_complete(hdev); + } else { + bt_dev_err(hdev, "RTL: Failed to generate devcoredump"); + kfree_skb(skb); + } +} + static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) { struct btusb_data *data =3D hci_get_drvdata(hdev); struct gpio_desc *reset_gpio =3D data->reset_gpio; + struct rtk_dev_coredump_hdr hdr =3D { + .type =3D RTK_DEVCOREDUMP_CODE_CMD_TIMEOUT, + }; + + btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0); =20 if (++data->cmd_timeout_cnt < 5) return; @@ -899,6 +938,18 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) gpiod_set_value_cansleep(reset_gpio, 0); } =20 +static void btusb_rtl_hw_error(struct hci_dev *hdev, u8 code) { + struct rtk_dev_coredump_hdr hdr =3D { + .type =3D RTK_DEVCOREDUMP_CODE_HW_ERR, + .code =3D code, + }; + + bt_dev_err(hdev, "RTL: hw err, trigger devcoredump (%d)", code); + + btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0); } + static void btusb_qca_cmd_timeout(struct hci_dev *hdev) { struct btusb_data *data =3D hci_get_drvdata(hdev); @@ -2539,6 +2590,25 @@= static int btusb_setup_realtek(struct hci_dev *hdev) return ret; } =20 +static int btusb_recv_event_realtek(struct hci_dev *hdev, struct=20 +sk_buff *skb) { + if (skb->data[0] =3D=3D HCI_VENDOR_PKT && skb->data[2] =3D=3D RTK_SUB_EVE= NT_CODE_COREDUMP) { + struct rtk_dev_coredump_hdr hdr =3D { + .code =3D RTK_DEVCOREDUMP_CODE_MEMDUMP, + }; + + bt_dev_dbg(hdev, "RTL: received coredump vendor evt, len %u", + skb->len); + + btusb_rtl_alloc_devcoredump(hdev, &hdr, skb->data, skb->len); + kfree_skb(skb); + + return 0; + } + + return hci_recv_frame(hdev, skb); +} + /* UHW CR mapping */ #define MTK_BT_MISC 0x70002510 #define MTK_BT_SUBSYS_RST 0x70002610 @@ -3978,6 +4048,8 @@ static int btusb_probe(struct usb_interface *intf, } else if (id->driver_info & BTUSB_REALTEK) { /* Allocate extra space for Realtek device */ priv_size +=3D sizeof(struct btrealtek_data); + + data->recv_event =3D btusb_recv_event_realtek; } =20 data->recv_acl =3D hci_recv_frame; @@ -4136,9 +4208,11 @@ static int btusb_probe(struct usb_interface *intf, =20 if (IS_ENABLED(CONFIG_BT_HCIBTUSB_RTL) && (id->driver_info & BTUSB_REALTEK)) { + btrtl_set_driver_name(hdev, btusb_driver.name); hdev->setup =3D btusb_setup_realtek; hdev->shutdown =3D btrtl_shutdown_realtek; hdev->cmd_timeout =3D btusb_rtl_cmd_timeout; + hdev->hw_error =3D btusb_rtl_hw_error; =20 /* Realtek devices need to set remote wakeup on auto-suspend */ set_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags); -- 2.17.1