summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-04-12 16:07:37 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-04-15 06:20:55 -0400
commit9fe24c4e92d3963d92d7d383e28ed098bd5689d8 (patch)
tree1f331b3ee3445cb7d3946a38b8ee8c57a0dc626e
parent205dcc1ecbc566cbc20acf246e68de3b080b3ecf (diff)
cpufreq/sparc-us3: Replace racy task affinity logic
The access to the safari config register in the CPU frequency functions must be executed on the target CPU. This is achieved by temporarily setting the affinity of the calling user space thread to the requested CPU and reset it to the original affinity afterwards. That's racy vs. CPU hotplug and concurrent affinity settings for that thread resulting in code executing on the wrong CPU and overwriting the new affinity setting. Replace it by a straight forward smp function call. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Sebastian Siewior <bigeasy@linutronix.de> Cc: linux-pm@vger.kernel.org Cc: Lai Jiangshan <jiangshanlai@gmail.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Tejun Heo <tj@kernel.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Len Brown <lenb@kernel.org> Link: http://lkml.kernel.org/r/20170412201043.047558840@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/cpufreq/sparc-us3-cpufreq.c46
1 files changed, 16 insertions, 30 deletions
diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c
index a8d86a449ca1..30645b0118f9 100644
--- a/drivers/cpufreq/sparc-us3-cpufreq.c
+++ b/drivers/cpufreq/sparc-us3-cpufreq.c
@@ -35,22 +35,28 @@ static struct us3_freq_percpu_info *us3_freq_table;
35#define SAFARI_CFG_DIV_32 0x0000000080000000UL 35#define SAFARI_CFG_DIV_32 0x0000000080000000UL
36#define SAFARI_CFG_DIV_MASK 0x00000000C0000000UL 36#define SAFARI_CFG_DIV_MASK 0x00000000C0000000UL
37 37
38static unsigned long read_safari_cfg(void) 38static void read_safari_cfg(void *arg)
39{ 39{
40 unsigned long ret; 40 unsigned long ret, *val = arg;
41 41
42 __asm__ __volatile__("ldxa [%%g0] %1, %0" 42 __asm__ __volatile__("ldxa [%%g0] %1, %0"
43 : "=&r" (ret) 43 : "=&r" (ret)
44 : "i" (ASI_SAFARI_CONFIG)); 44 : "i" (ASI_SAFARI_CONFIG));
45 return ret; 45 *val = ret;
46} 46}
47 47
48static void write_safari_cfg(unsigned long val) 48static void update_safari_cfg(void *arg)
49{ 49{
50 unsigned long reg, *new_bits = arg;
51
52 read_safari_cfg(&reg);
53 reg &= ~SAFARI_CFG_DIV_MASK;
54 reg |= *new_bits;
55
50 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" 56 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
51 "membar #Sync" 57 "membar #Sync"
52 : /* no outputs */ 58 : /* no outputs */
53 : "r" (val), "i" (ASI_SAFARI_CONFIG) 59 : "r" (reg), "i" (ASI_SAFARI_CONFIG)
54 : "memory"); 60 : "memory");
55} 61}
56 62
@@ -78,29 +84,17 @@ static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg
78 84
79static unsigned int us3_freq_get(unsigned int cpu) 85static unsigned int us3_freq_get(unsigned int cpu)
80{ 86{
81 cpumask_t cpus_allowed;
82 unsigned long reg; 87 unsigned long reg;
83 unsigned int ret;
84
85 cpumask_copy(&cpus_allowed, &current->cpus_allowed);
86 set_cpus_allowed_ptr(current, cpumask_of(cpu));
87
88 reg = read_safari_cfg();
89 ret = get_current_freq(cpu, reg);
90
91 set_cpus_allowed_ptr(current, &cpus_allowed);
92 88
93 return ret; 89 if (smp_call_function_single(cpu, read_safari_cfg, &reg, 1))
90 return 0;
91 return get_current_freq(cpu, reg);
94} 92}
95 93
96static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index) 94static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
97{ 95{
98 unsigned int cpu = policy->cpu; 96 unsigned int cpu = policy->cpu;
99 unsigned long new_bits, new_freq, reg; 97 unsigned long new_bits, new_freq;
100 cpumask_t cpus_allowed;
101
102 cpumask_copy(&cpus_allowed, &current->cpus_allowed);
103 set_cpus_allowed_ptr(current, cpumask_of(cpu));
104 98
105 new_freq = sparc64_get_clock_tick(cpu) / 1000; 99 new_freq = sparc64_get_clock_tick(cpu) / 1000;
106 switch (index) { 100 switch (index) {
@@ -121,15 +115,7 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
121 BUG(); 115 BUG();
122 } 116 }
123 117
124 reg = read_safari_cfg(); 118 return smp_call_function_single(cpu, update_safari_cfg, &new_bits, 1);
125
126 reg &= ~SAFARI_CFG_DIV_MASK;
127 reg |= new_bits;
128 write_safari_cfg(reg);
129
130 set_cpus_allowed_ptr(current, &cpus_allowed);
131
132 return 0;
133} 119}
134 120
135static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) 121static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)