You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/04/28 02:14:11 UTC

[12/50] [abbrv] incubator-mynewt-core git commit: ble host - major changes.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e32f9f9f/net/nimble/host/src/ble_gap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap.c b/net/nimble/host/src/ble_gap.c
index f4cac43..7e87661 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -27,32 +27,12 @@
 #include "ble_hs_priv.h"
 
 #define BLE_GAP_OP_NULL                                 0
-#define BLE_GAP_STATE_NULL                              255
 
 #define BLE_GAP_OP_M_DISC                               1
 #define BLE_GAP_OP_M_CONN                               2
 
 #define BLE_GAP_OP_S_ADV                                1
 
-/** Discovery master states. */
-#define BLE_GAP_STATE_M_DISC_PENDING                    0
-#define BLE_GAP_STATE_M_DISC_ACTIVE                     1
-#define BLE_GAP_STATE_M_DISC_DISABLE                    2
-
-/** Connect master states. */
-#define BLE_GAP_STATE_M_CONN_PENDING                    0
-#define BLE_GAP_STATE_M_CONN_ACTIVE                     1
-
-/** Advertise slave states. */
-#define BLE_GAP_STATE_S_ADV_PENDING                     0
-#define BLE_GAP_STATE_S_ADV_ACTIVE                      1
-
-/** Connection update states. */
-#define BLE_GAP_STATE_U_UPDATE                          0
-#define BLE_GAP_STATE_U_REPLY                           1
-#define BLE_GAP_STATE_U_REPLY_ACKED                     2
-#define BLE_GAP_STATE_U_NEG_REPLY                       3
-
 /**
  * The maximum amount of user data that can be put into the advertising data.
  * The stack may automatically insert some fields on its own, limiting the
@@ -92,24 +72,20 @@ static const struct hci_adv_params ble_gap_adv_params_dflt = {
  */
 static bssnz_t struct {
     uint8_t op;
-    uint8_t state;
 
     unsigned exp_set:1;
     uint32_t exp_os_ticks;
 
     union {
         struct {
-            uint8_t addr_type;
-            uint8_t addr[6];
-            struct ble_gap_crt_params params;
             ble_gap_conn_fn *cb;
             void *cb_arg;
+
+            unsigned using_wl:1;
         } conn;
 
         struct {
             uint8_t disc_mode;
-            uint8_t filter_policy;
-            uint8_t scan_type;
             ble_gap_disc_fn *cb;
             void *cb_arg;
         } disc;
@@ -124,16 +100,10 @@ static bssnz_t struct {
     uint8_t op;
 
     uint8_t conn_mode;
-    uint8_t state;
     uint8_t disc_mode;
     ble_gap_conn_fn *cb;
     void *cb_arg;
 
-    uint8_t dir_addr_type;
-    uint8_t dir_addr[BLE_DEV_ADDR_LEN];
-
-    struct hci_adv_params adv_params;
-    struct hci_adv_params rsp_params;
     uint8_t adv_data[BLE_HCI_MAX_ADV_DATA_LEN];
     uint8_t rsp_data[BLE_HCI_MAX_ADV_DATA_LEN];
     uint8_t adv_data_len;
@@ -143,20 +113,7 @@ static bssnz_t struct {
     unsigned adv_pwr_lvl:1;
 } ble_gap_slave;
 
-struct ble_gap_update_entry {
-    SLIST_ENTRY(ble_gap_update_entry) next;
-    struct ble_gap_upd_params params;
-    uint16_t conn_handle;
-    uint8_t reject_reason;
-    uint8_t state;
-    uint8_t hci_handle;
-};
-static SLIST_HEAD(, ble_gap_update_entry) ble_gap_update_entries;
-
-static void *ble_gap_update_mem;
-static struct os_mempool ble_gap_update_pool;
-
-static int ble_gap_disc_tx_disable(void *arg);
+static int ble_gap_disc_tx_disable(void);
 
 struct ble_gap_snapshot {
     struct ble_gap_conn_desc desc;
@@ -164,8 +121,6 @@ struct ble_gap_snapshot {
     void *cb_arg;
 };
 
-static struct os_mutex ble_gap_mutex;
-
 STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
 STATS_NAME_START(ble_gap_stats)
     STATS_NAME(ble_gap_stats, wl_set)
@@ -198,83 +153,45 @@ STATS_NAME_START(ble_gap_stats)
 STATS_NAME_END(ble_gap_stats)
 
 /*****************************************************************************
- * $mutex                                                                    *
+ * $log                                                                      *
  *****************************************************************************/
 
 static void
-ble_gap_lock(void)
+ble_gap_log_conn(uint8_t addr_type, uint8_t *addr,
+                 struct ble_gap_crt_params *params)
 {
-    struct os_task *owner;
-    int rc;
-
-    owner = ble_gap_mutex.mu_owner;
-    if (owner != NULL) {
-        BLE_HS_DBG_ASSERT_EVAL(owner != os_sched_get_current_task());
+    BLE_HS_LOG(INFO, "addr_type=%d addr=", addr_type);
+    if (addr == NULL) {
+        BLE_HS_LOG(INFO, "N/A");
+    } else {
+        BLE_HS_LOG_ADDR(INFO, addr);
     }
 
-    rc = os_mutex_pend(&ble_gap_mutex, 0xffffffff);
-    BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
-}
-
-static void
-ble_gap_unlock(void)
-{
-    int rc;
-
-    rc = os_mutex_release(&ble_gap_mutex);
-    BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
-}
-
-int
-ble_gap_locked_by_cur_task(void)
-{
-    struct os_task *owner;
-
-    owner = ble_gap_mutex.mu_owner;
-    return owner != NULL && owner == os_sched_get_current_task();
-}
-
-/*****************************************************************************
- * $log                                                                      *
- *****************************************************************************/
-
-static void
-ble_gap_log_conn(void)
-{
-    BLE_HS_LOG(INFO, "addr_type=%d addr=", ble_gap_master.conn.addr_type);
-    BLE_HS_LOG_ADDR(INFO, ble_gap_master.conn.addr);
     BLE_HS_LOG(INFO, " scan_itvl=%d scan_window=%d itvl_min=%d itvl_max=%d "
                      "latency=%d supervision_timeout=%d min_ce_len=%d "
                      "max_ce_len=%d",
-               ble_gap_master.conn.params.scan_itvl,
-               ble_gap_master.conn.params.scan_window,
-               ble_gap_master.conn.params.itvl_min,
-               ble_gap_master.conn.params.itvl_max,
-               ble_gap_master.conn.params.latency,
-               ble_gap_master.conn.params.supervision_timeout,
-               ble_gap_master.conn.params.min_ce_len,
-               ble_gap_master.conn.params.max_ce_len);
+               params->scan_itvl, params->scan_window, params->itvl_min,
+               params->itvl_max, params->latency, params->supervision_timeout,
+               params->min_ce_len, params->max_ce_len);
 }
 
 static void
-ble_gap_log_disc(void)
+ble_gap_log_disc(uint8_t scan_type, uint8_t filter_policy)
 {
     BLE_HS_LOG(INFO, "disc_mode=%d filter_policy=%d scan_type=%d",
                ble_gap_master.disc.disc_mode,
-               ble_gap_master.disc.filter_policy,
-               ble_gap_master.disc.scan_type);
+               filter_policy, scan_type);
 }
 
 static void
-ble_gap_log_update(struct ble_gap_update_entry *entry)
+ble_gap_log_update(uint16_t conn_handle, struct ble_gap_upd_params *params)
 {
     BLE_HS_LOG(INFO, "connection parameter update; "
                      "conn_handle=%d itvl_min=%d itvl_max=%d latency=%d "
                      "supervision_timeout=%d min_ce_len=%d max_ce_len=%d",
-               entry->conn_handle, entry->params.itvl_min,
-               entry->params.itvl_max, entry->params.latency,
-               entry->params.supervision_timeout, entry->params.min_ce_len,
-               entry->params.max_ce_len);
+               conn_handle, params->itvl_min, params->itvl_max,
+               params->latency, params->supervision_timeout,
+               params->min_ce_len, params->max_ce_len);
 }
 
 static void
@@ -296,20 +213,20 @@ ble_gap_log_wl(struct ble_gap_white_entry *white_list,
 }
 
 static void
-ble_gap_log_adv(void)
+ble_gap_log_adv(struct hci_adv_params *adv_params)
 {
     BLE_HS_LOG(INFO, "disc_mode=%d addr_type=%d addr=",
-               ble_gap_slave.disc_mode, ble_gap_slave.dir_addr_type);
-    BLE_HS_LOG_ADDR(INFO, ble_gap_slave.dir_addr);
+               ble_gap_slave.disc_mode, adv_params->peer_addr_type);
+    BLE_HS_LOG_ADDR(INFO, adv_params->peer_addr);
     BLE_HS_LOG(INFO, " adv_type=%d adv_channel_map=%d own_addr_type=%d "
                      "adv_filter_policy=%d adv_itvl_min=%d  adv_itvl_max=%d "
                      "adv_data_len=%d",
-               ble_gap_slave.adv_params.adv_type,
-               ble_gap_slave.adv_params.adv_channel_map,
-               ble_gap_slave.adv_params.own_addr_type,
-               ble_gap_slave.adv_params.adv_filter_policy,
-               ble_gap_slave.adv_params.adv_itvl_min,
-               ble_gap_slave.adv_params.adv_itvl_max,
+               adv_params->adv_type,
+               adv_params->adv_channel_map,
+               adv_params->own_addr_type,
+               adv_params->adv_filter_policy,
+               adv_params->adv_itvl_min,
+               adv_params->adv_itvl_max,
                ble_gap_slave.adv_data_len);
 }
 
@@ -353,17 +270,17 @@ ble_gap_find_snapshot(uint16_t handle, struct ble_gap_snapshot *snap)
 {
     struct ble_hs_conn *conn;
 
-    ble_hs_conn_lock();
+    ble_hs_lock();
 
     conn = ble_hs_conn_find(handle);
     if (conn != NULL) {
         ble_gap_conn_to_snapshot(conn, snap);
     }
 
-    ble_hs_conn_unlock();
+    ble_hs_unlock();
 
     if (conn == NULL) {
-        return BLE_HS_ENOENT;
+        return BLE_HS_ENOTCONN;
     } else {
         return 0;
     }
@@ -375,28 +292,6 @@ ble_gap_find_snapshot(uint16_t handle, struct ble_gap_snapshot *snap)
 
 /**
  * Lock restrictions:
- *     o Caller locks gap.
- */
-static void
-ble_gap_master_reset_state(void)
-{
-    ble_gap_master.state = BLE_GAP_STATE_NULL;
-    ble_gap_master.op = BLE_GAP_OP_NULL;
-}
-
-/**
- * Lock restrictions:
- *     o Caller locks gap.
- */
-static void
-ble_gap_slave_reset_state(void)
-{
-    ble_gap_slave.state = BLE_GAP_STATE_NULL;
-    ble_gap_slave.op = BLE_GAP_OP_NULL;
-}
-
-/**
- * Lock restrictions:
  *     o Caller unlocks all ble_hs mutexes.
  */
 static int
@@ -405,7 +300,7 @@ ble_gap_call_conn_cb(int event, int status, struct ble_gap_conn_ctxt *ctxt,
 {
     int rc;
 
-    ble_hs_misc_assert_no_locks();
+    ble_hs_misc_assert_not_locked();
 
     if (cb != NULL) {
         rc = cb(event, status, ctxt, cb_arg);
@@ -432,22 +327,18 @@ ble_gap_call_slave_cb(int event, int status, int reset_state)
     ble_gap_conn_fn *cb;
     void *cb_arg;
 
-    ble_hs_misc_assert_no_locks();
-
-    ble_gap_lock();
+    ble_hs_lock();
 
     desc.conn_handle = BLE_HS_CONN_HANDLE_NONE;
-    desc.peer_addr_type = ble_gap_slave.dir_addr_type;
-    memcpy(desc.peer_addr, ble_gap_slave.dir_addr, sizeof desc.peer_addr);
 
     cb = ble_gap_slave.cb;
     cb_arg = ble_gap_slave.cb_arg;
 
     if (reset_state) {
-        ble_gap_slave_reset_state();
+        ble_gap_slave.op = BLE_GAP_OP_NULL;
     }
 
-    ble_gap_unlock();
+    ble_hs_unlock();
 
     if (cb != NULL) {
         memset(&ctxt, 0, sizeof ctxt);
@@ -470,25 +361,20 @@ ble_gap_call_master_conn_cb(int event, int status, int reset_state)
     void *cb_arg;
     int rc;
 
-    ble_hs_misc_assert_no_locks();
-
-    ble_gap_lock();
+    ble_hs_lock();
 
     memset(&desc, 0, sizeof ctxt);
 
     desc.conn_handle = BLE_HS_CONN_HANDLE_NONE;
-    desc.peer_addr_type = ble_gap_master.conn.addr_type;
-    memcpy(desc.peer_addr, ble_gap_master.conn.addr,
-           sizeof desc.peer_addr);
 
     cb = ble_gap_master.conn.cb;
     cb_arg = ble_gap_master.conn.cb_arg;
 
     if (reset_state) {
-        ble_gap_master_reset_state();
+        ble_gap_master.op = BLE_GAP_OP_NULL;
     }
 
-    ble_gap_unlock();
+    ble_hs_unlock();
 
     if (cb != NULL) {
         memset(&ctxt, 0, sizeof ctxt);
@@ -514,9 +400,7 @@ ble_gap_call_master_disc_cb(int event, int status, struct ble_hs_adv *adv,
     ble_gap_disc_fn *cb;
     void *cb_arg;
 
-    ble_hs_misc_assert_no_locks();
-
-    ble_gap_lock();
+    ble_hs_lock();
 
     if (adv != NULL) {
         desc.event_type = adv->event_type;
@@ -534,10 +418,10 @@ ble_gap_call_master_disc_cb(int event, int status, struct ble_hs_adv *adv,
     cb_arg = ble_gap_master.disc.cb_arg;
 
     if (reset_state) {
-        ble_gap_master_reset_state();
+        ble_gap_master.op = BLE_GAP_OP_NULL;
     }
 
-    ble_gap_unlock();
+    ble_hs_unlock();
 
     if (cb != NULL) {
         cb(event, status, &desc, cb_arg);
@@ -548,48 +432,33 @@ ble_gap_call_master_disc_cb(int event, int status, struct ble_hs_adv *adv,
  * Lock restrictions:
  *     o Caller locks gap.
  */
-static struct ble_gap_update_entry *
-ble_gap_update_find(uint16_t conn_handle)
+int
+ble_gap_update_in_progress(uint16_t conn_handle)
 {
-    struct ble_gap_update_entry *entry;
-
-    SLIST_FOREACH(entry, &ble_gap_update_entries, next) {
-        if (entry->conn_handle == conn_handle) {
-            return entry;
-        }
-    }
+    struct ble_hs_conn *conn;
 
-    return NULL;
+    /* XXX LOCKING */
+    conn = ble_hs_conn_find(conn_handle);
+    return conn != NULL && conn->bhc_flags & BLE_HS_CONN_F_UPDATE;
 }
 
-/**
- * Lock restrictions: None.
- */
-static struct ble_gap_update_entry *
-ble_gap_update_entry_alloc(void)
+static int
+ble_gap_update_set_flag(uint16_t conn_handle, int val)
 {
-    struct ble_gap_update_entry *entry;
+    struct ble_hs_conn *conn;
 
-    entry = os_memblock_get(&ble_gap_update_pool);
-    if (entry == NULL) {
-        return NULL;
+    /* XXX LOCKING */
+    conn = ble_hs_conn_find(conn_handle);
+    if (conn == NULL) {
+        return BLE_HS_ENOTCONN;
+    } else {
+        if (val) {
+            conn->bhc_flags |= BLE_HS_CONN_F_UPDATE;
+        } else {
+            conn->bhc_flags &= ~BLE_HS_CONN_F_UPDATE;
+        }
+        return 0;
     }
-
-    memset(entry, 0, sizeof *entry);
-
-    return entry;
-}
-
-/**
- * Lock restrictions: None.
- */
-static void
-ble_gap_update_entry_free(struct ble_gap_update_entry *entry)
-{
-    int rc;
-
-    rc = os_memblock_put(&ble_gap_update_pool, entry);
-    BLE_HS_DBG_ASSERT_EVAL(rc == 0);
 }
 
 /**
@@ -597,13 +466,13 @@ ble_gap_update_entry_free(struct ble_gap_update_entry *entry)
  *     o Caller unlocks all ble_hs mutexes.
  */
 static void
-ble_gap_update_notify(struct ble_gap_update_entry *entry, int status)
+ble_gap_update_notify(uint16_t conn_handle, int status)
 {
     struct ble_gap_conn_ctxt ctxt;
     struct ble_gap_snapshot snap;
     int rc;
 
-    rc = ble_gap_find_snapshot(entry->conn_handle, &snap);
+    rc = ble_gap_find_snapshot(conn_handle, &snap);
     if (rc != 0) {
         return;
     }
@@ -650,26 +519,12 @@ ble_gap_master_failed(int status)
     }
 }
 
-/**
- * Lock restrictions: None.
- */
 static void
-ble_gap_update_entry_remove_free(struct ble_gap_update_entry *entry)
-{
-    SLIST_REMOVE(&ble_gap_update_entries, entry, ble_gap_update_entry, next);
-    ble_gap_update_entry_free(entry);
-}
-
-/**
- * Lock restrictions:
- *     o Caller unlocks all ble_hs mutexes.
- */
-static void
-ble_gap_update_failed(struct ble_gap_update_entry *entry, int status)
+ble_gap_update_failed(uint16_t conn_handle, int status)
 {
     STATS_INC(ble_gap_stats, update_fail);
-    ble_gap_update_notify(entry, status);
-    ble_gap_update_entry_free(entry);
+    ble_gap_update_set_flag(conn_handle, 0);
+    ble_gap_update_notify(conn_handle, status);
 }
 
 /**
@@ -677,24 +532,18 @@ ble_gap_update_failed(struct ble_gap_update_entry *entry, int status)
  *     o Caller unlocks gap.
  */
 static void
-ble_gap_conn_broken(uint16_t conn_handle)
+ble_gap_conn_broken(struct ble_gap_snapshot *snap)
 {
-    struct ble_gap_update_entry *entry;
-
-    ble_gap_lock();
-
-    entry = ble_gap_update_find(conn_handle);
-    if (entry != NULL) {
-        if (entry->hci_handle != BLE_HCI_SCHED_HANDLE_NONE) {
-            ble_hci_sched_cancel(entry->hci_handle);
-        }
-        ble_gap_update_entry_remove_free(entry);
-    }
+    struct ble_gap_conn_ctxt ctxt;
 
-    ble_gap_unlock();
+    ble_gattc_connection_broken(snap->desc.conn_handle);
+    ble_l2cap_sm_connection_broken(snap->desc.conn_handle);
 
-    ble_gattc_connection_broken(conn_handle);
-    ble_l2cap_sm_connection_broken(conn_handle);
+    memset(&ctxt, 0, sizeof ctxt);
+    ctxt.desc = &snap->desc;
+    ble_gap_call_conn_cb(BLE_GAP_EVENT_CONN, BLE_HS_ENOTCONN, &ctxt,
+                         snap->cb, snap->cb_arg);
+    ble_hs_atomic_conn_delete(snap->desc.conn_handle);
 
     STATS_INC(ble_gap_stats, disconnect);
 }
@@ -712,41 +561,24 @@ ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt)
 
     struct ble_gap_conn_ctxt ctxt;
     struct ble_gap_snapshot snap;
-    struct ble_hs_conn *conn;
     int rc;
 
-    ble_hs_misc_assert_no_locks();
-
     STATS_INC(ble_gap_stats, rx_disconnect);
 
-    if (evt->status == 0) {
-        /* Find the connection that this event refers to. */
-        ble_hs_conn_lock();
-        conn = ble_hs_conn_find(evt->connection_handle);
-        if (conn != NULL) {
-            ble_gap_conn_to_snapshot(conn, &snap);
-            ble_hs_conn_remove(conn);
-            ble_hs_conn_free(conn);
-        }
-        ble_hs_conn_unlock();
-
-        if (conn != NULL) {
-            ble_gap_conn_broken(evt->connection_handle);
+    rc = ble_gap_find_snapshot(evt->connection_handle, &snap);
+    if (rc != 0) {
+        /* No longer connected. */
+        return;
+    }
 
-            memset(&ctxt, 0, sizeof ctxt);
-            ctxt.desc = &snap.desc;
-            ble_gap_call_conn_cb(BLE_GAP_EVENT_CONN, BLE_HS_ENOTCONN, &ctxt,
-                                 snap.cb, snap.cb_arg);
-        }
+    if (evt->status == 0) {
+        ble_gap_conn_broken(&snap);
     } else {
-        rc = ble_gap_find_snapshot(evt->connection_handle, &snap);
-        if (rc == 0) {
-            memset(&ctxt, 0, sizeof ctxt);
-            ctxt.desc = &snap.desc;
-            ble_gap_call_conn_cb(BLE_GAP_EVENT_TERM_FAILURE,
-                                 BLE_HS_HCI_ERR(evt->status), &ctxt,
-                                 snap.cb, snap.cb_arg);
-        }
+        memset(&ctxt, 0, sizeof ctxt);
+        ctxt.desc = &snap.desc;
+        ble_gap_call_conn_cb(BLE_GAP_EVENT_TERM_FAILURE,
+                             BLE_HS_HCI_ERR(evt->status), &ctxt,
+                             snap.cb, snap.cb_arg);
     }
 }
 
@@ -761,28 +593,18 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt)
     return;
 #endif
 
-    struct ble_gap_update_entry *entry;
     struct ble_gap_conn_ctxt ctxt;
     struct ble_gap_snapshot snap;
     struct ble_hs_conn *conn;
 
-    ble_hs_misc_assert_no_locks();
+    ble_hs_misc_assert_not_locked();
 
     STATS_INC(ble_gap_stats, rx_update_complete);
 
-    ble_hs_conn_lock();
+    ble_hs_lock();
 
     conn = ble_hs_conn_find(evt->connection_handle);
     if (conn != NULL) {
-        ble_gap_lock();
-
-        entry = ble_gap_update_find(evt->connection_handle);
-        if (entry != NULL) {
-            ble_gap_update_entry_remove_free(entry);
-        }
-
-        ble_gap_unlock();
-
         if (evt->status == 0) {
             conn->bhc_itvl = evt->conn_itvl;
             conn->bhc_latency = evt->conn_latency;
@@ -792,7 +614,8 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt)
         ble_gap_conn_to_snapshot(conn, &snap);
     }
 
-    ble_hs_conn_unlock();
+    ble_gap_update_set_flag(evt->connection_handle, 0);
+    ble_hs_unlock();
 
     if (conn != NULL) {
         memset(&ctxt, 0, sizeof ctxt);
@@ -826,84 +649,6 @@ ble_gap_slave_in_progress(void)
 }
 
 /**
- * Tells you if the BLE host is in the process of updating a connection.
- *
- * Lock restrictions:
- *     o Caller unlocks gap.
- *
- * @param conn_handle           The connection to test, or
- *                                  BLE_HS_CONN_HANDLE_NONE to check all
- *                                  connections.
- *
- * @return                      0=connection not being updated;
- *                              1=connection being updated.
- */
-int
-ble_gap_update_in_progress(uint16_t conn_handle)
-{
-#if !NIMBLE_OPT_CONNECT
-    return BLE_HS_ENOTSUP;
-#endif
-
-    struct ble_gap_update_entry *entry;
-
-    ble_gap_lock();
-
-    if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
-        entry = ble_gap_update_find(conn_handle);
-    } else {
-        entry = SLIST_FIRST(&ble_gap_update_entries);
-    }
-
-    ble_gap_unlock();
-
-    return entry != NULL;
-}
-
-/**
- * Lock restrictions:
- *     o Caller unlocks gap.
- */
-static int
-ble_gap_gen_set_op(uint8_t *slot, uint8_t op)
-{
-    int rc;
-
-    ble_gap_lock();
-
-    if (*slot != BLE_GAP_OP_NULL) {
-        rc = BLE_HS_EALREADY;
-    } else {
-        *slot = op;
-        rc = 0;
-    }
-
-    ble_gap_unlock();
-
-    return rc;
-}
-
-/**
- * Lock restrictions:
- *     o Caller unlocks gap.
- */
-static int
-ble_gap_master_set_op(uint8_t op)
-{
-    return ble_gap_gen_set_op(&ble_gap_master.op, op);
-}
-
-/**
- * Lock restrictions:
- *     o Caller unlocks gap.
- */
-static int
-ble_gap_slave_set_op(uint8_t op)
-{
-    return ble_gap_gen_set_op(&ble_gap_slave.op, op);
-}
-
-/**
  * Lock restrictions: None.
  */
 static int
@@ -943,17 +688,7 @@ ble_gap_accept_master_conn(uint8_t addr_type, uint8_t *addr)
         break;
 
     case BLE_GAP_OP_M_CONN:
-        if (ble_gap_master.state != BLE_GAP_STATE_M_CONN_ACTIVE) {
-            rc = BLE_HS_ENOENT;
-        } else if (ble_gap_master.conn.addr_type == BLE_GAP_ADDR_TYPE_WL ||
-                   (addr_type == ble_gap_master.conn.addr_type &&
-                    memcmp(addr, ble_gap_master.conn.addr,
-                           BLE_DEV_ADDR_LEN) == 0)) {
-            rc = 0;
-        } else {
-            ble_gap_master_failed(BLE_HS_ECONTROLLER);
-            rc = BLE_HS_ECONTROLLER;
-        }
+        rc = 0;
         break;
 
     default:
@@ -1005,13 +740,7 @@ ble_gap_accept_slave_conn(uint8_t addr_type, uint8_t *addr)
             break;
 
         case BLE_GAP_CONN_MODE_DIR:
-            if (ble_gap_slave.dir_addr_type != addr_type ||
-                memcmp(ble_gap_slave.dir_addr, addr, BLE_DEV_ADDR_LEN) != 0) {
-
-                rc = BLE_HS_ENOENT;
-            } else {
-                rc = 0;
-            }
+            rc = 0;
             break;
 
         default:
@@ -1044,9 +773,7 @@ ble_gap_rx_adv_report(struct ble_hs_adv *adv)
 
     STATS_INC(ble_gap_stats, rx_adv_report);
 
-    if (ble_gap_master.op      != BLE_GAP_OP_M_DISC ||
-        ble_gap_master.state   != BLE_GAP_STATE_M_DISC_ACTIVE) {
-
+    if (ble_gap_master.op != BLE_GAP_OP_M_DISC) {
         return;
     }
 
@@ -1089,30 +816,14 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
     /* Determine if this event refers to a completed connection or a connection
      * in progress.
      */
-    ble_hs_conn_lock();
-    conn = ble_hs_conn_find(evt->connection_handle);
+    rc = ble_gap_find_snapshot(evt->connection_handle, &snap);
 
     /* Apply the event to the existing connection if it exists. */
-    if (conn != NULL) {
+    if (rc == 0) {
         /* XXX: Does this ever happen? */
-        if (evt->status != 0) {
-            ble_gap_conn_to_snapshot(conn, &snap);
-
-            ble_gap_conn_broken(evt->connection_handle);
-
-            ble_hs_conn_remove(conn);
-            ble_hs_conn_free(conn);
-        }
-    }
 
-    ble_hs_conn_unlock();
-
-    if (conn != NULL) {
         if (evt->status != 0) {
-            memset(&ctxt, 0, sizeof ctxt);
-            ctxt.desc = &snap.desc;
-            ble_gap_call_conn_cb(BLE_GAP_EVENT_CONN, evt->status, &ctxt,
-                                 snap.cb, snap.cb_arg);
+            ble_gap_conn_broken(&snap);
         }
         return 0;
     }
@@ -1176,16 +887,16 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
         conn->bhc_flags |= BLE_HS_CONN_F_MASTER;
         conn->bhc_cb = ble_gap_master.conn.cb;
         conn->bhc_cb_arg = ble_gap_master.conn.cb_arg;
-        ble_gap_master_reset_state();
+        ble_gap_master.op = BLE_GAP_OP_NULL;
     } else {
         conn->bhc_cb = ble_gap_slave.cb;
         conn->bhc_cb_arg = ble_gap_slave.cb_arg;
-        ble_gap_slave_reset_state();
+        ble_gap_slave.op = BLE_GAP_OP_NULL;
     }
 
     ble_gap_conn_to_snapshot(conn, &snap);
 
-    ble_hs_conn_insert(conn);
+    ble_hs_atomic_conn_insert(conn);
 
     memset(&ctxt, 0, sizeof ctxt);
     ctxt.desc = &snap.desc;
@@ -1206,7 +917,7 @@ ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
     struct ble_gap_snapshot snap;
     int rc;
 
-    ble_hs_misc_assert_no_locks();
+    ble_hs_misc_assert_not_locked();
 
     rc = ble_gap_find_snapshot(conn_handle, &snap);
     if (rc != 0) {
@@ -1253,11 +964,9 @@ ble_gap_heartbeat(void)
         switch (ble_gap_master.op) {
         case BLE_GAP_OP_M_DISC:
             /* When a discovery procedure times out, it is not a failure. */
-            ble_gap_master.state = BLE_GAP_STATE_M_DISC_DISABLE;
-            rc = ble_hci_sched_enqueue(ble_gap_disc_tx_disable, NULL, NULL);
-            if (rc != 0) {
-                ble_gap_master_failed(rc);
-            }
+            rc = ble_gap_disc_tx_disable();
+            ble_gap_call_master_disc_cb(BLE_GAP_EVENT_DISC_FINISHED, rc,
+                                        NULL, NULL, 1);
             break;
 
         default:
@@ -1285,7 +994,7 @@ ble_gap_wl_busy(void)
      * progress.
      */
     return ble_gap_master.op == BLE_GAP_OP_M_CONN &&
-           ble_gap_master.conn.addr_type == BLE_GAP_ADDR_TYPE_WL;
+           ble_gap_master.conn.using_wl;
 }
 
 /**
@@ -1304,7 +1013,7 @@ ble_gap_wl_tx_add(struct ble_gap_white_entry *entry)
         return rc;
     }
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1322,8 +1031,8 @@ ble_gap_wl_tx_clear(void)
     uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     int rc;
 
-    host_hci_cmd_le_build_clear_whitelist(buf, sizeof buf);
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    host_hci_cmd_build_le_clear_whitelist(buf, sizeof buf);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1350,7 +1059,7 @@ ble_gap_wl_set(struct ble_gap_white_entry *white_list,
 
     if (white_list_count == 0) {
         rc = BLE_HS_EINVAL;
-        goto done;
+        goto err;
     }
 
     for (i = 0; i < white_list_count; i++) {
@@ -1358,36 +1067,35 @@ ble_gap_wl_set(struct ble_gap_white_entry *white_list,
             white_list[i].addr_type != BLE_ADDR_TYPE_RANDOM) {
 
             rc = BLE_HS_EINVAL;
-            goto done;
+            goto err;
         }
     }
 
     if (ble_gap_wl_busy()) {
         rc = BLE_HS_EBUSY;
-        goto done;
+        goto err;
     }
 
+    BLE_HS_LOG(INFO, "GAP procedure initiated: set whitelist; ");
+    ble_gap_log_wl(white_list, white_list_count);
+    BLE_HS_LOG(INFO, "\n");
+
     rc = ble_gap_wl_tx_clear();
     if (rc != 0) {
-        goto done;
+        goto err;
     }
 
     for (i = 0; i < white_list_count; i++) {
         rc = ble_gap_wl_tx_add(white_list + i);
         if (rc != 0) {
-            goto done;
+            goto err;
         }
     }
 
-done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: set whitelist; ");
-        ble_gap_log_wl(white_list, white_list_count);
-        BLE_HS_LOG(INFO, "\n");
-    } else {
-        STATS_INC(ble_gap_stats, wl_set_fail);
-    }
+    return 0;
 
+err:
+    STATS_INC(ble_gap_stats, wl_set_fail);
     return rc;
 }
 
@@ -1406,7 +1114,7 @@ ble_gap_adv_disable_tx(void)
     int rc;
 
     host_hci_cmd_build_le_set_adv_enable(0, buf, sizeof buf);
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1432,25 +1140,22 @@ ble_gap_adv_stop(void)
     /* Do nothing if advertising is already disabled. */
     if (!ble_gap_currently_advertising()) {
         rc = BLE_HS_EALREADY;
-        goto done;
+        goto err;
     }
 
+    BLE_HS_LOG(INFO, "GAP procedure initiated: stop advertising.\n");
+
     rc = ble_gap_adv_disable_tx();
     if (rc != 0) {
-        goto done;
+        goto err;
     }
 
-    ble_gap_slave_reset_state();
+    ble_gap_slave.op = BLE_GAP_OP_NULL;
 
-done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: stop advertising; ");
-        ble_gap_log_adv();
-        BLE_HS_LOG(INFO, "\n");
-    } else {
-        STATS_INC(ble_gap_stats, adv_set_fields_fail);
-    }
+    return 0;
 
+err:
+    STATS_INC(ble_gap_stats, adv_set_fields_fail);
     return rc;
 }
 
@@ -1463,7 +1168,7 @@ done:
  */
 static void
 ble_gap_adv_itvls(uint8_t disc_mode, uint8_t conn_mode,
-                       uint16_t *out_itvl_min, uint16_t *out_itvl_max)
+                  uint16_t *out_itvl_min, uint16_t *out_itvl_max)
 {
     switch (conn_mode) {
     case BLE_GAP_CONN_MODE_NON:
@@ -1499,7 +1204,7 @@ ble_gap_adv_enable_tx(void)
 
     host_hci_cmd_build_le_set_adv_enable(1, buf, sizeof buf);
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1524,7 +1229,7 @@ ble_gap_adv_rsp_data_tx(void)
         return rc;
     }
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1589,7 +1294,7 @@ ble_gap_adv_data_tx(void)
         return rc;
     }
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1602,56 +1307,22 @@ ble_gap_adv_data_tx(void)
  *     o Caller unlocks all ble_hs mutexes.
  */
 static int
-ble_gap_adv_power_tx(void)
-{
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
-    struct ble_hci_block_result result;
-    uint8_t tx_pwr;
-    int rc;
-
-    host_hci_cmd_build_read_adv_pwr(buf, sizeof buf);
-    rc = ble_hci_block_tx(buf, &tx_pwr, 1, &result);
-    if (rc != 0) {
-        return rc;
-    }
-
-    if (result.evt_total_len != 1           ||
-        tx_pwr < BLE_HCI_ADV_CHAN_TXPWR_MIN ||
-        tx_pwr > BLE_HCI_ADV_CHAN_TXPWR_MAX) {
-
-        return BLE_HS_ECONTROLLER;
-    }
-
-    ble_gap_slave.tx_pwr_lvl = tx_pwr;
-
-    return 0;
-}
-
-/**
- * Lock restrictions:
- *     o Caller unlocks all ble_hs mutexes.
- */
-static int
-ble_gap_adv_params_tx(void)
+ble_gap_adv_params_tx(struct hci_adv_params *adv_params)
 {
     uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_PARAM_LEN];
-    struct hci_adv_params hap;
     int rc;
 
-    hap = ble_gap_slave.adv_params;
-
     switch (ble_gap_slave.conn_mode) {
     case BLE_GAP_CONN_MODE_NON:
-        hap.adv_type = BLE_HCI_ADV_TYPE_ADV_NONCONN_IND;
+        adv_params->adv_type = BLE_HCI_ADV_TYPE_ADV_NONCONN_IND;
         break;
 
     case BLE_GAP_CONN_MODE_DIR:
-        hap.adv_type = BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD;
-        memcpy(hap.peer_addr, ble_gap_slave.dir_addr, sizeof hap.peer_addr);
+        adv_params->adv_type = BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD;
         break;
 
     case BLE_GAP_CONN_MODE_UND:
-        hap.adv_type = BLE_HCI_ADV_TYPE_ADV_IND;
+        adv_params->adv_type = BLE_HCI_ADV_TYPE_ADV_IND;
         break;
 
     default:
@@ -1659,12 +1330,12 @@ ble_gap_adv_params_tx(void)
         break;
     }
 
-    rc = host_hci_cmd_build_le_set_adv_params(&hap, buf, sizeof buf);
+    rc = host_hci_cmd_build_le_set_adv_params(adv_params, buf, sizeof buf);
     if (rc != 0) {
         return rc;
     }
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1718,10 +1389,18 @@ ble_gap_adv_start(uint8_t discoverable_mode, uint8_t connectable_mode,
     return BLE_HS_ENOTSUP;
 #endif
 
+    struct hci_adv_params adv_params_copy;
     int rc;
 
+    ble_hs_lock();
+
     STATS_INC(ble_gap_stats, adv_start);
 
+    if (ble_gap_slave.op != BLE_GAP_OP_NULL) {
+        rc = BLE_HS_EALREADY;
+        goto done;
+    }
+
     if (discoverable_mode >= BLE_GAP_DISC_MODE_MAX) {
         rc = BLE_HS_EINVAL;
         goto done;
@@ -1756,40 +1435,38 @@ ble_gap_adv_start(uint8_t discoverable_mode, uint8_t connectable_mode,
         goto done;
     }
 
-    rc = ble_gap_slave_set_op(BLE_GAP_OP_S_ADV);
-    if (rc != 0) {
-        goto done;
+    if (adv_params != NULL) {
+        adv_params_copy = *adv_params;
+    } else {
+        adv_params_copy = ble_gap_adv_params_dflt;
     }
-    ble_gap_slave.state = BLE_GAP_STATE_S_ADV_PENDING;
+
+    BLE_HS_LOG(INFO, "GAP procedure initiated: advertise; ");
+    ble_gap_log_adv(&adv_params_copy);
+    BLE_HS_LOG(INFO, "\n");
 
     if (connectable_mode == BLE_GAP_CONN_MODE_DIR) {
-        ble_gap_slave.dir_addr_type = peer_addr_type;
-        memcpy(ble_gap_slave.dir_addr, peer_addr, 6);
+        adv_params_copy.peer_addr_type = peer_addr_type;
+        memcpy(adv_params_copy.peer_addr, peer_addr,
+               sizeof adv_params_copy.peer_addr);
     }
 
     ble_gap_slave.cb = cb;
     ble_gap_slave.cb_arg = cb_arg;
-    ble_gap_slave.state = 0;
     ble_gap_slave.conn_mode = connectable_mode;
     ble_gap_slave.disc_mode = discoverable_mode;
 
-    if (adv_params != NULL) {
-        ble_gap_slave.adv_params = *adv_params;
-    } else {
-        ble_gap_slave.adv_params = ble_gap_adv_params_dflt;
-    }
-
     ble_gap_adv_itvls(discoverable_mode, connectable_mode,
-                      &ble_gap_slave.adv_params.adv_itvl_min,
-                      &ble_gap_slave.adv_params.adv_itvl_max);
+                      &adv_params_copy.adv_itvl_min,
+                      &adv_params_copy.adv_itvl_max);
 
-    rc = ble_gap_adv_params_tx();
+    rc = ble_gap_adv_params_tx(&adv_params_copy);
     if (rc != 0) {
         goto done;
     }
 
     if (ble_gap_slave.adv_pwr_lvl) {
-        rc = ble_gap_adv_power_tx();
+        rc = ble_hci_util_read_adv_tx_pwr(&ble_gap_slave.tx_pwr_lvl);
         if (rc != 0) {
             goto done;
         }
@@ -1812,20 +1489,17 @@ ble_gap_adv_start(uint8_t discoverable_mode, uint8_t connectable_mode,
         goto done;
     }
 
-    ble_gap_slave.state = BLE_GAP_STATE_S_ADV_ACTIVE;
+    ble_gap_slave.op = BLE_GAP_OP_S_ADV;
+
+    rc = 0;
 
 done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: advertise; ");
-        ble_gap_log_adv();
-        BLE_HS_LOG(INFO, "\n");
-    } else {
+    if (rc != 0) {
         STATS_INC(ble_gap_stats, adv_start_fail);
-        if (rc != BLE_HS_EALREADY) {
-            ble_gap_slave_reset_state();
-        }
     }
 
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -1842,6 +1516,8 @@ ble_gap_adv_set_fields(struct ble_hs_adv_fields *adv_fields)
     int max_sz;
     int rc;
 
+    ble_hs_lock();
+
     STATS_INC(ble_gap_stats, adv_set_fields);
 
     if (adv_fields->tx_pwr_lvl_is_present) {
@@ -1858,6 +1534,8 @@ ble_gap_adv_set_fields(struct ble_hs_adv_fields *adv_fields)
         STATS_INC(ble_gap_stats, adv_set_fields_fail);
     }
 
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -1873,6 +1551,8 @@ ble_gap_adv_rsp_set_fields(struct ble_hs_adv_fields *rsp_fields)
 
     int rc;
 
+    ble_hs_lock();
+
     STATS_INC(ble_gap_stats, adv_rsp_set_fields);
 
     rc = ble_hs_adv_set_fields(rsp_fields, ble_gap_slave.rsp_data,
@@ -1882,6 +1562,8 @@ ble_gap_adv_rsp_set_fields(struct ble_hs_adv_fields *rsp_fields)
         STATS_INC(ble_gap_stats, adv_rsp_set_fields_fail);
     }
 
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -1893,37 +1575,15 @@ ble_gap_adv_rsp_set_fields(struct ble_hs_adv_fields *rsp_fields)
  * Lock restrictions:
  *     o Caller unlocks all ble_hs mutexes.
  */
-static void
-ble_gap_disc_ack_disable(struct ble_hci_ack *ack, void *arg)
-{
-    BLE_HS_DBG_ASSERT(ble_gap_master.op == BLE_GAP_OP_M_DISC);
-    BLE_HS_DBG_ASSERT(ble_gap_master.state == BLE_GAP_STATE_M_DISC_DISABLE);
-
-    if (ack->bha_status != 0) {
-        ble_gap_master_failed(ack->bha_status);
-    } else {
-        ble_gap_call_master_disc_cb(BLE_GAP_EVENT_DISC_FINISHED, 0,
-                                    NULL, NULL, 1);
-    }
-}
-
-/**
- * Lock restrictions:
- *     o Caller unlocks all ble_hs mutexes.
- */
 static int
-ble_gap_disc_tx_disable(void *arg)
+ble_gap_disc_tx_disable(void)
 {
+    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_ENABLE_LEN];
     int rc;
 
-    BLE_HS_DBG_ASSERT(ble_gap_master.op == BLE_GAP_OP_M_DISC);
-    BLE_HS_DBG_ASSERT(ble_gap_master.state == BLE_GAP_STATE_M_DISC_DISABLE);
-
-    ble_hci_sched_set_ack_cb(ble_gap_disc_ack_disable, NULL);
-    rc = host_hci_cmd_le_set_scan_enable(0, 0);
+    host_hci_cmd_build_le_set_scan_enable(0, 0, buf, sizeof buf);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
-        /* XXX: What can we do? */
-        ble_gap_master_failed(rc);
         return rc;
     }
 
@@ -1941,7 +1601,7 @@ ble_gap_disc_tx_enable(void)
     int rc;
 
     host_hci_cmd_build_le_set_scan_enable(1, 0, buf, sizeof buf);
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1954,24 +1614,21 @@ ble_gap_disc_tx_enable(void)
  *     o Caller unlocks all ble_hs mutexes.
  */
 static int
-ble_gap_disc_tx_params(void)
+ble_gap_disc_tx_params(uint8_t scan_type, uint8_t filter_policy)
 {
     uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
     int rc;
 
-    BLE_HS_DBG_ASSERT(ble_gap_master.op == BLE_GAP_OP_M_DISC);
-    BLE_HS_DBG_ASSERT(ble_gap_master.state == BLE_GAP_STATE_M_DISC_PENDING);
-
     rc = host_hci_cmd_build_le_set_scan_params(
-        ble_gap_master.disc.scan_type,
+        scan_type,
         BLE_GAP_SCAN_FAST_INTERVAL_MIN,
         BLE_GAP_SCAN_FAST_WINDOW,
         BLE_HCI_ADV_OWN_ADDR_PUBLIC,
-        ble_gap_master.disc.filter_policy,
+        filter_policy,
         buf, sizeof buf);
     BLE_HS_DBG_ASSERT_EVAL(rc == 0);
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -1999,6 +1656,13 @@ ble_gap_disc(uint32_t duration_ms, uint8_t discovery_mode,
 
     int rc;
 
+    ble_hs_lock();
+
+    if (ble_gap_master.op != BLE_GAP_OP_NULL) {
+        rc = BLE_HS_EALREADY;
+        goto done;
+    }
+
     STATS_INC(ble_gap_stats, discover);
 
     if (discovery_mode != BLE_GAP_DISC_MODE_LTD &&
@@ -2024,18 +1688,15 @@ ble_gap_disc(uint32_t duration_ms, uint8_t discovery_mode,
         duration_ms = BLE_GAP_GEN_DISC_SCAN_MIN;
     }
 
-    rc = ble_gap_master_set_op(BLE_GAP_OP_M_DISC);
-    if (rc != 0) {
-        goto done;
-    }
-
     ble_gap_master.disc.disc_mode = discovery_mode;
-    ble_gap_master.disc.scan_type = scan_type;
-    ble_gap_master.disc.filter_policy = filter_policy;
     ble_gap_master.disc.cb = cb;
     ble_gap_master.disc.cb_arg = cb_arg;
 
-    rc = ble_gap_disc_tx_params();
+    BLE_HS_LOG(INFO, "GAP procedure initiated: discovery; ");
+    ble_gap_log_disc(scan_type, filter_policy);
+    BLE_HS_LOG(INFO, "\n");
+
+    rc = ble_gap_disc_tx_params(scan_type, filter_policy);
     if (rc != 0) {
         goto done;
     }
@@ -2046,19 +1707,17 @@ ble_gap_disc(uint32_t duration_ms, uint8_t discovery_mode,
     }
 
     ble_gap_master_set_timer(duration_ms);
+    ble_gap_master.op = BLE_GAP_OP_M_DISC;
+
+    rc = 0;
 
 done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: discovery; ");
-        ble_gap_log_disc();
-        BLE_HS_LOG(INFO, "\n");
-    } else {
-        if (rc != BLE_HS_EALREADY) {
-            ble_gap_master_reset_state();
-        }
+    if (rc != 0) {
         STATS_INC(ble_gap_stats, discover_fail);
     }
 
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -2079,48 +1738,43 @@ done:
  *     o Caller unlocks all ble_hs mutexes.
  */
 static int
-ble_gap_conn_create_tx(void *arg)
+ble_gap_conn_create_tx(int addr_type, uint8_t *addr,
+                       struct ble_gap_crt_params *params)
 {
     uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CREATE_CONN_LEN];
     struct hci_create_conn hcc;
     int rc;
 
-    BLE_HS_DBG_ASSERT(ble_gap_master.op == BLE_GAP_OP_M_CONN);
+    hcc.scan_itvl = params->scan_itvl;
+    hcc.scan_window = params->scan_window;
 
-    hcc.scan_itvl = ble_gap_master.conn.params.scan_itvl;
-    hcc.scan_window = ble_gap_master.conn.params.scan_window;
-
-    if (ble_gap_master.conn.addr_type == BLE_GAP_ADDR_TYPE_WL) {
+    if (addr_type == BLE_GAP_ADDR_TYPE_WL) {
         hcc.filter_policy = BLE_HCI_CONN_FILT_USE_WL;
         hcc.peer_addr_type = BLE_HCI_ADV_PEER_ADDR_PUBLIC;
         memset(hcc.peer_addr, 0, sizeof hcc.peer_addr);
     } else {
         hcc.filter_policy = BLE_HCI_CONN_FILT_NO_WL;
-        hcc.peer_addr_type = ble_gap_master.conn.addr_type;
-        memcpy(hcc.peer_addr, ble_gap_master.conn.addr,
-               sizeof hcc.peer_addr);
+        hcc.peer_addr_type = addr_type;
+        memcpy(hcc.peer_addr, addr, sizeof hcc.peer_addr);
     }
     hcc.own_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
-    hcc.conn_itvl_min = ble_gap_master.conn.params.itvl_min;
-    hcc.conn_itvl_max = ble_gap_master.conn.params.itvl_max;
-    hcc.conn_latency = ble_gap_master.conn.params.latency;
-    hcc.supervision_timeout =
-        ble_gap_master.conn.params.supervision_timeout;
-    hcc.min_ce_len = ble_gap_master.conn.params.min_ce_len;
-    hcc.max_ce_len = ble_gap_master.conn.params.max_ce_len;
+    hcc.conn_itvl_min = params->itvl_min;
+    hcc.conn_itvl_max = params->itvl_max;
+    hcc.conn_latency = params->latency;
+    hcc.supervision_timeout = params->supervision_timeout;
+    hcc.min_ce_len = params->min_ce_len;
+    hcc.max_ce_len = params->max_ce_len;
 
     rc = host_hci_cmd_build_le_create_connection(&hcc, buf, sizeof buf);
     if (rc != 0) {
         return BLE_HS_EUNKNOWN;
     }
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
 
-    ble_gap_master.state = BLE_GAP_STATE_M_CONN_ACTIVE;
-
     return 0;
 }
 
@@ -2152,6 +1806,13 @@ ble_gap_conn_initiate(int addr_type, uint8_t *addr,
 
     int rc;
 
+    ble_hs_lock();
+
+    if (ble_gap_master.op != BLE_GAP_OP_NULL) {
+        rc = BLE_HS_EALREADY;
+        goto done;
+    }
+
     STATS_INC(ble_gap_stats, initiate);
 
     if (addr_type != BLE_HCI_CONN_PEER_ADDR_PUBLIC &&
@@ -2162,44 +1823,36 @@ ble_gap_conn_initiate(int addr_type, uint8_t *addr,
         goto done;
     }
 
-    rc = ble_gap_master_set_op(BLE_GAP_OP_M_CONN);
-    if (rc != 0) {
-        goto done;
-    }
-    ble_gap_master.state = BLE_GAP_STATE_M_CONN_PENDING;
-
     if (params == NULL) {
-        ble_gap_master.conn.params = ble_gap_params_dflt;
-    } else {
-        /* XXX: Verify params. */
-        ble_gap_master.conn.params = *params;
+        params = (void *)&ble_gap_params_dflt;
     }
 
-    ble_gap_master.conn.addr_type = addr_type;
+    /* XXX: Verify params. */
+
+    BLE_HS_LOG(INFO, "GAP procedure initiated: connect; ");
+    ble_gap_log_conn(addr_type, addr, params);
+    BLE_HS_LOG(INFO, "\n");
+
     ble_gap_master.conn.cb = cb;
     ble_gap_master.conn.cb_arg = cb_arg;
+    ble_gap_master.conn.using_wl = addr_type == BLE_GAP_ADDR_TYPE_WL;
 
-    if (addr_type != BLE_GAP_ADDR_TYPE_WL) {
-        memcpy(ble_gap_master.conn.addr, addr, BLE_DEV_ADDR_LEN);
-    }
-
-    rc = ble_gap_conn_create_tx(NULL);
+    rc = ble_gap_conn_create_tx(addr_type, addr, params);
     if (rc != 0) {
         goto done;
     }
 
+    ble_gap_master.op = BLE_GAP_OP_M_CONN;
+
+    rc = 0;
+
 done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: connect; ");
-        ble_gap_log_conn();
-        BLE_HS_LOG(INFO, "\n");
-    } else {
-        if (rc != BLE_HS_EALREADY) {
-            ble_gap_master_reset_state();
-        }
+    if (rc != 0) {
         STATS_INC(ble_gap_stats, initiate_fail);
     }
 
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -2217,6 +1870,8 @@ ble_gap_terminate(uint16_t conn_handle)
     uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_DISCONNECT_CMD_LEN];
     int rc;
 
+    ble_hs_lock();
+
     STATS_INC(ble_gap_stats, terminate);
 
     if (!ble_hs_conn_exists(conn_handle)) {
@@ -2224,21 +1879,25 @@ ble_gap_terminate(uint16_t conn_handle)
         goto done;
     }
 
+    BLE_HS_LOG(INFO, "GAP procedure initiated: terminate connection; "
+                     "conn_handle=%d\n", conn_handle);
+
     host_hci_cmd_build_disconnect(conn_handle, BLE_ERR_REM_USER_CONN_TERM,
                                   buf, sizeof buf);
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         goto done;
     }
 
+    rc = 0;
+
 done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: terminate connection; "
-                         "conn_handle=%d\n", conn_handle);
-    } else {
+    if (rc != 0) {
         STATS_INC(ble_gap_stats, terminate_fail);
     }
 
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -2256,6 +1915,8 @@ ble_gap_cancel(void)
     uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     int rc;
 
+    ble_hs_lock();
+
     STATS_INC(ble_gap_stats, cancel);
 
     if (!ble_gap_master_in_progress()) {
@@ -2263,19 +1924,23 @@ ble_gap_cancel(void)
         goto done;
     }
 
+    BLE_HS_LOG(INFO, "GAP procedure initiated: cancel connection\n");
+
     host_hci_cmd_build_le_create_conn_cancel(buf, sizeof buf);
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         goto done;
     }
 
+    rc = 0;
+
 done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: cancel connection\n");
-    } else {
+    if (rc != 0) {
         STATS_INC(ble_gap_stats, cancel_fail);
     }
 
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -2283,128 +1948,48 @@ done:
  * $update connection parameters                                             *
  *****************************************************************************/
 
-/**
- * Lock restrictions:
- *     o Caller unlocks gap.
- */
-static void
-ble_gap_param_neg_reply_ack(struct ble_hci_ack *ack, void *arg)
-{
-    struct ble_gap_update_entry *entry;
-
-    ble_gap_lock();
-
-    entry = arg;
-    BLE_HS_DBG_ASSERT(entry->state == BLE_GAP_STATE_U_NEG_REPLY);
-    BLE_HS_DBG_ASSERT(entry->hci_handle == ack->bha_hci_handle);
-
-    entry->hci_handle = BLE_HCI_SCHED_HANDLE_NONE;
-
-    SLIST_REMOVE(&ble_gap_update_entries, entry,
-                 ble_gap_update_entry, next);
-
-    ble_gap_unlock();
-
-    ble_gap_update_entry_free(entry);
-}
-
-/**
- * Lock restrictions:
- *     o Caller unlocks all ble_hs mutexes.
- */
-static void
-ble_gap_param_reply_ack(struct ble_hci_ack *ack, void *arg)
-{
-    struct ble_gap_update_entry *entry;
-
-    ble_gap_lock();
-
-    entry = arg;
-    BLE_HS_DBG_ASSERT(entry->state == BLE_GAP_STATE_U_REPLY);
-    BLE_HS_DBG_ASSERT(entry->hci_handle == ack->bha_hci_handle);
-
-    entry->hci_handle = BLE_HCI_SCHED_HANDLE_NONE;
-
-    if (ack->bha_status != 0) {
-        SLIST_REMOVE(&ble_gap_update_entries, entry,
-                     ble_gap_update_entry, next);
-    } else {
-        entry->state = BLE_GAP_STATE_U_REPLY_ACKED;
-    }
-
-    ble_gap_unlock();
-
-    if (ack->bha_status != 0) {
-        ble_gap_update_failed(entry, ack->bha_status);
-    }
-}
-
 static int
-ble_gap_tx_param_pos_reply(void *arg)
+ble_gap_tx_param_pos_reply(uint16_t conn_handle,
+                           struct ble_gap_upd_params *params)
 {
+    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_PARAM_REPLY_LEN];
     struct hci_conn_param_reply pos_reply;
-    struct ble_gap_update_entry *entry;
-    struct ble_gap_conn_ctxt ctxt;
-    struct ble_gap_snapshot snap;
-    int snap_rc;
     int rc;
 
-    entry = arg;
-
-    pos_reply.handle = entry->conn_handle;
-    pos_reply.conn_itvl_min = entry->params.itvl_min;
-    pos_reply.conn_itvl_max = entry->params.itvl_max;
-    pos_reply.conn_latency = entry->params.latency;
-    pos_reply.supervision_timeout = entry->params.supervision_timeout;
-    pos_reply.min_ce_len = entry->params.min_ce_len;
-    pos_reply.max_ce_len = entry->params.max_ce_len;
-
-    ble_hci_sched_set_ack_cb(ble_gap_param_reply_ack, entry);
+    pos_reply.handle = conn_handle;
+    pos_reply.conn_itvl_min = params->itvl_min;
+    pos_reply.conn_itvl_max = params->itvl_max;
+    pos_reply.conn_latency = params->latency;
+    pos_reply.supervision_timeout = params->supervision_timeout;
+    pos_reply.min_ce_len = params->min_ce_len;
+    pos_reply.max_ce_len = params->max_ce_len;
 
-    rc = host_hci_cmd_le_conn_param_reply(&pos_reply);
+    host_hci_cmd_build_le_conn_param_reply(&pos_reply, buf, sizeof buf);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
-        rc = BLE_HS_HCI_ERR(rc);
-        snap_rc = ble_gap_find_snapshot(entry->conn_handle, &snap);
-        if (snap_rc == 0) {
-            memset(&ctxt, 0, sizeof ctxt);
-            ctxt.desc = &snap.desc;
-            ble_gap_call_conn_cb(BLE_GAP_EVENT_CONN_UPDATE_REQ, rc, &ctxt,
-                                 snap.cb, snap.cb_arg);
-        }
+        return rc;
     }
 
-    return rc;
+    return 0;
 }
 
 static int
-ble_gap_tx_param_neg_reply(void *arg)
+ble_gap_tx_param_neg_reply(uint16_t conn_handle, uint8_t reject_reason)
 {
+    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_PARAM_NEG_REPLY_LEN];
     struct hci_conn_param_neg_reply neg_reply;
-    struct ble_gap_update_entry *entry;
-    struct ble_gap_conn_ctxt ctxt;
-    struct ble_gap_snapshot snap;
-    int snap_rc;
     int rc;
 
-    entry = arg;
-
-    neg_reply.handle = entry->conn_handle;
-    neg_reply.reason = entry->reject_reason;
+    neg_reply.handle = conn_handle;
+    neg_reply.reason = reject_reason;
 
-    ble_hci_sched_set_ack_cb(ble_gap_param_neg_reply_ack, entry);
-    rc = host_hci_cmd_le_conn_param_neg_reply(&neg_reply);
+    host_hci_cmd_build_le_conn_param_neg_reply(&neg_reply, buf, sizeof buf);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
-        rc = BLE_HS_HCI_ERR(rc);
-        snap_rc = ble_gap_find_snapshot(entry->conn_handle, &snap);
-        if (snap_rc == 0) {
-            memset(&ctxt, 0, sizeof ctxt);
-            ctxt.desc = &snap.desc;
-            ble_gap_call_conn_cb(BLE_GAP_EVENT_CONN_UPDATE_REQ, rc, &ctxt,
-                                 snap.cb, snap.cb_arg);
-        }
+        return rc;
     }
 
-    return rc;
+    return 0;
 }
 
 /**
@@ -2419,29 +2004,22 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt)
 #endif
 
     struct ble_gap_upd_params peer_params;
-    struct ble_gap_update_entry *entry;
+    struct ble_gap_upd_params self_params;
     struct ble_gap_conn_ctxt ctxt;
     struct ble_gap_snapshot snap;
+    uint8_t reject_reason;
     int rc;
 
+    ble_hs_lock();
+
+    reject_reason = 0; /* Silence warning. */
+
     rc = ble_gap_find_snapshot(evt->connection_handle, &snap);
     if (rc != 0) {
         /* We are not connected to the sender. */
-        return;
+        goto done;;
     }
 
-    ble_gap_lock();
-
-    entry = ble_gap_update_find(evt->connection_handle);
-    if (entry != NULL) {
-        /* Parameter update already in progress; replace existing request with
-         * new one.
-         */
-        ble_gap_update_entry_remove_free(entry);
-    }
-
-    ble_gap_unlock();
-
     peer_params.itvl_min = evt->itvl_min;
     peer_params.itvl_max = evt->itvl_max;
     peer_params.latency = evt->latency;
@@ -2449,51 +2027,32 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt)
     peer_params.min_ce_len = 0;
     peer_params.max_ce_len = 0;
 
-    entry = ble_gap_update_entry_alloc();
-    if (entry == NULL) {
-        /* Out of memory; reject. */
-        /* XXX: Our negative response should indicate which connection handle
-         * it applies to, but we don't have anywhere to store this information.
-         * For now, just send a connection handle of 0 and hope the peer can
-         * sort it out.
-         */
-        rc = BLE_ERR_MEM_CAPACITY;
-    } else {
-        entry->state = BLE_GAP_STATE_U_REPLY;
-        entry->conn_handle = evt->connection_handle;
-        entry->params = peer_params;
+    /* By default, the application will just XXX */
+    self_params = peer_params;
 
-        memset(&ctxt, 0, sizeof ctxt);
-        ctxt.desc = &snap.desc;
-        ctxt.update.self_params = &entry->params;
-        ctxt.update.peer_params = &peer_params;
-        rc = ble_gap_call_conn_cb(BLE_GAP_EVENT_CONN_UPDATE_REQ, 0, &ctxt,
-                                  snap.cb, snap.cb_arg);
-        if (rc != 0) {
-            entry->reject_reason = rc;
-        }
+    memset(&ctxt, 0, sizeof ctxt);
+    ctxt.desc = &snap.desc;
+    ctxt.update.self_params = &self_params;
+    ctxt.update.peer_params = &peer_params;
+    rc = ble_gap_call_conn_cb(BLE_GAP_EVENT_CONN_UPDATE_REQ, 0, &ctxt,
+                              snap.cb, snap.cb_arg);
+    if (rc != 0) {
+        reject_reason = rc;
     }
 
     if (rc == 0) {
-        ble_hci_sched_enqueue(ble_gap_tx_param_pos_reply, entry,
-                              &entry->hci_handle);
-    }
-
-    if (rc != 0) {
-        if (entry != NULL) {
-            entry->state = BLE_GAP_STATE_U_NEG_REPLY;
-            ble_hci_sched_enqueue(ble_gap_tx_param_neg_reply, entry,
-                                  &entry->hci_handle);
+        rc = ble_gap_tx_param_pos_reply(evt->connection_handle, &self_params);
+        if (rc != 0) {
+            ble_gap_update_failed(evt->connection_handle, rc);
         } else {
-            ble_hci_sched_enqueue(ble_gap_tx_param_neg_reply, NULL, NULL);
+            ble_gap_update_set_flag(evt->connection_handle, 1);
         }
+    } else {
+        ble_gap_tx_param_neg_reply(evt->connection_handle, reject_reason);
     }
 
-    if (entry != NULL) {
-        ble_gap_lock();
-        SLIST_INSERT_HEAD(&ble_gap_update_entries, entry, next);
-        ble_gap_unlock();
-    }
+done:
+    ble_hs_unlock();
 }
 
 /**
@@ -2501,26 +2060,26 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt)
  *     o Caller locks gap.
  */
 static int
-ble_gap_update_tx(struct ble_gap_update_entry *entry)
+ble_gap_update_tx(uint16_t conn_handle, struct ble_gap_upd_params *params)
 {
     uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_UPDATE_LEN];
     struct hci_conn_update cmd;
     int rc;
 
-    cmd.handle = entry->conn_handle;
-    cmd.conn_itvl_min = entry->params.itvl_min;
-    cmd.conn_itvl_max = entry->params.itvl_max;
-    cmd.conn_latency = entry->params.latency;
-    cmd.supervision_timeout = entry->params.supervision_timeout;
-    cmd.min_ce_len = entry->params.min_ce_len;
-    cmd.max_ce_len = entry->params.max_ce_len;
+    cmd.handle = conn_handle;
+    cmd.conn_itvl_min = params->itvl_min;
+    cmd.conn_itvl_max = params->itvl_max;
+    cmd.conn_latency = params->latency;
+    cmd.supervision_timeout = params->supervision_timeout;
+    cmd.min_ce_len = params->min_ce_len;
+    cmd.max_ce_len = params->max_ce_len;
 
     rc = host_hci_cmd_build_le_conn_update(&cmd, buf, sizeof buf);
     if (rc != 0) {
         return rc;
     }
 
-    rc = ble_hci_block_tx(buf, NULL, 0, NULL);
+    rc = ble_hci_tx_cmd_empty_ack(buf);
     if (rc != 0) {
         return rc;
     }
@@ -2540,50 +2099,39 @@ ble_gap_update_params(uint16_t conn_handle, struct ble_gap_upd_params *params)
     return BLE_HS_ENOTSUP;
 #endif
 
-    struct ble_gap_update_entry *entry;
     int rc;
 
-    STATS_INC(ble_gap_stats, update);
+    ble_hs_lock();
 
-    ble_gap_lock();
+    STATS_INC(ble_gap_stats, update);
 
     if (!ble_hs_conn_exists(conn_handle)) {
         rc = BLE_HS_ENOTCONN;
         goto done;
     }
 
-    entry = ble_gap_update_find(conn_handle);
-    if (entry != NULL) {
+    if (ble_gap_update_in_progress(conn_handle)) {
         rc = BLE_HS_EALREADY;
         goto done;
     }
 
-    entry = ble_gap_update_entry_alloc();
-    if (entry == NULL) {
-        rc = BLE_HS_ENOMEM;
-        goto done;
-    }
-
-    entry->state = BLE_GAP_STATE_U_UPDATE;
-    entry->conn_handle = conn_handle;
-    entry->params = *params;
+    BLE_HS_LOG(INFO, "GAP procedure initiated: ");
+    ble_gap_log_update(conn_handle, params);
+    BLE_HS_LOG(INFO, "\n");
 
-    rc = ble_gap_update_tx(entry);
+    rc = ble_gap_update_tx(conn_handle, params);
     if (rc != 0) {
         goto done;
     }
 
+    ble_gap_update_set_flag(conn_handle, 1);
+
 done:
-    if (rc == 0) {
-        BLE_HS_LOG(INFO, "GAP procedure initiated: ");
-        ble_gap_log_update(entry);
-        BLE_HS_LOG(INFO, "\n");
-        SLIST_INSERT_HEAD(&ble_gap_update_entries, entry, next);
-    } else {
+    if (rc != 0) {
         STATS_INC(ble_gap_stats, update_fail);
     }
 
-    ble_gap_unlock();
+    ble_hs_unlock();
 
     return rc;
 }
@@ -2600,12 +2148,14 @@ ble_gap_security_initiate(uint16_t conn_handle)
     struct ble_hs_conn *conn;
     int rc;
 
-    ble_hs_conn_lock();
+    ble_hs_lock();
+
     conn = ble_hs_conn_find(conn_handle);
     if (conn != NULL) {
         conn_flags = conn->bhc_flags;
     }
-    ble_hs_conn_unlock();
+
+    ble_hs_unlock();
 
     if (conn == NULL) {
         return BLE_HS_ENOTCONN;
@@ -2627,7 +2177,7 @@ ble_gap_security_event(uint16_t conn_handle, int status,
     struct ble_gap_snapshot snap;
     struct ble_hs_conn *conn;
 
-    ble_hs_conn_lock();
+    ble_hs_lock();
 
     conn = ble_hs_conn_find(conn_handle);
     if (conn != NULL) {
@@ -2635,7 +2185,7 @@ ble_gap_security_event(uint16_t conn_handle, int status,
         ble_gap_conn_to_snapshot(conn, &snap);
     }
 
-    ble_hs_conn_unlock();
+    ble_hs_unlock();
 
     if (conn == NULL) {
         /* No longer connected. */
@@ -2664,36 +2214,12 @@ ble_gap_init(void)
     memset(&ble_gap_master, 0, sizeof ble_gap_master);
     memset(&ble_gap_slave, 0, sizeof ble_gap_slave);
 
-    free(ble_gap_update_mem);
-    ble_gap_update_mem = malloc(
-        OS_MEMPOOL_BYTES(ble_hs_cfg.max_conn_update_entries,
-                         sizeof (struct ble_gap_update_entry)));
-
-    if (ble_hs_cfg.max_conn_update_entries > 0) {
-        rc = os_mempool_init(&ble_gap_update_pool,
-                             ble_hs_cfg.max_conn_update_entries,
-                             sizeof (struct ble_gap_update_entry),
-                             ble_gap_update_mem, "ble_gap_update_pool");
-        if (rc != 0) {
-            rc = BLE_HS_EOS;
-            goto err;
-        }
-    }
-
-    SLIST_INIT(&ble_gap_update_entries);
-
     rc = stats_init_and_reg(
         STATS_HDR(ble_gap_stats), STATS_SIZE_INIT_PARMS(ble_gap_stats,
         STATS_SIZE_32), STATS_NAME_INIT_PARMS(ble_gap_stats), "ble_gap");
     if (rc != 0) {
-        rc = BLE_HS_EOS;
-        goto err;
+        return BLE_HS_EOS;
     }
 
     return 0;
-
-err:
-    free(ble_gap_update_mem);
-    ble_gap_update_mem = NULL;
-    return rc;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e32f9f9f/net/nimble/host/src/ble_gatt_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatt_priv.h b/net/nimble/host/src/ble_gatt_priv.h
index 9200c4c..704d441 100644
--- a/net/nimble/host/src/ble_gatt_priv.h
+++ b/net/nimble/host/src/ble_gatt_priv.h
@@ -104,7 +104,6 @@ int ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
                        ble_gatt_attr_fn *cb, void *cb_arg);
 
 void ble_gattc_rx_err(uint16_t conn_handle, struct ble_att_error_rsp *rsp);
-void ble_gattc_wakeup(void);
 void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu);
 void ble_gattc_rx_read_type_adata(uint16_t conn_handle,
                                   struct ble_att_read_type_adata *adata);