diff options
| -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); |
