Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrf fromlist] drivers: bluetooth: hci: Add retries for IPC interface #2550

Merged
merged 1 commit into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions drivers/bluetooth/hci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ config BT_HCI_IPC
Bluetooth HCI driver for communication with another CPU
using the IPC subsystem.

config BT_HCI_IPC_SEND_RETRY_COUNT
int "HCI IPC send retry count"
depends on BT_HCI_IPC
default 3
help
Number of times to retry sending a message via IPC.
The retries occur in case of a failure to send a message
through IPC (-ENOMEM returned by ipc_service_send).

config BT_HCI_IPC_SEND_RETRY_DELAY_US
int "HCI IPC send retry delay (us)"
depends on BT_HCI_IPC
default 75
help
Delay in microseconds between retries when sending a message via IPC.
When a single tick (CONFIG_SYS_CLOCK_TICKS_PER_SEC) is bigger then
the retry delay the k_busy_wait function is used. Set with care.

config BT_SPI
bool
select SPI
Expand Down
28 changes: 26 additions & 2 deletions drivers/bluetooth/hci/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ LOG_MODULE_REGISTER(bt_hci_driver);

#define IPC_BOUND_TIMEOUT_IN_MS K_MSEC(1000)

/* The retry of ipc_service_send function requires a small (tens of us) delay.
* In order to ensure proper delay k_usleep is used when the system clock is
* precise enough and available (CONFIG_SYS_CLOCK_TICKS_PER_SEC different than 0).
*/
#define USE_SLEEP_BETWEEN_IPC_RETRIES COND_CODE_0(CONFIG_SYS_CLOCK_TICKS_PER_SEC, \
(false), \
((USEC_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) > CONFIG_BT_HCI_IPC_SEND_RETRY_DELAY_US))

struct ipc_data {
bt_hci_recv_t recv;
struct ipc_ept hci_ept;
Expand Down Expand Up @@ -265,19 +273,35 @@ static int bt_ipc_send(const struct device *dev, struct net_buf *buf)
break;
default:
LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
err = -ENOMSG;
goto done;
}
net_buf_push_u8(buf, pkt_indicator);

LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
err = ipc_service_send(&data->hci_ept, buf->data, buf->len);

for (int retries = 0; retries < CONFIG_BT_HCI_IPC_SEND_RETRY_COUNT + 1; retries++) {
err = ipc_service_send(&data->hci_ept, buf->data, buf->len);
if ((err >= 0) || (err != -ENOMEM)) {
break;
}

if (USE_SLEEP_BETWEEN_IPC_RETRIES) {
k_usleep(CONFIG_BT_HCI_IPC_SEND_RETRY_DELAY_US);
} else {
k_busy_wait(CONFIG_BT_HCI_IPC_SEND_RETRY_DELAY_US);
}
}

if (err < 0) {
LOG_ERR("Failed to send (err %d)", err);
} else {
err = 0;
}

done:
net_buf_unref(buf);
return 0;
return err;
}

static void hci_ept_bound(void *priv)
Expand Down