From 500010d369035ff2bef1b54fc2d46e1844447043 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 10 Nov 2016 22:45:08 +0200 Subject: [PATCH] Bluetooth: Remove need for fiber offload The bt_recv() function had protections for being called from a preemptible task context, however nothing was protecting preemption by ISR. A fairly simple fix is to protect the couple of critical regions that can be reached from bt_recv() with the help of irq_lock(). Change-Id: Ifc29fd31205eb5425e1b7c862347d9420688df4e Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/hci_core.c | 52 +++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 599899235cd..1bc69281fee 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -521,15 +521,19 @@ static void hci_num_completed_packets(struct net_buf *buf) for (i = 0; i < num_handles; i++) { uint16_t handle, count; struct bt_conn *conn; + int key; handle = sys_le16_to_cpu(evt->h[i].handle); count = sys_le16_to_cpu(evt->h[i].count); BT_DBG("handle %u count %u", handle, count); + key = irq_lock(); + conn = bt_conn_lookup_handle(handle); if (!conn) { BT_ERR("No connection for handle %u", handle); + irq_unlock(key); continue; } @@ -541,6 +545,8 @@ static void hci_num_completed_packets(struct net_buf *buf) conn->pending_pkts = 0; } + irq_unlock(key); + while (count--) { k_sem_give(bt_conn_get_pkts(conn)); } @@ -2261,20 +2267,26 @@ static void hci_reset_complete(struct net_buf *buf) static void hci_cmd_done(uint16_t opcode, uint8_t status, struct net_buf *buf) { - struct net_buf *sent = bt_dev.sent_cmd; + struct net_buf *sent; + int key = irq_lock(); + sent = bt_dev.sent_cmd; if (!sent) { + irq_unlock(key); return; } if (cmd(sent)->opcode != opcode) { BT_ERR("Unexpected completion of opcode 0x%04x expected 0x%04x", opcode, cmd(sent)->opcode); + irq_unlock(key); return; } bt_dev.sent_cmd = NULL; + irq_unlock(key); + /* If the command was synchronous wake up bt_hci_cmd_send_sync() */ if (cmd(sent)->sync) { struct k_sem *sem = cmd(sent)->sync; @@ -2296,6 +2308,7 @@ static void hci_cmd_complete(struct net_buf *buf) struct bt_hci_evt_cmd_complete *evt = (void *)buf->data; uint16_t opcode = sys_le16_to_cpu(evt->opcode); uint8_t status; + int key; BT_DBG("opcode 0x%04x", opcode); @@ -2308,17 +2321,25 @@ static void hci_cmd_complete(struct net_buf *buf) hci_cmd_done(opcode, status, buf); - if (evt->ncmd && !bt_dev.ncmd) { - /* Allow next command to be sent */ - bt_dev.ncmd = 1; - k_sem_give(&bt_dev.ncmd_sem); + key = irq_lock(); + + if (!evt->ncmd || bt_dev.ncmd) { + irq_unlock(key); + return; } + + /* Allow next command to be sent */ + bt_dev.ncmd = 1; + irq_unlock(key); + + k_sem_give(&bt_dev.ncmd_sem); } static void hci_cmd_status(struct net_buf *buf) { struct bt_hci_evt_cmd_status *evt = (void *)buf->data; uint16_t opcode = sys_le16_to_cpu(evt->opcode); + int key; BT_DBG("opcode 0x%04x", opcode); @@ -2326,11 +2347,18 @@ static void hci_cmd_status(struct net_buf *buf) hci_cmd_done(opcode, evt->status, buf); - if (evt->ncmd && !bt_dev.ncmd) { - /* Allow next command to be sent */ - bt_dev.ncmd = 1; - k_sem_give(&bt_dev.ncmd_sem); + key = irq_lock(); + + if (!evt->ncmd || bt_dev.ncmd) { + irq_unlock(key); + return; } + + /* Allow next command to be sent */ + bt_dev.ncmd = 1; + irq_unlock(key); + + k_sem_give(&bt_dev.ncmd_sem); } static int prng_reseed(struct tc_hmac_prng_struct *h) @@ -3417,12 +3445,6 @@ int bt_recv(struct net_buf *buf) { struct bt_hci_evt_hdr *hdr; -#if defined(CONFIG_MICROKERNEL) - if (sys_execution_context_type_get() == NANO_CTX_TASK) { - return task_offload_to_fiber(bt_recv, buf); - } -#endif /* CONFIG_MICROKERNEL */ - bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len); BT_DBG("buf %p len %u", buf, buf->len);