Add a flags field to struct dev_pagemap to replace the altmap_valid boolean to be a little more extensible. Also add a pgmap_altmap() helper to find the optional altmap and clean up the code using the altmap using it.
Unified · Split
| @@ -131,17 +131,9 @@ void __ref arch_remove_memory(int nid, u64 start, u64 size, · 130 unmodified lines | ||
| 131 | 131 | { |
| 132 | 132 | unsigned long start_pfn = start >> PAGE_SHIFT; |
| 133 | 133 | unsigned long nr_pages = size >> PAGE_SHIFT; |
| 134 | − struct page *page; | |
| 134 | + struct page *page = pfn_to_page(start_pfn) + vmem_altmap_offset(altmap); | |
| 135 | 135 | int ret; |
| 136 | 136 | |
| 137 | − /* | |
| 138 | − * If we have an altmap then we need to skip over any reserved PFNs | |
| 139 | − * when querying the zone. | |
| 140 | − */ | |
| 141 | − page = pfn_to_page(start_pfn); | |
| 142 | − if (altmap) | |
| 143 | − page += vmem_altmap_offset(altmap); | |
| 144 | − | |
| 145 | 137 | __remove_pages(page_zone(page), start_pfn, nr_pages, altmap); |
| 146 | 138 | |
| 147 | 139 | /* Remove htab bolted mappings for this section of memory */ |
| @@ -1213,13 +1213,9 @@ void __ref arch_remove_memory(int nid, u64 start, u64 size, · 1212 unmodified lines | ||
| 1213 | 1213 | { |
| 1214 | 1214 | unsigned long start_pfn = start >> PAGE_SHIFT; |
| 1215 | 1215 | unsigned long nr_pages = size >> PAGE_SHIFT; |
| 1216 | − struct page *page = pfn_to_page(start_pfn); | |
| 1217 | − struct zone *zone; | |
| 1216 | + struct page *page = pfn_to_page(start_pfn) + vmem_altmap_offset(altmap); | |
| 1217 | + struct zone *zone = page_zone(page); | |
| 1218 | 1218 | |
| 1219 | − /* With altmap the first mapped page is offset from @start */ | |
| 1220 | − if (altmap) | |
| 1221 | − page += vmem_altmap_offset(altmap); | |
| 1222 | − zone = page_zone(page); | |
| 1223 | 1219 | __remove_pages(zone, start_pfn, nr_pages, altmap); |
| 1224 | 1220 | kernel_physical_mapping_remove(start, start + size); |
| 1225 | 1221 | } |
| @@ -622,7 +622,6 @@ static int __nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap) · 621 unmodified lines | ||
| 622 | 622 | if (offset < reserve) |
| 623 | 623 | return -EINVAL; |
| 624 | 624 | nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns); |
| 625 | − pgmap->altmap_valid = false; | |
| 626 | 625 | } else if (nd_pfn->mode == PFN_MODE_PMEM) { |
| 627 | 626 | nd_pfn->npfns = PFN_SECTION_ALIGN_UP((resource_size(res) |
| 628 | 627 | - offset) / PAGE_SIZE); |
| @@ -634,7 +633,7 @@ static int __nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap) · 5 unmodified lines | ||
| 634 | 633 | memcpy(altmap, &__altmap, sizeof(*altmap)); |
| 635 | 634 | altmap->free = PHYS_PFN(offset - reserve); |
| 636 | 635 | altmap->alloc = 0; |
| 637 | − pgmap->altmap_valid = true; | |
| 636 | + pgmap->flags |= PGMAP_ALTMAP_VALID; | |
| 638 | 637 | } else |
| 639 | 638 | return -ENXIO; |
| 640 | 639 | |
| @@ -412,7 +412,6 @@ static int pmem_attach_disk(struct device *dev, · 411 unmodified lines | ||
| 412 | 412 | bb_res.start += pmem->data_offset; |
| 413 | 413 | } else if (pmem_should_map_pages(dev)) { |
| 414 | 414 | memcpy(&pmem->pgmap.res, &nsio->res, sizeof(pmem->pgmap.res)); |
| 415 | − pmem->pgmap.altmap_valid = false; | |
| 416 | 415 | pmem->pgmap.type = MEMORY_DEVICE_FS_DAX; |
| 417 | 416 | pmem->pgmap.ops = &fsdax_pagemap_ops; |
| 418 | 417 | addr = devm_memremap_pages(dev, &pmem->pgmap); |
| @@ -88,6 +88,8 @@ struct dev_pagemap_ops { · 87 unmodified lines | ||
| 88 | 88 | vm_fault_t (*migrate_to_ram)(struct vm_fault *vmf); |
| 89 | 89 | }; |
| 90 | 90 | |
| 91 | +#define PGMAP_ALTMAP_VALID (1 << 0) | |
| 92 | + | |
| 91 | 93 | /** |
| 92 | 94 | * struct dev_pagemap - metadata for ZONE_DEVICE mappings |
| 93 | 95 | * @altmap: pre-allocated/reserved memory for vmemmap allocations |
| @@ -96,19 +98,27 @@ struct dev_pagemap_ops { · 2 unmodified lines | ||
| 96 | 98 | * @dev: host device of the mapping for debug |
| 97 | 99 | * @data: private data pointer for page_free() |
| 98 | 100 | * @type: memory type: see MEMORY_* in memory_hotplug.h |
| 101 | + * @flags: PGMAP_* flags to specify defailed behavior | |
| 99 | 102 | * @ops: method table |
| 100 | 103 | */ |
| 101 | 104 | struct dev_pagemap { |
| 102 | 105 | struct vmem_altmap altmap; |
| 103 | − bool altmap_valid; | |
| 104 | 106 | struct resource res; |
| 105 | 107 | struct percpu_ref *ref; |
| 106 | 108 | struct device *dev; |
| 107 | 109 | enum memory_type type; |
| 110 | + unsigned int flags; | |
| 108 | 111 | u64 pci_p2pdma_bus_offset; |
| 109 | 112 | const struct dev_pagemap_ops *ops; |
| 110 | 113 | }; |
| 111 | 114 | |
| 115 | +static inline struct vmem_altmap *pgmap_altmap(struct dev_pagemap *pgmap) | |
| 116 | +{ | |
| 117 | + if (pgmap->flags & PGMAP_ALTMAP_VALID) | |
| 118 | + return &pgmap->altmap; | |
| 119 | + return NULL; | |
| 120 | +} | |
| 121 | + | |
| 112 | 122 | #ifdef CONFIG_ZONE_DEVICE |
| 113 | 123 | void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap); |
| 114 | 124 | void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap); |
| @@ -54,14 +54,8 @@ static void pgmap_array_delete(struct resource *res) · 53 unmodified lines | ||
| 54 | 54 | |
| 55 | 55 | static unsigned long pfn_first(struct dev_pagemap *pgmap) |
| 56 | 56 | { |
| 57 | − const struct resource *res = &pgmap->res; | |
| 58 | − struct vmem_altmap *altmap = &pgmap->altmap; | |
| 59 | − unsigned long pfn; | |
| 60 | − | |
| 61 | − pfn = res->start >> PAGE_SHIFT; | |
| 62 | − if (pgmap->altmap_valid) | |
| 63 | − pfn += vmem_altmap_offset(altmap); | |
| 64 | − return pfn; | |
| 57 | + return (pgmap->res.start >> PAGE_SHIFT) + | |
| 58 | + vmem_altmap_offset(pgmap_altmap(pgmap)); | |
| 65 | 59 | } |
| 66 | 60 | |
| 67 | 61 | static unsigned long pfn_end(struct dev_pagemap *pgmap) |
| @@ -109,7 +103,7 @@ static void devm_memremap_pages_release(void *data) · 41 unmodified lines | ||
| 109 | 103 | align_size >> PAGE_SHIFT, NULL); |
| 110 | 104 | } else { |
| 111 | 105 | arch_remove_memory(nid, align_start, align_size, |
| 112 | − pgmap->altmap_valid ? &pgmap->altmap : NULL); | |
| 106 | + pgmap_altmap(pgmap)); | |
| 113 | 107 | kasan_remove_zero_shadow(__va(align_start), align_size); |
| 114 | 108 | } |
| 115 | 109 | mem_hotplug_done(); |
| @@ -129,8 +123,8 @@ static void devm_memremap_pages_release(void *data) · 13 unmodified lines | ||
| 129 | 123 | * 1/ At a minimum the res, ref and type and ops members of @pgmap must be |
| 130 | 124 | * initialized by the caller before passing it to this function |
| 131 | 125 | * |
| 132 | − * 2/ The altmap field may optionally be initialized, in which case altmap_valid | |
| 133 | − * must be set to true | |
| 126 | + * 2/ The altmap field may optionally be initialized, in which case | |
| 127 | + * PGMAP_ALTMAP_VALID must be set in pgmap->flags. | |
| 134 | 128 | * |
| 135 | 129 | * 3/ pgmap->ref must be 'live' on entry and will be killed and reaped |
| 136 | 130 | * at devm_memremap_pages_release() time, or if this routine fails. |
| @@ -142,15 +136,13 @@ static void devm_memremap_pages_release(void *data) · 5 unmodified lines | ||
| 142 | 136 | void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) |
| 143 | 137 | { |
| 144 | 138 | resource_size_t align_start, align_size, align_end; |
| 145 | − struct vmem_altmap *altmap = pgmap->altmap_valid ? | |
| 146 | − &pgmap->altmap : NULL; | |
| 147 | 139 | struct resource *res = &pgmap->res; |
| 148 | 140 | struct dev_pagemap *conflict_pgmap; |
| 149 | 141 | struct mhp_restrictions restrictions = { |
| 150 | 142 | /* |
| 151 | 143 | * We do not want any optional features only our own memmap |
| 152 | 144 | */ |
| 153 | − .altmap = altmap, | |
| 145 | + .altmap = pgmap_altmap(pgmap), | |
| 154 | 146 | }; |
| 155 | 147 | pgprot_t pgprot = PAGE_KERNEL; |
| 156 | 148 | int error, nid, is_ram; |
| @@ -274,7 +266,7 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) · 117 unmodified lines | ||
| 274 | 266 | |
| 275 | 267 | zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE]; |
| 276 | 268 | move_pfn_range_to_zone(zone, align_start >> PAGE_SHIFT, |
| 277 | − align_size >> PAGE_SHIFT, altmap); | |
| 269 | + align_size >> PAGE_SHIFT, pgmap_altmap(pgmap)); | |
| 278 | 270 | } |
| 279 | 271 | |
| 280 | 272 | mem_hotplug_done(); |
| @@ -319,7 +311,9 @@ EXPORT_SYMBOL_GPL(devm_memunmap_pages); · 38 unmodified lines | ||
| 319 | 311 | unsigned long vmem_altmap_offset(struct vmem_altmap *altmap) |
| 320 | 312 | { |
| 321 | 313 | /* number of pfns from base where pfn_to_page() is valid */ |
| 322 | − return altmap->reserve + altmap->free; | |
| 314 | + if (altmap) | |
| 315 | + return altmap->reserve + altmap->free; | |
| 316 | + return 0; | |
| 323 | 317 | } |
| 324 | 318 | |
| 325 | 319 | void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns) |
| @@ -1442,7 +1442,6 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops, · 1441 unmodified lines | ||
| 1442 | 1442 | devmem->pagemap.type = MEMORY_DEVICE_PRIVATE; |
| 1443 | 1443 | devmem->pagemap.res = *devmem->resource; |
| 1444 | 1444 | devmem->pagemap.ops = &hmm_pagemap_ops; |
| 1445 | − devmem->pagemap.altmap_valid = false; | |
| 1446 | 1445 | devmem->pagemap.ref = &devmem->ref; |
| 1447 | 1446 | |
| 1448 | 1447 | result = devm_memremap_pages(devmem->device, &devmem->pagemap); |
| @@ -557,10 +557,8 @@ void __remove_pages(struct zone *zone, unsigned long phys_start_pfn, · 556 unmodified lines | ||
| 557 | 557 | int sections_to_remove; |
| 558 | 558 | |
| 559 | 559 | /* In the ZONE_DEVICE case device driver owns the memory region */ |
| 560 | − if (is_dev_zone(zone)) { | |
| 561 | − if (altmap) | |
| 562 | − map_offset = vmem_altmap_offset(altmap); | |
| 563 | − } | |
| 560 | + if (is_dev_zone(zone)) | |
| 561 | + map_offset = vmem_altmap_offset(altmap); | |
| 564 | 562 | |
| 565 | 563 | clear_zone_contiguous(zone); |
| 566 | 564 | |
| @@ -5853,6 +5853,7 @@ void __ref memmap_init_zone_device(struct zone *zone, · 5852 unmodified lines | ||
| 5853 | 5853 | { |
| 5854 | 5854 | unsigned long pfn, end_pfn = start_pfn + size; |
| 5855 | 5855 | struct pglist_data *pgdat = zone->zone_pgdat; |
| 5856 | + struct vmem_altmap *altmap = pgmap_altmap(pgmap); | |
| 5856 | 5857 | unsigned long zone_idx = zone_idx(zone); |
| 5857 | 5858 | unsigned long start = jiffies; |
| 5858 | 5859 | int nid = pgdat->node_id; |
| @@ -5865,9 +5866,7 @@ void __ref memmap_init_zone_device(struct zone *zone, · 6 unmodified lines | ||
| 5865 | 5866 | * of the pages reserved for the memmap, so we can just jump to |
| 5866 | 5867 | * the end of that region and start processing the device pages. |
| 5867 | 5868 | */ |
| 5868 | − if (pgmap->altmap_valid) { | |
| 5869 | − struct vmem_altmap *altmap = &pgmap->altmap; | |
| 5870 | − | |
| 5869 | + if (altmap) { | |
| 5871 | 5870 | start_pfn = altmap->base_pfn + vmem_altmap_offset(altmap); |
| 5872 | 5871 | size = end_pfn - start_pfn; |
| 5873 | 5872 | } |