Skip to content

Commit 0aa2141

Browse files
dchat-nordicnordicjm
authored andcommitted
[nrf fromlist] drivers: bluetooth: hci: Add retries for IPC interface
Add HCI IPC retry handling in case of full IPC queue. This mechanism improves reliability. The ipc_service_send can return -ENOMEM in case of full queue. If this happens the retries are executed in order to wait for queue to empty and not drop messages. If the retry mechanism reaches maximum then the error code is passed back to the host. The change should improve the handling of passing messages to full ipc and reduce dropping of packets. Upstream PR #: 85649 Signed-off-by: Dominik Chat <[email protected]>
1 parent cd78af5 commit 0aa2141

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

drivers/bluetooth/hci/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ config BT_HCI_IPC
4040
Bluetooth HCI driver for communication with another CPU
4141
using the IPC subsystem.
4242

43+
config BT_HCI_IPC_SEND_RETRY_COUNT
44+
int "HCI IPC send retry count"
45+
depends on BT_HCI_IPC
46+
default 3
47+
help
48+
Number of times to retry sending a message via IPC.
49+
The retries occur in case of a failure to send a message
50+
through IPC (-ENOMEM returned by ipc_service_send).
51+
52+
config BT_HCI_IPC_SEND_RETRY_DELAY_US
53+
int "HCI IPC send retry delay (us)"
54+
depends on BT_HCI_IPC
55+
default 75
56+
help
57+
Delay in microseconds between retries when sending a message via IPC.
58+
When a single tick (CONFIG_SYS_CLOCK_TICKS_PER_SEC) is bigger then
59+
the retry delay the k_busy_wait function is used. Set with care.
60+
4361
config BT_SPI
4462
bool
4563
select SPI

drivers/bluetooth/hci/ipc.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ LOG_MODULE_REGISTER(bt_hci_driver);
2222

2323
#define IPC_BOUND_TIMEOUT_IN_MS K_MSEC(1000)
2424

25+
/* The retry of ipc_service_send function requires a small (tens of us) delay.
26+
* In order to ensure proper delay k_usleep is used when the system clock is
27+
* precise enough and available (CONFIG_SYS_CLOCK_TICKS_PER_SEC different than 0).
28+
*/
29+
#define USE_SLEEP_BETWEEN_IPC_RETRIES COND_CODE_0(CONFIG_SYS_CLOCK_TICKS_PER_SEC, \
30+
(false), \
31+
((USEC_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) > CONFIG_BT_HCI_IPC_SEND_RETRY_DELAY_US))
32+
2533
struct ipc_data {
2634
bt_hci_recv_t recv;
2735
struct ipc_ept hci_ept;
@@ -265,19 +273,35 @@ static int bt_ipc_send(const struct device *dev, struct net_buf *buf)
265273
break;
266274
default:
267275
LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
276+
err = -ENOMSG;
268277
goto done;
269278
}
270279
net_buf_push_u8(buf, pkt_indicator);
271280

272281
LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
273-
err = ipc_service_send(&data->hci_ept, buf->data, buf->len);
282+
283+
for (int retries = 0; retries < CONFIG_BT_HCI_IPC_SEND_RETRY_COUNT + 1; retries++) {
284+
err = ipc_service_send(&data->hci_ept, buf->data, buf->len);
285+
if ((err >= 0) || (err != -ENOMEM)) {
286+
break;
287+
}
288+
289+
if (USE_SLEEP_BETWEEN_IPC_RETRIES) {
290+
k_usleep(CONFIG_BT_HCI_IPC_SEND_RETRY_DELAY_US);
291+
} else {
292+
k_busy_wait(CONFIG_BT_HCI_IPC_SEND_RETRY_DELAY_US);
293+
}
294+
}
295+
274296
if (err < 0) {
275297
LOG_ERR("Failed to send (err %d)", err);
298+
} else {
299+
err = 0;
276300
}
277301

278302
done:
279303
net_buf_unref(buf);
280-
return 0;
304+
return err;
281305
}
282306

283307
static void hci_ept_bound(void *priv)

0 commit comments

Comments
 (0)