diff options
Diffstat (limited to 'mm/percpu.c')
-rw-r--r-- | mm/percpu.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/mm/percpu.c b/mm/percpu.c index 46485e1b26fc..6470e7710231 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
@@ -229,8 +229,8 @@ static int __maybe_unused pcpu_page_idx(unsigned int cpu, int page_idx) | |||
229 | return pcpu_unit_map[cpu] * pcpu_unit_pages + page_idx; | 229 | return pcpu_unit_map[cpu] * pcpu_unit_pages + page_idx; |
230 | } | 230 | } |
231 | 231 | ||
232 | static unsigned long __maybe_unused pcpu_chunk_addr(struct pcpu_chunk *chunk, | 232 | static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk, |
233 | unsigned int cpu, int page_idx) | 233 | unsigned int cpu, int page_idx) |
234 | { | 234 | { |
235 | return (unsigned long)chunk->base_addr + pcpu_unit_offsets[cpu] + | 235 | return (unsigned long)chunk->base_addr + pcpu_unit_offsets[cpu] + |
236 | (page_idx << PAGE_SHIFT); | 236 | (page_idx << PAGE_SHIFT); |
@@ -978,7 +978,32 @@ bool is_kernel_percpu_address(unsigned long addr) | |||
978 | */ | 978 | */ |
979 | phys_addr_t per_cpu_ptr_to_phys(void *addr) | 979 | phys_addr_t per_cpu_ptr_to_phys(void *addr) |
980 | { | 980 | { |
981 | if (pcpu_addr_in_first_chunk(addr)) { | 981 | void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr); |
982 | bool in_first_chunk = false; | ||
983 | unsigned long first_start, first_end; | ||
984 | unsigned int cpu; | ||
985 | |||
986 | /* | ||
987 | * The following test on first_start/end isn't strictly | ||
988 | * necessary but will speed up lookups of addresses which | ||
989 | * aren't in the first chunk. | ||
990 | */ | ||
991 | first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0); | ||
992 | first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu, | ||
993 | pcpu_unit_pages); | ||
994 | if ((unsigned long)addr >= first_start && | ||
995 | (unsigned long)addr < first_end) { | ||
996 | for_each_possible_cpu(cpu) { | ||
997 | void *start = per_cpu_ptr(base, cpu); | ||
998 | |||
999 | if (addr >= start && addr < start + pcpu_unit_size) { | ||
1000 | in_first_chunk = true; | ||
1001 | break; | ||
1002 | } | ||
1003 | } | ||
1004 | } | ||
1005 | |||
1006 | if (in_first_chunk) { | ||
982 | if ((unsigned long)addr < VMALLOC_START || | 1007 | if ((unsigned long)addr < VMALLOC_START || |
983 | (unsigned long)addr >= VMALLOC_END) | 1008 | (unsigned long)addr >= VMALLOC_END) |
984 | return __pa(addr); | 1009 | return __pa(addr); |