|
@@ -1786,7 +1786,7 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, ssize_t dyn_size,
|
|
void *base = (void *)ULONG_MAX;
|
|
void *base = (void *)ULONG_MAX;
|
|
void **areas = NULL;
|
|
void **areas = NULL;
|
|
struct pcpu_alloc_info *ai;
|
|
struct pcpu_alloc_info *ai;
|
|
- size_t size_sum, areas_size;
|
|
|
|
|
|
+ size_t size_sum, areas_size, max_distance;
|
|
int group, i, rc;
|
|
int group, i, rc;
|
|
|
|
|
|
ai = pcpu_build_alloc_info(reserved_size, dyn_size, atom_size,
|
|
ai = pcpu_build_alloc_info(reserved_size, dyn_size, atom_size,
|
|
@@ -1836,8 +1836,24 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, ssize_t dyn_size,
|
|
}
|
|
}
|
|
|
|
|
|
/* base address is now known, determine group base offsets */
|
|
/* base address is now known, determine group base offsets */
|
|
- for (group = 0; group < ai->nr_groups; group++)
|
|
|
|
|
|
+ max_distance = 0;
|
|
|
|
+ for (group = 0; group < ai->nr_groups; group++) {
|
|
ai->groups[group].base_offset = areas[group] - base;
|
|
ai->groups[group].base_offset = areas[group] - base;
|
|
|
|
+ max_distance = max(max_distance, ai->groups[group].base_offset);
|
|
|
|
+ }
|
|
|
|
+ max_distance += ai->unit_size;
|
|
|
|
+
|
|
|
|
+ /* warn if maximum distance is further than 75% of vmalloc space */
|
|
|
|
+ if (max_distance > (VMALLOC_END - VMALLOC_START) * 3 / 4) {
|
|
|
|
+ pr_warning("PERCPU: max_distance=0x%lx too large for vmalloc "
|
|
|
|
+ "space 0x%lx\n",
|
|
|
|
+ max_distance, VMALLOC_END - VMALLOC_START);
|
|
|
|
+#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
|
|
|
|
+ /* and fail if we have fallback */
|
|
|
|
+ rc = -EINVAL;
|
|
|
|
+ goto out_free;
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
|
|
pr_info("PERCPU: Embedded %zu pages/cpu @%p s%zu r%zu d%zu u%zu\n",
|
|
pr_info("PERCPU: Embedded %zu pages/cpu @%p s%zu r%zu d%zu u%zu\n",
|
|
PFN_DOWN(size_sum), base, ai->static_size, ai->reserved_size,
|
|
PFN_DOWN(size_sum), base, ai->static_size, ai->reserved_size,
|