Skip to content

Commit

Permalink
os/pm: fix board hang issue
Browse files Browse the repository at this point in the history
This commit resolve hang issue of pm with amp. The issue happens when
CPU0 gated the CPU1 and exited from critical section without undoing
gating of CPU1. Later when tick interrupt came, the gated CPU0 tries to
pause CPU1, but since CPU1 is in gating it can not release spinlock
require by CPU0 to proceed CPU pause request. This creates deadlock
which results in hang. To prevent this case we are setting gated_cpu_count
just after performing gating and at EXIT case it will ensure the gated
CPUs get ungated.
  • Loading branch information
gSahitya-samsung authored and r-prabu committed Dec 16, 2024
1 parent 511aa52 commit 9e60686
Showing 1 changed file with 15 additions and 15 deletions.
30 changes: 15 additions & 15 deletions os/pm/pm_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ void pm_idle(void)
newstate = pm_checkstate();
#ifdef CONFIG_PM_METRICS
pm_metrics_update_idle();
#endif
#ifdef CONFIG_PM_TIMEDWAKEUP
/* get wakeup timer */
if (newstate == PM_SLEEP) {
delay = wd_getwakeupdelay();
if ((delay > 0) && (delay < MSEC2TICK(CONFIG_PM_SLEEP_ENTRY_WAIT_MS))) {
pmvdbg("Wdog Timer Delay: %ldms is less than SLEEP_ENTRY_WAIT: %ldms\n", TICK2MSEC(delay), CONFIG_PM_SLEEP_ENTRY_WAIT_MS);
goto EXIT;
}
}
#endif
/* Perform state-dependent logic here */
/* For SMP case, we need to check secondary core status
Expand All @@ -118,12 +128,12 @@ void pm_idle(void)
if (!up_get_gating_flag_status(cpu)) {
up_set_gating_flag_status(cpu, 1);
up_cpu_gating(cpu);
gated_cpu_count = cpu;
}
while (up_get_gating_flag_status(cpu) == 1) {
/* If there is a pause request, we should handle it first */
if (up_cpu_pausereq(up_cpu_index())) {
pmdbg("Sleep abort! CPU%d task: %s!\n", cpu, tcb->name);
gated_cpu_count = cpu;
pmdbg("Sleep abort! CPU%d\n", cpu);
goto EXIT;
}
}
Expand All @@ -133,22 +143,11 @@ void pm_idle(void)
* pause request on primary core
*/
if (tcb->pid != cpu) {
pmdbg("Sleep abort! CPU%d task: %s!\n", cpu, tcb->name);
gated_cpu_count = cpu;
pmvdbg("Sleep abort! CPU%d task: %s!\n", cpu, tcb->name);
goto EXIT;
}
}
}
#endif
#ifdef CONFIG_PM_TIMEDWAKEUP
/* get wakeup timer */
if (newstate == PM_SLEEP) {
delay = wd_getwakeupdelay();
if ((delay > 0) && (delay < MSEC2TICK(CONFIG_PM_SLEEP_ENTRY_WAIT_MS))) {
pmvdbg("Wdog Timer Delay: %ldms is less than SLEEP_ENTRY_WAIT: %ldms\n", TICK2MSEC(delay), CONFIG_PM_SLEEP_ENTRY_WAIT_MS);
goto EXIT;
}
}
#endif
/* Then force the global state change */
if (pm_changestate(newstate) < 0) {
Expand All @@ -169,8 +168,9 @@ void pm_idle(void)
/* Reset core gating status flag */
up_set_gating_flag_status(cpu, 0);
/* Check whether each of the cpu has entered hotplug */
while(up_get_cpu_state(cpu) != CPU_HOTPLUG);
while (up_get_cpu_state(cpu) != CPU_HOTPLUG);
}
gated_cpu_count = 0;
#endif
#ifdef CONFIG_PM_TIMEDWAKEUP
/* set wakeup timer */
Expand Down

0 comments on commit 9e60686

Please sign in to comment.