Commit | Line | Data |
---|---|---|
989d42e8 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
69dcc991 ZY |
2 | /* |
3 | * driver/base/topology.c - Populate sysfs with cpu topology information | |
4 | * | |
5 | * Written by: Zhang Yanmin, Intel Corporation | |
6 | * | |
7 | * Copyright (C) 2006, Intel Corp. | |
8 | * | |
9 | * All rights reserved. | |
69dcc991 | 10 | */ |
69dcc991 ZY |
11 | #include <linux/mm.h> |
12 | #include <linux/cpu.h> | |
13 | #include <linux/module.h> | |
b13d3720 | 14 | #include <linux/hardirq.h> |
69dcc991 ZY |
15 | #include <linux/topology.h> |
16 | ||
182ecfaf | 17 | #define define_id_show_func(name, fmt) \ |
948b3edb JP |
18 | static ssize_t name##_show(struct device *dev, \ |
19 | struct device_attribute *attr, char *buf) \ | |
20 | { \ | |
182ecfaf | 21 | return sysfs_emit(buf, fmt "\n", topology_##name(dev->id)); \ |
69dcc991 ZY |
22 | } |
23 | ||
bb9ec13d TT |
24 | #define define_siblings_read_func(name, mask) \ |
25 | static ssize_t name##_read(struct file *file, struct kobject *kobj, \ | |
26 | struct bin_attribute *attr, char *buf, \ | |
27 | loff_t off, size_t count) \ | |
28 | { \ | |
29 | struct device *dev = kobj_to_dev(kobj); \ | |
30 | \ | |
31 | return cpumap_print_bitmask_to_buf(buf, topology_##mask(dev->id), \ | |
32 | off, count); \ | |
33 | } \ | |
34 | \ | |
35 | static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \ | |
36 | struct bin_attribute *attr, char *buf, \ | |
37 | loff_t off, size_t count) \ | |
38 | { \ | |
39 | struct device *dev = kobj_to_dev(kobj); \ | |
40 | \ | |
41 | return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \ | |
42 | off, count); \ | |
23ca4bba MT |
43 | } |
44 | ||
182ecfaf | 45 | define_id_show_func(physical_package_id, "%d"); |
d6ea8d01 | 46 | static DEVICE_ATTR_RO(physical_package_id); |
69dcc991 | 47 | |
2c4dcd7f | 48 | #ifdef TOPOLOGY_DIE_SYSFS |
182ecfaf | 49 | define_id_show_func(die_id, "%d"); |
0e344d8c | 50 | static DEVICE_ATTR_RO(die_id); |
2c4dcd7f | 51 | #endif |
0e344d8c | 52 | |
e7957077 | 53 | #ifdef TOPOLOGY_CLUSTER_SYSFS |
182ecfaf | 54 | define_id_show_func(cluster_id, "%d"); |
c5e22fef | 55 | static DEVICE_ATTR_RO(cluster_id); |
e7957077 | 56 | #endif |
c5e22fef | 57 | |
182ecfaf | 58 | define_id_show_func(core_id, "%d"); |
d6ea8d01 | 59 | static DEVICE_ATTR_RO(core_id); |
69dcc991 | 60 | |
ab28e944 TL |
61 | define_id_show_func(ppin, "0x%llx"); |
62 | static DEVICE_ATTR_ADMIN_RO(ppin); | |
63 | ||
bb9ec13d TT |
64 | define_siblings_read_func(thread_siblings, sibling_cpumask); |
65 | static BIN_ATTR_RO(thread_siblings, 0); | |
66 | static BIN_ATTR_RO(thread_siblings_list, 0); | |
69dcc991 | 67 | |
bb9ec13d TT |
68 | define_siblings_read_func(core_cpus, sibling_cpumask); |
69 | static BIN_ATTR_RO(core_cpus, 0); | |
70 | static BIN_ATTR_RO(core_cpus_list, 0); | |
2e4c54da | 71 | |
bb9ec13d TT |
72 | define_siblings_read_func(core_siblings, core_cpumask); |
73 | static BIN_ATTR_RO(core_siblings, 0); | |
74 | static BIN_ATTR_RO(core_siblings_list, 0); | |
69dcc991 | 75 | |
e7957077 | 76 | #ifdef TOPOLOGY_CLUSTER_SYSFS |
c5e22fef JC |
77 | define_siblings_read_func(cluster_cpus, cluster_cpumask); |
78 | static BIN_ATTR_RO(cluster_cpus, 0); | |
79 | static BIN_ATTR_RO(cluster_cpus_list, 0); | |
e7957077 | 80 | #endif |
c5e22fef | 81 | |
2c4dcd7f | 82 | #ifdef TOPOLOGY_DIE_SYSFS |
bb9ec13d TT |
83 | define_siblings_read_func(die_cpus, die_cpumask); |
84 | static BIN_ATTR_RO(die_cpus, 0); | |
85 | static BIN_ATTR_RO(die_cpus_list, 0); | |
2c4dcd7f | 86 | #endif |
2e4c54da | 87 | |
bb9ec13d TT |
88 | define_siblings_read_func(package_cpus, core_cpumask); |
89 | static BIN_ATTR_RO(package_cpus, 0); | |
90 | static BIN_ATTR_RO(package_cpus_list, 0); | |
b73ed8dc | 91 | |
f1045056 | 92 | #ifdef TOPOLOGY_BOOK_SYSFS |
182ecfaf | 93 | define_id_show_func(book_id, "%d"); |
d6ea8d01 | 94 | static DEVICE_ATTR_RO(book_id); |
bb9ec13d TT |
95 | define_siblings_read_func(book_siblings, book_cpumask); |
96 | static BIN_ATTR_RO(book_siblings, 0); | |
97 | static BIN_ATTR_RO(book_siblings_list, 0); | |
b40d8ed4 HC |
98 | #endif |
99 | ||
f1045056 | 100 | #ifdef TOPOLOGY_DRAWER_SYSFS |
182ecfaf | 101 | define_id_show_func(drawer_id, "%d"); |
a62247e1 | 102 | static DEVICE_ATTR_RO(drawer_id); |
bb9ec13d TT |
103 | define_siblings_read_func(drawer_siblings, drawer_cpumask); |
104 | static BIN_ATTR_RO(drawer_siblings, 0); | |
105 | static BIN_ATTR_RO(drawer_siblings_list, 0); | |
a62247e1 HC |
106 | #endif |
107 | ||
bb9ec13d TT |
108 | static struct bin_attribute *bin_attrs[] = { |
109 | &bin_attr_core_cpus, | |
110 | &bin_attr_core_cpus_list, | |
111 | &bin_attr_thread_siblings, | |
112 | &bin_attr_thread_siblings_list, | |
113 | &bin_attr_core_siblings, | |
114 | &bin_attr_core_siblings_list, | |
e7957077 | 115 | #ifdef TOPOLOGY_CLUSTER_SYSFS |
c5e22fef JC |
116 | &bin_attr_cluster_cpus, |
117 | &bin_attr_cluster_cpus_list, | |
e7957077 | 118 | #endif |
2c4dcd7f | 119 | #ifdef TOPOLOGY_DIE_SYSFS |
bb9ec13d TT |
120 | &bin_attr_die_cpus, |
121 | &bin_attr_die_cpus_list, | |
2c4dcd7f | 122 | #endif |
bb9ec13d TT |
123 | &bin_attr_package_cpus, |
124 | &bin_attr_package_cpus_list, | |
f1045056 | 125 | #ifdef TOPOLOGY_BOOK_SYSFS |
bb9ec13d TT |
126 | &bin_attr_book_siblings, |
127 | &bin_attr_book_siblings_list, | |
128 | #endif | |
f1045056 | 129 | #ifdef TOPOLOGY_DRAWER_SYSFS |
bb9ec13d TT |
130 | &bin_attr_drawer_siblings, |
131 | &bin_attr_drawer_siblings_list, | |
132 | #endif | |
133 | NULL | |
134 | }; | |
135 | ||
69dcc991 | 136 | static struct attribute *default_attrs[] = { |
8a25a2fd | 137 | &dev_attr_physical_package_id.attr, |
2c4dcd7f | 138 | #ifdef TOPOLOGY_DIE_SYSFS |
0e344d8c | 139 | &dev_attr_die_id.attr, |
2c4dcd7f | 140 | #endif |
e7957077 | 141 | #ifdef TOPOLOGY_CLUSTER_SYSFS |
c5e22fef | 142 | &dev_attr_cluster_id.attr, |
e7957077 | 143 | #endif |
8a25a2fd | 144 | &dev_attr_core_id.attr, |
f1045056 | 145 | #ifdef TOPOLOGY_BOOK_SYSFS |
8a25a2fd | 146 | &dev_attr_book_id.attr, |
a62247e1 | 147 | #endif |
f1045056 | 148 | #ifdef TOPOLOGY_DRAWER_SYSFS |
a62247e1 | 149 | &dev_attr_drawer_id.attr, |
b40d8ed4 | 150 | #endif |
ab28e944 | 151 | &dev_attr_ppin.attr, |
69dcc991 ZY |
152 | NULL |
153 | }; | |
154 | ||
aa63a74d TL |
155 | static umode_t topology_is_visible(struct kobject *kobj, |
156 | struct attribute *attr, int unused) | |
157 | { | |
c95ce3a2 | 158 | if (attr == &dev_attr_ppin.attr && !topology_ppin(kobj_to_dev(kobj)->id)) |
aa63a74d TL |
159 | return 0; |
160 | ||
161 | return attr->mode; | |
162 | } | |
163 | ||
df44d30d | 164 | static const struct attribute_group topology_attr_group = { |
69dcc991 | 165 | .attrs = default_attrs, |
bb9ec13d | 166 | .bin_attrs = bin_attrs, |
aa63a74d | 167 | .is_visible = topology_is_visible, |
69dcc991 ZY |
168 | .name = "topology" |
169 | }; | |
170 | ||
171 | /* Add/Remove cpu_topology interface for CPU device */ | |
a83048eb | 172 | static int topology_add_dev(unsigned int cpu) |
69dcc991 | 173 | { |
8a25a2fd | 174 | struct device *dev = get_cpu_device(cpu); |
06a4bcae | 175 | |
8a25a2fd | 176 | return sysfs_create_group(&dev->kobj, &topology_attr_group); |
69dcc991 ZY |
177 | } |
178 | ||
38643a0e | 179 | static int topology_remove_dev(unsigned int cpu) |
69dcc991 | 180 | { |
8a25a2fd | 181 | struct device *dev = get_cpu_device(cpu); |
06a4bcae | 182 | |
8a25a2fd | 183 | sysfs_remove_group(&dev->kobj, &topology_attr_group); |
38643a0e | 184 | return 0; |
69dcc991 | 185 | } |
69dcc991 | 186 | |
0d989da3 | 187 | static int __init topology_sysfs_init(void) |
69dcc991 | 188 | { |
38643a0e SAS |
189 | return cpuhp_setup_state(CPUHP_TOPOLOGY_PREPARE, |
190 | "base/topology:prepare", topology_add_dev, | |
191 | topology_remove_dev); | |
69dcc991 ZY |
192 | } |
193 | ||
194 | device_initcall(topology_sysfs_init); |