diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 29ba94efcd925ac498c460e26be93e37decff8eb..2156f71a4745b37bb1fb1e621b7941bd930c0e9f 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -37,6 +37,13 @@ static int numa_distance_cnt; static u8 *numa_distance; bool numa_off; +#ifdef CONFIG_COHERENT_DEVICE +inline int arch_check_node_cdm(int nid) +{ + return 0; +} +#endif + static __init int numa_parse_early_param(char *opt) { if (!opt) diff --git a/drivers/base/node.c b/drivers/base/node.c index c3968e2d0a98a8b788d47776b9942d32ad274f42..e6b0060cc27389949b156c1438948e60e7b6c891 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -634,6 +634,9 @@ static struct node_attr node_state_attr[] = { #endif [N_MEMORY] = _NODE_ATTR(has_memory, N_MEMORY), [N_CPU] = _NODE_ATTR(has_cpu, N_CPU), +#ifdef CONFIG_COHERENT_DEVICE + [N_COHERENT_DEVICE] = _NODE_ATTR(is_cdm_node, N_COHERENT_DEVICE), +#endif }; static struct attribute *node_state_attrs[] = { @@ -645,6 +648,9 @@ static struct attribute *node_state_attrs[] = { #endif &node_state_attr[N_MEMORY].attr.attr, &node_state_attr[N_CPU].attr.attr, +#ifdef CONFIG_COHERENT_DEVICE + &node_state_attr[N_COHERENT_DEVICE].attr.attr, +#endif NULL }; diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 5a30ad594ccc11d40879ec8438b587f519b5c791..41fb047bdba805da9231f415e268ecd89c90ac9f 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -397,8 +397,11 @@ enum node_states { #else N_HIGH_MEMORY = N_NORMAL_MEMORY, #endif - N_MEMORY, /* The node has memory(regular, high, movable) */ + N_MEMORY, /* The node has memory(regular, high, movable, cdm) */ N_CPU, /* The node has one or more cpus */ +#ifdef CONFIG_COHERENT_DEVICE + N_COHERENT_DEVICE, /* The node has CDM memory */ +#endif NR_NODE_STATES }; @@ -502,6 +505,77 @@ static inline int node_random(const nodemask_t *mask) } #endif +#ifdef CONFIG_COHERENT_DEVICE +extern int arch_check_node_cdm(int nid); + +static inline nodemask_t system_mem_nodemask(void) +{ + nodemask_t system_mem; + + nodes_clear(system_mem); + nodes_andnot(system_mem, node_states[N_MEMORY], + node_states[N_COHERENT_DEVICE]); + return system_mem; +} + +static inline bool is_cdm_node(int node) +{ + return node_isset(node, node_states[N_COHERENT_DEVICE]); +} + +static inline bool nodemask_has_cdm(nodemask_t mask) +{ + int node, i; + + node = first_node(mask); + for (i = 0; i < nodes_weight(mask); i++) { + if (is_cdm_node(node)) + return true; + node = next_node(node, mask); + } + return false; +} + +static inline void node_set_state_cdm(int node) +{ + if (arch_check_node_cdm(node)) + node_set_state(node, N_COHERENT_DEVICE); +} + +static inline void node_clear_state_cdm(int node) +{ + if (arch_check_node_cdm(node)) + node_clear_state(node, N_COHERENT_DEVICE); +} + +#else + +static inline int arch_check_node_cdm(int nid) { return 0; } + +static inline nodemask_t system_mem_nodemask(void) +{ + return node_states[N_MEMORY]; +} + +static inline bool is_cdm_node(int node) +{ + return false; +} + +static inline bool nodemask_has_cdm(nodemask_t mask) +{ + return false; +} + +static inline void node_set_state_cdm(int node) +{ +} + +static inline void node_clear_state_cdm(int node) +{ +} +#endif /* CONFIG_COHERENT_DEVICE */ + #define node_online_map node_states[N_ONLINE] #define node_possible_map node_states[N_POSSIBLE] diff --git a/mm/Kconfig b/mm/Kconfig index aba6e953d3976b22c2d9d21b3aec23cdbc39947a..114d78e74ed37ce81bc41d4f48c8f8b7820f1073 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -142,6 +142,14 @@ config HAVE_GENERIC_GUP config ARCH_DISCARD_MEMBLOCK bool +config COHERENT_DEVICE + bool "coherent device memory" + def_bool n + depends on CPUSETS && ARM64 + help + Enable coherent device memory (CDM) support. + + config NO_BOOTMEM bool diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7cae100adb5f57f2b3b3c6bd85178874ec044dee..0b27d786982d9bd2639c887b0991f0070585e650 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6600,8 +6600,10 @@ static unsigned long __init early_calculate_totalpages(void) unsigned long pages = end_pfn - start_pfn; totalpages += pages; - if (pages) + if (pages) { + node_set_state_cdm(nid); node_set_state(nid, N_MEMORY); + } } return totalpages; } @@ -6922,8 +6924,10 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) find_min_pfn_for_node(nid), NULL); /* Any memory on that node */ - if (pgdat->node_present_pages) + if (pgdat->node_present_pages) { + node_set_state_cdm(nid); node_set_state(nid, N_MEMORY); + } check_for_memory(pgdat, nid); } }