Skip to content

Commit e3c4891

Browse files
NeerajSanjayKaleVudentz
authored andcommitted
Bluetooth: btnxpuart: Handle FW Download Abort scenario
This adds a new flag BTNXPUART_FW_DOWNLOAD_ABORT which handles the situation where driver is removed while firmware download is in progress. logs: modprobe btnxpuart [65239.230431] Bluetooth: hci0: ChipID: 7601, Version: 0 [65239.236670] Bluetooth: hci0: Request Firmware: nxp/uartspi_n61x_v1.bin.se rmmod btnxpuart [65241.425300] Bluetooth: hci0: FW Download Aborted Signed-off-by: Neeraj Sanjay Kale <[email protected]> Tested-by: Guillaume Legoupil <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 2684dd6 commit e3c4891

File tree

1 file changed

+33
-14
lines changed

1 file changed

+33
-14
lines changed

drivers/bluetooth/btnxpuart.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define BTNXPUART_CHECK_BOOT_SIGNATURE 3
3030
#define BTNXPUART_SERDEV_OPEN 4
3131
#define BTNXPUART_IR_IN_PROGRESS 5
32+
#define BTNXPUART_FW_DOWNLOAD_ABORT 6
3233

3334
/* NXP HW err codes */
3435
#define BTNXPUART_IR_HW_ERR 0xb0
@@ -159,6 +160,7 @@ struct btnxpuart_dev {
159160
u8 fw_name[MAX_FW_FILE_NAME_LEN];
160161
u32 fw_dnld_v1_offset;
161162
u32 fw_v1_sent_bytes;
163+
u32 fw_dnld_v3_offset;
162164
u32 fw_v3_offset_correction;
163165
u32 fw_v1_expected_len;
164166
u32 boot_reg_offset;
@@ -550,6 +552,7 @@ static int nxp_download_firmware(struct hci_dev *hdev)
550552
nxpdev->fw_v1_sent_bytes = 0;
551553
nxpdev->fw_v1_expected_len = HDR_LEN;
552554
nxpdev->boot_reg_offset = 0;
555+
nxpdev->fw_dnld_v3_offset = 0;
553556
nxpdev->fw_v3_offset_correction = 0;
554557
nxpdev->baudrate_changed = false;
555558
nxpdev->timeout_changed = false;
@@ -564,14 +567,23 @@ static int nxp_download_firmware(struct hci_dev *hdev)
564567
!test_bit(BTNXPUART_FW_DOWNLOADING,
565568
&nxpdev->tx_state),
566569
msecs_to_jiffies(60000));
570+
571+
release_firmware(nxpdev->fw);
572+
memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
573+
567574
if (err == 0) {
568-
bt_dev_err(hdev, "FW Download Timeout.");
575+
bt_dev_err(hdev, "FW Download Timeout. offset: %d",
576+
nxpdev->fw_dnld_v1_offset ?
577+
nxpdev->fw_dnld_v1_offset :
578+
nxpdev->fw_dnld_v3_offset);
569579
return -ETIMEDOUT;
570580
}
581+
if (test_bit(BTNXPUART_FW_DOWNLOAD_ABORT, &nxpdev->tx_state)) {
582+
bt_dev_err(hdev, "FW Download Aborted");
583+
return -EINTR;
584+
}
571585

572586
serdev_device_set_flow_control(nxpdev->serdev, true);
573-
release_firmware(nxpdev->fw);
574-
memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
575587

576588
/* Allow the downloaded FW to initialize */
577589
msleep(1200);
@@ -955,8 +967,9 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
955967
goto free_skb;
956968
}
957969

958-
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data + offset -
959-
nxpdev->fw_v3_offset_correction, len);
970+
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
971+
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
972+
nxpdev->fw_dnld_v3_offset, len);
960973

961974
free_skb:
962975
kfree_skb(skb);
@@ -1390,16 +1403,22 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
13901403
struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
13911404
struct hci_dev *hdev = nxpdev->hdev;
13921405

1393-
/* Restore FW baudrate to fw_init_baudrate if changed.
1394-
* This will ensure FW baudrate is in sync with
1395-
* driver baudrate in case this driver is re-inserted.
1396-
*/
1397-
if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
1398-
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
1399-
nxp_set_baudrate_cmd(hdev, NULL);
1406+
if (is_fw_downloading(nxpdev)) {
1407+
set_bit(BTNXPUART_FW_DOWNLOAD_ABORT, &nxpdev->tx_state);
1408+
clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
1409+
wake_up_interruptible(&nxpdev->check_boot_sign_wait_q);
1410+
wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
1411+
} else {
1412+
/* Restore FW baudrate to fw_init_baudrate if changed.
1413+
* This will ensure FW baudrate is in sync with
1414+
* driver baudrate in case this driver is re-inserted.
1415+
*/
1416+
if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
1417+
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
1418+
nxp_set_baudrate_cmd(hdev, NULL);
1419+
}
1420+
ps_cancel_timer(nxpdev);
14001421
}
1401-
1402-
ps_cancel_timer(nxpdev);
14031422
hci_unregister_dev(hdev);
14041423
hci_free_dev(hdev);
14051424
}

0 commit comments

Comments
 (0)