sched: walt: fix stale window_start for walt load

Currently the code uses walt_load_reported_window (wlrw in short) to
mark the beginning of the new window. All the updates to cpufreq use the
latest wlrw.

With 'commit acd27bd371dd2 ("sched/walt: walt irq work reduce locking")'
we could hit BUG(curr_ws < last_ws) in cpufreq_walt.c because of using a
stale wlrw. An example of the race.

 cpu0 ED tick                 cpu1 ED tick                  cpu2 tick utra                  G->P migration

 rq_lock(0)                                                 rq_lock(2)
 cpu_util_freq_walt()                                       detects   rollover sets         walt_irq_work_for_mgrtn
 read wlrw =760                                             walt_irq_work_lastq_ws =776     rq_lock 3,4,5,6,7
                                                            rq_unlock(2)                    UPDATE wlrw =  776
                                                            walt_irq_work_for_rlvr          ...
 EL2/EL3 EXCEPTION                                          ...waits for all rq lock        ...
 OR SVM                                                                                     rq_unlock 3,4,5,6,7

                               rq_lock(1)
 RUNS                          cpu_util_freq_walt()
                               read wlrw =776
                               write load->ws =776
                               waltgov_calc_avg_cap()
 HERE                          silver_policy->last_ws =776
                               rq_unlock(1)

 write load->ws=760
 waltgov_calc_avg_cap()
 BUG(walt_load->ws 760 <
      silver_policy->last_ws 776)

To fix this ensure that wlrw is updated ONLY when rq locks of all the
cpus are held.

Change-Id: I9a6649cbccdfdb5a70a0256703624dde47868a15
Signed-off-by: Sai Harshini Nimmala <quic_snimmala@quicinc.com>
This commit is contained in:
Sai Harshini Nimmala 2022-03-16 23:38:03 -07:00 committed by Rishabh Bhatnagar
parent fb76acffb0
commit adeb747e70

View File

@ -3421,7 +3421,8 @@ static inline void __walt_irq_work_locked(bool is_migration, struct cpumask *loc
struct walt_rq *wrq;
wc = walt_sched_clock();
walt_load_reported_window = atomic64_read(&walt_irq_work_lastq_ws);
if (!is_migration)
walt_load_reported_window = atomic64_read(&walt_irq_work_lastq_ws);
for_each_sched_cluster(cluster) {
u64 aggr_grp_load = 0;