@@ -733,6 +733,16 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
733733 {}
734734};
735735
736+ struct qca_dump_info {
737+ /* fields for dump collection */
738+ u16 id_vendor ;
739+ u16 id_product ;
740+ u32 fw_version ;
741+ u32 controller_id ;
742+ u32 ram_dump_size ;
743+ u16 ram_dump_seqno ;
744+ };
745+
736746#define BTUSB_MAX_ISOC_FRAMES 10
737747
738748#define BTUSB_INTR_RUNNING 0
@@ -752,6 +762,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
752762#define BTUSB_WAKEUP_AUTOSUSPEND 14
753763#define BTUSB_USE_ALT3_FOR_WBS 15
754764#define BTUSB_ALT6_CONTINUOUS_TX 16
765+ #define BTUSB_HW_SSR_ACTIVE 17
755766
756767struct btusb_data {
757768 struct hci_dev * hdev ;
@@ -814,6 +825,8 @@ struct btusb_data {
814825
815826 int oob_wake_irq ; /* irq for out-of-band wake-on-bt */
816827 unsigned cmd_timeout_cnt ;
828+
829+ struct qca_dump_info qca_dump ;
817830};
818831
819832static void btusb_reset (struct hci_dev * hdev )
@@ -904,6 +917,11 @@ static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
904917 struct btusb_data * data = hci_get_drvdata (hdev );
905918 struct gpio_desc * reset_gpio = data -> reset_gpio ;
906919
920+ if (test_bit (BTUSB_HW_SSR_ACTIVE , & data -> flags )) {
921+ bt_dev_info (hdev , "Ramdump in progress, defer cmd_timeout" );
922+ return ;
923+ }
924+
907925 if (++ data -> cmd_timeout_cnt < 5 )
908926 return ;
909927
@@ -3294,6 +3312,202 @@ static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
32943312 return 0 ;
32953313}
32963314
3315+ #define QCA_MEMDUMP_ACL_HANDLE 0x2EDD
3316+ #define QCA_MEMDUMP_SIZE_MAX 0x100000
3317+ #define QCA_MEMDUMP_VSE_CLASS 0x01
3318+ #define QCA_MEMDUMP_MSG_TYPE 0x08
3319+ #define QCA_MEMDUMP_PKT_SIZE 248
3320+ #define QCA_LAST_SEQUENCE_NUM 0xffff
3321+
3322+ struct qca_dump_hdr {
3323+ u8 vse_class ;
3324+ u8 msg_type ;
3325+ __le16 seqno ;
3326+ u8 reserved ;
3327+ union {
3328+ u8 data [0 ];
3329+ struct {
3330+ __le32 ram_dump_size ;
3331+ u8 data0 [0 ];
3332+ } __packed ;
3333+ };
3334+ } __packed ;
3335+
3336+
3337+ static void btusb_dump_hdr_qca (struct hci_dev * hdev , struct sk_buff * skb )
3338+ {
3339+ char buf [128 ];
3340+ struct btusb_data * btdata = hci_get_drvdata (hdev );
3341+
3342+ snprintf (buf , sizeof (buf ), "Controller Name: 0x%x\n" ,
3343+ btdata -> qca_dump .controller_id );
3344+ skb_put_data (skb , buf , strlen (buf ));
3345+
3346+ snprintf (buf , sizeof (buf ), "Firmware Version: 0x%x\n" ,
3347+ btdata -> qca_dump .fw_version );
3348+ skb_put_data (skb , buf , strlen (buf ));
3349+
3350+ snprintf (buf , sizeof (buf ), "Driver: %s\nVendor: qca\n" ,
3351+ btusb_driver .name );
3352+ skb_put_data (skb , buf , strlen (buf ));
3353+
3354+ snprintf (buf , sizeof (buf ), "VID: 0x%x\nPID:0x%x\n" ,
3355+ btdata -> qca_dump .id_vendor , btdata -> qca_dump .id_product );
3356+ skb_put_data (skb , buf , strlen (buf ));
3357+
3358+ snprintf (buf , sizeof (buf ), "Lmp Subversion: 0x%x\n" ,
3359+ hdev -> lmp_subver );
3360+ skb_put_data (skb , buf , strlen (buf ));
3361+ }
3362+
3363+ static void btusb_coredump_qca (struct hci_dev * hdev )
3364+ {
3365+ static const u8 param [] = { 0x26 };
3366+ struct sk_buff * skb ;
3367+
3368+ skb = __hci_cmd_sync (hdev , 0xfc0c , 1 , param , HCI_CMD_TIMEOUT );
3369+ if (IS_ERR (skb ))
3370+ bt_dev_err (hdev , "%s: triggle crash failed (%ld)" , __func__ , PTR_ERR (skb ));
3371+ kfree_skb (skb );
3372+ }
3373+
3374+ /*
3375+ * ==0: not a dump pkt.
3376+ * < 0: fails to handle a dump pkt
3377+ * > 0: otherwise.
3378+ */
3379+ static int handle_dump_pkt_qca (struct hci_dev * hdev , struct sk_buff * skb )
3380+ {
3381+ int ret = 1 ;
3382+ u8 pkt_type ;
3383+ u8 * sk_ptr ;
3384+ unsigned int sk_len ;
3385+ u16 seqno ;
3386+ u32 dump_size ;
3387+
3388+ struct hci_event_hdr * event_hdr ;
3389+ struct hci_acl_hdr * acl_hdr ;
3390+ struct qca_dump_hdr * dump_hdr ;
3391+ struct btusb_data * btdata = hci_get_drvdata (hdev );
3392+ struct usb_device * udev = btdata -> udev ;
3393+
3394+ pkt_type = hci_skb_pkt_type (skb );
3395+ sk_ptr = skb -> data ;
3396+ sk_len = skb -> len ;
3397+
3398+ if (pkt_type == HCI_ACLDATA_PKT ) {
3399+ acl_hdr = hci_acl_hdr (skb );
3400+ if (le16_to_cpu (acl_hdr -> handle ) != QCA_MEMDUMP_ACL_HANDLE )
3401+ return 0 ;
3402+ sk_ptr += HCI_ACL_HDR_SIZE ;
3403+ sk_len -= HCI_ACL_HDR_SIZE ;
3404+ event_hdr = (struct hci_event_hdr * )sk_ptr ;
3405+ } else {
3406+ event_hdr = hci_event_hdr (skb );
3407+ }
3408+
3409+ if ((event_hdr -> evt != HCI_VENDOR_PKT )
3410+ || (event_hdr -> plen != (sk_len - HCI_EVENT_HDR_SIZE )))
3411+ return 0 ;
3412+
3413+ sk_ptr += HCI_EVENT_HDR_SIZE ;
3414+ sk_len -= HCI_EVENT_HDR_SIZE ;
3415+
3416+ dump_hdr = (struct qca_dump_hdr * )sk_ptr ;
3417+ if ((sk_len < offsetof(struct qca_dump_hdr , data ))
3418+ || (dump_hdr -> vse_class != QCA_MEMDUMP_VSE_CLASS )
3419+ || (dump_hdr -> msg_type != QCA_MEMDUMP_MSG_TYPE ))
3420+ return 0 ;
3421+
3422+ /*it is dump pkt now*/
3423+ seqno = le16_to_cpu (dump_hdr -> seqno );
3424+ if (seqno == 0 ) {
3425+ set_bit (BTUSB_HW_SSR_ACTIVE , & btdata -> flags );
3426+ dump_size = le32_to_cpu (dump_hdr -> ram_dump_size );
3427+ if (!dump_size || (dump_size > QCA_MEMDUMP_SIZE_MAX )) {
3428+ ret = - EILSEQ ;
3429+ bt_dev_err (hdev , "Invalid memdump size(%u)" ,
3430+ dump_size );
3431+ goto out ;
3432+ }
3433+
3434+ ret = hci_devcd_init (hdev , dump_size );
3435+ if (ret < 0 ) {
3436+ bt_dev_err (hdev , "memdump init error(%d)" , ret );
3437+ goto out ;
3438+ }
3439+
3440+ btdata -> qca_dump .ram_dump_size = dump_size ;
3441+ btdata -> qca_dump .ram_dump_seqno = 0 ;
3442+ sk_ptr += offsetof(struct qca_dump_hdr , data0 );
3443+ sk_len -= offsetof(struct qca_dump_hdr , data0 );
3444+
3445+ usb_disable_autosuspend (udev );
3446+ bt_dev_info (hdev , "%s memdump size(%u)\n" ,
3447+ (pkt_type == HCI_ACLDATA_PKT ) ? "ACL" : "event" ,
3448+ dump_size );
3449+ } else {
3450+ sk_ptr += offsetof(struct qca_dump_hdr , data );
3451+ sk_len -= offsetof(struct qca_dump_hdr , data );
3452+ }
3453+
3454+ if (!btdata -> qca_dump .ram_dump_size ) {
3455+ ret = - EINVAL ;
3456+ bt_dev_err (hdev , "memdump is not active" );
3457+ goto out ;
3458+ }
3459+
3460+ if ((seqno > btdata -> qca_dump .ram_dump_seqno + 1 ) && (seqno != QCA_LAST_SEQUENCE_NUM )) {
3461+ dump_size = QCA_MEMDUMP_PKT_SIZE * (seqno - btdata -> qca_dump .ram_dump_seqno - 1 );
3462+ hci_devcd_append_pattern (hdev , 0x0 , dump_size );
3463+ bt_dev_err (hdev ,
3464+ "expected memdump seqno(%u) is not received(%u)\n" ,
3465+ btdata -> qca_dump .ram_dump_seqno , seqno );
3466+ btdata -> qca_dump .ram_dump_seqno = seqno ;
3467+ kfree_skb (skb );
3468+ return ret ;
3469+ }
3470+
3471+ skb_pull (skb , skb -> len - sk_len );
3472+ hci_devcd_append (hdev , skb );
3473+ btdata -> qca_dump .ram_dump_seqno ++ ;
3474+ if (seqno == QCA_LAST_SEQUENCE_NUM ) {
3475+ bt_dev_info (hdev ,
3476+ "memdump done: pkts(%u), total(%u)\n" ,
3477+ btdata -> qca_dump .ram_dump_seqno , btdata -> qca_dump .ram_dump_size );
3478+
3479+ hci_devcd_complete (hdev );
3480+ goto out ;
3481+ }
3482+ return ret ;
3483+
3484+ out :
3485+ if (btdata -> qca_dump .ram_dump_size )
3486+ usb_enable_autosuspend (udev );
3487+ btdata -> qca_dump .ram_dump_size = 0 ;
3488+ btdata -> qca_dump .ram_dump_seqno = 0 ;
3489+ clear_bit (BTUSB_HW_SSR_ACTIVE , & btdata -> flags );
3490+
3491+ if (ret < 0 )
3492+ kfree_skb (skb );
3493+ return ret ;
3494+ }
3495+
3496+ static int btusb_recv_acl_qca (struct hci_dev * hdev , struct sk_buff * skb )
3497+ {
3498+ if (handle_dump_pkt_qca (hdev , skb ))
3499+ return 0 ;
3500+ return hci_recv_frame (hdev , skb );
3501+ }
3502+
3503+ static int btusb_recv_evt_qca (struct hci_dev * hdev , struct sk_buff * skb )
3504+ {
3505+ if (handle_dump_pkt_qca (hdev , skb ))
3506+ return 0 ;
3507+ return hci_recv_frame (hdev , skb );
3508+ }
3509+
3510+
32973511#define QCA_DFU_PACKET_LEN 4096
32983512
32993513#define QCA_GET_TARGET_VERSION 0x09
@@ -3628,6 +3842,9 @@ static int btusb_setup_qca(struct hci_dev *hdev)
36283842 if (err < 0 )
36293843 return err ;
36303844
3845+ btdata -> qca_dump .fw_version = le32_to_cpu (ver .patch_version );
3846+ btdata -> qca_dump .controller_id = le32_to_cpu (ver .rom_version );
3847+
36313848 if (!(status & QCA_SYSCFG_UPDATED )) {
36323849 err = btusb_setup_qca_load_nvm (hdev , & ver , info );
36333850 if (err < 0 )
@@ -4117,6 +4334,11 @@ static int btusb_probe(struct usb_interface *intf,
41174334 }
41184335
41194336 if (id -> driver_info & BTUSB_QCA_WCN6855 ) {
4337+ data -> qca_dump .id_vendor = id -> idVendor ;
4338+ data -> qca_dump .id_product = id -> idProduct ;
4339+ data -> recv_event = btusb_recv_evt_qca ;
4340+ data -> recv_acl = btusb_recv_acl_qca ;
4341+ hci_devcd_register (hdev , btusb_coredump_qca , btusb_dump_hdr_qca , NULL );
41204342 data -> setup_on_usb = btusb_setup_qca ;
41214343 hdev -> shutdown = btusb_shutdown_qca ;
41224344 hdev -> set_bdaddr = btusb_set_bdaddr_wcn6855 ;
0 commit comments