|
| 1 | +/* |
| 2 | + * Copyright (c) 2025 Nordic Semiconductor ASA |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause |
| 5 | + */ |
| 6 | + |
| 7 | +#include "hci_internal_wrappers.h" |
| 8 | +#include <zephyr/sys/util.h> |
| 9 | +#include <zephyr/bluetooth/buf.h> |
| 10 | + |
| 11 | +#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) |
| 12 | +/* |
| 13 | + * The Host will generate up to acl_pkts number of Host Number of Completed Packets command plus a |
| 14 | + * number of normal HCI commands, as such we need to ensure the tx command buffer count is big |
| 15 | + * enough to not block incoming ACKs from the host. |
| 16 | + * |
| 17 | + * When Controller to Host data flow control is supported, ensure that `CONFIG_BT_BUF_CMD_TX_COUNT` |
| 18 | + * is greater than or equal to `BT_BUF_ACL_RX_COUNT + Ncmd`, where Ncmd is the supported maximum |
| 19 | + * Num_HCI_Command_Packets. |
| 20 | + * |
| 21 | + * The SDC controller (currently) does not support Num_HCI_Command_Packets > 1, which means Ncmd |
| 22 | + * is always 1. |
| 23 | + * |
| 24 | + * `CONFIG_BT_BUF_CMD_TX_COUNT` is used differently depending on whether `CONFIG_BT_HCI_HOST` or |
| 25 | + * `BT_HCI_RAW` is defined. And as ACL packet pools are only used in connections, |
| 26 | + * we need to limit the build assert as such. See the comments above the asserts for more |
| 27 | + * information on the specific scenario. |
| 28 | + */ |
| 29 | +#if defined(CONFIG_BT_HCI_HOST) && (BT_BUF_ACL_RX_COUNT > 0) |
| 30 | +/* |
| 31 | + * When `CONFIG_BT_HCI_HOST`, `CONFIG_BT_BUF_CMD_TX_COUNT` controls the capacity of |
| 32 | + * `bt_hci_cmd_create`. Which is used for all BT HCI Commands, and can be called concurrently from |
| 33 | + * many different application contexts, initiating various processes. |
| 34 | + * |
| 35 | + * Currently `bt_hci_cmd_create` is generally `K_FOREVER`, as such this build assert only guarantees |
| 36 | + * to avoid deadlocks due to missing CMD buffers, if the host is only allocating the next command |
| 37 | + * once the previous is completed. |
| 38 | + */ |
| 39 | +BUILD_ASSERT(BT_BUF_ACL_RX_COUNT < CONFIG_BT_BUF_CMD_TX_COUNT, |
| 40 | + "Too low HCI command buffers compared to ACL Rx buffers."); |
| 41 | +#else /* controller-only build */ |
| 42 | +/* |
| 43 | + * On a controller-only build (`BT_HCI_RAW`) `CONFIG_BT_BUF_CMD_TX_COUNT` controls the capacity of |
| 44 | + * `bt_buf_get_tx(BT_BUF_CMD)`. Which is only used to receive commands from the Host at the rate the |
| 45 | + * command flow control dictates. Considering one buffer is needed to the Num_HCI_Command_Packet, to |
| 46 | + * do flow control, at least one more buffer is needed. |
| 47 | + * |
| 48 | + */ |
| 49 | +BUILD_ASSERT((CONFIG_BT_BUF_CMD_TX_COUNT - 1) > 0, |
| 50 | + "We need at least two HCI command buffers to avoid deadlocks."); |
| 51 | +#endif /* CONFIG_BT_CONN && CONFIG_BT_HCI_HOST */ |
| 52 | + |
| 53 | +/* |
| 54 | + * This wrapper addresses a limitation in some Zephyr HCI samples such as Zephyr hci_ipc, namely the |
| 55 | + * dropping of Host Number of Completed Packets (HNCP) messages when buffers are full. Dropping |
| 56 | + * these messages causes a resource leak. |
| 57 | + * |
| 58 | + * The buffers are full when CONFIG_BT_BUF_CMD_TX_COUNT is exhausted. This wrapper implements a |
| 59 | + * workaround that ensures the buffers are never exhausted, by limiting the |
| 60 | + * Host_Total_Num_ACL_Data_Packets value. Limiting this value naturally limits the number of HNCP to |
| 61 | + * one the sample buffers can handle. |
| 62 | + * |
| 63 | + * Considering the sample uses the same buffer pool for normal commands, which take up one buffer at |
| 64 | + * most (look up `HCI_Command_Complete` for more details), this wrapper artifically limits the |
| 65 | + * Host_Total_Num_ACL_Data_Packets to at most one less than the CONFIG_BT_BUF_CMD_TX_COUNT pool |
| 66 | + * capacity. |
| 67 | + * . |
| 68 | + */ |
| 69 | +int sdc_hci_cmd_cb_host_buffer_size_wrapper(const sdc_hci_cmd_cb_host_buffer_size_t *cmd_params) |
| 70 | +{ |
| 71 | + sdc_hci_cmd_cb_host_buffer_size_t ctrl_cmd_params = *cmd_params; |
| 72 | + |
| 73 | + ctrl_cmd_params.host_total_num_acl_data_packets = MIN( |
| 74 | + ctrl_cmd_params.host_total_num_acl_data_packets, (CONFIG_BT_BUF_CMD_TX_COUNT - 1)); |
| 75 | + |
| 76 | + return sdc_hci_cmd_cb_host_buffer_size(&ctrl_cmd_params); |
| 77 | +} |
| 78 | +#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ |
0 commit comments