3131#define BTNXPUART_SERDEV_OPEN 4
3232#define BTNXPUART_IR_IN_PROGRESS 5
3333#define BTNXPUART_FW_DOWNLOAD_ABORT 6
34+ #define BTNXPUART_FW_DUMP_IN_PROGRESS 7
3435
3536/* NXP HW err codes */
3637#define BTNXPUART_IR_HW_ERR 0xb0
106107#define HCI_NXP_SET_OPER_SPEED 0xfc09
107108/* Bluetooth vendor command: Independent Reset */
108109#define HCI_NXP_IND_RESET 0xfcfc
110+ /* Bluetooth vendor command: Trigger FW dump */
111+ #define HCI_NXP_TRIGGER_DUMP 0xfe91
109112
110113/* Bluetooth Power State : Vendor cmd params */
111114#define BT_PS_ENABLE 0x02
@@ -310,6 +313,16 @@ union nxp_v3_rx_timeout_nak_u {
310313 u8 buf [6 ];
311314};
312315
316+ /* FW dump */
317+ #define NXP_FW_DUMP_SIZE (1024 * 1000)
318+
319+ struct nxp_fw_dump_hdr {
320+ __le16 seq_num ;
321+ __le16 reserved ;
322+ __le16 buf_type ;
323+ __le16 buf_len ;
324+ };
325+
313326static u8 crc8_table [CRC8_TABLE_SIZE ];
314327
315328/* Default configurations */
@@ -774,6 +787,16 @@ static bool is_fw_downloading(struct btnxpuart_dev *nxpdev)
774787 return test_bit (BTNXPUART_FW_DOWNLOADING , & nxpdev -> tx_state );
775788}
776789
790+ static bool ind_reset_in_progress (struct btnxpuart_dev * nxpdev )
791+ {
792+ return test_bit (BTNXPUART_IR_IN_PROGRESS , & nxpdev -> tx_state );
793+ }
794+
795+ static bool fw_dump_in_progress (struct btnxpuart_dev * nxpdev )
796+ {
797+ return test_bit (BTNXPUART_FW_DUMP_IN_PROGRESS , & nxpdev -> tx_state );
798+ }
799+
777800static bool process_boot_signature (struct btnxpuart_dev * nxpdev )
778801{
779802 if (test_bit (BTNXPUART_CHECK_BOOT_SIGNATURE , & nxpdev -> tx_state )) {
@@ -1175,7 +1198,7 @@ static int nxp_set_baudrate_cmd(struct hci_dev *hdev, void *data)
11751198static int nxp_check_boot_sign (struct btnxpuart_dev * nxpdev )
11761199{
11771200 serdev_device_set_baudrate (nxpdev -> serdev , HCI_NXP_PRI_BAUDRATE );
1178- if (test_bit ( BTNXPUART_IR_IN_PROGRESS , & nxpdev -> tx_state ))
1201+ if (ind_reset_in_progress ( nxpdev ))
11791202 serdev_device_set_flow_control (nxpdev -> serdev , false);
11801203 else
11811204 serdev_device_set_flow_control (nxpdev -> serdev , true);
@@ -1204,6 +1227,73 @@ static int nxp_set_ind_reset(struct hci_dev *hdev, void *data)
12041227 return hci_recv_frame (hdev , skb );
12051228}
12061229
1230+ /* Firmware dump */
1231+ static void nxp_coredump (struct hci_dev * hdev )
1232+ {
1233+ struct sk_buff * skb ;
1234+ u8 pcmd = 2 ;
1235+
1236+ skb = nxp_drv_send_cmd (hdev , HCI_NXP_TRIGGER_DUMP , 1 , & pcmd );
1237+ if (!IS_ERR (skb ))
1238+ kfree_skb (skb );
1239+ }
1240+
1241+ static void nxp_coredump_hdr (struct hci_dev * hdev , struct sk_buff * skb )
1242+ {
1243+ /* Nothing to be added in FW dump header */
1244+ }
1245+
1246+ static int nxp_process_fw_dump (struct hci_dev * hdev , struct sk_buff * skb )
1247+ {
1248+ struct hci_acl_hdr * acl_hdr = (struct hci_acl_hdr * )skb_pull_data (skb ,
1249+ sizeof (* acl_hdr ));
1250+ struct nxp_fw_dump_hdr * fw_dump_hdr = (struct nxp_fw_dump_hdr * )skb -> data ;
1251+ struct btnxpuart_dev * nxpdev = hci_get_drvdata (hdev );
1252+ __u16 seq_num = __le16_to_cpu (fw_dump_hdr -> seq_num );
1253+ __u16 buf_len = __le16_to_cpu (fw_dump_hdr -> buf_len );
1254+ int err ;
1255+
1256+ if (seq_num == 0x0001 ) {
1257+ if (test_and_set_bit (BTNXPUART_FW_DUMP_IN_PROGRESS , & nxpdev -> tx_state )) {
1258+ bt_dev_err (hdev , "FW dump already in progress" );
1259+ goto free_skb ;
1260+ }
1261+ bt_dev_warn (hdev , "==== Start FW dump ===" );
1262+ err = hci_devcd_init (hdev , NXP_FW_DUMP_SIZE );
1263+ if (err < 0 )
1264+ goto free_skb ;
1265+
1266+ schedule_delayed_work (& hdev -> dump .dump_timeout ,
1267+ msecs_to_jiffies (20000 ));
1268+ }
1269+
1270+ err = hci_devcd_append (hdev , skb_clone (skb , GFP_ATOMIC ));
1271+ if (err < 0 )
1272+ goto free_skb ;
1273+
1274+ if (buf_len == 0 ) {
1275+ bt_dev_warn (hdev , "==== FW dump complete ===" );
1276+ clear_bit (BTNXPUART_FW_DUMP_IN_PROGRESS , & nxpdev -> tx_state );
1277+ hci_devcd_complete (hdev );
1278+ nxp_set_ind_reset (hdev , NULL );
1279+ }
1280+
1281+ free_skb :
1282+ kfree_skb (skb );
1283+ return 0 ;
1284+ }
1285+
1286+ static int nxp_recv_acl_pkt (struct hci_dev * hdev , struct sk_buff * skb )
1287+ {
1288+ __u16 handle = __le16_to_cpu (hci_acl_hdr (skb )-> handle );
1289+
1290+ /* FW dump chunks are ACL packets with conn handle 0xfff */
1291+ if ((handle & 0x0FFF ) == 0xFFF )
1292+ return nxp_process_fw_dump (hdev , skb );
1293+ else
1294+ return hci_recv_frame (hdev , skb );
1295+ }
1296+
12071297/* NXP protocol */
12081298static int nxp_setup (struct hci_dev * hdev )
12091299{
@@ -1265,20 +1355,15 @@ static int nxp_shutdown(struct hci_dev *hdev)
12651355{
12661356 struct btnxpuart_dev * nxpdev = hci_get_drvdata (hdev );
12671357 struct sk_buff * skb ;
1268- u8 * status ;
12691358 u8 pcmd = 0 ;
12701359
1271- if (test_bit ( BTNXPUART_IR_IN_PROGRESS , & nxpdev -> tx_state )) {
1360+ if (ind_reset_in_progress ( nxpdev )) {
12721361 skb = nxp_drv_send_cmd (hdev , HCI_NXP_IND_RESET , 1 , & pcmd );
1273- if (IS_ERR (skb ))
1274- return PTR_ERR (skb );
1275-
1276- status = skb_pull_data (skb , 1 );
1277- if (status ) {
1278- serdev_device_set_flow_control (nxpdev -> serdev , false);
1279- set_bit (BTNXPUART_FW_DOWNLOADING , & nxpdev -> tx_state );
1280- }
1281- kfree_skb (skb );
1362+ serdev_device_set_flow_control (nxpdev -> serdev , false);
1363+ set_bit (BTNXPUART_FW_DOWNLOADING , & nxpdev -> tx_state );
1364+ /* HCI_NXP_IND_RESET command may not returns any response */
1365+ if (!IS_ERR (skb ))
1366+ kfree_skb (skb );
12821367 } else if (nxpdev -> current_baudrate != nxpdev -> fw_init_baudrate ) {
12831368 nxpdev -> new_baudrate = nxpdev -> fw_init_baudrate ;
12841369 nxp_set_baudrate_cmd (hdev , NULL );
@@ -1298,6 +1383,16 @@ static bool nxp_wakeup(struct hci_dev *hdev)
12981383 return false;
12991384}
13001385
1386+ static void nxp_reset (struct hci_dev * hdev )
1387+ {
1388+ struct btnxpuart_dev * nxpdev = hci_get_drvdata (hdev );
1389+
1390+ if (!ind_reset_in_progress (nxpdev ) && !fw_dump_in_progress (nxpdev )) {
1391+ bt_dev_dbg (hdev , "CMD Timeout detected. Resetting." );
1392+ nxp_set_ind_reset (hdev , NULL );
1393+ }
1394+ }
1395+
13011396static int btnxpuart_queue_skb (struct hci_dev * hdev , struct sk_buff * skb )
13021397{
13031398 struct btnxpuart_dev * nxpdev = hci_get_drvdata (hdev );
@@ -1318,6 +1413,9 @@ static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
13181413 struct wakeup_cmd_payload wakeup_parm ;
13191414 __le32 baudrate_parm ;
13201415
1416+ if (fw_dump_in_progress (nxpdev ))
1417+ return - EBUSY ;
1418+
13211419 /* if vendor commands are received from user space (e.g. hcitool), update
13221420 * driver flags accordingly and ask driver to re-send the command to FW.
13231421 * In case the payload for any command does not match expected payload
@@ -1486,7 +1584,7 @@ static int btnxpuart_flush(struct hci_dev *hdev)
14861584}
14871585
14881586static const struct h4_recv_pkt nxp_recv_pkts [] = {
1489- { H4_RECV_ACL , .recv = hci_recv_frame },
1587+ { H4_RECV_ACL , .recv = nxp_recv_acl_pkt },
14901588 { H4_RECV_SCO , .recv = hci_recv_frame },
14911589 { H4_RECV_EVENT , .recv = hci_recv_frame },
14921590 { H4_RECV_ISO , .recv = hci_recv_frame },
@@ -1508,11 +1606,13 @@ static size_t btnxpuart_receive_buf(struct serdev_device *serdev,
15081606 if (IS_ERR (nxpdev -> rx_skb )) {
15091607 int err = PTR_ERR (nxpdev -> rx_skb );
15101608 /* Safe to ignore out-of-sync bootloader signatures */
1511- if (!is_fw_downloading (nxpdev ))
1609+ if (!is_fw_downloading (nxpdev ) &&
1610+ !ind_reset_in_progress (nxpdev ))
15121611 bt_dev_err (nxpdev -> hdev , "Frame reassembly failed (%d)" , err );
15131612 return count ;
15141613 }
1515- if (!is_fw_downloading (nxpdev ))
1614+ if (!is_fw_downloading (nxpdev ) &&
1615+ !ind_reset_in_progress (nxpdev ))
15161616 nxpdev -> hdev -> stat .byte_rx += count ;
15171617 return count ;
15181618}
@@ -1580,6 +1680,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
15801680 hdev -> hw_error = nxp_hw_err ;
15811681 hdev -> shutdown = nxp_shutdown ;
15821682 hdev -> wakeup = nxp_wakeup ;
1683+ hdev -> reset = nxp_reset ;
15831684 SET_HCIDEV_DEV (hdev , & serdev -> dev );
15841685
15851686 if (hci_register_dev (hdev ) < 0 ) {
@@ -1590,6 +1691,8 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
15901691 if (ps_setup (hdev ))
15911692 goto probe_fail ;
15921693
1694+ hci_devcd_register (hdev , nxp_coredump , nxp_coredump_hdr , NULL );
1695+
15931696 return 0 ;
15941697
15951698probe_fail :
@@ -1641,6 +1744,17 @@ static int nxp_serdev_resume(struct device *dev)
16411744}
16421745#endif
16431746
1747+ #ifdef CONFIG_DEV_COREDUMP
1748+ static void nxp_serdev_coredump (struct device * dev )
1749+ {
1750+ struct btnxpuart_dev * nxpdev = dev_get_drvdata (dev );
1751+ struct hci_dev * hdev = nxpdev -> hdev ;
1752+
1753+ if (hdev -> dump .coredump )
1754+ hdev -> dump .coredump (hdev );
1755+ }
1756+ #endif
1757+
16441758static struct btnxpuart_data w8987_data __maybe_unused = {
16451759 .helper_fw_name = NULL ,
16461760 .fw_name = FIRMWARE_W8987 ,
@@ -1671,6 +1785,9 @@ static struct serdev_device_driver nxp_serdev_driver = {
16711785 .name = "btnxpuart" ,
16721786 .of_match_table = of_match_ptr (nxpuart_of_match_table ),
16731787 .pm = & nxp_pm_ops ,
1788+ #ifdef CONFIG_DEV_COREDUMP
1789+ .coredump = nxp_serdev_coredump ,
1790+ #endif
16741791 },
16751792};
16761793
0 commit comments