Skip to content

Commit af39533

Browse files
apanditVudentz
authored andcommitted
Bluetooth: btintel: Add Intel devcoredump support
Intercept debug exception events from the controller and put them into a devcoredump using hci devcoredump APIs. The debug exception contains data in a TLV format and it will be parsed in userspace. Signed-off-by: Abhishek Pandit-Subedi <[email protected]> Signed-off-by: Manish Mandlik <[email protected]> Reviewed-by: Abhishek Pandit-Subedi <[email protected]> Reviewed-by: Chethan Tumkur Narayan <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 4f9c1a0 commit af39533

File tree

3 files changed

+128
-10
lines changed

3 files changed

+128
-10
lines changed

drivers/bluetooth/btintel.c

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ struct cmd_write_boot_params {
4343
u8 fw_build_yy;
4444
} __packed;
4545

46+
static struct {
47+
const char *driver_name;
48+
u8 hw_variant;
49+
u32 fw_build_num;
50+
} coredump_info;
51+
4652
int btintel_check_bdaddr(struct hci_dev *hdev)
4753
{
4854
struct hci_rp_read_bd_addr *bda;
@@ -315,6 +321,9 @@ int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
315321
return -EINVAL;
316322
}
317323

324+
coredump_info.hw_variant = ver->hw_variant;
325+
coredump_info.fw_build_num = ver->fw_build_num;
326+
318327
bt_dev_info(hdev, "%s revision %u.%u build %u week %u %u",
319328
variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f,
320329
ver->fw_build_num, ver->fw_build_ww,
@@ -509,6 +518,9 @@ static int btintel_version_info_tlv(struct hci_dev *hdev,
509518
return -EINVAL;
510519
}
511520

521+
coredump_info.hw_variant = INTEL_HW_VARIANT(version->cnvi_bt);
522+
coredump_info.fw_build_num = version->build_num;
523+
512524
bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant,
513525
2000 + (version->timestamp >> 8), version->timestamp & 0xff,
514526
version->build_type, version->build_num);
@@ -1462,6 +1474,59 @@ int btintel_set_quality_report(struct hci_dev *hdev, bool enable)
14621474
}
14631475
EXPORT_SYMBOL_GPL(btintel_set_quality_report);
14641476

1477+
static void btintel_coredump(struct hci_dev *hdev)
1478+
{
1479+
struct sk_buff *skb;
1480+
1481+
skb = __hci_cmd_sync(hdev, 0xfc4e, 0, NULL, HCI_CMD_TIMEOUT);
1482+
if (IS_ERR(skb)) {
1483+
bt_dev_err(hdev, "Coredump failed (%ld)", PTR_ERR(skb));
1484+
return;
1485+
}
1486+
1487+
kfree_skb(skb);
1488+
}
1489+
1490+
static void btintel_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb)
1491+
{
1492+
char buf[80];
1493+
1494+
snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
1495+
coredump_info.hw_variant);
1496+
skb_put_data(skb, buf, strlen(buf));
1497+
1498+
snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
1499+
coredump_info.fw_build_num);
1500+
skb_put_data(skb, buf, strlen(buf));
1501+
1502+
snprintf(buf, sizeof(buf), "Driver: %s\n", coredump_info.driver_name);
1503+
skb_put_data(skb, buf, strlen(buf));
1504+
1505+
snprintf(buf, sizeof(buf), "Vendor: Intel\n");
1506+
skb_put_data(skb, buf, strlen(buf));
1507+
}
1508+
1509+
static int btintel_register_devcoredump_support(struct hci_dev *hdev)
1510+
{
1511+
struct intel_debug_features features;
1512+
int err;
1513+
1514+
err = btintel_read_debug_features(hdev, &features);
1515+
if (err) {
1516+
bt_dev_info(hdev, "Error reading debug features");
1517+
return err;
1518+
}
1519+
1520+
if (!(features.page1[0] & 0x3f)) {
1521+
bt_dev_dbg(hdev, "Telemetry exception format not supported");
1522+
return -EOPNOTSUPP;
1523+
}
1524+
1525+
hci_devcd_register(hdev, btintel_coredump, btintel_dmp_hdr, NULL);
1526+
1527+
return err;
1528+
}
1529+
14651530
static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev,
14661531
struct intel_version *ver)
14671532
{
@@ -2597,6 +2662,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
25972662
btintel_set_msft_opcode(hdev, ver.hw_variant);
25982663

25992664
err = btintel_bootloader_setup(hdev, &ver);
2665+
btintel_register_devcoredump_support(hdev);
26002666
break;
26012667
default:
26022668
bt_dev_err(hdev, "Unsupported Intel hw variant (%u)",
@@ -2670,6 +2736,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
26702736
btintel_set_msft_opcode(hdev, ver.hw_variant);
26712737

26722738
err = btintel_bootloader_setup(hdev, &ver);
2739+
btintel_register_devcoredump_support(hdev);
26732740
break;
26742741
case 0x17:
26752742
case 0x18:
@@ -2692,6 +2759,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
26922759
INTEL_HW_VARIANT(ver_tlv.cnvi_bt));
26932760

26942761
err = btintel_bootloader_setup_tlv(hdev, &ver_tlv);
2762+
btintel_register_devcoredump_support(hdev);
26952763
break;
26962764
default:
26972765
bt_dev_err(hdev, "Unsupported Intel hw variant (%u)",
@@ -2741,7 +2809,7 @@ static int btintel_shutdown_combined(struct hci_dev *hdev)
27412809
return 0;
27422810
}
27432811

2744-
int btintel_configure_setup(struct hci_dev *hdev)
2812+
int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name)
27452813
{
27462814
hdev->manufacturer = 2;
27472815
hdev->setup = btintel_setup_combined;
@@ -2750,6 +2818,8 @@ int btintel_configure_setup(struct hci_dev *hdev)
27502818
hdev->set_diag = btintel_set_diag_combined;
27512819
hdev->set_bdaddr = btintel_set_bdaddr;
27522820

2821+
coredump_info.driver_name = driver_name;
2822+
27532823
return 0;
27542824
}
27552825
EXPORT_SYMBOL_GPL(btintel_configure_setup);

drivers/bluetooth/btintel.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ struct btintel_loc_aware_reg {
143143
__le32 delta;
144144
} __packed;
145145

146+
#define INTEL_TLV_TYPE_ID 0x01
147+
148+
#define INTEL_TLV_SYSTEM_EXCEPTION 0x00
149+
#define INTEL_TLV_FATAL_EXCEPTION 0x01
150+
#define INTEL_TLV_DEBUG_EXCEPTION 0x02
151+
#define INTEL_TLV_TEST_EXCEPTION 0xDE
152+
146153
#define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8))
147154
#define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16))
148155
#define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)
@@ -212,7 +219,7 @@ int btintel_read_boot_params(struct hci_dev *hdev,
212219
struct intel_boot_params *params);
213220
int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver,
214221
const struct firmware *fw, u32 *boot_param);
215-
int btintel_configure_setup(struct hci_dev *hdev);
222+
int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name);
216223
void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len);
217224
void btintel_secure_send_result(struct hci_dev *hdev,
218225
const void *ptr, unsigned int len);
@@ -293,7 +300,8 @@ static inline int btintel_download_firmware(struct hci_dev *dev,
293300
return -EOPNOTSUPP;
294301
}
295302

296-
static inline int btintel_configure_setup(struct hci_dev *hdev)
303+
static inline int btintel_configure_setup(struct hci_dev *hdev,
304+
const char *driver_name)
297305
{
298306
return -ENODEV;
299307
}

drivers/bluetooth/btusb.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,16 +2386,47 @@ static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer,
23862386
return btusb_recv_bulk(data, buffer, count);
23872387
}
23882388

2389+
static int btusb_intel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
2390+
{
2391+
struct intel_tlv *tlv = (void *)&skb->data[5];
2392+
2393+
/* The first event is always an event type TLV */
2394+
if (tlv->type != INTEL_TLV_TYPE_ID)
2395+
goto recv_frame;
2396+
2397+
switch (tlv->val[0]) {
2398+
case INTEL_TLV_SYSTEM_EXCEPTION:
2399+
case INTEL_TLV_FATAL_EXCEPTION:
2400+
case INTEL_TLV_DEBUG_EXCEPTION:
2401+
case INTEL_TLV_TEST_EXCEPTION:
2402+
/* Generate devcoredump from exception */
2403+
if (!hci_devcd_init(hdev, skb->len)) {
2404+
hci_devcd_append(hdev, skb);
2405+
hci_devcd_complete(hdev);
2406+
} else {
2407+
bt_dev_err(hdev, "Failed to generate devcoredump");
2408+
kfree_skb(skb);
2409+
}
2410+
return 0;
2411+
default:
2412+
bt_dev_err(hdev, "Invalid exception type %02X", tlv->val[0]);
2413+
}
2414+
2415+
recv_frame:
2416+
return hci_recv_frame(hdev, skb);
2417+
}
2418+
23892419
static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)
23902420
{
2391-
if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
2392-
struct hci_event_hdr *hdr = (void *)skb->data;
2421+
struct hci_event_hdr *hdr = (void *)skb->data;
2422+
const char diagnostics_hdr[] = { 0x87, 0x80, 0x03 };
23932423

2394-
if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff &&
2395-
hdr->plen > 0) {
2396-
const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1;
2397-
unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1;
2424+
if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff &&
2425+
hdr->plen > 0) {
2426+
const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1;
2427+
unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1;
23982428

2429+
if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
23992430
switch (skb->data[2]) {
24002431
case 0x02:
24012432
/* When switching to the operational firmware
@@ -2414,6 +2445,15 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)
24142445
break;
24152446
}
24162447
}
2448+
2449+
/* Handle all diagnostics events separately. May still call
2450+
* hci_recv_frame.
2451+
*/
2452+
if (len >= sizeof(diagnostics_hdr) &&
2453+
memcmp(&skb->data[2], diagnostics_hdr,
2454+
sizeof(diagnostics_hdr)) == 0) {
2455+
return btusb_intel_diagnostics(hdev, skb);
2456+
}
24172457
}
24182458

24192459
return hci_recv_frame(hdev, skb);
@@ -4018,7 +4058,7 @@ static int btusb_probe(struct usb_interface *intf,
40184058

40194059
/* Combined Intel Device setup to support multiple setup routine */
40204060
if (id->driver_info & BTUSB_INTEL_COMBINED) {
4021-
err = btintel_configure_setup(hdev);
4061+
err = btintel_configure_setup(hdev, btusb_driver.name);
40224062
if (err)
40234063
goto out_free_dev;
40244064

0 commit comments

Comments
 (0)