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. Signed-off-by: Dominik Chat <dominik.chat@nordicsemi.no>
This commit is contained in:
parent
f48344364c
commit
93d15996e9
2 changed files with 44 additions and 2 deletions
|
@ -40,6 +40,24 @@ config BT_HCI_IPC
|
||||||
Bluetooth HCI driver for communication with another CPU
|
Bluetooth HCI driver for communication with another CPU
|
||||||
using the IPC subsystem.
|
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
|
config BT_SPI
|
||||||
bool
|
bool
|
||||||
select SPI
|
select SPI
|
||||||
|
|
|
@ -23,6 +23,14 @@ LOG_MODULE_REGISTER(bt_hci_driver);
|
||||||
|
|
||||||
#define IPC_BOUND_TIMEOUT_IN_MS K_MSEC(1000)
|
#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 {
|
struct ipc_data {
|
||||||
bt_hci_recv_t recv;
|
bt_hci_recv_t recv;
|
||||||
struct ipc_ept hci_ept;
|
struct ipc_ept hci_ept;
|
||||||
|
@ -268,19 +276,35 @@ static int bt_ipc_send(const struct device *dev, struct net_buf *buf)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
|
LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
|
||||||
|
err = -ENOMSG;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
net_buf_push_u8(buf, pkt_indicator);
|
net_buf_push_u8(buf, pkt_indicator);
|
||||||
|
|
||||||
LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
|
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) {
|
if (err < 0) {
|
||||||
LOG_ERR("Failed to send (err %d)", err);
|
LOG_ERR("Failed to send (err %d)", err);
|
||||||
|
} else {
|
||||||
|
err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
net_buf_unref(buf);
|
net_buf_unref(buf);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_ept_bound(void *priv)
|
static void hci_ept_bound(void *priv)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue