Skip to content

Commit d089815

Browse files
dcpleungkartben
authored andcommitted
soc: intel_adsp/ace: use custom arch_spin_relax()
Intel Audio DSP ACE needs to use arch_spin_relax() to give the bus more time to propagate the RCW transactions among CPUs, and to avoid sending too many requests to the bus after failing to lock spinlocks. However, the number of NOPs results in a very big arch_spin_relax() that spans multiple instruction cache lines, and requires evicting them just for NOPs. With 5 CPUs, it can span 6 cache lines (if using nop.n instead of nop). That's a waste of space and cache. So instead, we do a tight loop instead. Since the SoC supports zero-overhead loops, this should have minimal performance impact. Signed-off-by: Daniel Leung <[email protected]>
1 parent 58b035b commit d089815

File tree

4 files changed

+58
-14
lines changed

4 files changed

+58
-14
lines changed

soc/intel/intel_adsp/ace/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ zephyr_include_directories(include)
1818
zephyr_include_directories(include/${CONFIG_SOC})
1919
zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget.c)
2020
zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget_messages.c)
21+
zephyr_library_sources_ifdef(
22+
CONFIG_SOC_SERIES_INTEL_ADSP_ACE_CUSTOM_MORE_SPIN_RELAX_NOPS
23+
spin_relax.c
24+
)
2125

2226
if (CONFIG_XTENSA_MMU)
2327
zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_ACE30 mmu_ace30.c)

soc/intel/intel_adsp/ace/Kconfig

+21
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,24 @@ config SRAM_RETENTION_MODE
3131
When this option is enabled, the SRAM retention mode will be
3232
activated during the firmware boot-up process. If disabled,
3333
the retention mode will not be activated.
34+
35+
config SOC_SERIES_INTEL_ADSP_ACE_CUSTOM_MORE_SPIN_RELAX_NOPS
36+
bool "Use Intel Audio DSP specific arch_spin_relax() with more NOPs"
37+
depends on !XTENSA_MORE_SPIN_RELAX_NOPS
38+
default y if SMP && MP_MAX_NUM_CPUS > 1
39+
help
40+
Add some NOPs after failure to lock a spinlock. This gives
41+
the bus extra time to synchronize the RCW transaction
42+
among CPUs.
43+
44+
config SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS
45+
int "Number of NOPs to be used in Intel Audio DSP specific arch_spin_relax()"
46+
depends on SOC_SERIES_INTEL_ADSP_ACE_CUSTOM_MORE_SPIN_RELAX_NOPS
47+
default 32 if MP_MAX_NUM_CPUS = 1
48+
default 64 if MP_MAX_NUM_CPUS = 2
49+
default 96 if MP_MAX_NUM_CPUS = 3
50+
default 128 if MP_MAX_NUM_CPUS = 4
51+
default 160 if MP_MAX_NUM_CPUS = 5
52+
help
53+
Specify the number of NOPs in Intel Audio DSP specific
54+
arch_spin_relax().

soc/intel/intel_adsp/ace/Kconfig.defconfig.series

-14
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,6 @@ config LOG_BACKEND_ADSP
5757

5858
endif # LOG
5959

60-
config XTENSA_MORE_SPIN_RELAX_NOPS
61-
default y if SMP && MP_MAX_NUM_CPUS > 1
62-
63-
if XTENSA_MORE_SPIN_RELAX_NOPS
64-
65-
config XTENSA_NUM_SPIN_RELAX_NOPS
66-
default 32 if MP_MAX_NUM_CPUS = 1
67-
default 64 if MP_MAX_NUM_CPUS = 2
68-
default 96 if MP_MAX_NUM_CPUS = 3
69-
default 128 if MP_MAX_NUM_CPUS = 4
70-
default 160 if MP_MAX_NUM_CPUS = 5
71-
72-
endif # XTENSA_MORE_SPIN_RELAX_NOPS
73-
7460
if KERNEL_VM_SUPPORT
7561

7662
config KERNEL_VM_SIZE

soc/intel/intel_adsp/ace/spin_relax.c

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2025 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <stdint.h>
8+
9+
#include <zephyr/toolchain.h>
10+
#include <zephyr/sys/util_macro.h>
11+
12+
#ifdef CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS
13+
void arch_spin_relax(void)
14+
{
15+
register uint32_t remaining = CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS;
16+
17+
while (remaining > 0) {
18+
#if (CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS % 4) == 0
19+
remaining -= 4;
20+
21+
/*
22+
* Note the xcc/xt-clang likes to "truncate"
23+
* continuous NOPs to max 4 NOPs. So this is
24+
* the most we can do in one loop.
25+
*/
26+
__asm__("nop.n; nop.n; nop.n; nop.n;");
27+
#else
28+
remaining--;
29+
__asm__("nop.n");
30+
#endif
31+
}
32+
}
33+
#endif /* CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS */

0 commit comments

Comments
 (0)