aboutsummaryrefslogtreecommitdiffstats
path: root/mm/percpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/percpu.c')
-rw-r--r--mm/percpu.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/mm/percpu.c b/mm/percpu.c
index 548624309f83..cc9c4c64606d 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -98,7 +98,7 @@ struct pcpu_chunk {
98 int map_used; /* # of map entries used */ 98 int map_used; /* # of map entries used */
99 int map_alloc; /* # of map entries allocated */ 99 int map_alloc; /* # of map entries allocated */
100 int *map; /* allocation map */ 100 int *map; /* allocation map */
101 struct vm_struct *vm; /* mapped vmalloc region */ 101 struct vm_struct **vms; /* mapped vmalloc regions */
102 bool immutable; /* no [de]population allowed */ 102 bool immutable; /* no [de]population allowed */
103 unsigned long populated[]; /* populated bitmap */ 103 unsigned long populated[]; /* populated bitmap */
104}; 104};
@@ -106,7 +106,7 @@ struct pcpu_chunk {
106static int pcpu_unit_pages __read_mostly; 106static int pcpu_unit_pages __read_mostly;
107static int pcpu_unit_size __read_mostly; 107static int pcpu_unit_size __read_mostly;
108static int pcpu_nr_units __read_mostly; 108static int pcpu_nr_units __read_mostly;
109static int pcpu_chunk_size __read_mostly; 109static int pcpu_atom_size __read_mostly;
110static int pcpu_nr_slots __read_mostly; 110static int pcpu_nr_slots __read_mostly;
111static size_t pcpu_chunk_struct_size __read_mostly; 111static size_t pcpu_chunk_struct_size __read_mostly;
112 112
@@ -121,6 +121,11 @@ EXPORT_SYMBOL_GPL(pcpu_base_addr);
121static const int *pcpu_unit_map __read_mostly; /* cpu -> unit */ 121static const int *pcpu_unit_map __read_mostly; /* cpu -> unit */
122const unsigned long *pcpu_unit_offsets __read_mostly; /* cpu -> unit offset */ 122const unsigned long *pcpu_unit_offsets __read_mostly; /* cpu -> unit offset */
123 123
124/* group information, used for vm allocation */
125static int pcpu_nr_groups __read_mostly;
126static const unsigned long *pcpu_group_offsets __read_mostly;
127static const size_t *pcpu_group_sizes __read_mostly;
128
124/* 129/*
125 * The first chunk which always exists. Note that unlike other 130 * The first chunk which always exists. Note that unlike other
126 * chunks, this one can be allocated and mapped in several different 131 * chunks, this one can be allocated and mapped in several different
@@ -988,8 +993,8 @@ static void free_pcpu_chunk(struct pcpu_chunk *chunk)
988{ 993{
989 if (!chunk) 994 if (!chunk)
990 return; 995 return;
991 if (chunk->vm) 996 if (chunk->vms)
992 free_vm_area(chunk->vm); 997 pcpu_free_vm_areas(chunk->vms, pcpu_nr_groups);
993 pcpu_mem_free(chunk->map, chunk->map_alloc * sizeof(chunk->map[0])); 998 pcpu_mem_free(chunk->map, chunk->map_alloc * sizeof(chunk->map[0]));
994 kfree(chunk); 999 kfree(chunk);
995} 1000}
@@ -1006,8 +1011,10 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void)
1006 chunk->map_alloc = PCPU_DFL_MAP_ALLOC; 1011 chunk->map_alloc = PCPU_DFL_MAP_ALLOC;
1007 chunk->map[chunk->map_used++] = pcpu_unit_size; 1012 chunk->map[chunk->map_used++] = pcpu_unit_size;
1008 1013
1009 chunk->vm = get_vm_area(pcpu_chunk_size, VM_ALLOC); 1014 chunk->vms = pcpu_get_vm_areas(pcpu_group_offsets, pcpu_group_sizes,
1010 if (!chunk->vm) { 1015 pcpu_nr_groups, pcpu_atom_size,
1016 GFP_KERNEL);
1017 if (!chunk->vms) {
1011 free_pcpu_chunk(chunk); 1018 free_pcpu_chunk(chunk);
1012 return NULL; 1019 return NULL;
1013 } 1020 }
@@ -1015,7 +1022,7 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void)
1015 INIT_LIST_HEAD(&chunk->list); 1022 INIT_LIST_HEAD(&chunk->list);
1016 chunk->free_size = pcpu_unit_size; 1023 chunk->free_size = pcpu_unit_size;
1017 chunk->contig_hint = pcpu_unit_size; 1024 chunk->contig_hint = pcpu_unit_size;
1018 chunk->base_addr = chunk->vm->addr; 1025 chunk->base_addr = chunk->vms[0]->addr - pcpu_group_offsets[0];
1019 1026
1020 return chunk; 1027 return chunk;
1021} 1028}
@@ -1571,6 +1578,8 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1571 size_t dyn_size = ai->dyn_size; 1578 size_t dyn_size = ai->dyn_size;
1572 size_t size_sum = ai->static_size + ai->reserved_size + dyn_size; 1579 size_t size_sum = ai->static_size + ai->reserved_size + dyn_size;
1573 struct pcpu_chunk *schunk, *dchunk = NULL; 1580 struct pcpu_chunk *schunk, *dchunk = NULL;
1581 unsigned long *group_offsets;
1582 size_t *group_sizes;
1574 unsigned long *unit_off; 1583 unsigned long *unit_off;
1575 unsigned int cpu; 1584 unsigned int cpu;
1576 int *unit_map; 1585 int *unit_map;
@@ -1588,7 +1597,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1588 1597
1589 pcpu_dump_alloc_info(KERN_DEBUG, ai); 1598 pcpu_dump_alloc_info(KERN_DEBUG, ai);
1590 1599
1591 /* determine number of units and initialize unit_map and base */ 1600 /* process group information and build config tables accordingly */
1601 group_offsets = alloc_bootmem(ai->nr_groups * sizeof(group_offsets[0]));
1602 group_sizes = alloc_bootmem(ai->nr_groups * sizeof(group_sizes[0]));
1592 unit_map = alloc_bootmem(nr_cpu_ids * sizeof(unit_map[0])); 1603 unit_map = alloc_bootmem(nr_cpu_ids * sizeof(unit_map[0]));
1593 unit_off = alloc_bootmem(nr_cpu_ids * sizeof(unit_off[0])); 1604 unit_off = alloc_bootmem(nr_cpu_ids * sizeof(unit_off[0]));
1594 1605
@@ -1599,6 +1610,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1599 for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) { 1610 for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
1600 const struct pcpu_group_info *gi = &ai->groups[group]; 1611 const struct pcpu_group_info *gi = &ai->groups[group];
1601 1612
1613 group_offsets[group] = gi->base_offset;
1614 group_sizes[group] = gi->nr_units * ai->unit_size;
1615
1602 for (i = 0; i < gi->nr_units; i++) { 1616 for (i = 0; i < gi->nr_units; i++) {
1603 cpu = gi->cpu_map[i]; 1617 cpu = gi->cpu_map[i];
1604 if (cpu == NR_CPUS) 1618 if (cpu == NR_CPUS)
@@ -1620,13 +1634,16 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1620 for_each_possible_cpu(cpu) 1634 for_each_possible_cpu(cpu)
1621 BUG_ON(unit_map[cpu] == NR_CPUS); 1635 BUG_ON(unit_map[cpu] == NR_CPUS);
1622 1636
1637 pcpu_nr_groups = ai->nr_groups;
1638 pcpu_group_offsets = group_offsets;
1639 pcpu_group_sizes = group_sizes;
1623 pcpu_unit_map = unit_map; 1640 pcpu_unit_map = unit_map;
1624 pcpu_unit_offsets = unit_off; 1641 pcpu_unit_offsets = unit_off;
1625 1642
1626 /* determine basic parameters */ 1643 /* determine basic parameters */
1627 pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT; 1644 pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT;
1628 pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT; 1645 pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
1629 pcpu_chunk_size = pcpu_nr_units * pcpu_unit_size; 1646 pcpu_atom_size = ai->atom_size;
1630 pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) + 1647 pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) +
1631 BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long); 1648 BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long);
1632 1649