|
1 |
| -/* |
2 |
| - * Copyright(c) 2015 Intel Corporation. All rights reserved. |
3 |
| - * |
4 |
| - * This program is free software; you can redistribute it and/or modify |
5 |
| - * it under the terms of version 2 of the GNU General Public License as |
6 |
| - * published by the Free Software Foundation. |
7 |
| - * |
8 |
| - * This program is distributed in the hope that it will be useful, but |
9 |
| - * WITHOUT ANY WARRANTY; without even the implied warranty of |
10 |
| - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11 |
| - * General Public License for more details. |
12 |
| - */ |
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | +/* Copyright(c) 2015 Intel Corporation. All rights reserved. */ |
13 | 3 | #include <linux/radix-tree.h>
|
14 | 4 | #include <linux/device.h>
|
15 | 5 | #include <linux/types.h>
|
|
20 | 10 | #include <linux/swap.h>
|
21 | 11 | #include <linux/swapops.h>
|
22 | 12 |
|
23 |
| -#ifndef ioremap_cache |
24 |
| -/* temporary while we convert existing ioremap_cache users to memremap */ |
25 |
| -__weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size) |
26 |
| -{ |
27 |
| - return ioremap(offset, size); |
28 |
| -} |
29 |
| -#endif |
30 |
| - |
31 |
| -#ifndef arch_memremap_wb |
32 |
| -static void *arch_memremap_wb(resource_size_t offset, unsigned long size) |
33 |
| -{ |
34 |
| - return (__force void *)ioremap_cache(offset, size); |
35 |
| -} |
36 |
| -#endif |
37 |
| - |
38 |
| -#ifndef arch_memremap_can_ram_remap |
39 |
| -static bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size, |
40 |
| - unsigned long flags) |
41 |
| -{ |
42 |
| - return true; |
43 |
| -} |
44 |
| -#endif |
45 |
| - |
46 |
| -static void *try_ram_remap(resource_size_t offset, size_t size, |
47 |
| - unsigned long flags) |
48 |
| -{ |
49 |
| - unsigned long pfn = PHYS_PFN(offset); |
50 |
| - |
51 |
| - /* In the simple case just return the existing linear address */ |
52 |
| - if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn)) && |
53 |
| - arch_memremap_can_ram_remap(offset, size, flags)) |
54 |
| - return __va(offset); |
55 |
| - |
56 |
| - return NULL; /* fallback to arch_memremap_wb */ |
57 |
| -} |
58 |
| - |
59 |
| -/** |
60 |
| - * memremap() - remap an iomem_resource as cacheable memory |
61 |
| - * @offset: iomem resource start address |
62 |
| - * @size: size of remap |
63 |
| - * @flags: any of MEMREMAP_WB, MEMREMAP_WT, MEMREMAP_WC, |
64 |
| - * MEMREMAP_ENC, MEMREMAP_DEC |
65 |
| - * |
66 |
| - * memremap() is "ioremap" for cases where it is known that the resource |
67 |
| - * being mapped does not have i/o side effects and the __iomem |
68 |
| - * annotation is not applicable. In the case of multiple flags, the different |
69 |
| - * mapping types will be attempted in the order listed below until one of |
70 |
| - * them succeeds. |
71 |
| - * |
72 |
| - * MEMREMAP_WB - matches the default mapping for System RAM on |
73 |
| - * the architecture. This is usually a read-allocate write-back cache. |
74 |
| - * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM |
75 |
| - * memremap() will bypass establishing a new mapping and instead return |
76 |
| - * a pointer into the direct map. |
77 |
| - * |
78 |
| - * MEMREMAP_WT - establish a mapping whereby writes either bypass the |
79 |
| - * cache or are written through to memory and never exist in a |
80 |
| - * cache-dirty state with respect to program visibility. Attempts to |
81 |
| - * map System RAM with this mapping type will fail. |
82 |
| - * |
83 |
| - * MEMREMAP_WC - establish a writecombine mapping, whereby writes may |
84 |
| - * be coalesced together (e.g. in the CPU's write buffers), but is otherwise |
85 |
| - * uncached. Attempts to map System RAM with this mapping type will fail. |
86 |
| - */ |
87 |
| -void *memremap(resource_size_t offset, size_t size, unsigned long flags) |
88 |
| -{ |
89 |
| - int is_ram = region_intersects(offset, size, |
90 |
| - IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE); |
91 |
| - void *addr = NULL; |
92 |
| - |
93 |
| - if (!flags) |
94 |
| - return NULL; |
95 |
| - |
96 |
| - if (is_ram == REGION_MIXED) { |
97 |
| - WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n", |
98 |
| - &offset, (unsigned long) size); |
99 |
| - return NULL; |
100 |
| - } |
101 |
| - |
102 |
| - /* Try all mapping types requested until one returns non-NULL */ |
103 |
| - if (flags & MEMREMAP_WB) { |
104 |
| - /* |
105 |
| - * MEMREMAP_WB is special in that it can be satisifed |
106 |
| - * from the direct map. Some archs depend on the |
107 |
| - * capability of memremap() to autodetect cases where |
108 |
| - * the requested range is potentially in System RAM. |
109 |
| - */ |
110 |
| - if (is_ram == REGION_INTERSECTS) |
111 |
| - addr = try_ram_remap(offset, size, flags); |
112 |
| - if (!addr) |
113 |
| - addr = arch_memremap_wb(offset, size); |
114 |
| - } |
115 |
| - |
116 |
| - /* |
117 |
| - * If we don't have a mapping yet and other request flags are |
118 |
| - * present then we will be attempting to establish a new virtual |
119 |
| - * address mapping. Enforce that this mapping is not aliasing |
120 |
| - * System RAM. |
121 |
| - */ |
122 |
| - if (!addr && is_ram == REGION_INTERSECTS && flags != MEMREMAP_WB) { |
123 |
| - WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n", |
124 |
| - &offset, (unsigned long) size); |
125 |
| - return NULL; |
126 |
| - } |
127 |
| - |
128 |
| - if (!addr && (flags & MEMREMAP_WT)) |
129 |
| - addr = ioremap_wt(offset, size); |
130 |
| - |
131 |
| - if (!addr && (flags & MEMREMAP_WC)) |
132 |
| - addr = ioremap_wc(offset, size); |
133 |
| - |
134 |
| - return addr; |
135 |
| -} |
136 |
| -EXPORT_SYMBOL(memremap); |
137 |
| - |
138 |
| -void memunmap(void *addr) |
139 |
| -{ |
140 |
| - if (is_vmalloc_addr(addr)) |
141 |
| - iounmap((void __iomem *) addr); |
142 |
| -} |
143 |
| -EXPORT_SYMBOL(memunmap); |
144 |
| - |
145 |
| -static void devm_memremap_release(struct device *dev, void *res) |
146 |
| -{ |
147 |
| - memunmap(*(void **)res); |
148 |
| -} |
149 |
| - |
150 |
| -static int devm_memremap_match(struct device *dev, void *res, void *match_data) |
151 |
| -{ |
152 |
| - return *(void **)res == match_data; |
153 |
| -} |
154 |
| - |
155 |
| -void *devm_memremap(struct device *dev, resource_size_t offset, |
156 |
| - size_t size, unsigned long flags) |
157 |
| -{ |
158 |
| - void **ptr, *addr; |
159 |
| - |
160 |
| - ptr = devres_alloc_node(devm_memremap_release, sizeof(*ptr), GFP_KERNEL, |
161 |
| - dev_to_node(dev)); |
162 |
| - if (!ptr) |
163 |
| - return ERR_PTR(-ENOMEM); |
164 |
| - |
165 |
| - addr = memremap(offset, size, flags); |
166 |
| - if (addr) { |
167 |
| - *ptr = addr; |
168 |
| - devres_add(dev, ptr); |
169 |
| - } else { |
170 |
| - devres_free(ptr); |
171 |
| - return ERR_PTR(-ENXIO); |
172 |
| - } |
173 |
| - |
174 |
| - return addr; |
175 |
| -} |
176 |
| -EXPORT_SYMBOL(devm_memremap); |
177 |
| - |
178 |
| -void devm_memunmap(struct device *dev, void *addr) |
179 |
| -{ |
180 |
| - WARN_ON(devres_release(dev, devm_memremap_release, |
181 |
| - devm_memremap_match, addr)); |
182 |
| -} |
183 |
| -EXPORT_SYMBOL(devm_memunmap); |
184 |
| - |
185 |
| -#ifdef CONFIG_ZONE_DEVICE |
186 | 13 | static DEFINE_MUTEX(pgmap_lock);
|
187 | 14 | static RADIX_TREE(pgmap_radix, GFP_KERNEL);
|
188 | 15 | #define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
|
@@ -473,7 +300,6 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
|
473 | 300 |
|
474 | 301 | return pgmap;
|
475 | 302 | }
|
476 |
| -#endif /* CONFIG_ZONE_DEVICE */ |
477 | 303 |
|
478 | 304 | #if IS_ENABLED(CONFIG_DEVICE_PRIVATE) || IS_ENABLED(CONFIG_DEVICE_PUBLIC)
|
479 | 305 | void put_zone_device_private_or_public_page(struct page *page)
|
|
0 commit comments