diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 34f562b50ac..0bebb185963 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,6 +26,7 @@ #include "lll.h" #include "lll_vendor.h" +#include "lll_clock.h" #include "lll_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) @@ -47,10 +48,6 @@ static struct { } curr; } event; -static struct { - struct device *clk; -} lll; - /* Entropy device */ static struct device *dev_entropy; @@ -128,7 +125,6 @@ static void swi_ull_low_nrf5_isr(void *arg) int lll_init(void) { - struct device *clk; int err; /* Get reference to entropy device */ @@ -140,17 +136,12 @@ int lll_init(void) /* Initialise LLL internals */ event.curr.abort_cb = NULL; - /* Initialize LF CLK */ - clk = device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL); - if (!clk) { - return -ENODEV; + /* Initialize Clocks */ + err = lll_clock_init(); + if (err) { + return err; } - clock_control_on(clk, CLOCK_CONTROL_NRF_SUBSYS_LF); - - /* Initialize HF CLK */ - lll.clk = clk; - err = init_reset(); if (err) { return err; @@ -313,51 +304,6 @@ bool lll_is_done(void *param) return !event.curr.abort_cb; } -int lll_clk_on(void) -{ - int err; - - /* turn on radio clock in non-blocking mode. */ - err = clock_control_on(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF); - if (!err || err == -EINPROGRESS) { - DEBUG_RADIO_XTAL(1); - } - - return err; -} - -int lll_clk_on_wait(void) -{ - int err; - - /* turn on radio clock in blocking mode. */ - err = clock_control_on(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF); - - while (clock_control_get_status(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF) != - CLOCK_CONTROL_STATUS_ON) { - k_cpu_idle(); - } - - DEBUG_RADIO_XTAL(1); - - return err; -} - -int lll_clk_off(void) -{ - int err; - - /* turn off radio clock in non-blocking mode. */ - err = clock_control_off(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF); - if (!err) { - DEBUG_RADIO_XTAL(0); - } else if (err == -EBUSY) { - DEBUG_RADIO_XTAL(1); - } - - return err; -} - u32_t lll_evt_offset_get(struct evt_hdr *evt) { if (0) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c index dd42a406c19..583d46c1e41 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,6 +26,7 @@ #include "lll.h" #include "lll_vendor.h" +#include "lll_clock.h" #include "lll_adv.h" #include "lll_conn.h" #include "lll_chan.h" @@ -105,7 +106,7 @@ void lll_adv_prepare(void *param) struct lll_prepare_param *p = param; int err; - err = lll_clk_on(); + err = lll_hfclock_on(); LL_ASSERT(!err || err == -EINPROGRESS); err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, p); @@ -134,7 +135,7 @@ static int prepare_cb(struct lll_prepare_param *prepare_param) if (lll_is_stop(lll)) { int err; - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(NULL); @@ -270,7 +271,7 @@ static int is_abort_cb(void *next, int prio, void *curr, *resume_prio = 0; /* TODO: */ /* Retain HF clk */ - err = lll_clk_on(); + err = lll_hfclock_on(); LL_ASSERT(!err || err == -EINPROGRESS); return -EAGAIN; @@ -308,7 +309,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* NOTE: Else clean the top half preparations of the aborted event * currently in preparation pipeline. */ - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(param); @@ -580,7 +581,7 @@ static void isr_cleanup(void *param) radio_tmr_stop(); - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(NULL); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.c index 8e58806301a..0c50244b63a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,25 +15,110 @@ #include "common/log.h" #include "hal/debug.h" -void lll_clock_wait(void) +/* Clock setup timeouts are unlikely, below values are experimental */ +#define LFCLOCK_TIMEOUT_MS 500 +#define HFCLOCK_TIMEOUT_MS 2 + +static void clock_ready(struct device *dev, clock_control_subsys_t subsys, + void *user_data); + +static struct device *dev; + +int lll_clock_init(void) +{ + int err; + + dev = device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL); + if (!dev) { + return -ENODEV; + } + + err = clock_control_on(dev, CLOCK_CONTROL_NRF_SUBSYS_LF); + + return err; +} + +int lll_clock_wait(void) { static bool done; if (done) { - return; + return 0; } done = true; - struct device *clock = - device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL); + struct k_sem sem_clock_wait; + struct clock_control_async_data async_data = { + .cb = clock_ready, + .user_data = &sem_clock_wait, + }; + int err; - LL_ASSERT(clock); + k_sem_init(&sem_clock_wait, 0, 1); - clock_control_on(clock, CLOCK_CONTROL_NRF_SUBSYS_LF); - while (clock_control_get_status(clock, CLOCK_CONTROL_NRF_SUBSYS_LF) != - CLOCK_CONTROL_STATUS_ON) { - DEBUG_CPU_SLEEP(1); - k_cpu_idle(); - DEBUG_CPU_SLEEP(0); + err = clock_control_async_on(dev, CLOCK_CONTROL_NRF_SUBSYS_LF, + &async_data); + if (err) { + return err; } + + err = k_sem_take(&sem_clock_wait, K_MSEC(LFCLOCK_TIMEOUT_MS)); + + return err; +} + +int lll_hfclock_on(void) +{ + int err; + + /* turn on radio clock in non-blocking mode. */ + err = clock_control_on(dev, CLOCK_CONTROL_NRF_SUBSYS_HF); + if (!err || err == -EINPROGRESS) { + DEBUG_RADIO_XTAL(1); + } + + return err; +} + +int lll_hfclock_on_wait(void) +{ + struct k_sem sem_clock_wait; + struct clock_control_async_data async_data = { + .cb = clock_ready, + .user_data = &sem_clock_wait, + }; + int err; + + k_sem_init(&sem_clock_wait, 0, 1); + + err = clock_control_async_on(dev, CLOCK_CONTROL_NRF_SUBSYS_HF, + &async_data); + LL_ASSERT(!err); + + err = k_sem_take(&sem_clock_wait, K_MSEC(HFCLOCK_TIMEOUT_MS)); + + DEBUG_RADIO_XTAL(1); + + return err; +} + +int lll_hfclock_off(void) +{ + int err; + + /* turn off radio clock in non-blocking mode. */ + err = clock_control_off(dev, CLOCK_CONTROL_NRF_SUBSYS_HF); + if (!err) { + DEBUG_RADIO_XTAL(0); + } else if (err == -EBUSY) { + DEBUG_RADIO_XTAL(1); + } + + return err; +} + +static void clock_ready(struct device *dev, clock_control_subsys_t subsys, + void *user_data) +{ + k_sem_give(user_data); } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.h index 079ca9c1a9e..d304313a286 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.h @@ -1,7 +1,11 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -void lll_clock_wait(void); +int lll_clock_init(void); +int lll_clock_wait(void); +int lll_hfclock_on(void); +int lll_hfclock_on_wait(void); +int lll_hfclock_off(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index ff540b4ffc2..6ffbdf7dafc 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,7 @@ #include "pdu.h" #include "lll.h" +#include "lll_clock.h" #include "lll_conn.h" #include "lll_internal.h" @@ -125,7 +126,7 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param) /* NOTE: Else clean the top half preparations of the aborted event * currently in preparation pipeline. */ - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(param); @@ -638,7 +639,7 @@ static void isr_cleanup(void *param) radio_tmr_stop(); - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(NULL); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h index a56e59c9898..f8cd4e7cd6b 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,9 +7,6 @@ int lll_prepare_done(void *param); int lll_done(void *param); bool lll_is_done(void *param); -int lll_clk_on(void); -int lll_clk_on_wait(void); -int lll_clk_off(void); u32_t lll_evt_offset_get(struct evt_hdr *evt); u32_t lll_preempt_calc(struct evt_hdr *evt, u8_t ticker_id, u32_t ticks_at_event); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c index 97c859d4445..fbdbcb084ef 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c @@ -20,6 +20,7 @@ #include "lll.h" #include "lll_vendor.h" +#include "lll_clock.h" #include "lll_conn.h" #include "lll_master.h" #include "lll_chan.h" @@ -65,7 +66,7 @@ void lll_master_prepare(void *param) struct lll_prepare_param *p = param; int err; - err = lll_clk_on(); + err = lll_hfclock_on(); LL_ASSERT(!err || err == -EINPROGRESS); err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb, diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c index 91860e3b462..8ac44b04762 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +25,7 @@ #include "lll.h" #include "lll_vendor.h" +#include "lll_clock.h" #include "lll_scan.h" #include "lll_conn.h" #include "lll_chan.h" @@ -104,7 +105,7 @@ void lll_scan_prepare(void *param) struct lll_prepare_param *p = param; int err; - err = lll_clk_on(); + err = lll_hfclock_on(); LL_ASSERT(!err || err == -EINPROGRESS); err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, p); @@ -134,7 +135,7 @@ static int prepare_cb(struct lll_prepare_param *prepare_param) if (lll_is_stop(lll)) { int err; - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(NULL); @@ -288,8 +289,8 @@ static int is_abort_cb(void *next, int prio, void *curr, *resume_cb = resume_prepare_cb; *resume_prio = 0; /* TODO: */ - /* Retain HF clk */ - err = lll_clk_on(); + /* Retain HF clock */ + err = lll_hfclock_on(); LL_ASSERT(!err || err == -EINPROGRESS); return -EAGAIN; @@ -331,7 +332,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* NOTE: Else clean the top half preparations of the aborted event * currently in preparation pipeline. */ - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(param); @@ -642,7 +643,7 @@ static void isr_cleanup(void *param) radio_tmr_stop(); - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); lll_done(NULL); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c index 5bf2531e8ae..86f9f8d51d0 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c @@ -20,6 +20,7 @@ #include "lll.h" #include "lll_vendor.h" +#include "lll_clock.h" #include "lll_conn.h" #include "lll_slave.h" #include "lll_chan.h" @@ -65,7 +66,7 @@ void lll_slave_prepare(void *param) struct lll_prepare_param *p = param; int err; - err = lll_clk_on(); + err = lll_hfclock_on(); LL_ASSERT(!err || err == -EINPROGRESS); err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb, diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c index f4501c9eb3f..f0cddd54363 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Nordic Semiconductor ASA + * Copyright (c) 2017-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ #include "util/memq.h" #include "lll.h" +#include "lll_clock.h" #include "lll_internal.h" #include "ll_test.h" @@ -172,7 +173,7 @@ static u32_t init(u8_t chan, u8_t phy, void (*isr)(void *)) cntr_start(); /* Setup resources required by Radio */ - err = lll_clk_on_wait(); + err = lll_hfclock_on_wait(); /* Reset Radio h/w */ radio_reset(); @@ -334,7 +335,7 @@ u32_t ll_test_end(u16_t *num_rx) radio_tmr_stop(); /* Release resources acquired for Radio */ - err = lll_clk_off(); + err = lll_hfclock_off(); LL_ASSERT(!err || err == -EBUSY); /* Stop coarse timer */ diff --git a/subsys/bluetooth/controller/ll_sw/nrf.cmake b/subsys/bluetooth/controller/ll_sw/nrf.cmake index 1109c4a7432..fb7652a4548 100644 --- a/subsys/bluetooth/controller/ll_sw/nrf.cmake +++ b/subsys/bluetooth/controller/ll_sw/nrf.cmake @@ -38,6 +38,7 @@ endif() if(CONFIG_BT_LL_SW_SPLIT) zephyr_library_sources( ll_sw/nordic/lll/lll.c + ll_sw/nordic/lll/lll_clock.c ) if(CONFIG_BT_BROADCASTER) zephyr_library_sources( @@ -51,7 +52,6 @@ if(CONFIG_BT_LL_SW_SPLIT) endif() if(CONFIG_BT_CONN) zephyr_library_sources( - ll_sw/nordic/lll/lll_clock.c ll_sw/nordic/lll/lll_conn.c ) zephyr_library_sources_ifdef( diff --git a/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.c b/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.c index 926e21e4d20..e94d91376b5 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.c +++ b/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,7 @@ #include "common/log.h" #include "hal/debug.h" -void lll_clock_wait(void) +int lll_clock_wait(void) { - + return 0; } diff --git a/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.h b/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.h index 079ca9c1a9e..1093be6e0e9 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.h +++ b/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -void lll_clock_wait(void); +int lll_clock_wait(void); diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 2050c3b6c58..b5d835796e6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Nordic Semiconductor ASA + * Copyright (c) 2016-2020 Nordic Semiconductor ASA * Copyright (c) 2016 Vinayak Kariappa Chettimada * * SPDX-License-Identifier: Apache-2.0 @@ -66,7 +66,7 @@ static void ticker_stop_cb(u32_t ticks_at_expire, u32_t remainder, u16_t lazy, void *param); static void ticker_op_stop_cb(u32_t status, void *params); static void disabled_cb(void *param); -static inline void conn_release(struct ll_adv_set *adv); +static void conn_release(struct ll_adv_set *adv); #endif /* CONFIG_BT_PERIPHERAL */ static inline u8_t disable(u16_t handle); @@ -549,6 +549,7 @@ u8_t ll_adv_enable(u8_t enable) struct ll_conn *conn; struct lll_conn *conn_lll; void *link; + int err; if (lll->conn) { return BT_HCI_ERR_CMD_DISALLOWED; @@ -704,7 +705,12 @@ u8_t ll_adv_enable(u8_t enable) lll_hdr_init(&conn->lll, conn); /* wait for stable clocks */ - lll_clock_wait(); + err = lll_clock_wait(); + if (err) { + conn_release(adv); + + return BT_HCI_ERR_HW_FAILURE; + } } #endif /* CONFIG_BT_PERIPHERAL */ @@ -1218,7 +1224,7 @@ static void disabled_cb(void *param) ll_rx_sched(); } -static inline void conn_release(struct ll_adv_set *adv) +static void conn_release(struct ll_adv_set *adv) { struct lll_conn *lll = adv->lll.conn; memq_link_t *link; diff --git a/subsys/bluetooth/controller/ll_sw/ull_master.c b/subsys/bluetooth/controller/ll_sw/ull_master.c index 5073040f3d5..78639a365c4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_master.c +++ b/subsys/bluetooth/controller/ll_sw/ull_master.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Nordic Semiconductor ASA + * Copyright (c) 2018-2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,7 +51,8 @@ static void ticker_op_stop_scan_cb(u32_t status, void *params); static void ticker_op_cb(u32_t status, void *params); -static void access_addr_get(u8_t access_addr[]); +static inline void access_addr_get(u8_t access_addr[]); +static inline void conn_release(struct ll_scan_set *scan); u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window, u8_t filter_policy, u8_t peer_addr_type, @@ -66,6 +67,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window, memq_link_t *link; u8_t access_addr[4]; u8_t hop; + int err; scan = ull_scan_is_disabled_get(0); if (!scan) { @@ -271,7 +273,12 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window, scan->own_addr_type = own_addr_type; /* wait for stable clocks */ - lll_clock_wait(); + err = lll_clock_wait(); + if (err) { + conn_release(scan); + + return BT_HCI_ERR_HW_FAILURE; + } return ull_scan_enable(scan); } @@ -699,7 +706,7 @@ static void ticker_op_cb(u32_t status, void *params) * - It shall have no more than eleven transitions in the least significant 16 * bits. */ -static void access_addr_get(u8_t access_addr[]) +static inline void access_addr_get(u8_t access_addr[]) { #if defined(CONFIG_BT_CTLR_PHY_CODED) u8_t transitions_lsb16; @@ -850,3 +857,27 @@ again: sys_put_le32(aa, access_addr); } + +static inline void conn_release(struct ll_scan_set *scan) +{ + struct lll_conn *lll = scan->lll.conn; + struct node_rx_pdu *cc; + struct ll_conn *conn; + memq_link_t *link; + + LL_ASSERT(!lll->link_tx_free); + link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail); + LL_ASSERT(link); + lll->link_tx_free = link; + + conn = (void *)HDR_LLL2EVT(lll); + + cc = (void *)&conn->llcp_terminate.node_rx; + link = cc->hdr.link; + LL_ASSERT(link); + + ll_rx_link_release(link); + + ll_conn_release(conn); + scan->lll.conn = NULL; +}