memremap: drop private struct page_map

'struct page_map' is a private structure of 'struct dev_pagemap' but the
latter replicates all the same fields as the former so there isn't much
value in it. Thus drop it in favour of a completely public struct.

This is a clean up in preperation for a more generally useful
'devm_memeremap_pages' interface.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Logan Gunthorpe 2017-12-29 08:54:04 +01:00 committed by Dan Williams
parent 7003e3b1f6
commit e7744aa25c
3 changed files with 30 additions and 45 deletions

View File

@ -113,8 +113,9 @@ typedef void (*dev_page_free_t)(struct page *page, void *data);
struct dev_pagemap { struct dev_pagemap {
dev_page_fault_t page_fault; dev_page_fault_t page_fault;
dev_page_free_t page_free; dev_page_free_t page_free;
struct vmem_altmap *altmap; struct vmem_altmap altmap;
const struct resource *res; bool altmap_valid;
struct resource res;
struct percpu_ref *ref; struct percpu_ref *ref;
struct device *dev; struct device *dev;
void *data; void *data;

View File

@ -188,13 +188,6 @@ static RADIX_TREE(pgmap_radix, GFP_KERNEL);
#define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1) #define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
#define SECTION_SIZE (1UL << PA_SECTION_SHIFT) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT)
struct page_map {
struct resource res;
struct percpu_ref *ref;
struct dev_pagemap pgmap;
struct vmem_altmap altmap;
};
static unsigned long order_at(struct resource *res, unsigned long pgoff) static unsigned long order_at(struct resource *res, unsigned long pgoff)
{ {
unsigned long phys_pgoff = PHYS_PFN(res->start) + pgoff; unsigned long phys_pgoff = PHYS_PFN(res->start) + pgoff;
@ -260,22 +253,21 @@ static void pgmap_radix_release(struct resource *res)
synchronize_rcu(); synchronize_rcu();
} }
static unsigned long pfn_first(struct page_map *page_map) static unsigned long pfn_first(struct dev_pagemap *pgmap)
{ {
struct dev_pagemap *pgmap = &page_map->pgmap; const struct resource *res = &pgmap->res;
const struct resource *res = &page_map->res; struct vmem_altmap *altmap = &pgmap->altmap;
struct vmem_altmap *altmap = pgmap->altmap;
unsigned long pfn; unsigned long pfn;
pfn = res->start >> PAGE_SHIFT; pfn = res->start >> PAGE_SHIFT;
if (altmap) if (pgmap->altmap_valid)
pfn += vmem_altmap_offset(altmap); pfn += vmem_altmap_offset(altmap);
return pfn; return pfn;
} }
static unsigned long pfn_end(struct page_map *page_map) static unsigned long pfn_end(struct dev_pagemap *pgmap)
{ {
const struct resource *res = &page_map->res; const struct resource *res = &pgmap->res;
return (res->start + resource_size(res)) >> PAGE_SHIFT; return (res->start + resource_size(res)) >> PAGE_SHIFT;
} }
@ -285,13 +277,12 @@ static unsigned long pfn_end(struct page_map *page_map)
static void devm_memremap_pages_release(struct device *dev, void *data) static void devm_memremap_pages_release(struct device *dev, void *data)
{ {
struct page_map *page_map = data; struct dev_pagemap *pgmap = data;
struct resource *res = &page_map->res; struct resource *res = &pgmap->res;
resource_size_t align_start, align_size; resource_size_t align_start, align_size;
struct dev_pagemap *pgmap = &page_map->pgmap;
unsigned long pfn; unsigned long pfn;
for_each_device_pfn(pfn, page_map) for_each_device_pfn(pfn, pgmap)
put_page(pfn_to_page(pfn)); put_page(pfn_to_page(pfn));
if (percpu_ref_tryget_live(pgmap->ref)) { if (percpu_ref_tryget_live(pgmap->ref)) {
@ -304,24 +295,22 @@ static void devm_memremap_pages_release(struct device *dev, void *data)
align_size = ALIGN(resource_size(res), SECTION_SIZE); align_size = ALIGN(resource_size(res), SECTION_SIZE);
mem_hotplug_begin(); mem_hotplug_begin();
arch_remove_memory(align_start, align_size, pgmap->altmap); arch_remove_memory(align_start, align_size, pgmap->altmap_valid ?
&pgmap->altmap : NULL);
mem_hotplug_done(); mem_hotplug_done();
untrack_pfn(NULL, PHYS_PFN(align_start), align_size); untrack_pfn(NULL, PHYS_PFN(align_start), align_size);
pgmap_radix_release(res); pgmap_radix_release(res);
dev_WARN_ONCE(dev, pgmap->altmap && pgmap->altmap->alloc, dev_WARN_ONCE(dev, pgmap->altmap.alloc,
"%s: failed to free all reserved pages\n", __func__); "%s: failed to free all reserved pages\n", __func__);
} }
/* assumes rcu_read_lock() held at entry */ /* assumes rcu_read_lock() held at entry */
static struct dev_pagemap *find_dev_pagemap(resource_size_t phys) static struct dev_pagemap *find_dev_pagemap(resource_size_t phys)
{ {
struct page_map *page_map;
WARN_ON_ONCE(!rcu_read_lock_held()); WARN_ON_ONCE(!rcu_read_lock_held());
page_map = radix_tree_lookup(&pgmap_radix, PHYS_PFN(phys)); return radix_tree_lookup(&pgmap_radix, PHYS_PFN(phys));
return page_map ? &page_map->pgmap : NULL;
} }
/** /**
@ -349,7 +338,6 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
unsigned long pfn, pgoff, order; unsigned long pfn, pgoff, order;
pgprot_t pgprot = PAGE_KERNEL; pgprot_t pgprot = PAGE_KERNEL;
struct dev_pagemap *pgmap; struct dev_pagemap *pgmap;
struct page_map *page_map;
int error, nid, is_ram, i = 0; int error, nid, is_ram, i = 0;
align_start = res->start & ~(SECTION_SIZE - 1); align_start = res->start & ~(SECTION_SIZE - 1);
@ -370,22 +358,20 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
if (!ref) if (!ref)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
page_map = devres_alloc_node(devm_memremap_pages_release, pgmap = devres_alloc_node(devm_memremap_pages_release,
sizeof(*page_map), GFP_KERNEL, dev_to_node(dev)); sizeof(*pgmap), GFP_KERNEL, dev_to_node(dev));
if (!page_map) if (!pgmap)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
pgmap = &page_map->pgmap;
memcpy(&page_map->res, res, sizeof(*res)); memcpy(&pgmap->res, res, sizeof(*res));
pgmap->dev = dev; pgmap->dev = dev;
if (altmap) { if (altmap) {
memcpy(&page_map->altmap, altmap, sizeof(*altmap)); memcpy(&pgmap->altmap, altmap, sizeof(*altmap));
pgmap->altmap = &page_map->altmap; pgmap->altmap_valid = true;
altmap = pgmap->altmap; altmap = &pgmap->altmap;
} }
pgmap->ref = ref; pgmap->ref = ref;
pgmap->res = &page_map->res;
pgmap->type = MEMORY_DEVICE_HOST; pgmap->type = MEMORY_DEVICE_HOST;
pgmap->page_fault = NULL; pgmap->page_fault = NULL;
pgmap->page_free = NULL; pgmap->page_free = NULL;
@ -397,7 +383,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
foreach_order_pgoff(res, order, pgoff) { foreach_order_pgoff(res, order, pgoff) {
error = __radix_tree_insert(&pgmap_radix, error = __radix_tree_insert(&pgmap_radix,
PHYS_PFN(res->start) + pgoff, order, page_map); PHYS_PFN(res->start) + pgoff, order, pgmap);
if (error) { if (error) {
dev_err(dev, "%s: failed: %d\n", __func__, error); dev_err(dev, "%s: failed: %d\n", __func__, error);
break; break;
@ -426,7 +412,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
if (error) if (error)
goto err_add_memory; goto err_add_memory;
for_each_device_pfn(pfn, page_map) { for_each_device_pfn(pfn, pgmap) {
struct page *page = pfn_to_page(pfn); struct page *page = pfn_to_page(pfn);
/* /*
@ -441,7 +427,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
if (!(++i % 1024)) if (!(++i % 1024))
cond_resched(); cond_resched();
} }
devres_add(dev, page_map); devres_add(dev, pgmap);
return __va(res->start); return __va(res->start);
err_add_memory: err_add_memory:
@ -449,7 +435,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
err_pfn_remap: err_pfn_remap:
err_radix: err_radix:
pgmap_radix_release(res); pgmap_radix_release(res);
devres_free(page_map); devres_free(pgmap);
return ERR_PTR(error); return ERR_PTR(error);
} }
EXPORT_SYMBOL(devm_memremap_pages); EXPORT_SYMBOL(devm_memremap_pages);
@ -482,9 +468,7 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
* In the cached case we're already holding a live reference. * In the cached case we're already holding a live reference.
*/ */
if (pgmap) { if (pgmap) {
const struct resource *res = pgmap ? pgmap->res : NULL; if (phys >= pgmap->res.start && phys <= pgmap->res.end)
if (res && phys >= res->start && phys <= res->end)
return pgmap; return pgmap;
put_dev_pagemap(pgmap); put_dev_pagemap(pgmap);
} }

View File

@ -882,7 +882,7 @@ static int hmm_devmem_pages_create(struct hmm_devmem *devmem)
else else
devmem->pagemap.type = MEMORY_DEVICE_PRIVATE; devmem->pagemap.type = MEMORY_DEVICE_PRIVATE;
devmem->pagemap.res = devmem->resource; devmem->pagemap.res = *devmem->resource;
devmem->pagemap.page_fault = hmm_devmem_fault; devmem->pagemap.page_fault = hmm_devmem_fault;
devmem->pagemap.page_free = hmm_devmem_free; devmem->pagemap.page_free = hmm_devmem_free;
devmem->pagemap.dev = devmem->device; devmem->pagemap.dev = devmem->device;