Skip to content

Commit 044014c

Browse files
hildawurVudentz
authored andcommitted
Bluetooth: btrtl: Add Realtek devcoredump support
Catch debug exception from controller and driver, and trigger a devcoredump using hci devcoredump APIs. The debug exception data will be parsed in userspace. Signed-off-by: Alex Lu <[email protected]> Signed-off-by: Hilda Wu <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent ae75336 commit 044014c

File tree

3 files changed

+205
-27
lines changed

3 files changed

+205
-27
lines changed

drivers/bluetooth/btrtl.c

Lines changed: 118 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#define RTL_ROM_LMP_8851B 0x8851
3333
#define RTL_CONFIG_MAGIC 0x8723ab55
3434

35+
#define RTL_VSC_OP_COREDUMP 0xfcff
36+
3537
#define IC_MATCH_FL_LMPSUBV (1 << 0)
3638
#define IC_MATCH_FL_HCIREV (1 << 1)
3739
#define IC_MATCH_FL_HCIVER (1 << 2)
@@ -81,6 +83,7 @@ struct id_table {
8183
bool has_msft_ext;
8284
char *fw_name;
8385
char *cfg_name;
86+
char *hw_info;
8487
};
8588

8689
struct btrtl_device_info {
@@ -102,21 +105,24 @@ static const struct id_table ic_id_table[] = {
102105
.config_needed = false,
103106
.has_rom_version = false,
104107
.fw_name = "rtl_bt/rtl8723a_fw.bin",
105-
.cfg_name = NULL },
108+
.cfg_name = NULL,
109+
.hw_info = "rtl8723au" },
106110

107111
/* 8723BS */
108112
{ IC_INFO(RTL_ROM_LMP_8723B, 0xb, 0x6, HCI_UART),
109113
.config_needed = true,
110114
.has_rom_version = true,
111115
.fw_name = "rtl_bt/rtl8723bs_fw.bin",
112-
.cfg_name = "rtl_bt/rtl8723bs_config" },
116+
.cfg_name = "rtl_bt/rtl8723bs_config",
117+
.hw_info = "rtl8723bs" },
113118

114119
/* 8723B */
115120
{ IC_INFO(RTL_ROM_LMP_8723B, 0xb, 0x6, HCI_USB),
116121
.config_needed = false,
117122
.has_rom_version = true,
118123
.fw_name = "rtl_bt/rtl8723b_fw.bin",
119-
.cfg_name = "rtl_bt/rtl8723b_config" },
124+
.cfg_name = "rtl_bt/rtl8723b_config",
125+
.hw_info = "rtl8723bu" },
120126

121127
/* 8723CS-CG */
122128
{ .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE |
@@ -127,7 +133,8 @@ static const struct id_table ic_id_table[] = {
127133
.config_needed = true,
128134
.has_rom_version = true,
129135
.fw_name = "rtl_bt/rtl8723cs_cg_fw.bin",
130-
.cfg_name = "rtl_bt/rtl8723cs_cg_config" },
136+
.cfg_name = "rtl_bt/rtl8723cs_cg_config",
137+
.hw_info = "rtl8723cs-cg" },
131138

132139
/* 8723CS-VF */
133140
{ .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE |
@@ -138,7 +145,8 @@ static const struct id_table ic_id_table[] = {
138145
.config_needed = true,
139146
.has_rom_version = true,
140147
.fw_name = "rtl_bt/rtl8723cs_vf_fw.bin",
141-
.cfg_name = "rtl_bt/rtl8723cs_vf_config" },
148+
.cfg_name = "rtl_bt/rtl8723cs_vf_config",
149+
.hw_info = "rtl8723cs-vf" },
142150

143151
/* 8723CS-XX */
144152
{ .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE |
@@ -149,138 +157,156 @@ static const struct id_table ic_id_table[] = {
149157
.config_needed = true,
150158
.has_rom_version = true,
151159
.fw_name = "rtl_bt/rtl8723cs_xx_fw.bin",
152-
.cfg_name = "rtl_bt/rtl8723cs_xx_config" },
160+
.cfg_name = "rtl_bt/rtl8723cs_xx_config",
161+
.hw_info = "rtl8723cs" },
153162

154163
/* 8723D */
155164
{ IC_INFO(RTL_ROM_LMP_8723B, 0xd, 0x8, HCI_USB),
156165
.config_needed = true,
157166
.has_rom_version = true,
158167
.fw_name = "rtl_bt/rtl8723d_fw.bin",
159-
.cfg_name = "rtl_bt/rtl8723d_config" },
168+
.cfg_name = "rtl_bt/rtl8723d_config",
169+
.hw_info = "rtl8723du" },
160170

161171
/* 8723DS */
162172
{ IC_INFO(RTL_ROM_LMP_8723B, 0xd, 0x8, HCI_UART),
163173
.config_needed = true,
164174
.has_rom_version = true,
165175
.fw_name = "rtl_bt/rtl8723ds_fw.bin",
166-
.cfg_name = "rtl_bt/rtl8723ds_config" },
176+
.cfg_name = "rtl_bt/rtl8723ds_config",
177+
.hw_info = "rtl8723ds" },
167178

168179
/* 8821A */
169180
{ IC_INFO(RTL_ROM_LMP_8821A, 0xa, 0x6, HCI_USB),
170181
.config_needed = false,
171182
.has_rom_version = true,
172183
.fw_name = "rtl_bt/rtl8821a_fw.bin",
173-
.cfg_name = "rtl_bt/rtl8821a_config" },
184+
.cfg_name = "rtl_bt/rtl8821a_config",
185+
.hw_info = "rtl8821au" },
174186

175187
/* 8821C */
176188
{ IC_INFO(RTL_ROM_LMP_8821A, 0xc, 0x8, HCI_USB),
177189
.config_needed = false,
178190
.has_rom_version = true,
179191
.has_msft_ext = true,
180192
.fw_name = "rtl_bt/rtl8821c_fw.bin",
181-
.cfg_name = "rtl_bt/rtl8821c_config" },
193+
.cfg_name = "rtl_bt/rtl8821c_config",
194+
.hw_info = "rtl8821cu" },
182195

183196
/* 8821CS */
184197
{ IC_INFO(RTL_ROM_LMP_8821A, 0xc, 0x8, HCI_UART),
185198
.config_needed = true,
186199
.has_rom_version = true,
187200
.has_msft_ext = true,
188201
.fw_name = "rtl_bt/rtl8821cs_fw.bin",
189-
.cfg_name = "rtl_bt/rtl8821cs_config" },
202+
.cfg_name = "rtl_bt/rtl8821cs_config",
203+
.hw_info = "rtl8821cs" },
190204

191205
/* 8761A */
192206
{ IC_INFO(RTL_ROM_LMP_8761A, 0xa, 0x6, HCI_USB),
193207
.config_needed = false,
194208
.has_rom_version = true,
195209
.fw_name = "rtl_bt/rtl8761a_fw.bin",
196-
.cfg_name = "rtl_bt/rtl8761a_config" },
210+
.cfg_name = "rtl_bt/rtl8761a_config",
211+
.hw_info = "rtl8761au" },
197212

198213
/* 8761B */
199214
{ IC_INFO(RTL_ROM_LMP_8761A, 0xb, 0xa, HCI_UART),
200215
.config_needed = false,
201216
.has_rom_version = true,
202217
.has_msft_ext = true,
203218
.fw_name = "rtl_bt/rtl8761b_fw.bin",
204-
.cfg_name = "rtl_bt/rtl8761b_config" },
219+
.cfg_name = "rtl_bt/rtl8761b_config",
220+
.hw_info = "rtl8761btv" },
205221

206222
/* 8761BU */
207223
{ IC_INFO(RTL_ROM_LMP_8761A, 0xb, 0xa, HCI_USB),
208224
.config_needed = false,
209225
.has_rom_version = true,
210226
.fw_name = "rtl_bt/rtl8761bu_fw.bin",
211-
.cfg_name = "rtl_bt/rtl8761bu_config" },
227+
.cfg_name = "rtl_bt/rtl8761bu_config",
228+
.hw_info = "rtl8761bu" },
212229

213230
/* 8822C with UART interface */
214231
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0x8, HCI_UART),
215232
.config_needed = true,
216233
.has_rom_version = true,
217234
.has_msft_ext = true,
218235
.fw_name = "rtl_bt/rtl8822cs_fw.bin",
219-
.cfg_name = "rtl_bt/rtl8822cs_config" },
236+
.cfg_name = "rtl_bt/rtl8822cs_config",
237+
.hw_info = "rtl8822cs" },
220238

221239
/* 8822C with UART interface */
222240
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_UART),
223241
.config_needed = true,
224242
.has_rom_version = true,
225243
.has_msft_ext = true,
226244
.fw_name = "rtl_bt/rtl8822cs_fw.bin",
227-
.cfg_name = "rtl_bt/rtl8822cs_config" },
245+
.cfg_name = "rtl_bt/rtl8822cs_config",
246+
.hw_info = "rtl8822cs" },
228247

229248
/* 8822C with USB interface */
230249
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_USB),
231250
.config_needed = false,
232251
.has_rom_version = true,
233252
.has_msft_ext = true,
234253
.fw_name = "rtl_bt/rtl8822cu_fw.bin",
235-
.cfg_name = "rtl_bt/rtl8822cu_config" },
254+
.cfg_name = "rtl_bt/rtl8822cu_config",
255+
.hw_info = "rtl8822cu" },
236256

237257
/* 8822B */
238258
{ IC_INFO(RTL_ROM_LMP_8822B, 0xb, 0x7, HCI_USB),
239259
.config_needed = true,
240260
.has_rom_version = true,
241261
.has_msft_ext = true,
242262
.fw_name = "rtl_bt/rtl8822b_fw.bin",
243-
.cfg_name = "rtl_bt/rtl8822b_config" },
263+
.cfg_name = "rtl_bt/rtl8822b_config",
264+
.hw_info = "rtl8822bu" },
244265

245266
/* 8852A */
246267
{ IC_INFO(RTL_ROM_LMP_8852A, 0xa, 0xb, HCI_USB),
247268
.config_needed = false,
248269
.has_rom_version = true,
249270
.has_msft_ext = true,
250271
.fw_name = "rtl_bt/rtl8852au_fw.bin",
251-
.cfg_name = "rtl_bt/rtl8852au_config" },
272+
.cfg_name = "rtl_bt/rtl8852au_config",
273+
.hw_info = "rtl8852au" },
252274

253275
/* 8852B with UART interface */
254276
{ IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_UART),
255277
.config_needed = true,
256278
.has_rom_version = true,
257279
.has_msft_ext = true,
258280
.fw_name = "rtl_bt/rtl8852bs_fw.bin",
259-
.cfg_name = "rtl_bt/rtl8852bs_config" },
281+
.cfg_name = "rtl_bt/rtl8852bs_config",
282+
.hw_info = "rtl8852bs" },
260283

261284
/* 8852B */
262285
{ IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_USB),
263286
.config_needed = false,
264287
.has_rom_version = true,
265288
.has_msft_ext = true,
266289
.fw_name = "rtl_bt/rtl8852bu_fw.bin",
267-
.cfg_name = "rtl_bt/rtl8852bu_config" },
290+
.cfg_name = "rtl_bt/rtl8852bu_config",
291+
.hw_info = "rtl8852bu" },
268292

269293
/* 8852C */
270294
{ IC_INFO(RTL_ROM_LMP_8852A, 0xc, 0xc, HCI_USB),
271295
.config_needed = false,
272296
.has_rom_version = true,
273297
.has_msft_ext = true,
274298
.fw_name = "rtl_bt/rtl8852cu_fw.bin",
275-
.cfg_name = "rtl_bt/rtl8852cu_config" },
299+
.cfg_name = "rtl_bt/rtl8852cu_config",
300+
.hw_info = "rtl8852cu" },
276301

277302
/* 8851B */
278303
{ IC_INFO(RTL_ROM_LMP_8851B, 0xb, 0xc, HCI_USB),
279304
.config_needed = false,
280305
.has_rom_version = true,
281306
.has_msft_ext = false,
282307
.fw_name = "rtl_bt/rtl8851bu_fw.bin",
283-
.cfg_name = "rtl_bt/rtl8851bu_config" },
308+
.cfg_name = "rtl_bt/rtl8851bu_config",
309+
.hw_info = "rtl8851bu" },
284310
};
285311

286312
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,
590616
unsigned char **_buf)
591617
{
592618
static const u8 extension_sig[] = { 0x51, 0x04, 0xfd, 0x77 };
619+
struct btrealtek_data *coredump_info = hci_get_priv(hdev);
593620
struct rtl_epatch_header *epatch_info;
594621
unsigned char *buf;
595622
int i, len;
@@ -705,8 +732,10 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
705732

706733
epatch_info = (struct rtl_epatch_header *)btrtl_dev->fw_data;
707734
num_patches = le16_to_cpu(epatch_info->num_patches);
735+
708736
BT_DBG("fw_version=%x, num_patches=%d",
709737
le32_to_cpu(epatch_info->fw_version), num_patches);
738+
coredump_info->rtl_dump.fw_version = le32_to_cpu(epatch_info->fw_version);
710739

711740
/* After the rtl_epatch_header there is a funky patch metadata section.
712741
* Assuming 2 patches, the layout is:
@@ -903,6 +932,53 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev,
903932
return ret;
904933
}
905934

935+
static void btrtl_coredump(struct hci_dev *hdev)
936+
{
937+
static const u8 param[] = { 0x00, 0x00 };
938+
939+
__hci_cmd_send(hdev, RTL_VSC_OP_COREDUMP, sizeof(param), param);
940+
}
941+
942+
static void btrtl_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb)
943+
{
944+
struct btrealtek_data *coredump_info = hci_get_priv(hdev);
945+
char buf[80];
946+
947+
if (coredump_info->rtl_dump.controller)
948+
snprintf(buf, sizeof(buf), "Controller Name: %s\n",
949+
coredump_info->rtl_dump.controller);
950+
else
951+
snprintf(buf, sizeof(buf), "Controller Name: Unknown\n");
952+
skb_put_data(skb, buf, strlen(buf));
953+
954+
snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
955+
coredump_info->rtl_dump.fw_version);
956+
skb_put_data(skb, buf, strlen(buf));
957+
958+
snprintf(buf, sizeof(buf), "Driver: %s\n", coredump_info->rtl_dump.driver_name);
959+
skb_put_data(skb, buf, strlen(buf));
960+
961+
snprintf(buf, sizeof(buf), "Vendor: Realtek\n");
962+
skb_put_data(skb, buf, strlen(buf));
963+
}
964+
965+
static int btrtl_register_devcoredump_support(struct hci_dev *hdev)
966+
{
967+
int err;
968+
969+
err = hci_devcd_register(hdev, btrtl_coredump, btrtl_dmp_hdr, NULL);
970+
971+
return err;
972+
}
973+
974+
void btrtl_set_driver_name(struct hci_dev *hdev, const char *driver_name)
975+
{
976+
struct btrealtek_data *coredump_info = hci_get_priv(hdev);
977+
978+
coredump_info->rtl_dump.driver_name = driver_name;
979+
}
980+
EXPORT_SYMBOL_GPL(btrtl_set_driver_name);
981+
906982
static bool rtl_has_chip_type(u16 lmp_subver)
907983
{
908984
switch (lmp_subver) {
@@ -964,6 +1040,7 @@ EXPORT_SYMBOL_GPL(btrtl_free);
9641040
struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
9651041
const char *postfix)
9661042
{
1043+
struct btrealtek_data *coredump_info = hci_get_priv(hdev);
9671044
struct btrtl_device_info *btrtl_dev;
9681045
struct sk_buff *skb;
9691046
struct hci_rp_read_local_version *resp;
@@ -1113,6 +1190,9 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
11131190
if (btrtl_dev->ic_info->has_msft_ext)
11141191
hci_set_msft_opcode(hdev, 0xFCF0);
11151192

1193+
if (btrtl_dev->ic_info)
1194+
coredump_info->rtl_dump.controller = btrtl_dev->ic_info->hw_info;
1195+
11161196
return btrtl_dev;
11171197

11181198
err_free:
@@ -1125,6 +1205,8 @@ EXPORT_SYMBOL_GPL(btrtl_initialize);
11251205
int btrtl_download_firmware(struct hci_dev *hdev,
11261206
struct btrtl_device_info *btrtl_dev)
11271207
{
1208+
int err = 0;
1209+
11281210
/* Match a set of subver values that correspond to stock firmware,
11291211
* which is not compatible with standard btusb.
11301212
* If matched, upload an alternative firmware that does conform to
@@ -1133,24 +1215,33 @@ int btrtl_download_firmware(struct hci_dev *hdev,
11331215
*/
11341216
if (!btrtl_dev->ic_info) {
11351217
rtl_dev_info(hdev, "assuming no firmware upload needed");
1136-
return 0;
1218+
err = 0;
1219+
goto done;
11371220
}
11381221

11391222
switch (btrtl_dev->ic_info->lmp_subver) {
11401223
case RTL_ROM_LMP_8723A:
1141-
return btrtl_setup_rtl8723a(hdev, btrtl_dev);
1224+
err = btrtl_setup_rtl8723a(hdev, btrtl_dev);
1225+
break;
11421226
case RTL_ROM_LMP_8723B:
11431227
case RTL_ROM_LMP_8821A:
11441228
case RTL_ROM_LMP_8761A:
11451229
case RTL_ROM_LMP_8822B:
11461230
case RTL_ROM_LMP_8852A:
11471231
case RTL_ROM_LMP_8703B:
11481232
case RTL_ROM_LMP_8851B:
1149-
return btrtl_setup_rtl8723b(hdev, btrtl_dev);
1233+
err = btrtl_setup_rtl8723b(hdev, btrtl_dev);
1234+
break;
11501235
default:
11511236
rtl_dev_info(hdev, "assuming no firmware upload needed");
1152-
return 0;
1237+
break;
11531238
}
1239+
1240+
done:
1241+
if (!err)
1242+
err = btrtl_register_devcoredump_support(hdev);
1243+
1244+
return err;
11541245
}
11551246
EXPORT_SYMBOL_GPL(btrtl_download_firmware);
11561247

0 commit comments

Comments
 (0)