0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/irqflags.h>
0014 #include <linux/cpumask.h>
0015
0016 #include <asm/r4k-timer.h>
0017 #include <linux/atomic.h>
0018 #include <asm/barrier.h>
0019 #include <asm/mipsregs.h>
0020
0021 static unsigned int initcount = 0;
0022 static atomic_t count_count_start = ATOMIC_INIT(0);
0023 static atomic_t count_count_stop = ATOMIC_INIT(0);
0024
0025 #define COUNTON 100
0026 #define NR_LOOPS 3
0027
0028 void synchronise_count_master(int cpu)
0029 {
0030 int i;
0031 unsigned long flags;
0032
0033 pr_info("Synchronize counters for CPU %u: ", cpu);
0034
0035 local_irq_save(flags);
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 for (i = 0; i < NR_LOOPS; i++) {
0049
0050 while (atomic_read(&count_count_start) != 1)
0051 mb();
0052 atomic_set(&count_count_stop, 0);
0053 smp_wmb();
0054
0055
0056 atomic_inc(&count_count_start);
0057
0058
0059 if (i == 1)
0060 initcount = read_c0_count();
0061
0062
0063
0064
0065 if (i == NR_LOOPS-1)
0066 write_c0_count(initcount);
0067
0068
0069
0070
0071 while (atomic_read(&count_count_stop) != 1)
0072 mb();
0073 atomic_set(&count_count_start, 0);
0074 smp_wmb();
0075 atomic_inc(&count_count_stop);
0076 }
0077
0078 write_c0_compare(read_c0_count() + COUNTON);
0079
0080 local_irq_restore(flags);
0081
0082
0083
0084
0085
0086
0087 pr_cont("done.\n");
0088 }
0089
0090 void synchronise_count_slave(int cpu)
0091 {
0092 int i;
0093 unsigned long flags;
0094
0095 local_irq_save(flags);
0096
0097
0098
0099
0100
0101
0102 for (i = 0; i < NR_LOOPS; i++) {
0103 atomic_inc(&count_count_start);
0104 while (atomic_read(&count_count_start) != 2)
0105 mb();
0106
0107
0108
0109
0110 if (i == NR_LOOPS-1)
0111 write_c0_count(initcount);
0112
0113 atomic_inc(&count_count_stop);
0114 while (atomic_read(&count_count_stop) != 2)
0115 mb();
0116 }
0117
0118 write_c0_compare(read_c0_count() + COUNTON);
0119
0120 local_irq_restore(flags);
0121 }
0122 #undef NR_LOOPS