Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <abhishekpandit@chromium.org>
Signed-off-by: Manish Mandlik <mmandlik@google.com>
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Reviewed-by: Chethan Tumkur Narayan <chethan.tumkur.narayan@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

authored by

Abhishek Pandit-Subedi and committed by
Luiz Augusto von Dentz
af395330 4f9c1a08

+128 -10
+71 -1
drivers/bluetooth/btintel.c
··· 43 43 u8 fw_build_yy; 44 44 } __packed; 45 45 46 + static struct { 47 + const char *driver_name; 48 + u8 hw_variant; 49 + u32 fw_build_num; 50 + } coredump_info; 51 + 46 52 int btintel_check_bdaddr(struct hci_dev *hdev) 47 53 { 48 54 struct hci_rp_read_bd_addr *bda; ··· 321 315 return -EINVAL; 322 316 } 323 317 318 + coredump_info.hw_variant = ver->hw_variant; 319 + coredump_info.fw_build_num = ver->fw_build_num; 320 + 324 321 bt_dev_info(hdev, "%s revision %u.%u build %u week %u %u", 325 322 variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f, 326 323 ver->fw_build_num, ver->fw_build_ww, ··· 517 508 bt_dev_err(hdev, "Unsupported image type(%02x)", version->img_type); 518 509 return -EINVAL; 519 510 } 511 + 512 + coredump_info.hw_variant = INTEL_HW_VARIANT(version->cnvi_bt); 513 + coredump_info.fw_build_num = version->build_num; 520 514 521 515 bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant, 522 516 2000 + (version->timestamp >> 8), version->timestamp & 0xff, ··· 1473 1461 return err; 1474 1462 } 1475 1463 EXPORT_SYMBOL_GPL(btintel_set_quality_report); 1464 + 1465 + static void btintel_coredump(struct hci_dev *hdev) 1466 + { 1467 + struct sk_buff *skb; 1468 + 1469 + skb = __hci_cmd_sync(hdev, 0xfc4e, 0, NULL, HCI_CMD_TIMEOUT); 1470 + if (IS_ERR(skb)) { 1471 + bt_dev_err(hdev, "Coredump failed (%ld)", PTR_ERR(skb)); 1472 + return; 1473 + } 1474 + 1475 + kfree_skb(skb); 1476 + } 1477 + 1478 + static void btintel_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb) 1479 + { 1480 + char buf[80]; 1481 + 1482 + snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n", 1483 + coredump_info.hw_variant); 1484 + skb_put_data(skb, buf, strlen(buf)); 1485 + 1486 + snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n", 1487 + coredump_info.fw_build_num); 1488 + skb_put_data(skb, buf, strlen(buf)); 1489 + 1490 + snprintf(buf, sizeof(buf), "Driver: %s\n", coredump_info.driver_name); 1491 + skb_put_data(skb, buf, strlen(buf)); 1492 + 1493 + snprintf(buf, sizeof(buf), "Vendor: Intel\n"); 1494 + skb_put_data(skb, buf, strlen(buf)); 1495 + } 1496 + 1497 + static int btintel_register_devcoredump_support(struct hci_dev *hdev) 1498 + { 1499 + struct intel_debug_features features; 1500 + int err; 1501 + 1502 + err = btintel_read_debug_features(hdev, &features); 1503 + if (err) { 1504 + bt_dev_info(hdev, "Error reading debug features"); 1505 + return err; 1506 + } 1507 + 1508 + if (!(features.page1[0] & 0x3f)) { 1509 + bt_dev_dbg(hdev, "Telemetry exception format not supported"); 1510 + return -EOPNOTSUPP; 1511 + } 1512 + 1513 + hci_devcd_register(hdev, btintel_coredump, btintel_dmp_hdr, NULL); 1514 + 1515 + return err; 1516 + } 1476 1517 1477 1518 static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev, 1478 1519 struct intel_version *ver) ··· 2662 2597 btintel_set_msft_opcode(hdev, ver.hw_variant); 2663 2598 2664 2599 err = btintel_bootloader_setup(hdev, &ver); 2600 + btintel_register_devcoredump_support(hdev); 2665 2601 break; 2666 2602 default: 2667 2603 bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", ··· 2736 2670 btintel_set_msft_opcode(hdev, ver.hw_variant); 2737 2671 2738 2672 err = btintel_bootloader_setup(hdev, &ver); 2673 + btintel_register_devcoredump_support(hdev); 2739 2674 break; 2740 2675 case 0x17: 2741 2676 case 0x18: ··· 2759 2692 INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); 2760 2693 2761 2694 err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); 2695 + btintel_register_devcoredump_support(hdev); 2762 2696 break; 2763 2697 default: 2764 2698 bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", ··· 2809 2741 return 0; 2810 2742 } 2811 2743 2812 - int btintel_configure_setup(struct hci_dev *hdev) 2744 + int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name) 2813 2745 { 2814 2746 hdev->manufacturer = 2; 2815 2747 hdev->setup = btintel_setup_combined; ··· 2817 2749 hdev->hw_error = btintel_hw_error; 2818 2750 hdev->set_diag = btintel_set_diag_combined; 2819 2751 hdev->set_bdaddr = btintel_set_bdaddr; 2752 + 2753 + coredump_info.driver_name = driver_name; 2820 2754 2821 2755 return 0; 2822 2756 }
+10 -2
drivers/bluetooth/btintel.h
··· 143 143 __le32 delta; 144 144 } __packed; 145 145 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 + 146 153 #define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8)) 147 154 #define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16)) 148 155 #define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff) ··· 219 212 struct intel_boot_params *params); 220 213 int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, 221 214 const struct firmware *fw, u32 *boot_param); 222 - int btintel_configure_setup(struct hci_dev *hdev); 215 + int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name); 223 216 void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len); 224 217 void btintel_secure_send_result(struct hci_dev *hdev, 225 218 const void *ptr, unsigned int len); ··· 300 293 return -EOPNOTSUPP; 301 294 } 302 295 303 - static inline int btintel_configure_setup(struct hci_dev *hdev) 296 + static inline int btintel_configure_setup(struct hci_dev *hdev, 297 + const char *driver_name) 304 298 { 305 299 return -ENODEV; 306 300 }
+47 -7
drivers/bluetooth/btusb.c
··· 2386 2386 return btusb_recv_bulk(data, buffer, count); 2387 2387 } 2388 2388 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 + 2389 2419 static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) 2390 2420 { 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 }; 2393 2423 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; 2398 2428 2429 + if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) { 2399 2430 switch (skb->data[2]) { 2400 2431 case 0x02: 2401 2432 /* When switching to the operational firmware ··· 2444 2413 btintel_secure_send_result(hdev, ptr, len); 2445 2414 break; 2446 2415 } 2416 + } 2417 + 2418 + /* Handle all diagnostics events separately. May still call 2419 + * hci_recv_frame. 2420 + */ 2421 + if (len >= sizeof(diagnostics_hdr) && 2422 + memcmp(&skb->data[2], diagnostics_hdr, 2423 + sizeof(diagnostics_hdr)) == 0) { 2424 + return btusb_intel_diagnostics(hdev, skb); 2447 2425 } 2448 2426 } 2449 2427 ··· 4058 4018 4059 4019 /* Combined Intel Device setup to support multiple setup routine */ 4060 4020 if (id->driver_info & BTUSB_INTEL_COMBINED) { 4061 - err = btintel_configure_setup(hdev); 4021 + err = btintel_configure_setup(hdev, btusb_driver.name); 4062 4022 if (err) 4063 4023 goto out_free_dev; 4064 4024