summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2017-01-08 05:01:11 -0500
committerHelge Deller <deller@gmx.de>2017-05-10 11:46:14 -0400
commitc8c3735997a3aa184fa81742bb6c4062a26af2f3 (patch)
tree3d6e8864e8935ac167efc3313913444b4eb2e811
parentc3e5523fcffdc9df8faa7d66f5ad8c1c833e1795 (diff)
parisc: Enhance detection of synchronous cr16 clocksources
The cr16 clocks of the physical PARISC CPUs are usually nonsynchronous. Nevertheless, it seems that each CPU socket (which holds two cores) of PA8800 and PA8900 CPUs (e.g. in a C8000 workstation) is fed by the same clock source, which makes the cr16 clocks of each CPU socket syncronous. Let's try to detect such situations and mark the cr16 clocksource stable on single-socket and single-core machines. Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--arch/parisc/include/asm/processor.h2
-rw-r--r--arch/parisc/kernel/processor.c5
-rw-r--r--arch/parisc/kernel/time.c24
3 files changed, 26 insertions, 5 deletions
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index a3661ee6b060..ea4e6ae091d0 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -103,6 +103,8 @@ struct cpuinfo_parisc {
103 unsigned long bh_count; /* number of times bh was invoked */ 103 unsigned long bh_count; /* number of times bh was invoked */
104 unsigned long fp_rev; 104 unsigned long fp_rev;
105 unsigned long fp_model; 105 unsigned long fp_model;
106 unsigned long cpu_num; /* CPU number from PAT firmware */
107 unsigned long cpu_loc; /* CPU location from PAT firmware */
106 unsigned int state; 108 unsigned int state;
107 struct parisc_device *dev; 109 struct parisc_device *dev;
108 unsigned long loops_per_jiffy; 110 unsigned long loops_per_jiffy;
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 85de47f4eb59..0ab32779dfa7 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -94,7 +94,7 @@ static int processor_probe(struct parisc_device *dev)
94 unsigned long txn_addr; 94 unsigned long txn_addr;
95 unsigned long cpuid; 95 unsigned long cpuid;
96 struct cpuinfo_parisc *p; 96 struct cpuinfo_parisc *p;
97 struct pdc_pat_cpu_num cpu_info __maybe_unused; 97 struct pdc_pat_cpu_num cpu_info = { };
98 98
99#ifdef CONFIG_SMP 99#ifdef CONFIG_SMP
100 if (num_online_cpus() >= nr_cpu_ids) { 100 if (num_online_cpus() >= nr_cpu_ids) {
@@ -113,6 +113,7 @@ static int processor_probe(struct parisc_device *dev)
113 */ 113 */
114 cpuid = boot_cpu_data.cpu_count; 114 cpuid = boot_cpu_data.cpu_count;
115 txn_addr = dev->hpa.start; /* for legacy PDC */ 115 txn_addr = dev->hpa.start; /* for legacy PDC */
116 cpu_info.cpu_num = cpu_info.cpu_loc = cpuid;
116 117
117#ifdef CONFIG_64BIT 118#ifdef CONFIG_64BIT
118 if (is_pdc_pat()) { 119 if (is_pdc_pat()) {
@@ -180,6 +181,8 @@ static int processor_probe(struct parisc_device *dev)
180 p->hpa = dev->hpa.start; /* save CPU hpa */ 181 p->hpa = dev->hpa.start; /* save CPU hpa */
181 p->cpuid = cpuid; /* save CPU id */ 182 p->cpuid = cpuid; /* save CPU id */
182 p->txn_addr = txn_addr; /* save CPU IRQ address */ 183 p->txn_addr = txn_addr; /* save CPU IRQ address */
184 p->cpu_num = cpu_info.cpu_num;
185 p->cpu_loc = cpu_info.cpu_loc;
183#ifdef CONFIG_SMP 186#ifdef CONFIG_SMP
184 /* 187 /*
185 ** FIXME: review if any other initialization is clobbered 188 ** FIXME: review if any other initialization is clobbered
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 89421df70160..2d956aa0a38a 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -243,14 +243,30 @@ void __init time_init(void)
243static int __init init_cr16_clocksource(void) 243static int __init init_cr16_clocksource(void)
244{ 244{
245 /* 245 /*
246 * The cr16 interval timers are not syncronized across CPUs, so mark 246 * The cr16 interval timers are not syncronized across CPUs on
247 * them unstable and lower rating on SMP systems. 247 * different sockets, so mark them unstable and lower rating on
248 * multi-socket SMP systems.
248 */ 249 */
249 if (num_online_cpus() > 1) { 250 if (num_online_cpus() > 1) {
250 clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; 251 int cpu;
251 clocksource_cr16.rating = 0; 252 unsigned long cpu0_loc;
253 cpu0_loc = per_cpu(cpu_data, 0).cpu_loc;
254
255 for_each_online_cpu(cpu) {
256 if (cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc)
257 continue;
258
259 clocksource_cr16.name = "cr16_unstable";
260 clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE;
261 clocksource_cr16.rating = 0;
262 break;
263 }
252 } 264 }
253 265
266 /* XXX: We may want to mark sched_clock stable here if cr16 clocks are
267 * in sync:
268 * (clocksource_cr16.flags == CLOCK_SOURCE_IS_CONTINUOUS) */
269
254 /* register at clocksource framework */ 270 /* register at clocksource framework */
255 clocksource_register_hz(&clocksource_cr16, 271 clocksource_register_hz(&clocksource_cr16,
256 100 * PAGE0->mem_10msec); 272 100 * PAGE0->mem_10msec);