Bluetooth: Add timeout to event & ACL buffer allocation functions

Not all users are in an ISR context where we can't block, so give the
callers the freedom to choose if they want to block or not.

Jira: ZEP-1481

Change-Id: I19bd7e2df94c4eeb60886a17a78f872bd7bea887
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2016-12-20 19:58:03 +02:00
commit f3c632bf44
7 changed files with 27 additions and 22 deletions

View file

@ -94,7 +94,7 @@ static struct net_buf *h4_evt_recv(int *remaining)
*remaining = hdr.len;
buf = bt_buf_get_evt(hdr.evt);
buf = bt_buf_get_evt(hdr.evt, K_NO_WAIT);
if (buf) {
memcpy(net_buf_add(buf, sizeof(hdr)), &hdr, sizeof(hdr));
} else {
@ -114,7 +114,7 @@ static struct net_buf *h4_acl_recv(int *remaining)
/* We can ignore the return value since we pass len == min */
h4_read(h4_dev, (void *)&hdr, sizeof(hdr), sizeof(hdr));
buf = bt_buf_get_acl();
buf = bt_buf_get_acl(K_NO_WAIT);
if (buf) {
memcpy(net_buf_add(buf, sizeof(hdr)), &hdr, sizeof(hdr));
} else {

View file

@ -475,7 +475,7 @@ static void bt_uart_isr(struct device *unused)
switch (H5_HDR_PKT_TYPE(hdr)) {
case HCI_EVENT_PKT:
h5.rx_buf = bt_buf_get_evt(0x00);
h5.rx_buf = bt_buf_get_evt(0x00, K_NO_WAIT);
if (!h5.rx_buf) {
BT_WARN("No available event buffers");
h5_reset_rx();
@ -485,7 +485,7 @@ static void bt_uart_isr(struct device *unused)
h5.rx_state = PAYLOAD;
break;
case HCI_ACLDATA_PKT:
h5.rx_buf = bt_buf_get_acl();
h5.rx_buf = bt_buf_get_acl(K_NO_WAIT);
if (!h5.rx_buf) {
BT_WARN("No available data buffers");
h5_reset_rx();

View file

@ -41,9 +41,11 @@ extern "C" {
* CONFIG_BLUETOOTH_HOST_BUFFERS has been selected.
*
* @param opcode HCI event opcode or 0 if not known
* @param timeout Timeout in milliseconds, or one of the special values
* K_NO_WAIT and K_FOREVER.
* @return A new buffer with the BT_BUF_EVT type.
*/
struct net_buf *bt_buf_get_evt(uint8_t opcode);
struct net_buf *bt_buf_get_evt(uint8_t opcode, int32_t timeout);
/** Allocate a buffer for incoming ACL data
*
@ -51,9 +53,11 @@ struct net_buf *bt_buf_get_evt(uint8_t opcode);
* doesn't need to be explicitly called. Only available when
* CONFIG_BLUETOOTH_HOST_BUFFERS has been selected.
*
* @param timeout Timeout in milliseconds, or one of the special values
* K_NO_WAIT and K_FOREVER.
* @return A new buffer with the BT_BUF_ACL_IN type.
*/
struct net_buf *bt_buf_get_acl(void);
struct net_buf *bt_buf_get_acl(int32_t timeout);
/* Receive data from the controller/HCI driver */
int bt_recv(struct net_buf *buf);

View file

@ -161,7 +161,8 @@ static void recv_thread(void *p1, void *p2, void *p3)
while ((num_cmplt = radio_rx_get(&node_rx, &handle))) {
buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS);
buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS,
K_FOREVER);
if (buf) {
hci_num_cmplt_encode(buf, handle, num_cmplt);
BT_DBG("Num Complete: 0x%04x:%u", handle,
@ -183,7 +184,7 @@ static void recv_thread(void *p1, void *p2, void *p3)
if (node_rx->hdr.type != NODE_RX_TYPE_DC_PDU ||
pdu_data->ll_id == PDU_DATA_LLID_CTRL) {
/* generate a (non-priority) HCI event */
buf = bt_buf_get_evt(0);
buf = bt_buf_get_evt(0, K_FOREVER);
if (buf) {
hci_evt_encode(node_rx, buf);
} else {
@ -191,7 +192,7 @@ static void recv_thread(void *p1, void *p2, void *p3)
}
} else {
/* generate ACL data */
buf = bt_buf_get_acl();
buf = bt_buf_get_acl(K_FOREVER);
if (buf) {
hci_acl_encode(node_rx, buf);
} else {
@ -235,7 +236,7 @@ static int cmd_handle(struct net_buf *buf)
* actual point is to retrieve the event from the priority
* queue
*/
evt = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE);
evt = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, K_FOREVER);
if (!evt) {
BT_ERR("No available event buffers");
return -ENOMEM;

View file

@ -4024,7 +4024,7 @@ int bt_le_scan_stop(void)
}
#if defined(CONFIG_BLUETOOTH_HOST_BUFFERS)
struct net_buf *bt_buf_get_evt(uint8_t opcode)
struct net_buf *bt_buf_get_evt(uint8_t opcode, int32_t timeout)
{
struct net_buf *buf;
@ -4032,12 +4032,12 @@ struct net_buf *bt_buf_get_evt(uint8_t opcode)
case BT_HCI_EVT_CMD_COMPLETE:
case BT_HCI_EVT_CMD_STATUS:
case BT_HCI_EVT_NUM_COMPLETED_PACKETS:
buf = net_buf_alloc(&hci_evt_prio_pool, K_NO_WAIT);
buf = net_buf_alloc(&hci_evt_prio_pool, timeout);
break;
default:
buf = net_buf_alloc(&hci_evt_pool, K_NO_WAIT);
if (!buf && opcode == 0x00) {
buf = net_buf_alloc(&hci_evt_prio_pool, K_NO_WAIT);
buf = net_buf_alloc(&hci_evt_prio_pool, timeout);
}
break;
}
@ -4050,12 +4050,12 @@ struct net_buf *bt_buf_get_evt(uint8_t opcode)
return buf;
}
struct net_buf *bt_buf_get_acl(void)
struct net_buf *bt_buf_get_acl(int32_t timeout)
{
#if defined(CONFIG_BLUETOOTH_CONN)
struct net_buf *buf;
buf = net_buf_alloc(&acl_in_pool, K_NO_WAIT);
buf = net_buf_alloc(&acl_in_pool, timeout);
if (buf) {
net_buf_reserve(buf, CONFIG_BLUETOOTH_HCI_RECV_RESERVE);
bt_buf_set_type(buf, BT_BUF_ACL_IN);

View file

@ -75,7 +75,7 @@ static void send_cmd_status(uint16_t opcode, uint8_t status)
BT_DBG("opcode %x status %x", opcode, status);
buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS);
buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, K_FOREVER);
if (!buf) {
BT_ERR("No available event buffers!");
return;
@ -137,7 +137,7 @@ static void emulate_le_p256_public_key_cmd(struct net_buf *buf)
send_cmd_status(BT_HCI_OP_LE_P256_PUBLIC_KEY, 0);
buf = bt_buf_get_evt(BT_HCI_EVT_LE_META_EVENT);
buf = bt_buf_get_evt(BT_HCI_EVT_LE_META_EVENT, K_FOREVER);
if (!buf) {
BT_ERR("No available event buffers!");
return;
@ -178,7 +178,7 @@ static void emulate_le_generate_dhkey(struct net_buf *buf)
net_buf_unref(buf);
buf = bt_buf_get_evt(BT_HCI_EVT_LE_META_EVENT);
buf = bt_buf_get_evt(BT_HCI_EVT_LE_META_EVENT, K_FOREVER);
if (!buf) {
BT_ERR("No available event buffers!");
return;

View file

@ -64,11 +64,11 @@ void bt_hci_driver_unregister(struct bt_hci_driver *drv)
bt_dev.drv = NULL;
}
struct net_buf *bt_buf_get_evt(uint8_t opcode)
struct net_buf *bt_buf_get_evt(uint8_t opcode, int timeout)
{
struct net_buf *buf;
buf = net_buf_alloc(&hci_evt_pool, K_NO_WAIT);
buf = net_buf_alloc(&hci_evt_pool, timeout);
if (buf) {
bt_buf_set_type(buf, BT_BUF_EVT);
}
@ -76,11 +76,11 @@ struct net_buf *bt_buf_get_evt(uint8_t opcode)
return buf;
}
struct net_buf *bt_buf_get_acl(void)
struct net_buf *bt_buf_get_acl(int32_t timeout)
{
struct net_buf *buf;
buf = net_buf_alloc(&acl_in_pool, K_NO_WAIT);
buf = net_buf_alloc(&acl_in_pool, timeout);
if (buf) {
bt_buf_set_type(buf, BT_BUF_ACL_IN);
}