|
@@ -293,29 +293,45 @@ static struct _cpuid4_info *cpuid4_info[NR_CPUS];
|
|
#ifdef CONFIG_SMP
|
|
#ifdef CONFIG_SMP
|
|
static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
|
|
static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
|
|
{
|
|
{
|
|
- struct _cpuid4_info *this_leaf;
|
|
|
|
|
|
+ struct _cpuid4_info *this_leaf, *sibling_leaf;
|
|
unsigned long num_threads_sharing;
|
|
unsigned long num_threads_sharing;
|
|
-#ifdef CONFIG_X86_HT
|
|
|
|
- struct cpuinfo_x86 *c = cpu_data + cpu;
|
|
|
|
-#endif
|
|
|
|
|
|
+ int index_msb, i;
|
|
|
|
+ struct cpuinfo_x86 *c = cpu_data;
|
|
|
|
|
|
this_leaf = CPUID4_INFO_IDX(cpu, index);
|
|
this_leaf = CPUID4_INFO_IDX(cpu, index);
|
|
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
|
|
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
|
|
|
|
|
|
if (num_threads_sharing == 1)
|
|
if (num_threads_sharing == 1)
|
|
cpu_set(cpu, this_leaf->shared_cpu_map);
|
|
cpu_set(cpu, this_leaf->shared_cpu_map);
|
|
-#ifdef CONFIG_X86_HT
|
|
|
|
- else if (num_threads_sharing == smp_num_siblings)
|
|
|
|
- this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
|
|
|
|
- else if (num_threads_sharing == (c->x86_max_cores * smp_num_siblings))
|
|
|
|
- this_leaf->shared_cpu_map = cpu_core_map[cpu];
|
|
|
|
- else
|
|
|
|
- printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "
|
|
|
|
- "any known set of CPUs\n");
|
|
|
|
-#endif
|
|
|
|
|
|
+ else {
|
|
|
|
+ index_msb = get_count_order(num_threads_sharing);
|
|
|
|
+
|
|
|
|
+ for_each_online_cpu(i) {
|
|
|
|
+ if (c[i].apicid >> index_msb ==
|
|
|
|
+ c[cpu].apicid >> index_msb) {
|
|
|
|
+ cpu_set(i, this_leaf->shared_cpu_map);
|
|
|
|
+ if (i != cpu && cpuid4_info[i]) {
|
|
|
|
+ sibling_leaf = CPUID4_INFO_IDX(i, index);
|
|
|
|
+ cpu_set(cpu, sibling_leaf->shared_cpu_map);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+static void __devinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
|
|
|
|
+{
|
|
|
|
+ struct _cpuid4_info *this_leaf, *sibling_leaf;
|
|
|
|
+ int sibling;
|
|
|
|
+
|
|
|
|
+ this_leaf = CPUID4_INFO_IDX(cpu, index);
|
|
|
|
+ for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) {
|
|
|
|
+ sibling_leaf = CPUID4_INFO_IDX(sibling, index);
|
|
|
|
+ cpu_clear(cpu, sibling_leaf->shared_cpu_map);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
#else
|
|
#else
|
|
static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
|
|
static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
|
|
|
|
+static void __init cache_remove_shared_cpu_map(unsigned int cpu, int index) {}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static void free_cache_attributes(unsigned int cpu)
|
|
static void free_cache_attributes(unsigned int cpu)
|
|
@@ -574,8 +590,10 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
|
|
unsigned int cpu = sys_dev->id;
|
|
unsigned int cpu = sys_dev->id;
|
|
unsigned long i;
|
|
unsigned long i;
|
|
|
|
|
|
- for (i = 0; i < num_cache_leaves; i++)
|
|
|
|
|
|
+ for (i = 0; i < num_cache_leaves; i++) {
|
|
|
|
+ cache_remove_shared_cpu_map(cpu, i);
|
|
kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
|
|
kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
|
|
|
|
+ }
|
|
kobject_unregister(cache_kobject[cpu]);
|
|
kobject_unregister(cache_kobject[cpu]);
|
|
cpuid4_cache_sysfs_exit(cpu);
|
|
cpuid4_cache_sysfs_exit(cpu);
|
|
return;
|
|
return;
|