> index 42d79bcc8aab..d3e52ae71bd9 100644
> --- a/mm/hmm.c
> +++ b/mm/hmm.c
> @@ -996,6 +996,7 @@ static void hmm_devmem_release(struct device *dev, void 
> *data)
>       struct zone *zone;
>       struct page *page;
>       int nid;
> +     bool mapping;
>  
>       if (percpu_ref_tryget_live(&devmem->ref)) {
>               dev_WARN(dev, "%s: page mapping is still live!\n", __func__);
> @@ -1010,12 +1011,15 @@ static void hmm_devmem_release(struct device *dev, 
> void *data)
>       zone = page_zone(page);
>       nid = zone->zone_pgdat->node_id;
>  
> -     mem_hotplug_begin();
>       if (resource->desc == IORES_DESC_DEVICE_PRIVATE_MEMORY)
> -             __remove_pages(zone, start_pfn, npages, NULL);
> +             mapping = false;
>       else
> -             arch_remove_memory(nid, start_pfn << PAGE_SHIFT,
> -                                npages << PAGE_SHIFT, NULL);
> +             mapping = true;
> +
> +     mem_hotplug_begin();
> +     del_device_memory(nid, start_pfn << PAGE_SHIFT, npages << PAGE_SHIFT,
> +                                                             NULL,
> +                                                             mapping);
>       mem_hotplug_done();
>  
>       hmm_devmem_radix_release(resource);
> @@ -1026,6 +1030,7 @@ static int hmm_devmem_pages_create(struct hmm_devmem 
> *devmem)
>       resource_size_t key, align_start, align_size, align_end;
>       struct device *device = devmem->device;
>       int ret, nid, is_ram;
> +     bool mapping;
>  
>       align_start = devmem->resource->start & ~(PA_SECTION_SIZE - 1);
>       align_size = ALIGN(devmem->resource->start +
> @@ -1084,7 +1089,6 @@ static int hmm_devmem_pages_create(struct hmm_devmem 
> *devmem)
>       if (nid < 0)
>               nid = numa_mem_id();
>  
> -     mem_hotplug_begin();
>       /*
>        * For device private memory we call add_pages() as we only need to
>        * allocate and initialize struct page for the device memory. More-
> @@ -1096,20 +1100,17 @@ static int hmm_devmem_pages_create(struct hmm_devmem 
> *devmem)
>        * want the linear mapping and thus use arch_add_memory().
>        */

Some parts of this comment should be moved into add_device_memory now.
(e.g. we call add_pages() ...)

>       if (devmem->pagemap.type == MEMORY_DEVICE_PUBLIC)
> -             ret = arch_add_memory(nid, align_start, align_size, NULL,
> -                             false);
> +             mapping = true;
>       else
> -             ret = add_pages(nid, align_start >> PAGE_SHIFT,
> -                             align_size >> PAGE_SHIFT, NULL, false);
> -     if (ret) {
> -             mem_hotplug_done();
> -             goto error_add_memory;
> -     }
> -     move_pfn_range_to_zone(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
> -                             align_start >> PAGE_SHIFT,
> -                             align_size >> PAGE_SHIFT, NULL);
> +             mapping = false;
> +
> +     mem_hotplug_begin();
> +     ret = add_device_memory(nid, align_start, align_size, NULL, mapping);
>       mem_hotplug_done();
>  
> +     if (ret)
> +             goto error_add_memory;
> +
>       /*
>        * Initialization of the pages has been deferred until now in order
>        * to allow us to do the work while not holding the hotplug lock.
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index 33d448314b3f..5874aceb81ac 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -1889,4 +1889,45 @@ void remove_memory(int nid, u64 start, u64 size)
>       unlock_device_hotplug();
>  }
>  EXPORT_SYMBOL_GPL(remove_memory);
> +
> +#ifdef CONFIG_ZONE_DEVICE
> +int del_device_memory(int nid, unsigned long start, unsigned long size,
> +                             struct vmem_altmap *altmap, bool mapping)
> +{
> +     int ret;

nit: personally I prefer short parameters last in the list.

> +     unsigned long start_pfn = PHYS_PFN(start);
> +     unsigned long nr_pages = size >> PAGE_SHIFT;
> +     struct zone *zone = page_zone(pfn_to_page(pfn));
> +
> +     if (mapping)
> +             ret = arch_remove_memory(nid, start, size, altmap);
> +     else
> +             ret = __remove_pages(zone, start_pfn, nr_pages, altmap);
> +
> +     return ret;
> +}
> +#endif
>  #endif /* CONFIG_MEMORY_HOTREMOVE */
> +
> +#ifdef CONFIG_ZONE_DEVICE
> +int add_device_memory(int nid, unsigned long start, unsigned long size,
> +                             struct vmem_altmap *altmap, bool mapping)
> +{
> +     int ret;

dito

> +     unsigned long start_pfn = PHYS_PFN(start);
> +     unsigned long nr_pages = size >> PAGE_SHIFT;
> +
> +     if (mapping)
> +             ret = arch_add_memory(nid, start, size, altmap, false);
> +     else
> +             ret = add_pages(nid, start_pfn, nr_pages, altmap, false);
> +
> +     if (!ret) {
> +             struct zone *zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE];
> +
> +             move_pfn_range_to_zone(zone, start_pfn, nr_pages, altmap);
> +     }
> +
> +     return ret;
> +}
> +#endif
> 

Can you document for both functions that they should be called with the
memory hotplug lock in write?

Apart from that looks good to me.

-- 

Thanks,

David / dhildenb

Reply via email to