1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/types.h>
3 #include <linux/nodemask.h>
4 #include <linux/slab.h>
5 #include <linux/lockdep.h>
6 #include <linux/memory-tiers.h>
9 /* hierarchy of memory tiers */
10 struct list_head list;
11 /* list of all memory types part of this tier */
12 struct list_head memory_types;
14 * start value of abstract distance. memory tier maps
15 * an abstract distance range,
16 * adistance_start .. adistance_start + MEMTIER_CHUNK_SIZE
21 struct memory_dev_type {
22 /* list of memory types that are part of same tier as this type */
23 struct list_head tier_sibiling;
24 /* abstract distance for this specific memory type */
26 /* Nodes of same abstract distance */
28 struct memory_tier *memtier;
31 static DEFINE_MUTEX(memory_tier_lock);
32 static LIST_HEAD(memory_tiers);
33 static struct memory_dev_type *node_memory_types[MAX_NUMNODES];
35 * For now we can have 4 faster memory tiers with smaller adistance
36 * than default DRAM tier.
38 static struct memory_dev_type default_dram_type = {
39 .adistance = MEMTIER_ADISTANCE_DRAM,
40 .tier_sibiling = LIST_HEAD_INIT(default_dram_type.tier_sibiling),
43 static struct memory_tier *find_create_memory_tier(struct memory_dev_type *memtype)
45 bool found_slot = false;
46 struct memory_tier *memtier, *new_memtier;
47 int adistance = memtype->adistance;
48 unsigned int memtier_adistance_chunk_size = MEMTIER_CHUNK_SIZE;
50 lockdep_assert_held_once(&memory_tier_lock);
53 * If the memtype is already part of a memory tier,
57 return memtype->memtier;
59 adistance = round_down(adistance, memtier_adistance_chunk_size);
60 list_for_each_entry(memtier, &memory_tiers, list) {
61 if (adistance == memtier->adistance_start) {
62 memtype->memtier = memtier;
63 list_add(&memtype->tier_sibiling, &memtier->memory_types);
65 } else if (adistance < memtier->adistance_start) {
71 new_memtier = kmalloc(sizeof(struct memory_tier), GFP_KERNEL);
73 return ERR_PTR(-ENOMEM);
75 new_memtier->adistance_start = adistance;
76 INIT_LIST_HEAD(&new_memtier->list);
77 INIT_LIST_HEAD(&new_memtier->memory_types);
79 list_add_tail(&new_memtier->list, &memtier->list);
81 list_add_tail(&new_memtier->list, &memory_tiers);
82 memtype->memtier = new_memtier;
83 list_add(&memtype->tier_sibiling, &new_memtier->memory_types);
87 static struct memory_tier *set_node_memory_tier(int node)
89 struct memory_tier *memtier;
90 struct memory_dev_type *memtype;
92 lockdep_assert_held_once(&memory_tier_lock);
94 if (!node_state(node, N_MEMORY))
95 return ERR_PTR(-EINVAL);
97 if (!node_memory_types[node])
98 node_memory_types[node] = &default_dram_type;
100 memtype = node_memory_types[node];
101 node_set(node, memtype->nodes);
102 memtier = find_create_memory_tier(memtype);
106 static int __init memory_tier_init(void)
109 struct memory_tier *memtier;
111 mutex_lock(&memory_tier_lock);
113 * Look at all the existing N_MEMORY nodes and add them to
114 * default memory tier or to a tier if we already have memory
117 for_each_node_state(node, N_MEMORY) {
118 memtier = set_node_memory_tier(node);
121 * Continue with memtiers we are able to setup
125 mutex_unlock(&memory_tier_lock);
129 subsys_initcall(memory_tier_init);