On Fri, Jan 6, 2017 at 8:46 AM, Jérôme Glisse <jgli...@redhat.com> wrote: > Some device driver manage multiple physical devices memory from a single > fake device driver. In that case the fake device might outlive the real > device and ZONE_DEVICE and its resource allocated for a real device would > waste resources in the meantime. > > This patch allow early removal of ZONE_DEVICE and associated resource, > before device driver is tear down. > > Signed-off-by: Jérôme Glisse <jgli...@redhat.com> > Cc: Dan Williams <dan.j.willi...@intel.com> > Cc: Ross Zwisler <ross.zwis...@linux.intel.com> > --- > include/linux/memremap.h | 7 +++++++ > kernel/memremap.c | 14 ++++++++++++++ > 2 files changed, 21 insertions(+) > > diff --git a/include/linux/memremap.h b/include/linux/memremap.h > index f7e0609..32314d2 100644 > --- a/include/linux/memremap.h > +++ b/include/linux/memremap.h > @@ -53,6 +53,7 @@ struct dev_pagemap { > void *devm_memremap_pages(struct device *dev, struct resource *res, > struct percpu_ref *ref, struct vmem_altmap *altmap); > struct dev_pagemap *find_dev_pagemap(resource_size_t phys); > +int devm_memremap_pages_remove(struct device *dev, struct dev_pagemap > *pgmap); > > static inline bool dev_page_allow_migrate(const struct page *page) > { > @@ -78,6 +79,12 @@ static inline struct dev_pagemap > *find_dev_pagemap(resource_size_t phys) > return NULL; > } > > +static inline int devm_memremap_pages_remove(struct device *dev, > + struct dev_pagemap *pgmap) > +{ > + return -EINVAL; > +} > + > static inline bool dev_page_allow_migrate(const struct page *page) > { > return false; > diff --git a/kernel/memremap.c b/kernel/memremap.c > index 07665eb..250ef25 100644 > --- a/kernel/memremap.c > +++ b/kernel/memremap.c > @@ -387,6 +387,20 @@ void *devm_memremap_pages(struct device *dev, struct > resource *res, > } > EXPORT_SYMBOL(devm_memremap_pages); > > +static int devm_page_map_match(struct device *dev, void *data, void > *match_data) > +{ > + struct page_map *page_map = data; > + > + return &page_map->pgmap == match_data; > +} > + > +int devm_memremap_pages_remove(struct device *dev, struct dev_pagemap *pgmap) > +{ > + return devres_release(dev, &devm_memremap_pages_release, > + &devm_page_map_match, pgmap); > +} > +EXPORT_SYMBOL(devm_memremap_pages_remove);
I think this should be called devm_memunmap_pages() to mirror devm_memunmap(), and it should take the virtual address returned from devm_memremap_pages() not pgmap which is an internal detail.