diff options
Diffstat (limited to 'include/linux/memremap.h')
| -rw-r--r-- | include/linux/memremap.h | 77 |
1 files changed, 23 insertions, 54 deletions
diff --git a/include/linux/memremap.h b/include/linux/memremap.h index 10d23c367048..7b4899c06f49 100644 --- a/include/linux/memremap.h +++ b/include/linux/memremap.h | |||
| @@ -26,18 +26,6 @@ struct vmem_altmap { | |||
| 26 | unsigned long alloc; | 26 | unsigned long alloc; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | unsigned long vmem_altmap_offset(struct vmem_altmap *altmap); | ||
| 30 | void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns); | ||
| 31 | |||
| 32 | #ifdef CONFIG_ZONE_DEVICE | ||
| 33 | struct vmem_altmap *to_vmem_altmap(unsigned long memmap_start); | ||
| 34 | #else | ||
| 35 | static inline struct vmem_altmap *to_vmem_altmap(unsigned long memmap_start) | ||
| 36 | { | ||
| 37 | return NULL; | ||
| 38 | } | ||
| 39 | #endif | ||
| 40 | |||
| 41 | /* | 29 | /* |
| 42 | * Specialize ZONE_DEVICE memory into multiple types each having differents | 30 | * Specialize ZONE_DEVICE memory into multiple types each having differents |
| 43 | * usage. | 31 | * usage. |
| @@ -125,8 +113,9 @@ typedef void (*dev_page_free_t)(struct page *page, void *data); | |||
| 125 | struct dev_pagemap { | 113 | struct dev_pagemap { |
| 126 | dev_page_fault_t page_fault; | 114 | dev_page_fault_t page_fault; |
| 127 | dev_page_free_t page_free; | 115 | dev_page_free_t page_free; |
| 128 | struct vmem_altmap *altmap; | 116 | struct vmem_altmap altmap; |
| 129 | const struct resource *res; | 117 | bool altmap_valid; |
| 118 | struct resource res; | ||
| 130 | struct percpu_ref *ref; | 119 | struct percpu_ref *ref; |
| 131 | struct device *dev; | 120 | struct device *dev; |
| 132 | void *data; | 121 | void *data; |
| @@ -134,15 +123,17 @@ struct dev_pagemap { | |||
| 134 | }; | 123 | }; |
| 135 | 124 | ||
| 136 | #ifdef CONFIG_ZONE_DEVICE | 125 | #ifdef CONFIG_ZONE_DEVICE |
| 137 | void *devm_memremap_pages(struct device *dev, struct resource *res, | 126 | void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap); |
| 138 | struct percpu_ref *ref, struct vmem_altmap *altmap); | 127 | struct dev_pagemap *get_dev_pagemap(unsigned long pfn, |
| 139 | struct dev_pagemap *find_dev_pagemap(resource_size_t phys); | 128 | struct dev_pagemap *pgmap); |
| 129 | |||
| 130 | unsigned long vmem_altmap_offset(struct vmem_altmap *altmap); | ||
| 131 | void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns); | ||
| 140 | 132 | ||
| 141 | static inline bool is_zone_device_page(const struct page *page); | 133 | static inline bool is_zone_device_page(const struct page *page); |
| 142 | #else | 134 | #else |
| 143 | static inline void *devm_memremap_pages(struct device *dev, | 135 | static inline void *devm_memremap_pages(struct device *dev, |
| 144 | struct resource *res, struct percpu_ref *ref, | 136 | struct dev_pagemap *pgmap) |
| 145 | struct vmem_altmap *altmap) | ||
| 146 | { | 137 | { |
| 147 | /* | 138 | /* |
| 148 | * Fail attempts to call devm_memremap_pages() without | 139 | * Fail attempts to call devm_memremap_pages() without |
| @@ -153,11 +144,22 @@ static inline void *devm_memremap_pages(struct device *dev, | |||
| 153 | return ERR_PTR(-ENXIO); | 144 | return ERR_PTR(-ENXIO); |
| 154 | } | 145 | } |
| 155 | 146 | ||
| 156 | static inline struct dev_pagemap *find_dev_pagemap(resource_size_t phys) | 147 | static inline struct dev_pagemap *get_dev_pagemap(unsigned long pfn, |
| 148 | struct dev_pagemap *pgmap) | ||
| 157 | { | 149 | { |
| 158 | return NULL; | 150 | return NULL; |
| 159 | } | 151 | } |
| 160 | #endif | 152 | |
| 153 | static inline unsigned long vmem_altmap_offset(struct vmem_altmap *altmap) | ||
| 154 | { | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | static inline void vmem_altmap_free(struct vmem_altmap *altmap, | ||
| 159 | unsigned long nr_pfns) | ||
| 160 | { | ||
| 161 | } | ||
| 162 | #endif /* CONFIG_ZONE_DEVICE */ | ||
| 161 | 163 | ||
| 162 | #if defined(CONFIG_DEVICE_PRIVATE) || defined(CONFIG_DEVICE_PUBLIC) | 164 | #if defined(CONFIG_DEVICE_PRIVATE) || defined(CONFIG_DEVICE_PUBLIC) |
| 163 | static inline bool is_device_private_page(const struct page *page) | 165 | static inline bool is_device_private_page(const struct page *page) |
| @@ -173,39 +175,6 @@ static inline bool is_device_public_page(const struct page *page) | |||
| 173 | } | 175 | } |
| 174 | #endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ | 176 | #endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ |
| 175 | 177 | ||
| 176 | /** | ||
| 177 | * get_dev_pagemap() - take a new live reference on the dev_pagemap for @pfn | ||
| 178 | * @pfn: page frame number to lookup page_map | ||
| 179 | * @pgmap: optional known pgmap that already has a reference | ||
| 180 | * | ||
| 181 | * @pgmap allows the overhead of a lookup to be bypassed when @pfn lands in the | ||
| 182 | * same mapping. | ||
| 183 | */ | ||
| 184 | static inline struct dev_pagemap *get_dev_pagemap(unsigned long pfn, | ||
| 185 | struct dev_pagemap *pgmap) | ||
| 186 | { | ||
| 187 | const struct resource *res = pgmap ? pgmap->res : NULL; | ||
| 188 | resource_size_t phys = PFN_PHYS(pfn); | ||
| 189 | |||
| 190 | /* | ||
| 191 | * In the cached case we're already holding a live reference so | ||
| 192 | * we can simply do a blind increment | ||
| 193 | */ | ||
| 194 | if (res && phys >= res->start && phys <= res->end) { | ||
| 195 | percpu_ref_get(pgmap->ref); | ||
| 196 | return pgmap; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* fall back to slow path lookup */ | ||
| 200 | rcu_read_lock(); | ||
| 201 | pgmap = find_dev_pagemap(phys); | ||
| 202 | if (pgmap && !percpu_ref_tryget_live(pgmap->ref)) | ||
| 203 | pgmap = NULL; | ||
| 204 | rcu_read_unlock(); | ||
| 205 | |||
| 206 | return pgmap; | ||
| 207 | } | ||
| 208 | |||
| 209 | static inline void put_dev_pagemap(struct dev_pagemap *pgmap) | 178 | static inline void put_dev_pagemap(struct dev_pagemap *pgmap) |
| 210 | { | 179 | { |
| 211 | if (pgmap) | 180 | if (pgmap) |
