[SPARC64]: Export basic cpu properties via sysfs.
[sfrench/cifs-2.6.git] / arch / sparc64 / kernel / sysfs.c
1 /* sysfs.c: Toplogy sysfs support code for sparc64.
2  *
3  * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4  */
5 #include <linux/sysdev.h>
6 #include <linux/cpu.h>
7 #include <linux/smp.h>
8 #include <linux/percpu.h>
9 #include <linux/init.h>
10
11 static DEFINE_PER_CPU(struct cpu, cpu_devices);
12
13 #define SHOW_ULONG_NAME(NAME, MEMBER) \
14 static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
15 { \
16         struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
17         cpuinfo_sparc *c = &cpu_data(cpu->sysdev.id); \
18         return sprintf(buf, "%lu\n", c->MEMBER); \
19 }
20
21 #define SHOW_UINT_NAME(NAME, MEMBER) \
22 static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
23 { \
24         struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
25         cpuinfo_sparc *c = &cpu_data(cpu->sysdev.id); \
26         return sprintf(buf, "%u\n", c->MEMBER); \
27 }
28
29 SHOW_ULONG_NAME(clock_tick, clock_tick);
30 SHOW_ULONG_NAME(udelay_val, udelay_val);
31 SHOW_UINT_NAME(l1_dcache_size, dcache_size);
32 SHOW_UINT_NAME(l1_dcache_line_size, dcache_line_size);
33 SHOW_UINT_NAME(l1_icache_size, icache_size);
34 SHOW_UINT_NAME(l1_icache_line_size, icache_line_size);
35 SHOW_UINT_NAME(l2_cache_size, ecache_size);
36 SHOW_UINT_NAME(l2_cache_line_size, ecache_line_size);
37
38 static struct sysdev_attribute cpu_core_attrs[] = {
39         _SYSDEV_ATTR(clock_tick,          0444, show_clock_tick, NULL),
40         _SYSDEV_ATTR(udelay_val,          0444, show_udelay_val, NULL),
41         _SYSDEV_ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
42         _SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
43         _SYSDEV_ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
44         _SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
45         _SYSDEV_ATTR(l2_cache_size,       0444, show_l2_cache_size, NULL),
46         _SYSDEV_ATTR(l2_cache_line_size,  0444, show_l2_cache_line_size, NULL),
47 };
48
49 static void register_cpu_online(unsigned int cpu)
50 {
51         struct cpu *c = &per_cpu(cpu_devices, cpu);
52         struct sys_device *s = &c->sysdev;
53         int i;
54
55         for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
56                 sysdev_create_file(s, &cpu_core_attrs[i]);
57 }
58
59 #ifdef CONFIG_HOTPLUG_CPU
60 static void unregister_cpu_online(unsigned int cpu)
61 {
62         struct cpu *c = &per_cpu(cpu_devices, cpu);
63         struct sys_device *s = &c->sysdev;
64         int i;
65
66         for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
67                 sysdev_remove_file(s, &cpu_core_attrs[i]);
68 }
69 #endif
70
71 static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
72                                       unsigned long action, void *hcpu)
73 {
74         unsigned int cpu = (unsigned int)(long)hcpu;
75
76         switch (action) {
77         case CPU_ONLINE:
78         case CPU_ONLINE_FROZEN:
79                 register_cpu_online(cpu);
80                 break;
81 #ifdef CONFIG_HOTPLUG_CPU
82         case CPU_DEAD:
83         case CPU_DEAD_FROZEN:
84                 unregister_cpu_online(cpu);
85                 break;
86 #endif
87         }
88         return NOTIFY_OK;
89 }
90
91 static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
92         .notifier_call  = sysfs_cpu_notify,
93 };
94
95 static int __init topology_init(void)
96 {
97         int cpu;
98
99         register_cpu_notifier(&sysfs_cpu_nb);
100
101         for_each_possible_cpu(cpu) {
102                 struct cpu *c = &per_cpu(cpu_devices, cpu);
103
104                 register_cpu(c, cpu);
105                 if (cpu_online(cpu))
106                         register_cpu_online(cpu);
107         }
108
109         return 0;
110 }
111
112 subsys_initcall(topology_init);