0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/arch_topology.h>
0015 #include <linux/cpu.h>
0016 #include <linux/cpufreq.h>
0017 #include <linux/cpumask.h>
0018 #include <linux/export.h>
0019 #include <linux/init.h>
0020 #include <linux/percpu.h>
0021 #include <linux/node.h>
0022 #include <linux/nodemask.h>
0023 #include <linux/of.h>
0024 #include <linux/sched.h>
0025 #include <linux/sched/topology.h>
0026 #include <linux/slab.h>
0027 #include <linux/string.h>
0028
0029 #include <asm/cpu.h>
0030 #include <asm/cputype.h>
0031 #include <asm/topology.h>
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 #ifdef CONFIG_OF
0050 struct cpu_efficiency {
0051 const char *compatible;
0052 unsigned long efficiency;
0053 };
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 static const struct cpu_efficiency table_efficiency[] = {
0066 {"arm,cortex-a15", 3891},
0067 {"arm,cortex-a7", 2048},
0068 {NULL, },
0069 };
0070
0071 static unsigned long *__cpu_capacity;
0072 #define cpu_capacity(cpu) __cpu_capacity[cpu]
0073
0074 static unsigned long middle_capacity = 1;
0075 static bool cap_from_dt = true;
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 static void __init parse_dt_topology(void)
0086 {
0087 const struct cpu_efficiency *cpu_eff;
0088 struct device_node *cn = NULL;
0089 unsigned long min_capacity = ULONG_MAX;
0090 unsigned long max_capacity = 0;
0091 unsigned long capacity = 0;
0092 int cpu = 0;
0093
0094 __cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity),
0095 GFP_NOWAIT);
0096
0097 for_each_possible_cpu(cpu) {
0098 const __be32 *rate;
0099 int len;
0100
0101
0102 cn = of_get_cpu_node(cpu, NULL);
0103 if (!cn) {
0104 pr_err("missing device node for CPU %d\n", cpu);
0105 continue;
0106 }
0107
0108 if (topology_parse_cpu_capacity(cn, cpu)) {
0109 of_node_put(cn);
0110 continue;
0111 }
0112
0113 cap_from_dt = false;
0114
0115 for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
0116 if (of_device_is_compatible(cn, cpu_eff->compatible))
0117 break;
0118
0119 if (cpu_eff->compatible == NULL)
0120 continue;
0121
0122 rate = of_get_property(cn, "clock-frequency", &len);
0123 if (!rate || len != 4) {
0124 pr_err("%pOF missing clock-frequency property\n", cn);
0125 continue;
0126 }
0127
0128 capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency;
0129
0130
0131 if (capacity < min_capacity)
0132 min_capacity = capacity;
0133
0134
0135 if (capacity > max_capacity)
0136 max_capacity = capacity;
0137
0138 cpu_capacity(cpu) = capacity;
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148 if (4*max_capacity < (3*(max_capacity + min_capacity)))
0149 middle_capacity = (min_capacity + max_capacity)
0150 >> (SCHED_CAPACITY_SHIFT+1);
0151 else
0152 middle_capacity = ((max_capacity / 3)
0153 >> (SCHED_CAPACITY_SHIFT-1)) + 1;
0154
0155 if (cap_from_dt)
0156 topology_normalize_cpu_scale();
0157 }
0158
0159
0160
0161
0162
0163
0164 static void update_cpu_capacity(unsigned int cpu)
0165 {
0166 if (!cpu_capacity(cpu) || cap_from_dt)
0167 return;
0168
0169 topology_set_cpu_scale(cpu, cpu_capacity(cpu) / middle_capacity);
0170
0171 pr_info("CPU%u: update cpu_capacity %lu\n",
0172 cpu, topology_get_cpu_scale(cpu));
0173 }
0174
0175 #else
0176 static inline void parse_dt_topology(void) {}
0177 static inline void update_cpu_capacity(unsigned int cpuid) {}
0178 #endif
0179
0180
0181
0182
0183
0184
0185 void store_cpu_topology(unsigned int cpuid)
0186 {
0187 struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
0188 unsigned int mpidr;
0189
0190 if (cpuid_topo->package_id != -1)
0191 goto topology_populated;
0192
0193 mpidr = read_cpuid_mpidr();
0194
0195
0196 if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) {
0197
0198
0199
0200
0201
0202 if (mpidr & MPIDR_MT_BITMASK) {
0203
0204 cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
0205 cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
0206 cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
0207 } else {
0208
0209 cpuid_topo->thread_id = -1;
0210 cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
0211 cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
0212 }
0213 } else {
0214
0215
0216
0217
0218
0219 cpuid_topo->thread_id = -1;
0220 cpuid_topo->core_id = 0;
0221 cpuid_topo->package_id = -1;
0222 }
0223
0224 update_cpu_capacity(cpuid);
0225
0226 pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
0227 cpuid, cpu_topology[cpuid].thread_id,
0228 cpu_topology[cpuid].core_id,
0229 cpu_topology[cpuid].package_id, mpidr);
0230
0231 topology_populated:
0232 update_siblings_masks(cpuid);
0233 }
0234
0235
0236
0237
0238
0239 void __init init_cpu_topology(void)
0240 {
0241 reset_cpu_topology();
0242 smp_wmb();
0243
0244 parse_dt_topology();
0245 }