From 8b74c98ed5da89adc401ad2b1639fbd0122e5d84 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 20 Jun 2017 21:17:50 +0200 Subject: [PATCH] Bluetooth: controller: Fix conn context leak under directed adv When directed advertisements timed out, connection context associated was not being released. Subsequent connectable advertising or connection creation failed. This is now fixed by releasing the connection context on directed advertisement timeout. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ctrl.c | 42 ++++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index e53503f13ab..1116399142e 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -751,10 +751,6 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t irkmatch_ok, conn = _radio.advertiser.conn; _radio.advertiser.conn = NULL; - /* Advertiser transitions to Slave role */ - LL_ASSERT(_radio.advertiser.is_enabled); - _radio.advertiser.is_enabled = 0; - /* Populate the slave context */ conn->handle = mem_index_get(conn, _radio.conn_pool, CONNECTION_T_SIZE); @@ -1041,10 +1037,6 @@ static inline u32_t isr_rx_scan(u8_t irkmatch_id, u8_t rssi_ready) conn = _radio.scanner.conn; _radio.scanner.conn = NULL; - /* Initiator transitions to Master role */ - LL_ASSERT(_radio.scanner.is_enabled); - _radio.scanner.is_enabled = 0; - /* Tx the connect request packet */ pdu_adv_tx = (struct pdu_adv *)radio_pkt_scratch_get(); pdu_adv_tx->type = PDU_ADV_TYPE_CONNECT_IND; @@ -9141,8 +9133,38 @@ void radio_rx_dequeue(void) } if (radio_pdu_node_rx->hdr.type == NODE_RX_TYPE_CONNECTION) { - u8_t bm = ((u8_t)_radio.scanner.is_enabled << 1) | - _radio.advertiser.is_enabled; + struct radio_le_conn_cmplt *radio_le_conn_cmplt; + struct connection *conn = NULL; + struct pdu_data *pdu_data_rx; + u8_t bm; + + pdu_data_rx = (void *)radio_pdu_node_rx->pdu_data; + radio_le_conn_cmplt = (void *)&pdu_data_rx->payload; + if ((radio_le_conn_cmplt->status == 0x3c) || + radio_le_conn_cmplt->role) { + if (radio_le_conn_cmplt->status == 0x3c) { + conn = _radio.advertiser.conn; + _radio.advertiser.conn = NULL; + } + + LL_ASSERT(_radio.advertiser.is_enabled); + _radio.advertiser.is_enabled = 0; + } else { + LL_ASSERT(_radio.scanner.is_enabled); + _radio.scanner.is_enabled = 0; + } + + if (conn) { + struct radio_pdu_node_rx *node_rx = (void *) + &conn->llcp_terminate.radio_pdu_node_rx; + + mem_release(node_rx->hdr.onion.link, + &_radio.link_rx_free); + mem_release(conn, &_radio.conn_free); + } + + bm = ((u8_t)_radio.scanner.is_enabled << 1) | + _radio.advertiser.is_enabled; if (!bm) { ll_adv_scan_state_cb(0);