1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * include/linux/node.h - generic node definition |
4 | * |
5 | * This is mainly for topological representation. We define the |
6 | * basic 'struct node' here, which can be embedded in per-arch |
7 | * definitions of processors. |
8 | * |
9 | * Basic handling of the devices is done in drivers/base/node.c |
10 | * and system devices are handled in drivers/base/sys.c. |
11 | * |
12 | * Nodes are exported via driverfs in the class/node/devices/ |
13 | * directory. |
14 | */ |
15 | #ifndef _LINUX_NODE_H_ |
16 | #define _LINUX_NODE_H_ |
17 | |
18 | #include <linux/device.h> |
19 | #include <linux/cpumask.h> |
20 | #include <linux/list.h> |
21 | |
22 | /** |
23 | * struct access_coordinate - generic performance coordinates container |
24 | * |
25 | * @read_bandwidth: Read bandwidth in MB/s |
26 | * @write_bandwidth: Write bandwidth in MB/s |
27 | * @read_latency: Read latency in nanoseconds |
28 | * @write_latency: Write latency in nanoseconds |
29 | */ |
30 | struct access_coordinate { |
31 | unsigned int read_bandwidth; |
32 | unsigned int write_bandwidth; |
33 | unsigned int read_latency; |
34 | unsigned int write_latency; |
35 | }; |
36 | |
37 | /* |
38 | * ACCESS_COORDINATE_LOCAL correlates to ACCESS CLASS 0 |
39 | * - access_coordinate between target node and nearest initiator node |
40 | * ACCESS_COORDINATE_CPU correlates to ACCESS CLASS 1 |
41 | * - access_coordinate between target node and nearest CPU node |
42 | */ |
43 | enum access_coordinate_class { |
44 | ACCESS_COORDINATE_LOCAL, |
45 | ACCESS_COORDINATE_CPU, |
46 | ACCESS_COORDINATE_MAX |
47 | }; |
48 | |
49 | enum cache_indexing { |
50 | NODE_CACHE_DIRECT_MAP, |
51 | NODE_CACHE_INDEXED, |
52 | NODE_CACHE_OTHER, |
53 | }; |
54 | |
55 | enum cache_write_policy { |
56 | NODE_CACHE_WRITE_BACK, |
57 | NODE_CACHE_WRITE_THROUGH, |
58 | NODE_CACHE_WRITE_OTHER, |
59 | }; |
60 | |
61 | /** |
62 | * struct node_cache_attrs - system memory caching attributes |
63 | * |
64 | * @indexing: The ways memory blocks may be placed in cache |
65 | * @write_policy: Write back or write through policy |
66 | * @size: Total size of cache in bytes |
67 | * @line_size: Number of bytes fetched on a cache miss |
68 | * @level: The cache hierarchy level |
69 | */ |
70 | struct node_cache_attrs { |
71 | enum cache_indexing indexing; |
72 | enum cache_write_policy write_policy; |
73 | u64 size; |
74 | u16 line_size; |
75 | u8 level; |
76 | }; |
77 | |
78 | #ifdef CONFIG_HMEM_REPORTING |
79 | void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs); |
80 | void node_set_perf_attrs(unsigned int nid, struct access_coordinate *coord, |
81 | enum access_coordinate_class access); |
82 | #else |
83 | static inline void node_add_cache(unsigned int nid, |
84 | struct node_cache_attrs *cache_attrs) |
85 | { |
86 | } |
87 | |
88 | static inline void node_set_perf_attrs(unsigned int nid, |
89 | struct access_coordinate *coord, |
90 | enum access_coordinate_class access) |
91 | { |
92 | } |
93 | #endif |
94 | |
95 | struct node { |
96 | struct device dev; |
97 | struct list_head access_list; |
98 | #ifdef CONFIG_HMEM_REPORTING |
99 | struct list_head cache_attrs; |
100 | struct device *cache_dev; |
101 | #endif |
102 | }; |
103 | |
104 | struct memory_block; |
105 | extern struct node *node_devices[]; |
106 | |
107 | #if defined(CONFIG_MEMORY_HOTPLUG) && defined(CONFIG_NUMA) |
108 | void register_memory_blocks_under_node(int nid, unsigned long start_pfn, |
109 | unsigned long end_pfn, |
110 | enum meminit_context context); |
111 | #else |
112 | static inline void register_memory_blocks_under_node(int nid, unsigned long start_pfn, |
113 | unsigned long end_pfn, |
114 | enum meminit_context context) |
115 | { |
116 | } |
117 | #endif |
118 | |
119 | extern void unregister_node(struct node *node); |
120 | #ifdef CONFIG_NUMA |
121 | extern void node_dev_init(void); |
122 | /* Core of the node registration - only memory hotplug should use this */ |
123 | extern int __register_one_node(int nid); |
124 | |
125 | /* Registers an online node */ |
126 | static inline int register_one_node(int nid) |
127 | { |
128 | int error = 0; |
129 | |
130 | if (node_online(nid)) { |
131 | struct pglist_data *pgdat = NODE_DATA(nid); |
132 | unsigned long start_pfn = pgdat->node_start_pfn; |
133 | unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages; |
134 | |
135 | error = __register_one_node(nid); |
136 | if (error) |
137 | return error; |
138 | register_memory_blocks_under_node(nid, start_pfn, end_pfn, |
139 | context: MEMINIT_EARLY); |
140 | } |
141 | |
142 | return error; |
143 | } |
144 | |
145 | extern void unregister_one_node(int nid); |
146 | extern int register_cpu_under_node(unsigned int cpu, unsigned int nid); |
147 | extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid); |
148 | extern void unregister_memory_block_under_nodes(struct memory_block *mem_blk); |
149 | |
150 | extern int register_memory_node_under_compute_node(unsigned int mem_nid, |
151 | unsigned int cpu_nid, |
152 | enum access_coordinate_class access); |
153 | #else |
154 | static inline void node_dev_init(void) |
155 | { |
156 | } |
157 | static inline int __register_one_node(int nid) |
158 | { |
159 | return 0; |
160 | } |
161 | static inline int register_one_node(int nid) |
162 | { |
163 | return 0; |
164 | } |
165 | static inline int unregister_one_node(int nid) |
166 | { |
167 | return 0; |
168 | } |
169 | static inline int register_cpu_under_node(unsigned int cpu, unsigned int nid) |
170 | { |
171 | return 0; |
172 | } |
173 | static inline int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) |
174 | { |
175 | return 0; |
176 | } |
177 | static inline void unregister_memory_block_under_nodes(struct memory_block *mem_blk) |
178 | { |
179 | } |
180 | #endif |
181 | |
182 | #define to_node(device) container_of(device, struct node, dev) |
183 | |
184 | #endif /* _LINUX_NODE_H_ */ |
185 | |