From f3c632bf44a67ec5dc0e17d5a4a818ab6642e9c2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 20 Dec 2016 19:58:03 +0200 Subject: [PATCH] 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 --- drivers/bluetooth/hci/h4.c | 4 ++-- drivers/bluetooth/hci/h5.c | 4 ++-- include/drivers/bluetooth/hci_driver.h | 8 ++++++-- subsys/bluetooth/controller/hci/hci_driver.c | 9 +++++---- subsys/bluetooth/host/hci_core.c | 10 +++++----- subsys/bluetooth/host/hci_ecc.c | 6 +++--- subsys/bluetooth/host/hci_raw.c | 8 ++++---- 7 files changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/bluetooth/hci/h4.c b/drivers/bluetooth/hci/h4.c index c18151a5216875..7bc53a22f3988c 100644 --- a/drivers/bluetooth/hci/h4.c +++ b/drivers/bluetooth/hci/h4.c @@ -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 { diff --git a/drivers/bluetooth/hci/h5.c b/drivers/bluetooth/hci/h5.c index 0f400fef5e6afd..a53f1eb9c06ef9 100644 --- a/drivers/bluetooth/hci/h5.c +++ b/drivers/bluetooth/hci/h5.c @@ -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(); diff --git a/include/drivers/bluetooth/hci_driver.h b/include/drivers/bluetooth/hci_driver.h index 436580b4df61be..8d00bb5803b7b5 100644 --- a/include/drivers/bluetooth/hci_driver.h +++ b/include/drivers/bluetooth/hci_driver.h @@ -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); diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 8ef0be78f4a7f3..379fb8003be42c 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -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; diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index b1be61eb05a3b3..ae2a3004df13eb 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -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); diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index 143bf57778cb08..72869de395e61c 100644 --- a/subsys/bluetooth/host/hci_ecc.c +++ b/subsys/bluetooth/host/hci_ecc.c @@ -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; diff --git a/subsys/bluetooth/host/hci_raw.c b/subsys/bluetooth/host/hci_raw.c index 2239765da92cc5..5a6d4fb4b81b5b 100644 --- a/subsys/bluetooth/host/hci_raw.c +++ b/subsys/bluetooth/host/hci_raw.c @@ -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); }