* [PATCH v1 1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump
@ 2025-07-03 13:05 Neeraj Sanjay Kale
2025-07-03 13:05 ` [PATCH v1 2/2] Bluetooth: btnxpuart: Add uevents for FW dump and FW download complete Neeraj Sanjay Kale
2025-07-03 14:08 ` [v1,1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump bluez.test.bot
0 siblings, 2 replies; 4+ messages in thread
From: Neeraj Sanjay Kale @ 2025-07-03 13:05 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar,
neeraj.sanjaykale, sherry.sun, manjeet.gupta, jean-yves.salaun
This adds proper handling for the independent reset command sent by the
driver after FW dump is complete.
In normal scenario, the independent reset vendor command gives a success
response before jumping to bootcode.
However, when FW goes in a bad state, and sends out FW dump packets, the
independent reset command does not get any response from the controller.
[ 159.807732] Bluetooth: hci0: ==== Start FW dump ===
[ 180.759060] Bluetooth: hci0: ==== FW dump complete ===
[ 182.779208] Bluetooth: hci0: command 0xfcfc tx timeout
[ 183.364974] Bluetooth: hci0: ChipID: 7601, Version: 0
[ 183.368490] Bluetooth: hci0: Request Firmware: nxp/uartspi_n61x_v1.bin.se
[ 184.679977] Bluetooth: hci0: FW Download Complete: 417064 bytes
[ 187.963102] Bluetooth: hci0: Opcode 0x0c03 failed: -110
As a fix for such scenario, the independent reset vendor command is sent
using the __hci_cmd_send() API, which does not expect any response for
vendor commands.
__hci_cmd_send is non blocking, so before the tx_work is scheduled, it
sometimes gets canceled and 3F|FC command is never sent. Adding a small
delay after __hci_cmd_send allows the command to be sent to the
controller.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Tested-by: Jean-Yves Salaün <jean-yves.salaun@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index c56b52bd8d98..f40794be2d89 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -367,17 +367,26 @@ static u8 crc8_table[CRC8_TABLE_SIZE];
static struct sk_buff *nxp_drv_send_cmd(struct hci_dev *hdev, u16 opcode,
u32 plen,
- void *param)
+ void *param,
+ bool resp)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
struct ps_data *psdata = &nxpdev->psdata;
- struct sk_buff *skb;
+ struct sk_buff *skb = NULL;
/* set flag to prevent nxp_enqueue from parsing values from this command and
* calling hci_cmd_sync_queue() again.
*/
psdata->driver_sent_cmd = true;
- skb = __hci_cmd_sync(hdev, opcode, plen, param, HCI_CMD_TIMEOUT);
+ if (resp) {
+ skb = __hci_cmd_sync(hdev, opcode, plen, param, HCI_CMD_TIMEOUT);
+ } else {
+ __hci_cmd_send(hdev, opcode, plen, param);
+ /* Allow command to be sent before tx_work is cancelled
+ * by btnxpuart_flush()
+ */
+ msleep(20);
+ }
psdata->driver_sent_cmd = false;
return skb;
@@ -597,7 +606,7 @@ static int send_ps_cmd(struct hci_dev *hdev, void *data)
pcmd.ps_cmd = BT_PS_DISABLE;
pcmd.c2h_ps_interval = __cpu_to_le16(psdata->c2h_ps_interval);
- skb = nxp_drv_send_cmd(hdev, HCI_NXP_AUTO_SLEEP_MODE, sizeof(pcmd), &pcmd);
+ skb = nxp_drv_send_cmd(hdev, HCI_NXP_AUTO_SLEEP_MODE, sizeof(pcmd), &pcmd, true);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Setting Power Save mode failed (%ld)", PTR_ERR(skb));
return PTR_ERR(skb);
@@ -646,7 +655,7 @@ static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data)
break;
}
- skb = nxp_drv_send_cmd(hdev, HCI_NXP_WAKEUP_METHOD, sizeof(pcmd), &pcmd);
+ skb = nxp_drv_send_cmd(hdev, HCI_NXP_WAKEUP_METHOD, sizeof(pcmd), &pcmd, true);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Setting wake-up method failed (%ld)", PTR_ERR(skb));
return PTR_ERR(skb);
@@ -1272,7 +1281,7 @@ static int nxp_set_baudrate_cmd(struct hci_dev *hdev, void *data)
if (!psdata)
return 0;
- skb = nxp_drv_send_cmd(hdev, HCI_NXP_SET_OPER_SPEED, 4, (u8 *)&new_baudrate);
+ skb = nxp_drv_send_cmd(hdev, HCI_NXP_SET_OPER_SPEED, 4, (u8 *)&new_baudrate, true);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Setting baudrate failed (%ld)", PTR_ERR(skb));
return PTR_ERR(skb);
@@ -1330,7 +1339,7 @@ static void nxp_coredump(struct hci_dev *hdev)
struct sk_buff *skb;
u8 pcmd = 2;
- skb = nxp_drv_send_cmd(hdev, HCI_NXP_TRIGGER_DUMP, 1, &pcmd);
+ skb = nxp_drv_send_cmd(hdev, HCI_NXP_TRIGGER_DUMP, 1, &pcmd, true);
if (IS_ERR(skb))
bt_dev_err(hdev, "Failed to trigger FW Dump. (%ld)", PTR_ERR(skb));
else
@@ -1372,7 +1381,6 @@ static int nxp_process_fw_dump(struct hci_dev *hdev, struct sk_buff *skb)
if (buf_len == 0) {
bt_dev_warn(hdev, "==== FW dump complete ===");
- clear_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state);
hci_devcd_complete(hdev);
nxp_set_ind_reset(hdev, NULL);
}
@@ -1486,7 +1494,13 @@ static int nxp_shutdown(struct hci_dev *hdev)
u8 pcmd = 0;
if (ind_reset_in_progress(nxpdev)) {
- skb = nxp_drv_send_cmd(hdev, HCI_NXP_IND_RESET, 1, &pcmd);
+ if (test_and_clear_bit(BTNXPUART_FW_DUMP_IN_PROGRESS,
+ &nxpdev->tx_state))
+ skb = nxp_drv_send_cmd(hdev, HCI_NXP_IND_RESET, 1,
+ &pcmd, false);
+ else
+ skb = nxp_drv_send_cmd(hdev, HCI_NXP_IND_RESET, 1,
+ &pcmd, true);
serdev_device_set_flow_control(nxpdev->serdev, false);
set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
/* HCI_NXP_IND_RESET command may not returns any response */
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v1 2/2] Bluetooth: btnxpuart: Add uevents for FW dump and FW download complete
2025-07-03 13:05 [PATCH v1 1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump Neeraj Sanjay Kale
@ 2025-07-03 13:05 ` Neeraj Sanjay Kale
2025-07-03 14:08 ` [v1,1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump bluez.test.bot
1 sibling, 0 replies; 4+ messages in thread
From: Neeraj Sanjay Kale @ 2025-07-03 13:05 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, amitkumar.karwar,
neeraj.sanjaykale, sherry.sun, manjeet.gupta, jean-yves.salaun
This adds uevents which will be generated whenever FW dump is triggered,
FW dump is complete and FW (re)download is done.
This feature is needed for IW612 chipset, which is a tri-radio chipset,
where WLAN runs on CPU1 and BT and Zigbee runs on CPU2.
Currently, whenever BT FW crashes, and FW dump is in progress, there is
no way for 15.4 application to know that CPU2 is in bad state, and when
it will be recovered.
With the help of these uevents and udev rules, the 15.4 app, or any
userspace application can be alerted whenever CPU2 goes in bad state and
recoveres after BTNXPUART reloads the firmware.
[ 334.255154] Bluetooth: hci0: ==== Start FW dump ===
[ 334.261003] Bluetooth: hci0: ==== Send uevent: BTNXPUART_DEV=serial0-0:BTNXPUART_STATE=FW_DUMP_ACTIVE ===
[ 351.486048] Bluetooth: hci0: ==== FW dump complete ===
[ 351.491356] Bluetooth: hci0: ==== Send uevent: BTNXPUART_DEV=serial0-0:BTNXPUART_STATE=FW_DUMP_DONE ===
[ 352.028974] Bluetooth: hci0: ChipID: 7601, Version: 0
[ 352.034490] Bluetooth: hci0: Request Firmware: nxp/uartspi_n61x_v1.bin.se
[ 353.979977] Bluetooth: hci0: FW Download Complete: 417064 bytes
[ 355.197222] Bluetooth: hci0: ==== Send uevent: BTNXPUART_DEV=serial0-0:BTNXPUART_STATE=FW_READY ===
Tested this change by creating a simple udev rule to store the
BTNXPUART_STATE value in a ~/<BTNXPUART_DEV>/state file, and running
15.4 traffic.
The 15.4 packets were sent over SPI only when BTNXPUART_STATE was
FW_READY.
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Tested-by: Jean-Yves Salaün <jean-yves.salaun@nxp.com>
---
drivers/bluetooth/btnxpuart.c | 38 ++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index f40794be2d89..c16ff72c9948 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1434,6 +1434,10 @@ static int nxp_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
static int nxp_setup(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct serdev_device *serdev = nxpdev->serdev;
+ char device_string[30];
+ char event_string[50];
+ char *envp[] = {device_string, event_string, NULL};
int err = 0;
if (nxp_check_boot_sign(nxpdev)) {
@@ -1446,6 +1450,11 @@ static int nxp_setup(struct hci_dev *hdev)
clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
}
+ snprintf(device_string, 30, "BTNXPUART_DEV=%s", dev_name(&serdev->dev));
+ snprintf(event_string, 50, "BTNXPUART_STATE=FW_READY");
+ bt_dev_dbg(hdev, "==== Send uevent: %s:%s ===", device_string, event_string);
+ kobject_uevent_env(&serdev->dev.kobj, KOBJ_CHANGE, envp);
+
serdev_device_set_baudrate(nxpdev->serdev, nxpdev->fw_init_baudrate);
nxpdev->current_baudrate = nxpdev->fw_init_baudrate;
@@ -1766,6 +1775,33 @@ static const struct serdev_device_ops btnxpuart_client_ops = {
.write_wakeup = btnxpuart_write_wakeup,
};
+static void nxp_coredump_notify(struct hci_dev *hdev, int state)
+{
+ struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct serdev_device *serdev = nxpdev->serdev;
+ char device_string[30];
+ char event_string[50];
+ char *envp[] = {device_string, event_string, NULL};
+
+ snprintf(device_string, 30, "BTNXPUART_DEV=%s", dev_name(&serdev->dev));
+ switch (state) {
+ case HCI_DEVCOREDUMP_ACTIVE:
+ snprintf(event_string, 50, "BTNXPUART_STATE=FW_DUMP_ACTIVE");
+ break;
+ case HCI_DEVCOREDUMP_DONE:
+ snprintf(event_string, 50, "BTNXPUART_STATE=FW_DUMP_DONE");
+ break;
+ case HCI_DEVCOREDUMP_TIMEOUT:
+ snprintf(event_string, 50, "BTNXPUART_STATE=FW_DUMP_TIMEOUT");
+ break;
+ default:
+ snprintf(event_string, 50, "BTNXPUART_STATE=FW_DUMP_STATE_%d", state);
+ break;
+ }
+ bt_dev_dbg(hdev, "==== Send uevent: %s:%s ===", device_string, event_string);
+ kobject_uevent_env(&serdev->dev.kobj, KOBJ_CHANGE, envp);
+}
+
static int nxp_serdev_probe(struct serdev_device *serdev)
{
struct hci_dev *hdev;
@@ -1849,7 +1885,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
if (ps_setup(hdev))
goto probe_fail;
- hci_devcd_register(hdev, nxp_coredump, nxp_coredump_hdr, NULL);
+ hci_devcd_register(hdev, nxp_coredump, nxp_coredump_hdr, nxp_coredump_notify);
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [v1,1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump
2025-07-03 13:05 [PATCH v1 1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump Neeraj Sanjay Kale
2025-07-03 13:05 ` [PATCH v1 2/2] Bluetooth: btnxpuart: Add uevents for FW dump and FW download complete Neeraj Sanjay Kale
@ 2025-07-03 14:08 ` bluez.test.bot
1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2025-07-03 14:08 UTC (permalink / raw)
To: linux-bluetooth, neeraj.sanjaykale
[-- Attachment #1: Type: text/plain, Size: 2376 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=978644
---Test result---
Test Summary:
CheckPatch PENDING 0.42 seconds
GitLint PENDING 0.35 seconds
SubjectPrefix PASS 0.32 seconds
BuildKernel PASS 24.10 seconds
CheckAllWarning PASS 26.48 seconds
CheckSparse PASS 30.12 seconds
BuildKernel32 PASS 24.28 seconds
TestRunnerSetup PASS 473.91 seconds
TestRunner_l2cap-tester PASS 25.40 seconds
TestRunner_iso-tester PASS 42.42 seconds
TestRunner_bnep-tester PASS 6.08 seconds
TestRunner_mgmt-tester FAIL 134.34 seconds
TestRunner_rfcomm-tester PASS 9.42 seconds
TestRunner_sco-tester PASS 14.80 seconds
TestRunner_ioctl-tester PASS 10.10 seconds
TestRunner_mesh-tester FAIL 11.42 seconds
TestRunner_smp-tester PASS 8.56 seconds
TestRunner_userchan-tester PASS 6.27 seconds
IncrementalBuild PENDING 0.99 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 490, Passed: 484 (98.8%), Failed: 2, Not Run: 4
Failed Test Cases
LL Privacy - Add Device 3 (AL is full) Failed 0.228 seconds
LL Privacy - Set Device Flag 1 (Device Privacy) Failed 0.163 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Timed out 2.071 seconds
Mesh - Send cancel - 2 Timed out 1.997 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [v1,1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump
2025-07-14 7:30 [PATCH v1 1/2] " Neeraj Sanjay Kale
@ 2025-07-14 8:43 ` bluez.test.bot
0 siblings, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2025-07-14 8:43 UTC (permalink / raw)
To: linux-bluetooth, neeraj.sanjaykale
[-- Attachment #1: Type: text/plain, Size: 2377 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=981936
---Test result---
Test Summary:
CheckPatch PENDING 0.30 seconds
GitLint PENDING 0.20 seconds
SubjectPrefix PASS 0.25 seconds
BuildKernel PASS 24.85 seconds
CheckAllWarning PASS 27.26 seconds
CheckSparse PASS 30.76 seconds
BuildKernel32 PASS 23.97 seconds
TestRunnerSetup PASS 482.23 seconds
TestRunner_l2cap-tester PASS 25.55 seconds
TestRunner_iso-tester PASS 50.31 seconds
TestRunner_bnep-tester PASS 6.11 seconds
TestRunner_mgmt-tester FAIL 136.49 seconds
TestRunner_rfcomm-tester PASS 9.60 seconds
TestRunner_sco-tester PASS 15.07 seconds
TestRunner_ioctl-tester PASS 10.49 seconds
TestRunner_mesh-tester FAIL 14.84 seconds
TestRunner_smp-tester PASS 10.01 seconds
TestRunner_userchan-tester PASS 6.41 seconds
IncrementalBuild PENDING 0.57 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 490, Passed: 484 (98.8%), Failed: 2, Not Run: 4
Failed Test Cases
LL Privacy - Set Flags 3 (2 Devices to RL) Failed 0.221 seconds
LL Privacy - Start Discovery 1 (Disable RL) Failed 0.208 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Timed out 2.096 seconds
Mesh - Send cancel - 2 Timed out 2.004 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-07-14 8:43 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-03 13:05 [PATCH v1 1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump Neeraj Sanjay Kale
2025-07-03 13:05 ` [PATCH v1 2/2] Bluetooth: btnxpuart: Add uevents for FW dump and FW download complete Neeraj Sanjay Kale
2025-07-03 14:08 ` [v1,1/2] Bluetooth: btnxpuart: Correct the Independent Reset handling after FW dump bluez.test.bot
-- strict thread matches above, loose matches on Subject: below --
2025-07-14 7:30 [PATCH v1 1/2] " Neeraj Sanjay Kale
2025-07-14 8:43 ` [v1,1/2] " bluez.test.bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox