diff options
author | Zhang, Yanmin <yanmin.zhang@intel.com> | 2006-02-03 06:04:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-03 11:32:09 -0500 |
commit | 69dcc99199fe29b0a29471a3488d39d9d33b25fc (patch) | |
tree | 4232ad9a782dee6abfe7fa20c95a49249195de8f /drivers | |
parent | 66ac5a294db70aa377c0d7bbdb0c4e3ef2349b7b (diff) |
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/Makefile | 1 | ||||
-rw-r--r-- | drivers/base/topology.c | 148 |
2 files changed, 149 insertions, 0 deletions
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index f12898d53078..e99471d3232b 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -8,6 +8,7 @@ obj-y += power/ | |||
8 | obj-$(CONFIG_FW_LOADER) += firmware_class.o | 8 | obj-$(CONFIG_FW_LOADER) += firmware_class.o |
9 | obj-$(CONFIG_NUMA) += node.o | 9 | obj-$(CONFIG_NUMA) += node.o |
10 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o | 10 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o |
11 | obj-$(CONFIG_SMP) += topology.o | ||
11 | 12 | ||
12 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | 13 | ifeq ($(CONFIG_DEBUG_DRIVER),y) |
13 | EXTRA_CFLAGS += -DDEBUG | 14 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c new file mode 100644 index 000000000000..915810f6237e --- /dev/null +++ b/drivers/base/topology.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * driver/base/topology.c - Populate sysfs with cpu topology information | ||
3 | * | ||
4 | * Written by: Zhang Yanmin, Intel Corporation | ||
5 | * | ||
6 | * Copyright (C) 2006, Intel Corp. | ||
7 | * | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
19 | * details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | #include <linux/sysdev.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/cpu.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/topology.h> | ||
32 | |||
33 | #define define_one_ro(_name) \ | ||
34 | static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) | ||
35 | |||
36 | #define define_id_show_func(name) \ | ||
37 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | ||
38 | { \ | ||
39 | unsigned int cpu = dev->id; \ | ||
40 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ | ||
41 | } | ||
42 | |||
43 | #define define_siblings_show_func(name) \ | ||
44 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | ||
45 | { \ | ||
46 | ssize_t len = -1; \ | ||
47 | unsigned int cpu = dev->id; \ | ||
48 | len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \ | ||
49 | return (len + sprintf(buf + len, "\n")); \ | ||
50 | } | ||
51 | |||
52 | #ifdef topology_physical_package_id | ||
53 | define_id_show_func(physical_package_id); | ||
54 | define_one_ro(physical_package_id); | ||
55 | #define ref_physical_package_id_attr &attr_physical_package_id.attr, | ||
56 | #else | ||
57 | #define ref_physical_package_id_attr | ||
58 | #endif | ||
59 | |||
60 | #ifdef topology_core_id | ||
61 | define_id_show_func(core_id); | ||
62 | define_one_ro(core_id); | ||
63 | #define ref_core_id_attr &attr_core_id.attr, | ||
64 | #else | ||
65 | #define ref_core_id_attr | ||
66 | #endif | ||
67 | |||
68 | #ifdef topology_thread_siblings | ||
69 | define_siblings_show_func(thread_siblings); | ||
70 | define_one_ro(thread_siblings); | ||
71 | #define ref_thread_siblings_attr &attr_thread_siblings.attr, | ||
72 | #else | ||
73 | #define ref_thread_siblings_attr | ||
74 | #endif | ||
75 | |||
76 | #ifdef topology_core_siblings | ||
77 | define_siblings_show_func(core_siblings); | ||
78 | define_one_ro(core_siblings); | ||
79 | #define ref_core_siblings_attr &attr_core_siblings.attr, | ||
80 | #else | ||
81 | #define ref_core_siblings_attr | ||
82 | #endif | ||
83 | |||
84 | static struct attribute *default_attrs[] = { | ||
85 | ref_physical_package_id_attr | ||
86 | ref_core_id_attr | ||
87 | ref_thread_siblings_attr | ||
88 | ref_core_siblings_attr | ||
89 | NULL | ||
90 | }; | ||
91 | |||
92 | static struct attribute_group topology_attr_group = { | ||
93 | .attrs = default_attrs, | ||
94 | .name = "topology" | ||
95 | }; | ||
96 | |||
97 | /* Add/Remove cpu_topology interface for CPU device */ | ||
98 | static int __cpuinit topology_add_dev(struct sys_device * sys_dev) | ||
99 | { | ||
100 | sysfs_create_group(&sys_dev->kobj, &topology_attr_group); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) | ||
105 | { | ||
106 | sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, | ||
111 | unsigned long action, void *hcpu) | ||
112 | { | ||
113 | unsigned int cpu = (unsigned long)hcpu; | ||
114 | struct sys_device *sys_dev; | ||
115 | |||
116 | sys_dev = get_cpu_sysdev(cpu); | ||
117 | switch (action) { | ||
118 | case CPU_ONLINE: | ||
119 | topology_add_dev(sys_dev); | ||
120 | break; | ||
121 | case CPU_DEAD: | ||
122 | topology_remove_dev(sys_dev); | ||
123 | break; | ||
124 | } | ||
125 | return NOTIFY_OK; | ||
126 | } | ||
127 | |||
128 | static struct notifier_block topology_cpu_notifier = | ||
129 | { | ||
130 | .notifier_call = topology_cpu_callback, | ||
131 | }; | ||
132 | |||
133 | static int __cpuinit topology_sysfs_init(void) | ||
134 | { | ||
135 | int i; | ||
136 | |||
137 | for_each_online_cpu(i) { | ||
138 | topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE, | ||
139 | (void *)(long)i); | ||
140 | } | ||
141 | |||
142 | register_cpu_notifier(&topology_cpu_notifier); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | device_initcall(topology_sysfs_init); | ||
148 | |||