Skip to content

Conversation

@cvinayak
Copy link
Contributor

@cvinayak cvinayak commented Apr 5, 2025

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.

Fixes #87906

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes the issue where the nRF CCM is not disabled on connection event abort, which could lead to data corruption when switching from encrypted to cleartext receptions.

  • Added calls to radio_ccm_disable() in various abort callbacks across connection and ISO contexts.
  • Declared and implemented the radio_ccm_disable() function in the radio HAL layer to properly stop the CCM module.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c Added encryption check for broadcast ISO and CCM disable call.
subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c Added encryption check on abort callback with ACL context.
subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c Added encryption check with conditional CCM disable call.
subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c Added encryption check on abort callback with ACL context.
subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h Declared the new radio_ccm_disable() API.
subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c Implemented the radio_ccm_disable() function.

Comment on lines +487 to +491
const struct lll_sync_iso *lll = param;

if (lll->enc) {
radio_ccm_disable();
}
Copy link

Copilot AI May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The encryption check and radio_ccm_disable() call in this abort callback is similar to logic in other modules. Consider refactoring this repeated logic into a shared helper function to improve maintainability.

Suggested change
const struct lll_sync_iso *lll = param;
if (lll->enc) {
radio_ccm_disable();
}
disable_ccm_if_encrypted(param);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The abort_cb is kept role specific to make it easy to update its logic in future, hence not considering using common helper functions. Also, the context that stores the enc state is different for different roles in the Controller.

Comment on lines +449 to +454
/* 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();
}
Copy link

Copilot AI May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The encryption check and CCM disable call here duplicate similar logic in other abort callbacks. Consider abstracting this into a common helper function to reduce code duplication.

Suggested change
/* 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();
}
/* Disable CCM if encryption is enabled */
disable_ccm_if_encrypted(cis_lll->acl_handle);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The abort_cb is kept role specific to make it easy to update its logic in future, hence not considering using common helper functions. Also, the context that stores the enc state is different for different roles in the Controller.

Comment on lines +233 to +235
if (lll->enc_rx) {
radio_ccm_disable();
}
Copy link

Copilot AI May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This encryption check and CCM disable logic is repeated in multiple abort callbacks. Refactoring this into a shared helper function could improve the code’s maintainability and reduce duplication.

Suggested change
if (lll->enc_rx) {
radio_ccm_disable();
}
disable_ccm_if_encrypted(lll);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The abort_cb is kept role specific to make it easy to update its logic in future, hence not considering using common helper functions. Also, the context that stores the enc state is different for different roles in the Controller.

Comment on lines +433 to +438
/* 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();
}
Copy link

Copilot AI May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The similar pattern of checking the encryption state and disabling CCM appears across different modules. Consider consolidating this logic into a helper function to ease future maintenance.

Suggested change
/* 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();
}
disable_ccm_if_encrypted(cis_lll->acl_handle);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The abort_cb is kept role specific to make it easy to update its logic in future, hence not considering using common helper functions. Also, the context that stores the enc state is different for different roles in the Controller.


void radio_ccm_disable(void)
{
if (IS_ENABLED(CONFIG_SOC_SERIES_BSIM_NRFXX)) {
Copy link

Copilot AI May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider adding inline comments within radio_ccm_disable() to explain the purpose of the IS_ENABLED(CONFIG_SOC_SERIES_BSIM_NRFXX) check and clarify the function’s behavior across different nRF SoC configurations.

Copilot uses AI. Check for mistakes.
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 <vich@nordicsemi.no>
@cvinayak cvinayak force-pushed the github_radio_ccm_disable branch from caa1a24 to b487dfc Compare May 14, 2025 14:00
@sonarqubecloud
Copy link

@cvinayak cvinayak requested a review from Thalley May 16, 2025 08:07
@kartben kartben merged commit 2fc54ae into zephyrproject-rtos:main May 16, 2025
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bluetooth: Disconnection due to "No pending ATT request"

4 participants