From 3f861315e76a366c19ed273e4c38beda28e287a6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Jun 2010 11:44:31 +0200 Subject: [PATCH] --- yaml --- r: 200563 b: refs/heads/master c: 9983b6f0cf8263e51bcf4c8a9dc0c1ef175b3c60 h: refs/heads/master i: 200561: 84dc5586c40e8dbd83b2de891ecaabee970ee22d 200559: f916c812ea3b20e2b4da793f49500e3c798dddbb v: v3 --- [refs] | 2 +- trunk/mm/percpu.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 43aa3f34a242..6106309581c5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a92d3ff9e5dbd958d8008a3e7a573e988e370ca3 +refs/heads/master: 9983b6f0cf8263e51bcf4c8a9dc0c1ef175b3c60 diff --git a/trunk/mm/percpu.c b/trunk/mm/percpu.c index 46485e1b26fc..6470e7710231 100644 --- a/trunk/mm/percpu.c +++ b/trunk/mm/percpu.c @@ -229,8 +229,8 @@ static int __maybe_unused pcpu_page_idx(unsigned int cpu, int page_idx) return pcpu_unit_map[cpu] * pcpu_unit_pages + page_idx; } -static unsigned long __maybe_unused pcpu_chunk_addr(struct pcpu_chunk *chunk, - unsigned int cpu, int page_idx) +static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk, + unsigned int cpu, int page_idx) { return (unsigned long)chunk->base_addr + pcpu_unit_offsets[cpu] + (page_idx << PAGE_SHIFT); @@ -978,7 +978,32 @@ bool is_kernel_percpu_address(unsigned long addr) */ phys_addr_t per_cpu_ptr_to_phys(void *addr) { - if (pcpu_addr_in_first_chunk(addr)) { + void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr); + bool in_first_chunk = false; + unsigned long first_start, first_end; + unsigned int cpu; + + /* + * The following test on first_start/end isn't strictly + * necessary but will speed up lookups of addresses which + * aren't in the first chunk. + */ + first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0); + first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu, + pcpu_unit_pages); + if ((unsigned long)addr >= first_start && + (unsigned long)addr < first_end) { + for_each_possible_cpu(cpu) { + void *start = per_cpu_ptr(base, cpu); + + if (addr >= start && addr < start + pcpu_unit_size) { + in_first_chunk = true; + break; + } + } + } + + if (in_first_chunk) { if ((unsigned long)addr < VMALLOC_START || (unsigned long)addr >= VMALLOC_END) return __pa(addr);