aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-08-14 02:00:51 -0400
committerTejun Heo <tj@kernel.org>2009-08-14 02:00:51 -0400
commitfb435d5233f8b6f9b93c11d6304d8e98fed03234 (patch)
tree76a210c3895b9db5dc7e1f185ee0a60744fef99a /arch
parentfd1e8a1fe2b54df6c185b4fa65f181f50b9c4d4e (diff)
percpu: add pcpu_unit_offsets[]
Currently units are mapped sequentially into address space. This patch adds pcpu_unit_offsets[] which allows units to be mapped to arbitrary offsets from the chunk base address. This is necessary to allow sparse embedding which might would need to allocate address ranges and memory areas which aren't aligned to unit size but allocation atom size (page or large page size). This also simplifies things a bit by removing the need to calculate offset from unit number. With this change, there's no need for the arch code to know pcpu_unit_size. Update pcpu_setup_first_chunk() and first chunk allocators to return regular 0 or -errno return code instead of unit size or -errno. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/kernel/smp_64.c12
-rw-r--r--arch/x86/kernel/setup_percpu.c51
2 files changed, 30 insertions, 33 deletions
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index a42a4a744d14..b03fd362c629 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1478,9 +1478,10 @@ void __init setup_per_cpu_areas(void)
1478 static struct vm_struct vm; 1478 static struct vm_struct vm;
1479 struct pcpu_alloc_info *ai; 1479 struct pcpu_alloc_info *ai;
1480 unsigned long delta, cpu; 1480 unsigned long delta, cpu;
1481 size_t size_sum, pcpu_unit_size; 1481 size_t size_sum;
1482 size_t ptrs_size; 1482 size_t ptrs_size;
1483 void **ptrs; 1483 void **ptrs;
1484 int rc;
1484 1485
1485 ai = pcpu_alloc_alloc_info(1, nr_cpu_ids); 1486 ai = pcpu_alloc_alloc_info(1, nr_cpu_ids);
1486 1487
@@ -1526,14 +1527,15 @@ void __init setup_per_cpu_areas(void)
1526 pcpu_map_range(start, end, virt_to_page(ptrs[cpu])); 1527 pcpu_map_range(start, end, virt_to_page(ptrs[cpu]));
1527 } 1528 }
1528 1529
1529 pcpu_unit_size = pcpu_setup_first_chunk(ai, vm.addr); 1530 rc = pcpu_setup_first_chunk(ai, vm.addr);
1531 if (rc)
1532 panic("failed to setup percpu first chunk (%d)", rc);
1530 1533
1531 free_bootmem(__pa(ptrs), ptrs_size); 1534 free_bootmem(__pa(ptrs), ptrs_size);
1532 1535
1533 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; 1536 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
1534 for_each_possible_cpu(cpu) { 1537 for_each_possible_cpu(cpu)
1535 __per_cpu_offset(cpu) = delta + cpu * pcpu_unit_size; 1538 __per_cpu_offset(cpu) = delta + pcpu_unit_offsets[cpu];
1536 }
1537 1539
1538 /* Setup %g5 for the boot cpu. */ 1540 /* Setup %g5 for the boot cpu. */
1539 __local_per_cpu_offset = __per_cpu_offset(smp_processor_id()); 1541 __local_per_cpu_offset = __per_cpu_offset(smp_processor_id());
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index db5f9c49fec5..9becc5d4b518 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -157,12 +157,12 @@ static int pcpu_lpage_cpu_distance(unsigned int from, unsigned int to)
157 return REMOTE_DISTANCE; 157 return REMOTE_DISTANCE;
158} 158}
159 159
160static ssize_t __init setup_pcpu_lpage(bool chosen) 160static int __init setup_pcpu_lpage(bool chosen)
161{ 161{
162 size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; 162 size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE;
163 size_t dyn_size = reserve - PERCPU_FIRST_CHUNK_RESERVE; 163 size_t dyn_size = reserve - PERCPU_FIRST_CHUNK_RESERVE;
164 struct pcpu_alloc_info *ai; 164 struct pcpu_alloc_info *ai;
165 ssize_t ret; 165 int rc;
166 166
167 /* on non-NUMA, embedding is better */ 167 /* on non-NUMA, embedding is better */
168 if (!chosen && !pcpu_need_numa()) 168 if (!chosen && !pcpu_need_numa())
@@ -196,19 +196,18 @@ static ssize_t __init setup_pcpu_lpage(bool chosen)
196 if (tot_size > vm_size / 5) { 196 if (tot_size > vm_size / 5) {
197 pr_info("PERCPU: too large chunk size %zuMB for " 197 pr_info("PERCPU: too large chunk size %zuMB for "
198 "large page remap\n", tot_size >> 20); 198 "large page remap\n", tot_size >> 20);
199 ret = -EINVAL; 199 rc = -EINVAL;
200 goto out_free; 200 goto out_free;
201 } 201 }
202 } 202 }
203 203
204 ret = pcpu_lpage_first_chunk(ai, pcpu_fc_alloc, pcpu_fc_free, 204 rc = pcpu_lpage_first_chunk(ai, pcpu_fc_alloc, pcpu_fc_free, pcpul_map);
205 pcpul_map);
206out_free: 205out_free:
207 pcpu_free_alloc_info(ai); 206 pcpu_free_alloc_info(ai);
208 return ret; 207 return rc;
209} 208}
210#else 209#else
211static ssize_t __init setup_pcpu_lpage(bool chosen) 210static int __init setup_pcpu_lpage(bool chosen)
212{ 211{
213 return -EINVAL; 212 return -EINVAL;
214} 213}
@@ -222,7 +221,7 @@ static ssize_t __init setup_pcpu_lpage(bool chosen)
222 * mapping so that it can use PMD mapping without additional TLB 221 * mapping so that it can use PMD mapping without additional TLB
223 * pressure. 222 * pressure.
224 */ 223 */
225static ssize_t __init setup_pcpu_embed(bool chosen) 224static int __init setup_pcpu_embed(bool chosen)
226{ 225{
227 size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; 226 size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE;
228 227
@@ -250,7 +249,7 @@ static void __init pcpup_populate_pte(unsigned long addr)
250 populate_extra_pte(addr); 249 populate_extra_pte(addr);
251} 250}
252 251
253static ssize_t __init setup_pcpu_page(void) 252static int __init setup_pcpu_page(void)
254{ 253{
255 return pcpu_page_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, 254 return pcpu_page_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
256 pcpu_fc_alloc, pcpu_fc_free, 255 pcpu_fc_alloc, pcpu_fc_free,
@@ -274,8 +273,7 @@ void __init setup_per_cpu_areas(void)
274{ 273{
275 unsigned int cpu; 274 unsigned int cpu;
276 unsigned long delta; 275 unsigned long delta;
277 size_t pcpu_unit_size; 276 int rc;
278 ssize_t ret;
279 277
280 pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n", 278 pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n",
281 NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids); 279 NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids);
@@ -285,36 +283,33 @@ void __init setup_per_cpu_areas(void)
285 * of large page mappings. Please read comments on top of 283 * of large page mappings. Please read comments on top of
286 * each allocator for details. 284 * each allocator for details.
287 */ 285 */
288 ret = -EINVAL; 286 rc = -EINVAL;
289 if (pcpu_chosen_fc != PCPU_FC_AUTO) { 287 if (pcpu_chosen_fc != PCPU_FC_AUTO) {
290 if (pcpu_chosen_fc != PCPU_FC_PAGE) { 288 if (pcpu_chosen_fc != PCPU_FC_PAGE) {
291 if (pcpu_chosen_fc == PCPU_FC_LPAGE) 289 if (pcpu_chosen_fc == PCPU_FC_LPAGE)
292 ret = setup_pcpu_lpage(true); 290 rc = setup_pcpu_lpage(true);
293 else 291 else
294 ret = setup_pcpu_embed(true); 292 rc = setup_pcpu_embed(true);
295 293
296 if (ret < 0) 294 if (rc < 0)
297 pr_warning("PERCPU: %s allocator failed (%zd), " 295 pr_warning("PERCPU: %s allocator failed (%d), "
298 "falling back to page size\n", 296 "falling back to page size\n",
299 pcpu_fc_names[pcpu_chosen_fc], ret); 297 pcpu_fc_names[pcpu_chosen_fc], rc);
300 } 298 }
301 } else { 299 } else {
302 ret = setup_pcpu_lpage(false); 300 rc = setup_pcpu_lpage(false);
303 if (ret < 0) 301 if (rc < 0)
304 ret = setup_pcpu_embed(false); 302 rc = setup_pcpu_embed(false);
305 } 303 }
306 if (ret < 0) 304 if (rc < 0)
307 ret = setup_pcpu_page(); 305 rc = setup_pcpu_page();
308 if (ret < 0) 306 if (rc < 0)
309 panic("cannot initialize percpu area (err=%zd)", ret); 307 panic("cannot initialize percpu area (err=%d)", rc);
310
311 pcpu_unit_size = ret;
312 308
313 /* alrighty, percpu areas up and running */ 309 /* alrighty, percpu areas up and running */
314 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; 310 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
315 for_each_possible_cpu(cpu) { 311 for_each_possible_cpu(cpu) {
316 per_cpu_offset(cpu) = 312 per_cpu_offset(cpu) = delta + pcpu_unit_offsets[cpu];
317 delta + pcpu_unit_map[cpu] * pcpu_unit_size;
318 per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); 313 per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu);
319 per_cpu(cpu_number, cpu) = cpu; 314 per_cpu(cpu_number, cpu) = cpu;
320 setup_percpu_segment(cpu); 315 setup_percpu_segment(cpu);