Bluetooth: controller: Reworked adv set terminate event

Reworked the implementation of Advertising Set Terminate
event.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-07-13 17:59:38 +05:30 committed by Carles Cufí
commit cd0e72a91e
6 changed files with 174 additions and 102 deletions

View file

@ -3604,12 +3604,12 @@ static void le_adv_ext_terminate(struct pdu_data *pdu_data,
}
sep = meta_evt(buf, BT_HCI_EVT_LE_ADV_SET_TERMINATED, sizeof(*sep));
sep->num_completed_ext_adv_evts =
(uint8_t)((uint32_t)node_rx->hdr.rx_ftr.extra & 0xff);
sep->status = ((uint32_t)node_rx->hdr.rx_ftr.extra >> 8) & 0xff;
sep->adv_handle = (node_rx->hdr.handle & 0xff);
sep->conn_handle = sys_cpu_to_le16
(*(uint16_t *)((uint32_t)node_rx->hdr.rx_ftr.extra >> 16));
sep->adv_handle = node_rx->hdr.handle & 0xff;
sep->conn_handle =
sys_cpu_to_le16((uint32_t)node_rx->hdr.rx_ftr.param & 0xffff);
sep->num_completed_ext_adv_evts =
(uint32_t)node_rx->hdr.rx_ftr.extra & 0xff;
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#endif /* CONFIG_BT_OBSERVER */
@ -4326,7 +4326,6 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
case NODE_RX_TYPE_EXT_1M_REPORT:
case NODE_RX_TYPE_EXT_2M_REPORT:
case NODE_RX_TYPE_EXT_CODED_REPORT:
case NODE_RX_TYPE_EXT_ADV_TERMINATE:
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#endif /* CONFIG_BT_OBSERVER */
@ -4354,6 +4353,11 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
case NODE_RX_TYPE_MESH_REPORT:
#endif /* CONFIG_BT_HCI_MESH_EXT */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
/* fallthrough */
case NODE_RX_TYPE_EXT_ADV_TERMINATE:
return HCI_CLASS_EVT_REQUIRED;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CONN)
case NODE_RX_TYPE_CONNECTION:

View file

@ -448,9 +448,6 @@ static void isr_done(void *param)
{
struct node_rx_hdr *node_rx;
struct lll_adv *lll = param;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct event_done_extra *e;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
/* Clear radio status and events */
lll_isr_status_reset();
@ -558,9 +555,12 @@ static void isr_done(void *param)
#endif /* !CONFIG_BT_CTLR_ADV_INDICATION */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
e = ull_event_done_extra_get();
LL_ASSERT(e);
e->type = EVENT_DONE_EXTRA_TYPE_ADV;
struct event_done_extra *extra;
extra = ull_event_done_extra_get();
LL_ASSERT(extra);
extra->type = EVENT_DONE_EXTRA_TYPE_ADV;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
lll_isr_cleanup(param);

View file

@ -280,10 +280,6 @@ static inline void rx_demux_event_done(memq_link_t *link,
static inline void ll_rx_link_inc_quota(int8_t delta);
static void disabled_cb(void *param);
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
static void term_evt_disable(struct ull_hdr *ull_hdr);
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_CONN)
static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last);
#endif /* CONFIG_BT_CONN */
@ -601,8 +597,39 @@ void ll_rx_dequeue(void)
break;
case NODE_RX_TYPE_EXT_ADV_TERMINATE:
break;
{
struct lll_conn *lll_conn;
struct ll_adv_set *adv;
struct ll_conn *conn;
memq_link_t *link;
adv = ull_adv_set_get(rx->handle);
lll_conn = adv->lll.conn;
if (!lll_conn) {
adv->is_enabled = 0U;
break;
}
LL_ASSERT(!lll_conn->link_tx_free);
link = memq_deinit(&lll_conn->memq_tx.head,
&lll_conn->memq_tx.tail);
LL_ASSERT(link);
lll_conn->link_tx_free = link;
conn = (void *)HDR_LLL2EVT(lll_conn);
ll_conn_release(conn);
adv->lll.conn = NULL;
ll_rx_release(adv->node_rx_cc_free);
adv->node_rx_cc_free = NULL;
ll_rx_link_release(adv->link_cc_free);
adv->link_cc_free = NULL;
adv->is_enabled = 0U;
}
break;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CONN)
@ -668,7 +695,7 @@ void ll_rx_dequeue(void)
* enabled status bitmask
*/
bm = (IS_ENABLED(CONFIG_BT_OBSERVER) &&
ull_scan_is_enabled(0) << 1) |
(ull_scan_is_enabled(0) << 1)) |
(IS_ENABLED(CONFIG_BT_BROADCASTER) &&
ull_adv_is_enabled(0));
@ -1745,28 +1772,6 @@ static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx)
return 0;
}
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
static void term_evt_disable(struct ull_hdr *ull_hdr)
{
struct lll_adv *lll;
struct ll_adv_set *adv;
uint8_t handle;
uint32_t ret;
lll = (struct lll_adv *)HDR_ULL2LLL(ull_hdr);
adv = (void *)HDR_LLL2EVT(lll);
handle = ull_adv_handle_get(adv);
LL_ASSERT(handle < BT_CTLR_ADV_SET);
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
TICKER_ID_ADV_BASE + handle, NULL, adv);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS)
|| (ret == TICKER_STATUS_BUSY));
}
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
static inline void rx_demux_event_done(memq_link_t *link,
struct node_rx_hdr *rx)
{
@ -1788,53 +1793,8 @@ static inline void rx_demux_event_done(memq_link_t *link,
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
case EVENT_DONE_EXTRA_TYPE_ADV:
{
struct lll_adv *lll;
struct ll_adv_set *adv;
bool send_term_evt = false;
lll = (struct lll_adv *)HDR_ULL2LLL(ull_hdr);
adv = (void *)HDR_LLL2EVT(lll);
if ((adv->max_events > 0) &&
(adv->event_counter >= adv->max_events)) {
adv->max_events = 0;
send_term_evt = true;
lll->node_rx_adv_term->rx_ftr.extra = (void *)
((uint32_t)adv->event_counter & 0xff);
}
if (adv->ticks_remain_duration &&
(adv->ticks_remain_duration <
HAL_TICKER_US_TO_TICKS((uint64_t)adv->interval * 625U))) {
adv->ticks_remain_duration = 0;
send_term_evt = true;
lll->node_rx_adv_term->rx_ftr.extra = (void *)
(((uint32_t)adv->event_counter & 0xff)
| (BT_HCI_ERR_ADV_TIMEOUT << 8));
}
if (send_term_evt) {
lll->node_rx_adv_term->rx_ftr.extra =
(void *)lll->node_rx_adv_term->rx_ftr.extra;
lll->node_rx_adv_term->type =
NODE_RX_TYPE_EXT_ADV_TERMINATE;
lll->node_rx_adv_term->handle =
(uint16_t)ull_adv_handle_get(adv);
lll->node_rx_adv_term->rx_ftr.param = (void *)lll;
rx = lll->node_rx_adv_term;
link = rx->link;
ll_rx_put(link, rx);
ll_rx_sched();
term_evt_disable(ull_hdr);
}
ull_adv_done(done);
break;
}
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_OBSERVER)

View file

@ -67,6 +67,11 @@ static void disabled_cb(void *param);
static void conn_release(struct ll_adv_set *adv);
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
static void ticker_op_ext_stop_cb(uint32_t status, void *param);
static void ext_disabled_cb(void *param);
#endif /* CONFIG_BT_CTLR_ADV_EXT */
static inline uint8_t disable(uint8_t handle);
#if defined(CONFIG_BT_CTLR_ADV_SET)
@ -825,23 +830,32 @@ uint8_t ll_adv_enable(uint8_t enable)
/* The alloc here used for ext adv termination event */
link_adv_term = ll_rx_link_alloc();
if (!link_adv_term) {
#if defined(CONFIG_BT_PERIPHERAL)
if (adv->lll.conn) {
conn_release(adv);
}
#endif /* CONFIG_BT_PERIPHERAL */
/* TODO: figure out right return value */
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
node_rx_adv_term = ll_rx_alloc();
if (!node_rx_adv_term) {
#if defined(CONFIG_BT_PERIPHERAL)
if (adv->lll.conn) {
conn_release(adv);
}
#endif /* CONFIG_BT_PERIPHERAL */
ll_rx_link_release(link_adv_term);
/* TODO: figure out right return value */
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
node_rx_adv_term->hdr.link =
(memq_link_t *)link_adv_term;
adv->lll.node_rx_adv_term =
(struct node_rx_hdr *)node_rx_adv_term;
node_rx_adv_term->hdr.link = (void *)link_adv_term;
adv->lll.node_rx_adv_term = (void *)node_rx_adv_term;
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#endif /* CONFIG_BT_PERIPHERAL */
@ -1378,6 +1392,51 @@ uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len,
return 0;
}
#if defined(CONFIG_BT_CTLR_ADV_EXT)
void ull_adv_done(struct node_rx_event_done *done)
{
struct lll_adv *lll = (void *)HDR_ULL2LLL(done->param);
struct ll_adv_set *adv = (void *)HDR_LLL2EVT(lll);
uint8_t handle;
uint32_t ret;
if (adv->max_events && (adv->event_counter >= adv->max_events)) {
adv->max_events = 0;
lll->node_rx_adv_term->rx_ftr.extra =
(void *)(((uint32_t)adv->event_counter & 0xff) |
(BT_HCI_ERR_LIMIT_REACHED << 8));
goto ext_adv_disable;
}
if (adv->ticks_remain_duration &&
(adv->ticks_remain_duration <
HAL_TICKER_US_TO_TICKS((uint64_t)adv->interval * 625U))) {
adv->ticks_remain_duration = 0;
lll->node_rx_adv_term->rx_ftr.extra =
(void *)(((uint32_t)adv->event_counter & 0xff) |
(BT_HCI_ERR_ADV_TIMEOUT << 8));
goto ext_adv_disable;
}
return;
ext_adv_disable:
handle = ull_adv_handle_get(adv);
LL_ASSERT(handle < BT_CTLR_ADV_SET);
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
(TICKER_ID_ADV_BASE + handle), ticker_op_ext_stop_cb,
adv);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_BUSY));
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */
static int init_reset(void)
{
return 0;
@ -1450,6 +1509,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t laz
ticker_op_update_cb, adv);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_BUSY));
#if defined(CONFIG_BT_CTLR_ADV_EXT)
adv->event_counter += (lazy + 1);
@ -1611,6 +1671,49 @@ static void conn_release(struct ll_adv_set *adv)
}
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
static void ticker_op_ext_stop_cb(uint32_t status, void *param)
{
static memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, NULL};
struct ll_adv_set *adv;
uint32_t ret;
/* Ignore if race between thread and ULL */
if (status != TICKER_STATUS_SUCCESS) {
/* TODO: detect race */
return;
}
adv = param;
mfy.fp = ext_disabled_cb;
mfy.param = &adv->lll;
ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0,
&mfy);
LL_ASSERT(!ret);
}
static void ext_disabled_cb(void *param)
{
struct lll_adv *lll = (void *)param;
struct node_rx_hdr *rx_hdr = (void *)lll->node_rx_adv_term;
/* Under race condition, if a connection has been established then
* node_rx is already utilized to send terminate event on connection */
if (!rx_hdr) {
return;
}
rx_hdr->type = NODE_RX_TYPE_EXT_ADV_TERMINATE;
/* NOTE: parameters are already populated on disable, just enqueue here
*/
ll_rx_put(rx_hdr->link, rx_hdr);
ll_rx_sched();
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */
static inline uint8_t disable(uint8_t handle)
{
uint32_t volatile ret_cb;
@ -1683,14 +1786,16 @@ static inline uint8_t disable(uint8_t handle)
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct node_rx_pdu *node_rx_adv_term;
struct lll_adv *lll = &adv->lll;
if (lll->node_rx_adv_term) {
node_rx_adv_term = (struct node_rx_pdu *)lll->node_rx_adv_term;
struct node_rx_pdu *node_rx_adv_term =
(void *)lll->node_rx_adv_term;
lll->node_rx_adv_term = NULL;
ll_rx_link_release(node_rx_adv_term->hdr.link);
ll_rx_release(node_rx_adv_term);
lll->node_rx_adv_term = NULL;
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */

View file

@ -46,6 +46,10 @@ uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len,
uint8_t const *const data);
#if defined(CONFIG_BT_CTLR_ADV_EXT)
/* helper function to handle adv done events */
void ull_adv_done(struct node_rx_event_done *done);
/* Helper functions to initialise and reset ull_adv_aux module */
int ull_adv_aux_init(void);
int ull_adv_aux_reset(void);

View file

@ -216,10 +216,7 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
#if defined(CONFIG_BT_CTLR_ADV_EXT)
if (adv->is_created & ULL_ADV_CREATED_BITMASK_EXTENDED) {
struct ull_hdr *ull;
ull = &adv->ull;
/* Enqueue connection or CSA event */
ll_rx_put(link, rx);
/* use reserved link and node_rx to prepare
@ -227,9 +224,11 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
*/
rx = adv->lll.node_rx_adv_term;
link = rx->link;
rx->handle = ull_adv_handle_get(adv);
rx->type = NODE_RX_TYPE_EXT_ADV_TERMINATE;
rx->rx_ftr.extra = (void *)((uint32_t)lll->handle << 16);
rx->rx_ftr.param = (void *)(uint32_t)lll->handle;
rx->rx_ftr.extra = NULL;
}
#endif