Skip to content

Bluetooth: controller: Fix MRAM latency race condition on nRF54H20#22

Draft
cvinayak with Copilot wants to merge 12 commits into
github_nrf54h20_cpurad_bt_ll_sw_split_supportfrom
copilot/fix-mram-no-latency-sync
Draft

Bluetooth: controller: Fix MRAM latency race condition on nRF54H20#22
cvinayak with Copilot wants to merge 12 commits into
github_nrf54h20_cpurad_bt_ll_sw_split_supportfrom
copilot/fix-mram-no-latency-sync

Conversation

Copilot AI commented Feb 4, 2026

Copy link
Copy Markdown
  • Review and understand the current implementation
  • Add atomic variable to track MRAM request completion state
  • Implement callback function for MRAM request completion
  • Update radio_reset() to use sys_notify_init_callback()
  • Update radio_stop() to wait for completion before cancel/release
  • Address code review feedback: Add timeout and arch_spin_relax()
  • Define named constant for timeout iterations
  • Add documentation for error handling in ISR context
  • Run final security check (no issues found)
  • Add validation checks for state, res, and return values

Summary

Successfully implemented callback-based MRAM no latency synchronization to fix race conditions when requests and releases happen in quick succession. The solution includes:

  1. Callback-based notification: Replaced sys_notify_init_spinwait() with sys_notify_init_callback() to properly track request completion
  2. Completion tracking: Added atomic variable to track when MRAM request completes
  3. Safe waiting: Wait for completion in radio_stop() before calling cancel/release
  4. Timeout protection: Added conservative timeout (1M iterations) to prevent infinite loops
  5. CPU-friendly waiting: Uses arch_spin_relax() to avoid wasting CPU cycles
  6. Proper validation: Added LL_ASSERT_DBG checks for callback parameters and return values
  7. Proper documentation: Added comments explaining the rationale and ISR context constraints
Original prompt

Problem

In the pull request zephyrproject-rtos#95417 (branch: github_nrf54h20_cpurad_bt_ll_sw_split_support), the mram_no_latency_request() and mram_no_latency_cancel_or_release() functions are used with sys_notify_init_spinwait() for synchronization.

The current implementation in subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c is:

#if defined(CONFIG_SOC_SERIES_NRF54H)
static struct onoff_client mram_cli;
static atomic_val_t mram_refcnt;
#endif /* CONFIG_SOC_SERIES_NRF54H */

void radio_reset(void)
{
    // ... other code ...
    
#if defined(CONFIG_SOC_SERIES_NRF54H)
    atomic_val_t refcnt;

    refcnt = atomic_inc(&mram_refcnt);
    if (refcnt == 0) {
        sys_notify_init_spinwait(&mram_cli.notify);

        (void)mram_no_latency_request(&mram_cli);
    } else {
        /* Nothing to do, reference count increased. */
    }
#endif /* CONFIG_SOC_SERIES_NRF54H */
    // ...
}

void radio_stop(void)
{
    // ... other code ...
    
#if defined(CONFIG_SOC_SERIES_NRF54H)
    atomic_val_t refcnt;

    refcnt = atomic_get(&mram_refcnt);
    if (refcnt > 0) {
        refcnt = atomic_dec(&mram_refcnt);
        if (refcnt == 1) {
            (void)mram_no_latency_cancel_or_release(&mram_cli);
        } else {
            /* Nothing to do, reference count decremented. */
        }
    } else {
        /* TODO: Development assertion on already cancel/release. */
    }
#endif /* CONFIG_SOC_SERIES_NRF54H */
}

Issue

When mram_no_latency_request() and mram_no_latency_cancel_or_release() are called in quick succession, the cancel/release call may fail because the request hasn't completed yet. This can leave the MRAM no latency request remaining on always, causing potential issues.

Required Changes

Instead of using sys_notify_init_spinwait(), implement a callback-based approach:

  1. Add a state variable to track whether mram_no_latency_request() has completed successfully
  2. Use sys_notify_init_callback() instead of sys_notify_init_spinwait()
  3. Implement a callback function that sets the completion state when the request finishes
  4. In radio_stop(), before calling mram_no_latency_cancel_or_release():
    • Check if the request has completed
    • If not completed, wait for completion (spin or use appropriate waiting mechanism)
    • Only then call mram_no_latency_cancel_or_release()

Implementation Guidelines

The callback approach should:

  • Use a static atomic variable to track the completion state (e.g., mram_no_latency_complete)
  • Define a callback function that atomically sets the completion state to true
  • In radio_reset(), clear the completion state before making the request, then use sys_notify_init_callback() with the callback function
  • In radio_stop(), wait (spin) until the completion state is true before calling mram_no_latency_cancel_or_release()

This ensures proper synchronization and prevents race conditions when requests and releases happen in quick succession.

Base Branch

This change should be based on the github_nrf54h20_cpurad_bt_ll_sw_split_support branch in cvinayak/zephyr repository.

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

cvinayak and others added 8 commits January 22, 2026 21:32
nrf54h20 cpurad bt_ll_sw_split support.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
FICR compile error fixed
ECB compile error fixed
SWI compile error fixed
draft modification for radio
Update radio.c due to miss some device check

Signed-off-by: Jui-Chou Chung <jui-chou.chung@nordicsemi.no>
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Added initial implementation for nrf54hx LF clock control.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Added initial implementation for nrf54hx GRTC use for Radio.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Added initial implementation for nrf54hx HF clock control.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Added initial implementation for nrf54hx MRAM no latency
control.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
nRF54H20 cpuapp peripheral_hr quirks.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Copilot AI and others added 3 commits February 4, 2026 18:59
Co-authored-by: cvinayak <6350656+cvinayak@users.noreply.github.com>
Co-authored-by: cvinayak <6350656+cvinayak@users.noreply.github.com>
Co-authored-by: cvinayak <6350656+cvinayak@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix synchronization for MRAM no latency requests Bluetooth: controller: Fix MRAM latency race condition on nRF54H20 Feb 4, 2026
Copilot AI requested a review from cvinayak February 4, 2026 19:04
Comment on lines +211 to +217
static void mram_no_latency_callback(struct onoff_manager *mgr,
struct onoff_client *cli,
uint32_t state, int res)
{
/* Mark that the MRAM no latency request has completed */
atomic_set(&mram_no_latency_complete, 1);
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@copilot add implementation to check state and res values.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added validation checks for state and res parameters in the callback using LL_ASSERT_DBG. The callback now verifies that res == 0 (success) and state == ONOFF_STATE_ON (on state). Commit: f3f0574

/* Use callback-based notification instead of spinwait */
sys_notify_init_callback(&mram_cli.notify, mram_no_latency_callback);

(void)mram_no_latency_request(&mram_cli);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@copilot add implementation to check return value.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added check for the return value of mram_no_latency_request(). The function now stores the return value and validates that it's non-negative using LL_ASSERT_DBG(ret >= 0). Commit: f3f0574

* if the callback hasn't fired within the timeout period.
*/

(void)mram_no_latency_cancel_or_release(&mram_cli);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@copilot add implementation to check return value.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added check for the return value of mram_no_latency_cancel_or_release(). The function now stores the return value and validates that it's non-negative using LL_ASSERT_DBG(ret >= 0). Commit: f3f0574

…lback parameters

Co-authored-by: cvinayak <6350656+cvinayak@users.noreply.github.com>
Copilot AI requested a review from cvinayak February 4, 2026 19:13
@cvinayak cvinayak force-pushed the github_nrf54h20_cpurad_bt_ll_sw_split_support branch 5 times, most recently from 33ce3e3 to ac07e93 Compare February 11, 2026 14:30
@cvinayak cvinayak force-pushed the github_nrf54h20_cpurad_bt_ll_sw_split_support branch from 0e0746d to 15252bd Compare February 13, 2026 12:28
@cvinayak cvinayak force-pushed the github_nrf54h20_cpurad_bt_ll_sw_split_support branch 2 times, most recently from 636ae76 to 2582a3b Compare March 6, 2026 22:27
@cvinayak cvinayak force-pushed the github_nrf54h20_cpurad_bt_ll_sw_split_support branch from 2582a3b to 29f739a Compare March 7, 2026 04:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants