You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/12/05 12:24:02 UTC

[GitHub] rymanluk closed pull request #244: nimble/ll: Qualification and performance issues

rymanluk closed pull request #244: nimble/ll: Qualification and performance issues
URL: https://github.com/apache/mynewt-nimble/pull/244
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h
index 6d86e370..36685fdf 100644
--- a/nimble/controller/include/controller/ble_ll.h
+++ b/nimble/controller/include/controller/ble_ll.h
@@ -189,6 +189,9 @@ STATS_SECT_START(ble_ll_stats)
     STATS_SECT_ENTRY(aux_scheduled)
     STATS_SECT_ENTRY(aux_received)
     STATS_SECT_ENTRY(aux_fired_for_read)
+    STATS_SECT_ENTRY(aux_allocated)
+    STATS_SECT_ENTRY(aux_freed)
+    STATS_SECT_ENTRY(aux_sched_cb)
     STATS_SECT_ENTRY(aux_conn_req_tx)
     STATS_SECT_ENTRY(aux_conn_rsp_tx)
     STATS_SECT_ENTRY(aux_conn_rsp_err)
diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h
index 5aa52340..65bff1c4 100644
--- a/nimble/controller/include/controller/ble_ll_scan.h
+++ b/nimble/controller/include/controller/ble_ll_scan.h
@@ -94,10 +94,13 @@ struct ble_ll_scan_params
 #define BLE_LL_AUX_HAS_ADDRA            0x08
 #define BLE_LL_AUX_IGNORE_BIT           0x10
 #define BLE_LL_AUX_HAS_DIR_ADDRA        0x20
+#define BLE_LL_AUX_TRUNCATED_SENT       0x40
 
+#define BLE_LL_SET_AUX_FLAG(aux_data, flag) ((aux_data)->flags |= flag)
 #define BLE_LL_CHECK_AUX_FLAG(aux_data, flag) (!!((aux_data)->flags & flag))
 
 struct ble_ll_aux_data {
+    uint8_t ref_cnt;
     uint8_t chan;
     uint8_t aux_phy;
     uint8_t aux_primary_phy;
@@ -230,9 +233,7 @@ int ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf,
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 /* Get aux ptr from ext advertising */
-int ble_ll_scan_get_aux_data(struct ble_ll_scan_sm *scansm,
-                             struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf,
-                             struct ble_ll_aux_data **aux_data);
+int ble_ll_scan_get_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf);
 
 /* Initialize the extended scanner when we start initiating */
 struct hci_ext_create_conn;
@@ -247,11 +248,13 @@ int ble_ll_scan_parse_ext_hdr(struct os_mbuf *om,
                               struct ble_mbuf_hdr *ble_hdr,
                               struct ble_ll_ext_adv_report *parsed_evt);
 
-void ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_scan);
+void ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan);
+int ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan);
 #endif
 
 /* Called to clean up current aux data */
 void ble_ll_scan_clean_cur_aux_data(void);
+void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
 
 #ifdef __cplusplus
 }
diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h
index 6c7d8a07..d41f4c1a 100644
--- a/nimble/controller/include/controller/ble_ll_sched.h
+++ b/nimble/controller/include/controller/ble_ll_sched.h
@@ -141,7 +141,7 @@ struct ble_ll_sched_item
 int ble_ll_sched_init(void);
 
 /* Remove item(s) from schedule */
-void ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch);
+int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch);
 
 void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb);
 
diff --git a/nimble/controller/include/controller/ble_ll_trace.h b/nimble/controller/include/controller/ble_ll_trace.h
index b2556d8d..7545b570 100644
--- a/nimble/controller/include/controller/ble_ll_trace.h
+++ b/nimble/controller/include/controller/ble_ll_trace.h
@@ -38,6 +38,8 @@ extern "C" {
 #define BLE_LL_TRACE_ID_CONN_RX                 9
 #define BLE_LL_TRACE_ID_ADV_TXDONE              10
 #define BLE_LL_TRACE_ID_ADV_HALT                11
+#define BLE_LL_TRACE_ID_AUX_REF                 12
+#define BLE_LL_TRACE_ID_AUX_UNREF               13
 
 #if MYNEWT_VAL(BLE_LL_SYSVIEW)
 
diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index 50e1749f..a2b59ef8 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -194,6 +194,9 @@ STATS_NAME_START(ble_ll_stats)
     STATS_NAME(ble_ll_stats, aux_scheduled)
     STATS_NAME(ble_ll_stats, aux_received)
     STATS_NAME(ble_ll_stats, aux_fired_for_read)
+    STATS_NAME(ble_ll_stats, aux_allocated)
+    STATS_NAME(ble_ll_stats, aux_freed)
+    STATS_NAME(ble_ll_stats, aux_sched_cb)
     STATS_NAME(ble_ll_stats, aux_conn_req_tx)
     STATS_NAME(ble_ll_stats, aux_conn_rsp_tx)
     STATS_NAME(ble_ll_stats, aux_conn_rsp_err)
diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c
index e0307bd3..bae72cc3 100644
--- a/nimble/controller/src/ble_ll_adv.c
+++ b/nimble/controller/src/ble_ll_adv.c
@@ -2628,6 +2628,9 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     struct aux_conn_rsp_data rsp_data;
 #endif
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+    struct ble_ll_resolv_entry *rl;
+#endif
 
     /* See if adva in the request (scan or connect) matches what we sent */
     advsm = g_ble_ll_cur_adv_sm;
@@ -2657,17 +2660,28 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
     resolved = 0;
 
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
-    if (ble_ll_is_rpa(peer, txadd) && ble_ll_resolv_enabled()) {
-        advsm->adv_rpa_index = ble_hw_resolv_list_match();
-        if (advsm->adv_rpa_index >= 0) {
-            ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
-            if (chk_wl) {
-                peer = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr;
-                peer_addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type;
-                resolved = 1;
+    rl = NULL;
+    if (ble_ll_resolv_enabled()) {
+        if (ble_ll_is_rpa(peer, txadd)) {
+            advsm->adv_rpa_index = ble_hw_resolv_list_match();
+            if (advsm->adv_rpa_index >= 0) {
+                ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
+                rl = &g_ble_ll_resolv_list[advsm->adv_rpa_index];
+                if (chk_wl) {
+                    peer = rl->rl_identity_addr;
+                    peer_addr_type = rl->rl_addr_type;
+                    resolved = 1;
+                }
+            } else {
+                if (chk_wl) {
+                    return -1;
+                }
             }
         } else {
-            if (chk_wl) {
+            /* Verify privacy mode */
+            rl = ble_ll_resolv_list_find(peer, peer_addr_type);
+            if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
+                                ble_ll_resolv_irk_nonzero(rl->rl_peer_irk)) {
                 return -1;
             }
         }
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 26090e50..3c407c5e 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -842,7 +842,9 @@ ble_ll_conn_init_wfr_timer_exp(void)
 
     scansm = connsm->scansm;
     if (scansm && scansm->cur_aux_data) {
-        ble_ll_scan_aux_data_free(scansm->cur_aux_data);
+        if (ble_ll_scan_aux_data_unref(scansm->cur_aux_data)) {
+            ble_ll_scan_aux_data_unref(scansm->cur_aux_data);
+        }
         scansm->cur_aux_data = NULL;
         STATS_INC(ble_ll_stats, aux_missed_adv);
         ble_ll_event_send(&scansm->scan_sched_ev);
@@ -2931,6 +2933,18 @@ ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
     uint8_t *adv_addr;
     struct ble_ll_conn_sm *connsm;
     int ext_adv_mode = -1;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data;
+
+    /*
+     * Let's take the reference for handover to LL.
+     * There shall be one more, if not something went very wrong
+     */
+    if (!ble_ll_scan_aux_data_unref(aux_data)) {
+        BLE_LL_ASSERT(0);
+    }
+
+#endif
 
     /* Get the connection state machine we are trying to create */
     connsm = g_ble_ll_conn_create_sm;
@@ -2946,13 +2960,14 @@ ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
     if (BLE_MBUF_HDR_AUX_INVALID(ble_hdr)) {
         goto scan_continue;
     }
+
     if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
         if (BLE_MBUF_HDR_WAIT_AUX(ble_hdr)) {
             /* Just continue scanning. We are waiting for AUX */
-            if (!ble_ll_sched_aux_scan(ble_hdr, connsm->scansm,
-                                      ble_hdr->rxinfo.user_data)) {
-               /* Wait for aux conn response */
-                ble_hdr->rxinfo.user_data = NULL;
+            if (!ble_ll_sched_aux_scan(ble_hdr, connsm->scansm, aux_data)) {
+                ble_ll_scan_aux_data_ref(aux_data);
+                ble_ll_scan_chk_resume();
+                return;
             }
             goto scan_continue;
         }
@@ -2963,7 +2978,6 @@ ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
         if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) {
             return;
         }
-        ble_ll_scan_aux_data_free(ble_hdr->rxinfo.user_data);
     }
 #endif
 
@@ -2974,7 +2988,8 @@ ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
         if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr,
                                         &adv_addr, &addr_type,
                                         NULL, NULL, &ext_adv_mode)) {
-            return;
+            /* Something got wrong, keep trying to connect */
+            goto scan_continue;
         }
 
         if (ble_ll_scan_whitelist_enabled()) {
@@ -3027,6 +3042,7 @@ ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
         /* Lets take last used phy */
         ble_ll_conn_init_phy(connsm, ble_hdr->rxinfo.phy);
 #endif
+        ble_ll_scan_aux_data_unref(aux_data);
 #endif
         ble_ll_conn_created(connsm, NULL);
         return;
@@ -3034,7 +3050,8 @@ ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
 
 scan_continue:
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    ble_ll_scan_aux_data_free(ble_hdr->rxinfo.user_data);
+    /* Drop last reference and keep continue to connect */
+    ble_ll_scan_aux_data_unref(aux_data);
 #endif
     ble_ll_scan_chk_resume();
 }
@@ -3170,27 +3187,32 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     struct ble_ll_scan_sm *scansm;
     uint8_t phy;
-    struct ble_ll_aux_data *aux_data = NULL;
 #endif
     int ext_adv_mode = -1;
 
     /* Get connection state machine to use if connection to be established */
     connsm = g_ble_ll_conn_create_sm;
 
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    scansm = connsm->scansm;
-    ble_hdr->rxinfo.user_data =scansm->cur_aux_data;
-#endif
-
     rc = -1;
     pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
     pyld_len = rxbuf[1];
 
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    scansm = connsm->scansm;
+    if (scansm->cur_aux_data) {
+        ble_hdr->rxinfo.user_data = scansm->cur_aux_data;
+        scansm->cur_aux_data = NULL;
+        if (ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data) == 0) {
+            ble_hdr->rxinfo.user_data = 0;
+            goto init_rx_isr_exit;
+        }
+    }
+#endif
+
     if (!crcok) {
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
         /* Invalid packet - make sure we do not wait for AUX_CONNECT_RSP */
         ble_ll_conn_reset_pending_aux_conn_rsp();
-        scansm->cur_aux_data = NULL;
 #endif
 
         /* Ignore this packet */
@@ -3221,16 +3243,14 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
             goto init_rx_isr_exit;
         }
 
-        rc = ble_ll_scan_get_aux_data(scansm, ble_hdr, rxbuf, &aux_data);
+        rc = ble_ll_scan_get_aux_data(ble_hdr, rxbuf);
         if (rc < 0) {
             /* No memory or broken packet */
             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
-            ble_ll_scan_aux_data_free(scansm->cur_aux_data);
-            scansm->cur_aux_data = NULL;
+            ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data);
+            ble_hdr->rxinfo.user_data = NULL;
             goto init_rx_isr_exit;
         }
-
-        ble_hdr->rxinfo.user_data = aux_data;
     }
 #endif
 
@@ -3436,6 +3456,12 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
     STATS_INC(ble_ll_conn_stats, conn_req_txd);
 
 init_rx_isr_exit:
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    if (ble_hdr->rxinfo.user_data) {
+        ble_ll_scan_aux_data_ref(ble_hdr->rxinfo.user_data);
+    }
+#endif
     /*
      * We have to restart receive if we cant hand up pdu. We return 0 so that
      * the phy does not get disabled.
diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c
index 07f520bf..95dd16ea 100644
--- a/nimble/controller/src/ble_ll_hci.c
+++ b/nimble/controller/src/ble_ll_hci.c
@@ -671,6 +671,7 @@ ble_ll_is_valid_adv_mode(uint8_t ocf)
     case BLE_HCI_OCF_LE_CREATE_CONN:
     case BLE_HCI_OCF_LE_SET_ADV_PARAMS:
     case BLE_HCI_OCF_LE_SET_ADV_ENABLE:
+    case BLE_HCI_OCF_LE_SET_ADV_DATA:
     case BLE_HCI_OCF_LE_SET_SCAN_PARAMS:
     case BLE_HCI_OCF_LE_SET_SCAN_ENABLE:
     case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA:
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 78234784..1fd0bf5d 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -38,6 +38,7 @@
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_resolv.h"
 #include "controller/ble_ll_xcvr.h"
+#include "controller/ble_ll_trace.h"
 #include "ble_ll_conn_priv.h"
 
 /*
@@ -162,17 +163,19 @@ ble_ll_aux_scan_cb(struct ble_ll_sched_item *sch)
     uint8_t lls = ble_ll_state_get();
     uint32_t wfr_usec;
 
+    STATS_INC(ble_ll_stats, aux_sched_cb);
+
     /* In case scan has been disabled or there is other aux ptr in progress
      * just drop the scheduled item
      */
     if (!scansm->scan_enabled || scansm->cur_aux_data) {
-        ble_ll_scan_aux_data_free(sch->cb_arg);
+        ble_ll_scan_aux_data_unref(sch->cb_arg);
         goto done;
     }
 
     /* Check if there is no aux connect sent. If so drop the sched item */
     if (lls == BLE_LL_STATE_INITIATING && ble_ll_conn_init_pending_aux_conn_rsp()) {
-        ble_ll_scan_aux_data_free(sch->cb_arg);
+        ble_ll_scan_aux_data_unref(sch->cb_arg);
         goto done;
     }
 
@@ -194,7 +197,7 @@ ble_ll_aux_scan_cb(struct ble_ll_sched_item *sch)
     scansm->cur_aux_data->scanning = 1;
 
     if (ble_ll_scan_start(scansm, sch)) {
-        ble_ll_scan_aux_data_free(scansm->cur_aux_data);
+        ble_ll_scan_aux_data_unref(scansm->cur_aux_data);
         scansm->cur_aux_data = NULL;
         ble_ll_scan_chk_resume();
         goto done;
@@ -224,8 +227,11 @@ ble_ll_scan_ext_adv_init(struct ble_ll_aux_data **aux_data)
     e->sch.sched_cb = ble_ll_aux_scan_cb;
     e->sch.cb_arg = e;
     e->sch.sched_type = BLE_LL_SCHED_TYPE_AUX_SCAN;
+    e->ref_cnt = 1;
+    ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t)e, e->ref_cnt);
 
     *aux_data = e;
+    STATS_INC(ble_ll_stats, aux_allocated);
 
     return 0;
 }
@@ -404,6 +410,112 @@ ble_ll_scan_find_dup_adv(uint8_t *addr, uint8_t txadd)
     return NULL;
 }
 
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+static struct ble_ll_ext_adv_report *
+ble_ll_scan_init_ext_adv_report(struct ble_ll_ext_adv_report *copy_from)
+{
+    struct ble_ll_ext_adv_report *evt;
+
+    evt = (struct ble_ll_ext_adv_report *) ble_hci_trans_buf_alloc(
+                                                    BLE_HCI_TRANS_BUF_EVT_LO);
+    if (!evt) {
+        return NULL;
+    }
+
+    if (copy_from) {
+        memcpy(evt, copy_from, sizeof(*evt));
+    } else {
+        memset(evt, 0, sizeof(*evt));
+
+        evt->event_meta = BLE_HCI_EVCODE_LE_META;
+        evt->subevt = BLE_HCI_LE_SUBEV_EXT_ADV_RPT;
+        /* We support only one report per event now */
+        evt->num_reports = 1;
+        /* Init TX Power with "Not available" which is 127 */
+        evt->tx_power = 127;
+        /* Init RSSI with "Not available" which is 127 */
+        evt->rssi = 127;
+        /* Init SID with "Not available" which is 0xFF */
+        evt->sid = 0xFF;
+        /* Init address type with "anonymous" which is 0xFF */
+        evt->addr_type = 0xFF;
+    }
+
+    return evt;
+}
+
+static void
+ble_ll_scan_send_truncated_if_chained(struct ble_ll_aux_data *aux_data)
+{
+    struct ble_ll_ext_adv_report *evt;
+
+    if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
+        goto done;
+    }
+
+    BLE_LL_ASSERT(aux_data);
+
+    if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_CHAIN_BIT)) {
+        /* if not chained, there is nothing to do here */
+        goto done;
+    }
+
+    if (aux_data->evt) {
+        evt = aux_data->evt;
+        aux_data->evt = NULL;
+    } else {
+        evt = ble_ll_scan_init_ext_adv_report(NULL);
+        if (!evt) {
+            goto done;
+        }
+    }
+
+    evt->event_len = sizeof(*evt);
+    evt->evt_type = aux_data->evt_type;
+    evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
+    BLE_LL_SET_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT);
+
+    if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_HAS_ADDRA)) {
+        memcpy(evt->addr, aux_data->addr, 6);
+        evt->addr_type = aux_data->addr_type;
+    }
+
+    if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_HAS_DIR_ADDRA)) {
+        memcpy(evt->dir_addr, aux_data->dir_addr, 6);
+        evt->dir_addr_type = aux_data->dir_addr_type;
+    }
+
+    evt->sid = (aux_data->adi >> 12);
+    ble_ll_hci_event_send((uint8_t *)evt);
+
+done:
+    ble_ll_scan_aux_data_unref(aux_data);
+}
+#endif
+
+void
+ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data)
+{
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    /*
+     * Check if tuncated has been sent
+     *
+     * Normally reference counter here should be 2. 1 for outstanding
+     * complete event and one for ongoing scanning. If there is only 1
+     * that means, advertising event is already completed
+     * (truncated was sent to the host) and we just need to drop last reference.
+     * Otherwise we should try to send truncated event to the host.
+     */
+    if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT)) {
+        ble_ll_scan_send_truncated_if_chained(aux_data);
+    }
+
+    if (ble_ll_scan_aux_data_unref(aux_data) > 0) {
+        BLE_LL_ASSERT(0);
+    }
+
+#endif
+}
 /**
  * Do scan machine clean up on PHY disabled
  *
@@ -416,7 +528,7 @@ ble_ll_scan_clean_cur_aux_data(void)
 
     /* If scanner was reading aux ptr, we need to clean it up */
     if (scansm && scansm->cur_aux_data) {
-        ble_ll_scan_aux_data_free(scansm->cur_aux_data);
+        ble_ll_scan_end_adv_evt(scansm->cur_aux_data);
         scansm->cur_aux_data = NULL;
     }
 #endif
@@ -571,40 +683,6 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd)
 }
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-
-static struct ble_ll_ext_adv_report *
-ble_ll_scan_init_ext_adv_report(struct ble_ll_ext_adv_report *copy_from)
-{
-    struct ble_ll_ext_adv_report *evt;
-
-    evt = (struct ble_ll_ext_adv_report *) ble_hci_trans_buf_alloc(
-                                                    BLE_HCI_TRANS_BUF_EVT_LO);
-    if (!evt) {
-        return NULL;
-    }
-
-    if (copy_from) {
-        memcpy(evt, copy_from, sizeof(*evt));
-    } else {
-        memset(evt, 0, sizeof(*evt));
-
-        evt->event_meta = BLE_HCI_EVCODE_LE_META;
-        evt->subevt = BLE_HCI_LE_SUBEV_EXT_ADV_RPT;
-        /* We support only one report per event now */
-        evt->num_reports = 1;
-        /* Init TX Power with "Not available" which is 127 */
-        evt->tx_power = 127;
-        /* Init RSSI with "Not available" which is 127 */
-        evt->rssi = 127;
-        /* Init SID with "Not available" which is 0xFF */
-        evt->sid = 0xFF;
-        /* Init address type with "anonymous" which is 0xFF */
-        evt->addr_type = 0xFF;
-    }
-
-    return evt;
-}
-
 static int
 ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,
                                       uint8_t addr_type, uint8_t *addr,
@@ -1110,6 +1188,59 @@ ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
     return 0;
 }
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+static void
+ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_scan)
+{
+    if (aux_scan) {
+        if (aux_scan->evt) {
+            ble_hci_trans_buf_free((uint8_t *)aux_scan->evt);
+            aux_scan->evt = NULL;
+        }
+        os_memblock_put(&ext_adv_pool, aux_scan);
+        STATS_INC(ble_ll_stats, aux_freed);
+    }
+}
+
+void
+ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_data)
+{
+    os_sr_t sr;
+
+    if (!aux_data) {
+        return;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    aux_data->ref_cnt++;
+    ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t) aux_data, aux_data->ref_cnt);
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+int
+ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_data)
+{
+    os_sr_t sr;
+    int ret;
+
+    if (!aux_data) {
+        return 0;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    aux_data->ref_cnt--;
+    ret = aux_data->ref_cnt;
+    ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_UNREF, (uint32_t) aux_data, aux_data->ref_cnt);
+
+    if (aux_data->ref_cnt == 0) {
+        ble_ll_scan_aux_data_free(aux_data);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+
+    return ret;
+}
+
 static void
 ble_ll_scan_sched_remove(struct ble_ll_sched_item *sch)
 {
@@ -1565,8 +1696,7 @@ ble_ll_ext_adv_phy_mode_to_local_phy(uint8_t adv_phy_mode)
 }
 
 static int
-ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_scan_sm *scansm,
-                              struct ble_ll_aux_data *aux_data, uint8_t *buf)
+ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data *aux_data, uint8_t *buf)
 {
     uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF;
 
@@ -1612,7 +1742,7 @@ ble_ll_ext_scan_parse_adv_info(struct ble_ll_scan_sm *scansm,
  * ble_ll_scan_get_aux_data
  *
  * Get aux data pointer. It is new allocated data for beacon or currently
- * processing aux data pointer
+ * processing aux data pointer. Aux data pointer will be attached to ble_hdr.rxinfo.user_data
  *
  * Context: Interrupt
  *
@@ -1627,9 +1757,7 @@ ble_ll_ext_scan_parse_adv_info(struct ble_ll_scan_sm *scansm,
  * -1: error
  */
 int
-ble_ll_scan_get_aux_data(struct ble_ll_scan_sm *scansm,
-                         struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf,
-                         struct ble_ll_aux_data **aux_data)
+ble_ll_scan_get_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf)
 {
     uint8_t ext_hdr_len;
     uint8_t pdu_len;
@@ -1639,7 +1767,10 @@ ble_ll_scan_get_aux_data(struct ble_ll_scan_sm *scansm,
     uint8_t has_dir_addr = 0;
     uint8_t has_adi = 0;
     int i;
+    struct ble_ll_aux_data *current_aux = ble_hdr->rxinfo.user_data;
+    struct ble_ll_aux_data *new_aux = NULL;
     struct ble_ll_aux_data tmp_aux_data = { 0 };
+    int rc;
 
     pdu_len = rxbuf[1];
     if (pdu_len == 0) {
@@ -1649,7 +1780,7 @@ ble_ll_scan_get_aux_data(struct ble_ll_scan_sm *scansm,
     tmp_aux_data.mode = rxbuf[2] >> 6;
 
     ext_hdr_len = rxbuf[2] & 0x3F;
-    if (ext_hdr_len < BLE_LL_EXT_ADV_AUX_PTR_SIZE && !scansm->cur_aux_data) {
+    if (ext_hdr_len < BLE_LL_EXT_ADV_AUX_PTR_SIZE && !ble_hdr->rxinfo.user_data) {
         return -1;
     }
 
@@ -1686,67 +1817,85 @@ ble_ll_scan_get_aux_data(struct ble_ll_scan_sm *scansm,
 
     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) {
 
-        if (ble_ll_ext_scan_parse_aux_ptr(scansm, &tmp_aux_data, ext_hdr + i) < 0) {
+        if (ble_ll_ext_scan_parse_aux_ptr(&tmp_aux_data, ext_hdr + i) < 0) {
             return -1;
         }
 
-        if (scansm->cur_aux_data) {
+        if (current_aux) {
             /* If we are here that means there is chain advertising. */
 
             /* Lets reuse old aux_data */
-            *aux_data = scansm->cur_aux_data;
+            new_aux = current_aux;
 
             /* TODO Collision; Do smth smart when did does not match */
-            if (!((*aux_data)->evt_type & (BLE_HCI_ADV_SCAN_MASK))
-                            && (tmp_aux_data.adi != (*aux_data)->adi)) {
+            if (!(new_aux->evt_type & (BLE_HCI_ADV_SCAN_MASK))
+                            && (tmp_aux_data.adi != new_aux->adi)) {
                 STATS_INC(ble_ll_stats, aux_chain_err);
-                (*aux_data)->flags |= BLE_LL_AUX_INCOMPLETE_ERR_BIT;
+                new_aux->flags |= BLE_LL_AUX_INCOMPLETE_ERR_BIT;
             }
 
-            (*aux_data)->flags |= BLE_LL_AUX_CHAIN_BIT;
-            (*aux_data)->flags |= BLE_LL_AUX_INCOMPLETE_BIT;
-        } else if (ble_ll_scan_ext_adv_init(aux_data) < 0) {
+            new_aux->flags |= BLE_LL_AUX_CHAIN_BIT;
+            new_aux->flags |= BLE_LL_AUX_INCOMPLETE_BIT;
+        } else {
+            if (ble_ll_scan_ext_adv_init(&new_aux) < 0) {
+            /* Out of memory */
             return -1;
+            }
         }
 
-        (*aux_data)->aux_phy = tmp_aux_data.aux_phy;
+        new_aux->aux_phy = tmp_aux_data.aux_phy;
 
-        if (!scansm->cur_aux_data) {
+        if (!current_aux) {
             /* Only for first ext adv we want to keep primary phy.*/
-            (*aux_data)->aux_primary_phy = ble_hdr->rxinfo.phy;
-        } else {
-            /* We are ok to clear cur_aux_data now. */
-            scansm->cur_aux_data = NULL;
+            new_aux->aux_primary_phy = ble_hdr->rxinfo.phy;
         }
 
-        if (has_adi) {
-            (*aux_data)->adi = tmp_aux_data.adi;
-        }
+        new_aux->chan = tmp_aux_data.chan;
+        new_aux->offset = tmp_aux_data.offset;
+        new_aux->mode = tmp_aux_data.mode;
 
-        (*aux_data)->chan = tmp_aux_data.chan;
-        (*aux_data)->offset = tmp_aux_data.offset;
-        (*aux_data)->mode = tmp_aux_data.mode;
-        if (has_addr) {
-            memcpy((*aux_data)->addr, tmp_aux_data.addr, 6);
-            (*aux_data)->addr_type = tmp_aux_data.addr_type;
-            (*aux_data)->flags |= BLE_LL_AUX_HAS_ADDRA;
-        }
-        if (has_dir_addr) {
-            memcpy((*aux_data)->dir_addr, tmp_aux_data.dir_addr, 6);
-            (*aux_data)->dir_addr_type = tmp_aux_data.dir_addr_type;
-            (*aux_data)->flags |= BLE_LL_AUX_HAS_DIR_ADDRA;
+        /* New aux_data or chaining */
+        rc = 0;
+    } else {
+
+        /* So ext packet does not have aux ptr. It can be because
+         * a) it is empty beacon (no aux ptr at all)
+         * b) there is no chaining or chaining has just stopped. In this case we do hava aux_data */
+
+        if (!current_aux) {
+            new_aux = NULL;
+            return 1;
         }
-        return 0;
+
+        /*If there is no new aux ptr, just get current one */
+        new_aux = ble_hdr->rxinfo.user_data;
+
+        /* Clear incomplete flag */
+        new_aux->flags &= ~BLE_LL_AUX_INCOMPLETE_BIT;
+
+        /* Current processing aux_ptr */
+        rc = 1;
+    }
+
+    if (has_adi) {
+        new_aux->adi = tmp_aux_data.adi;
     }
 
-    /*If there is no new aux ptr, just get current one */
-    (*aux_data) = scansm->cur_aux_data;
-    scansm->cur_aux_data = NULL;
+    if (has_addr) {
+        memcpy(new_aux->addr, tmp_aux_data.addr, 6);
+        new_aux->addr_type = tmp_aux_data.addr_type;
+        new_aux->flags |= BLE_LL_AUX_HAS_ADDRA;
+    }
+
+    if (has_dir_addr) {
+        memcpy(new_aux->dir_addr, tmp_aux_data.dir_addr, 6);
+        new_aux->dir_addr_type = tmp_aux_data.dir_addr_type;
+        new_aux->flags |= BLE_LL_AUX_HAS_DIR_ADDRA;
+    }
 
-    /* Clear incomplete flag */
-    (*aux_data)->flags &= ~BLE_LL_AUX_INCOMPLETE_BIT;
+    ble_hdr->rxinfo.user_data = new_aux;
 
-    return 1;
+    return rc;
 }
 /**
  * Called when a receive ADV_EXT PDU has ended.
@@ -1903,6 +2052,27 @@ ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr,
         return -1;
     }
 
+    if (aux_data) {
+        /* If address has been provided, we do have it already in aux_data.*/
+        if (aux_data->flags & BLE_LL_AUX_HAS_ADDRA) {
+            *addr = aux_data->addr;
+            *addr_type = aux_data->addr_type;
+        }
+
+        if (!inita) {
+            return 0;
+        }
+
+        if (aux_data->flags & BLE_LL_AUX_HAS_DIR_ADDRA) {
+            *inita = aux_data->dir_addr;
+            *inita_type = aux_data->dir_addr_type;
+        }
+
+        return 0;
+    }
+
+    /* If this is just becon with no aux data, lets get address from the packet */
+
     ext_hdr_len = rxbuf[2] & 0x3F;
 
     ext_hdr_flags = rxbuf[3];
@@ -1918,19 +2088,6 @@ ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr,
         *addr_type =
                 ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK);
         i += BLE_LL_EXT_ADV_ADVA_SIZE;
-        if (aux_data) {
-            /* Lets copy addr to aux_data. Need it for e.g. chaining */
-            /* XXX add sanity checks */
-            memcpy(aux_data->addr, *addr, 6);
-            aux_data->addr_type = *addr_type;
-            aux_data->flags |= BLE_LL_AUX_HAS_ADDRA;
-        }
-    } else {
-        /* We should have address already in aux_data */
-        if (aux_data->flags & BLE_LL_AUX_HAS_ADDRA) {
-            *addr = aux_data->addr;
-            *addr_type = aux_data->addr_type;
-        }
     }
 
     if (!inita) {
@@ -1942,18 +2099,6 @@ ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr,
         *inita_type =
                 ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK);
         i += BLE_LL_EXT_ADV_TARGETA_SIZE;
-        if (aux_data) {
-            /* Lets copy addr to aux_data. Need it for e.g. chaining */
-            memcpy(aux_data->dir_addr, *inita, 6);
-            aux_data->dir_addr_type = *inita_type;
-            aux_data->flags |= BLE_LL_AUX_HAS_DIR_ADDRA;
-        }
-    } else {
-        /* We should have address already in aux_data */
-        if (aux_data->flags & BLE_LL_AUX_HAS_DIR_ADDRA) {
-            *inita = aux_data->dir_addr;
-            *inita_type = aux_data->dir_addr_type;
-        }
     }
 
     return 0;
@@ -2033,7 +2178,6 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
     struct ble_ll_scan_params *scanphy;
     int ext_adv_mode = -1;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    struct ble_ll_aux_data *aux_data = NULL;
     uint8_t phy_mode;
 #endif
 
@@ -2058,16 +2202,27 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
         return 0;
     }
 
+    rc = -1;
+
     ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    ble_hdr->rxinfo.user_data = scansm->cur_aux_data;
+    if (scansm->cur_aux_data) {
+        ble_hdr->rxinfo.user_data = scansm->cur_aux_data;
+        scansm->cur_aux_data = NULL;
+        if (ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data) == 0) {
+            ble_hdr->rxinfo.user_data = NULL;
+            ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
+            goto scan_rx_isr_exit;
+        }
+    }
 #endif
 
     /* Just leave if the CRC is not OK. */
-    rc = -1;
     if (!crcok) {
-        scansm->cur_aux_data = NULL;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+        ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
+#endif
         goto scan_rx_isr_exit;
     }
 
@@ -2081,13 +2236,10 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
             goto scan_rx_isr_exit;
         }
         /* Create new aux data for beacon or get current processing aux ptr */
-        rc = ble_ll_scan_get_aux_data(scansm, ble_hdr, rxbuf, &aux_data);
+        rc = ble_ll_scan_get_aux_data(ble_hdr, rxbuf);
         if (rc < 0) {
             /* No memory or broken packet */
             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
-            /* cur_aux_data is already in the ble_hdr->rxinfo.user_data and
-             * will be taken care by LL task */
-            scansm->cur_aux_data = NULL;
 
             goto scan_rx_isr_exit;
         }
@@ -2096,11 +2248,6 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT;
         }
 
-        /* If the ble_ll_scan_get_aux_data() succeed, scansm->cur_aux_data is NULL
-         * and aux_data contains correct data
-         */
-        BLE_LL_ASSERT(scansm->cur_aux_data == NULL);
-        ble_hdr->rxinfo.user_data = aux_data;
         rc = -1;
     }
 #endif
@@ -2213,6 +2360,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
                 if (ble_hdr->rxinfo.channel <  BLE_PHY_NUM_DATA_CHANS) {
                     /* Let's keep the aux ptr as a reference to scan rsp */
                     scansm->cur_aux_data = ble_hdr->rxinfo.user_data;
+                    ble_ll_scan_aux_data_ref(scansm->cur_aux_data);
                     STATS_INC(ble_ll_stats, aux_scan_req_tx);
                 }
 #endif
@@ -2224,6 +2372,12 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
     if (rc) {
         ble_ll_state_set(BLE_LL_STATE_STANDBY);
     }
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    /* On handover lets increase ref count */
+    if (ble_hdr->rxinfo.user_data) {
+        ble_ll_scan_aux_data_ref(ble_hdr->rxinfo.user_data);
+    }
+#endif
     return rc;
 }
 
@@ -2303,8 +2457,7 @@ ble_ll_scan_wfr_timer_exp(void)
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     if (scansm->cur_aux_data) {
-        /*TODO handle chain incomplete, data truncated */
-        ble_ll_scan_aux_data_free(scansm->cur_aux_data);
+        ble_ll_scan_end_adv_evt(scansm->cur_aux_data);
         scansm->cur_aux_data = NULL;
         STATS_INC(ble_ll_stats, aux_missed_adv);
         ble_ll_scan_chk_resume();
@@ -2315,17 +2468,6 @@ ble_ll_scan_wfr_timer_exp(void)
 }
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-void
-ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_scan)
-{
-    if (aux_scan) {
-        if (aux_scan->evt) {
-            ble_hci_trans_buf_free((uint8_t *)aux_scan->evt);
-        }
-        os_memblock_put(&ext_adv_pool, aux_scan);
-    }
-}
-
 /*
  * Send extended advertising report
  *
@@ -2346,9 +2488,11 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
     int datalen;
     int rc;
     bool need_event;
+    uint8_t max_event_len;
 
     if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
-        return -1;
+        rc = -1;
+        goto done;
     }
 
     /*
@@ -2358,10 +2502,12 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
      */
     if (aux_data && aux_data->evt) {
         evt = aux_data->evt;
+        aux_data->evt = NULL;
     } else {
         evt = ble_ll_scan_init_ext_adv_report(NULL);
         if (!evt) {
-            return -1;
+            rc = -1;
+            goto done;
         }
     }
 
@@ -2369,19 +2515,21 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
     if (datalen < 0) {
         /* XXX what should we do here? send some trimmed event? */
         ble_hci_trans_buf_free((uint8_t *)evt);
-        return -1;
+        rc = -1;
+        goto done;
     }
 
     offset = 0;
+    max_event_len = min(UINT8_MAX, BLE_LL_MAX_EVT_LEN);
 
     do {
         need_event = false;
         next_evt = NULL;
 
-        evt->adv_data_len = min(BLE_LL_MAX_EVT_LEN - sizeof(*evt),
+        evt->adv_data_len = min(max_event_len - sizeof(*evt),
                                 datalen - offset);
-        evt->event_len = (sizeof(*evt) - BLE_HCI_EVENT_HDR_LEN) +
-                         evt->adv_data_len;
+        /* Event len, should not contain event meta code and let itself */
+        evt->event_len = (sizeof(*evt) - BLE_HCI_EVENT_HDR_LEN) + evt->adv_data_len;
         evt->rssi = hdr->rxinfo.rssi;
 
         os_mbuf_copydata(om, offset, evt->adv_data_len, evt->adv_data);
@@ -2391,13 +2539,11 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
         if (offset < datalen) {
             /* Need another event for next fragment of this PDU */
             need_event = true;
-        } else if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) {
+        } else if (aux_data && BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) {
             need_event = false;
-        } else if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_BIT)) {
+        } else if (aux_data && BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_BIT)) {
             /* Need another event for next PDU in chain */
             need_event = true;
-        } else {
-            need_event = false;
         }
 
         /* Assume data status is not "completed" */
@@ -2414,14 +2560,17 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE);
             } else {
                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
+                BLE_LL_SET_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT);
                 rc = -1;
             }
-        } else if (aux_data) { 
+        } else if (aux_data ) {
             if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) {
                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
                 rc = -1;
             } else if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_BIT)) {
                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE);
+            } else {
+                rc = 0;
             }
         } else {
             rc = 0;
@@ -2434,8 +2583,19 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
 
     BLE_LL_ASSERT(offset <= datalen);
 
-    /* Store any event left for later use */
-    aux_data->evt = evt;
+    if (aux_data){
+        /* Store any event left for later use */
+        aux_data->evt = evt;
+    } else {
+        /* If it is empty beacon, evt shall be NULL */
+        BLE_LL_ASSERT(!evt);
+    }
+
+done:
+    /* If advertising event is completed or failed, we can drop the reference */
+    if (rc <= 0) {
+        ble_ll_scan_aux_data_unref(aux_data);
+    }
 
     return rc;
 }
@@ -2469,16 +2629,25 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
     struct ble_mbuf_hdr *ble_hdr;
     int ext_adv_mode = -1;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    struct ble_ll_aux_data *aux_data;
+    struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
     int rc;
+    uint8_t evt_possibly_truncated = 0;
 #endif
 
     /* Set scan response check flag */
     scan_rsp_chk = BLE_MBUF_HDR_SCAN_RSP_RCV(hdr);
 
     /* We dont care about scan requests or connect requests */
-    if (!BLE_MBUF_HDR_CRC_OK(hdr) || (ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) ||
-        (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
+    if (!BLE_MBUF_HDR_CRC_OK(hdr)) {
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+        if (BLE_MBUF_HDR_AUX_INVALID(hdr)) {
+            evt_possibly_truncated = 1;
+        }
+#endif
+        goto scan_continue;
+    }
+
+    if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) || (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
         goto scan_continue;
     }
 
@@ -2486,7 +2655,10 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
                                     &adv_addr, &txadd,
                                     &init_addr, &init_addr_type,
                                     &ext_adv_mode)) {
-       goto scan_continue;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+        evt_possibly_truncated = 1;
+#endif
+        goto scan_continue;
     }
 
     ident_addr = adv_addr;
@@ -2519,6 +2691,9 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
     if (ble_ll_scan_chk_filter_policy(ptype, adv_addr, txadd, init_addr,
                                       init_addr_type,
                                       BLE_MBUF_HDR_DEVMATCH(hdr))) {
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+        ble_ll_scan_aux_data_unref(aux_data);
+#endif
         goto scan_continue;
     }
 
@@ -2559,6 +2734,11 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
     /* Filter duplicates */
     if (scansm->scan_filt_dups) {
         if (ble_ll_scan_is_dup_adv(ptype, ident_addr_type, ident_addr)) {
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+            if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
+                ble_ll_scan_aux_data_unref(aux_data);
+            }
+#endif
             goto scan_continue;
         }
     }
@@ -2566,33 +2746,45 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
         if (!scansm->ext_scanning) {
+            ble_ll_scan_aux_data_unref(aux_data);
             goto scan_continue;
         }
 
         if (BLE_MBUF_HDR_AUX_INVALID(hdr)) {
+            evt_possibly_truncated = 1;
             goto scan_continue;
         }
 
-        aux_data = hdr->rxinfo.user_data;
-
-        if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_IGNORE_BIT)) {
+        /* If it is ignore it means event is already truncated, just unref aux */
+        if (aux_data && BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_IGNORE_BIT)) {
+            ble_ll_scan_aux_data_unref(aux_data);
             goto scan_continue;
         }
 
         /* Let's see if that packet contains aux ptr*/
         if (BLE_MBUF_HDR_WAIT_AUX(hdr)) {
+           BLE_LL_ASSERT(aux_data);
             if (ble_ll_sched_aux_scan(hdr, scansm, hdr->rxinfo.user_data)) {
                 /* We are here when could not schedule the aux ptr */
                 hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT;
                 /* Mark that chain is trimmed */
                 aux_data->flags |= BLE_LL_AUX_INCOMPLETE_ERR_BIT;
+                /* Note: aux_data unref will be done when truncated is sent to the host or
+                 * below if we failed to schedule for the very first aux packet.
+                 */
+            } else {
+                /* We are here because successfully scheduled for next aux */
+                ble_ll_scan_aux_data_ref(aux_data);
             }
 
+            /*
+             * If this is ext adv, there is nothing to do here but just leave and wait
+             * for aux packet. However, if we was not able to schedule for first aux packet,
+             * make sure to unref aux_data here
+             */
             if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_CHAIN_BIT)) {
-                /* This is just beacon. Let's wait for more data */
-                if (BLE_MBUF_HDR_WAIT_AUX(hdr)) {
-                    /* If scheduled for aux let's don't remove aux data */
-                    hdr->rxinfo.user_data = NULL;
+                if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) {
+                    ble_ll_scan_aux_data_unref(aux_data);
                 }
                 goto scan_continue;
             }
@@ -2600,6 +2792,8 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
             STATS_INC(ble_ll_stats, aux_chain_cnt);
         }
 
+        /* For the time when sending events up, lets increase ref count */
+        ble_ll_scan_aux_data_ref(aux_data);
         rc = ble_ll_hci_send_ext_adv_report(ptype, ident_addr, ident_addr_type,
                                             init_addr, init_addr_type, om, hdr);
         if (rc < 0) {
@@ -2608,19 +2802,25 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
              * make sure we do not send any more events for this chain, just in
              * case we managed to scan something before events were processed.
              */
-            ble_ll_sched_rmv_elem(&aux_data->sch);
-            hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT;
+            if (BLE_MBUF_HDR_WAIT_AUX(hdr)) {
+                hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT;
+                if (ble_ll_sched_rmv_elem(&aux_data->sch) == 0) {
+                    ble_ll_scan_aux_data_unref(aux_data);
+                }
+            }
             aux_data->flags |= BLE_LL_AUX_IGNORE_BIT;
         }
-        ble_ll_scan_switch_phy(scansm);
+        ble_ll_scan_aux_data_unref(aux_data);
 
-        if (BLE_MBUF_HDR_WAIT_AUX(hdr)) {
-            /* If scheduled for aux let's don't remove aux data */
-            hdr->rxinfo.user_data = NULL;
-        }
+        ble_ll_scan_switch_phy(scansm);
 
         if (scansm->scan_rsp_pending) {
             if (!scan_rsp_chk) {
+                /* We are here because we sent SCAN_REQ and wait for SCAN_RSP.
+                 * We do not drop reference here by purpose, because
+                 * it was already dropped in ble_ll_hci_send_ext_adv_report() as
+                 * very first advertising report for scannable report is "completed"
+                 */
                 return;
             }
 
@@ -2638,7 +2838,14 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
 scan_continue:
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-        ble_ll_scan_aux_data_free(hdr->rxinfo.user_data);
+    if (aux_data) {
+        if (evt_possibly_truncated) {
+            ble_ll_scan_end_adv_evt(aux_data);
+        } else {
+            /* This is ref for handover to LL */
+            ble_ll_scan_aux_data_unref(aux_data);
+        }
+    }
 #endif
     /*
      * If the scan response check bit is set and we are pending a response,
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index cb00ea0c..ffdbf8ef 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -250,8 +250,9 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
                 break;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
             case BLE_LL_SCHED_TYPE_AUX_SCAN:
-                ble_ll_scan_aux_data_free((struct ble_ll_aux_data *)
+                ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)
                                           entry->cb_arg);
+
                 break;
 #endif
             default:
@@ -1066,16 +1067,17 @@ ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch)
  *
  * @param sched_type
  *
- * @return int
+ * @return int 0 - removed, 1 - not in the list
  */
-void
+int
 ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch)
 {
     os_sr_t sr;
     struct ble_ll_sched_item *first;
+    int rc = 1;
 
     if (!sch) {
-        return;
+        return rc;
     }
 
     OS_ENTER_CRITICAL(sr);
@@ -1087,6 +1089,7 @@ ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch)
 
         TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link);
         sch->enqueued = 0;
+        rc = 0;
 
         if (first == sch) {
             first = TAILQ_FIRST(&g_ble_ll_sched_q);
@@ -1096,6 +1099,8 @@ ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch)
         }
     }
     OS_EXIT_CRITICAL(sr);
+
+    return rc;
 }
 
 void
@@ -1357,7 +1362,7 @@ ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode)
             return 1;
         }
 
-        ble_ll_scan_aux_data_free((struct ble_ll_aux_data *)sch->cb_arg);
+        ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)sch->cb_arg);
         TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link);
         sch->enqueued = 0;
         sch = TAILQ_FIRST(&g_ble_ll_sched_q);
diff --git a/nimble/controller/src/ble_ll_trace.c b/nimble/controller/src/ble_ll_trace.c
index bdea2bf8..330b3d4c 100644
--- a/nimble/controller/src/ble_ll_trace.c
+++ b/nimble/controller/src/ble_ll_trace.c
@@ -41,6 +41,8 @@ ble_ll_trace_module_send_desc(void)
     os_trace_module_desc(&g_ble_ll_trace_mod, "9 ll_conn_rx conn_sn=%u pdu_nesn=%u");
     os_trace_module_desc(&g_ble_ll_trace_mod, "10 ll_adv_txdone inst=%u chanset=%x");
     os_trace_module_desc(&g_ble_ll_trace_mod, "11 ll_adv_halt inst=%u");
+    os_trace_module_desc(&g_ble_ll_trace_mod, "12 ll_aux_ref aux=%p ref=%u");
+    os_trace_module_desc(&g_ble_ll_trace_mod, "13 ll_aux_unref aux=%p ref=%u");
 }
 
 void


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services