diff options
author | Pavel Tatashin <pasha.tatashin@oracle.com> | 2017-06-15 10:40:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-15 11:19:34 -0400 |
commit | eea9833453bd39e2f35325abb985d00486c8aa69 (patch) | |
tree | 3d8607f52ec703e18b80bf7722c8c1b3a4eb62cd | |
parent | fca4afe400cb68fe5a7f0a97fb1ba5cfdcb81675 (diff) |
sparc64: broken %tick frequency on spitfire cpus
After early boot time stamps project the %tick frequency is detected
incorrectly on spittfire cpus.
We must use cpuid of boot cpu to find corresponding cpu node in OpenBoot,
and extract clock-frequency property from there.
Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/kernel/time_64.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index a62758ce9e19..f584c53e769a 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -162,9 +162,34 @@ static unsigned long tick_add_tick(unsigned long adj) | |||
162 | return new_tick; | 162 | return new_tick; |
163 | } | 163 | } |
164 | 164 | ||
165 | /* Searches for cpu clock frequency with given cpuid in OpenBoot tree */ | ||
166 | static unsigned long cpuid_to_freq(phandle node, int cpuid) | ||
167 | { | ||
168 | bool is_cpu_node = false; | ||
169 | unsigned long freq = 0; | ||
170 | char type[128]; | ||
171 | |||
172 | if (!node) | ||
173 | return freq; | ||
174 | |||
175 | if (prom_getproperty(node, "device_type", type, sizeof(type)) != -1) | ||
176 | is_cpu_node = (strcmp(type, "cpu") == 0); | ||
177 | |||
178 | /* try upa-portis then cpuid to get cpuid, see prom_64.c */ | ||
179 | if (is_cpu_node && (prom_getint(node, "upa-portis") == cpuid || | ||
180 | prom_getint(node, "cpuid") == cpuid)) | ||
181 | freq = prom_getintdefault(node, "clock-frequency", 0); | ||
182 | if (!freq) | ||
183 | freq = cpuid_to_freq(prom_getchild(node), cpuid); | ||
184 | if (!freq) | ||
185 | freq = cpuid_to_freq(prom_getsibling(node), cpuid); | ||
186 | |||
187 | return freq; | ||
188 | } | ||
189 | |||
165 | static unsigned long tick_get_frequency(void) | 190 | static unsigned long tick_get_frequency(void) |
166 | { | 191 | { |
167 | return local_cpu_data().clock_tick; | 192 | return cpuid_to_freq(prom_root_node, hard_smp_processor_id()); |
168 | } | 193 | } |
169 | 194 | ||
170 | static struct sparc64_tick_ops tick_operations __cacheline_aligned = { | 195 | static struct sparc64_tick_ops tick_operations __cacheline_aligned = { |