[PATCH] create and destroy cache sysfs entries based on cpu notifiers
Ashok Raj [Sun, 30 Oct 2005 22:59:50 +0000 (14:59 -0800)]
cpu cache entries should be populated only when cpu is online and removed
when they are logically offlined.

Without which entries are not removed when cpu is offlined, or dont appear
when we boot with maxcpus=1 and then kick the rest of the cpus via echo 1
to the sysfs online file.

- Changed __devinit to __cpuinit for consistency.
- Changed sysfs_driver_register to register_cpu_notifier.

Signed-off-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: Dave Jones <davej@codemonkey.org.uk>
Cc: Zwane Mwaikambo <zwane@holomorphy.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

arch/i386/kernel/cpu/intel_cacheinfo.c

index 7cc84a4..f083933 100644 (file)
@@ -3,6 +3,7 @@
  *
  *      Changes:
  *      Venkatesh Pallipadi    : Adding cache identification through cpuid(4)
+ *             Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
  */
 
 #include <linux/init.h>
@@ -28,7 +29,7 @@ struct _cache_table
 };
 
 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
-static struct _cache_table cache_table[] __devinitdata =
+static struct _cache_table cache_table[] __cpuinitdata =
 {
        { 0x06, LVL_1_INST, 8 },        /* 4-way set assoc, 32 byte line size */
        { 0x08, LVL_1_INST, 16 },       /* 4-way set assoc, 32 byte line size */
@@ -119,7 +120,7 @@ struct _cpuid4_info {
 
 static unsigned short                  num_cache_leaves;
 
-static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
+static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
 {
        unsigned int            eax, ebx, ecx, edx;
        union _cpuid4_leaf_eax  cache_eax;
@@ -154,7 +155,7 @@ static int __init find_num_cache_leaves(void)
        return i;
 }
 
-unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
+unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 {
        unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
        unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
@@ -289,7 +290,7 @@ static struct _cpuid4_info *cpuid4_info[NR_CPUS];
 #define CPUID4_INFO_IDX(x,y)    (&((cpuid4_info[x])[y]))
 
 #ifdef CONFIG_SMP
-static void __devinit 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;
        unsigned long num_threads_sharing;
@@ -322,7 +323,7 @@ static void free_cache_attributes(unsigned int cpu)
        cpuid4_info[cpu] = NULL;
 }
 
-static int __devinit detect_cache_attributes(unsigned int cpu)
+static int __cpuinit detect_cache_attributes(unsigned int cpu)
 {
        struct _cpuid4_info     *this_leaf;
        unsigned long           j;
@@ -499,7 +500,7 @@ static void cpuid4_cache_sysfs_exit(unsigned int cpu)
        free_cache_attributes(cpu);
 }
 
-static int __devinit cpuid4_cache_sysfs_init(unsigned int cpu)
+static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
 {
 
        if (num_cache_leaves == 0)
@@ -530,7 +531,7 @@ err_out:
 }
 
 /* Add/Remove cache interface for CPU device */
-static int __devinit cache_add_dev(struct sys_device * sys_dev)
+static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
 {
        unsigned int cpu = sys_dev->id;
        unsigned long i, j;
@@ -567,7 +568,7 @@ static int __devinit cache_add_dev(struct sys_device * sys_dev)
        return retval;
 }
 
-static int __devexit cache_remove_dev(struct sys_device * sys_dev)
+static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
 {
        unsigned int cpu = sys_dev->id;
        unsigned long i;
@@ -576,24 +577,49 @@ static int __devexit cache_remove_dev(struct sys_device * sys_dev)
                kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
        kobject_unregister(cache_kobject[cpu]);
        cpuid4_cache_sysfs_exit(cpu);
-       return 0;
+       return;
+}
+
+static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
+                                       unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct sys_device *sys_dev;
+
+       sys_dev = get_cpu_sysdev(cpu);
+       switch (action) {
+       case CPU_ONLINE:
+               cache_add_dev(sys_dev);
+               break;
+       case CPU_DEAD:
+               cache_remove_dev(sys_dev);
+               break;
+       }
+       return NOTIFY_OK;
 }
 
-static struct sysdev_driver cache_sysdev_driver = {
-       .add = cache_add_dev,
-       .remove = __devexit_p(cache_remove_dev),
+static struct notifier_block cacheinfo_cpu_notifier =
+{
+    .notifier_call = cacheinfo_cpu_callback,
 };
 
-/* Register/Unregister the cpu_cache driver */
-static int __devinit cache_register_driver(void)
+static int __cpuinit cache_sysfs_init(void)
 {
+       int i;
+
        if (num_cache_leaves == 0)
                return 0;
 
-       return sysdev_driver_register(&cpu_sysdev_class,&cache_sysdev_driver);
+       register_cpu_notifier(&cacheinfo_cpu_notifier);
+
+       for_each_online_cpu(i) {
+               cacheinfo_cpu_callback(&cacheinfo_cpu_notifier, CPU_ONLINE,
+                       (void *)(long)i);
+       }
+
+       return 0;
 }
 
-device_initcall(cache_register_driver);
+device_initcall(cache_sysfs_init);
 
 #endif
-