From 2fc54ae3bb74cdb2d2bc81d9248a809276cd33e4 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sat, 5 Apr 2025 02:30:03 +0200 Subject: [PATCH] Bluetooth: Controller: Fix nRF CCM disable on connection event abort Fix missing nRF CCM disable on connection event abort. There can be a problem on nRF SoC for example when a S8 "encrypted" reception is aborted, and a 2M "cleartext" reception starts; slow CCM (that is not stopped as part of radio disable) will corrupt a fast received "cleartext" when the same current free rx buffer is reused in the Controller. This is not a problem when the connection being abort-ee is on a faster PHY than the abort-er. Signed-off-by: Vinayak Kariappa Chettimada --- .../controller/ll_sw/nordic/hal/nrf5/radio/radio.c | 6 ++++++ .../controller/ll_sw/nordic/hal/nrf5/radio/radio.h | 1 + .../controller/ll_sw/nordic/lll/lll_central_iso.c | 9 +++++++++ subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c | 7 +++++++ .../controller/ll_sw/nordic/lll/lll_peripheral_iso.c | 9 +++++++++ .../bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c | 9 +++++++++ 6 files changed, 41 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 83c250923f2..596d0137388 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -2511,6 +2511,12 @@ uint32_t radio_ccm_mic_is_valid(void) return (NRF_CCM->MICSTATUS != 0); } +void radio_ccm_disable(void) +{ + nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_STOP); + nrf_ccm_disable(NRF_CCM); +} + #if defined(CONFIG_BT_CTLR_PRIVACY) static uint8_t MALIGN(4) _aar_scratch[3]; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h index ae334df9af5..c1f13dfb8b5 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h @@ -179,6 +179,7 @@ void *radio_ccm_tx_pkt_set(struct ccm *ccm, void *pkt); void *radio_ccm_iso_tx_pkt_set(struct ccm *ccm, uint8_t pdu_type, void *pkt); uint32_t radio_ccm_is_done(void); uint32_t radio_ccm_mic_is_valid(void); +void radio_ccm_disable(void); void radio_ar_configure(uint32_t nirk, void *irk, uint8_t flags); uint32_t radio_ar_match_get(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index ca776a043a1..948ce68a25d 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -429,6 +429,15 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) radio_isr_set(isr_done, cis_lll); radio_disable(); +#if defined(CONFIG_BT_CTLR_LE_ENC) + /* Get reference to ACL context */ + const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); + + if (conn_lll->enc_rx) { + radio_ccm_disable(); + } +#endif /* CONFIG_BT_CTLR_LE_ENC */ + return; } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 3ff4e29efea..ea5028a00f1 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -228,6 +228,13 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param) */ radio_isr_set(isr_done, param); radio_disable(); + +#if defined(CONFIG_BT_CTLR_LE_ENC) + if (lll->enc_rx) { + radio_ccm_disable(); + } +#endif /* CONFIG_BT_CTLR_LE_ENC */ + return; } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index bb17e2efbc1..13003e7b1c6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -445,6 +445,15 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) radio_isr_set(isr_done, cis_lll); radio_disable(); +#if defined(CONFIG_BT_CTLR_LE_ENC) + /* Get reference to ACL context */ + const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); + + if (conn_lll->enc_rx) { + radio_ccm_disable(); + } +#endif /* CONFIG_BT_CTLR_LE_ENC */ + return; } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c index 35b1ec30379..b8ec3f58674 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c @@ -482,6 +482,15 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) if (!prepare_param) { radio_isr_set(isr_done, param); radio_disable(); + + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC)) { + const struct lll_sync_iso *lll = param; + + if (lll->enc) { + radio_ccm_disable(); + } + } + return; }