]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - mm/hmm.c
mm, hmm: use devm semantics for hmm_devmem_{add, remove}
[mirror_ubuntu-bionic-kernel.git] / mm / hmm.c
index ea19742a5d60b1a6270629a024d88a13b9c5f3c1..9767a9ad5779d54bb2dc7729a6271a42ed6096dc 100644 (file)
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -277,7 +277,8 @@ static int hmm_pfns_bad(unsigned long addr,
                        unsigned long end,
                        struct mm_walk *walk)
 {
-       struct hmm_range *range = walk->private;
+       struct hmm_vma_walk *hmm_vma_walk = walk->private;
+       struct hmm_range *range = hmm_vma_walk->range;
        hmm_pfn_t *pfns = range->pfns;
        unsigned long i;
 
@@ -766,7 +767,6 @@ static void hmm_devmem_ref_exit(void *data)
 
        devmem = container_of(ref, struct hmm_devmem, ref);
        percpu_ref_exit(ref);
-       devm_remove_action(devmem->device, &hmm_devmem_ref_exit, data);
 }
 
 static void hmm_devmem_ref_kill(void *data)
@@ -777,7 +777,6 @@ static void hmm_devmem_ref_kill(void *data)
        devmem = container_of(ref, struct hmm_devmem, ref);
        percpu_ref_kill(ref);
        wait_for_completion(&devmem->completion);
-       devm_remove_action(devmem->device, &hmm_devmem_ref_kill, data);
 }
 
 static int hmm_devmem_fault(struct vm_area_struct *vma,
@@ -795,6 +794,8 @@ static void hmm_devmem_free(struct page *page, void *data)
 {
        struct hmm_devmem *devmem = data;
 
+       page->mapping = NULL;
+
        devmem->ops->free(devmem, page);
 }
 
@@ -816,7 +817,7 @@ static void hmm_devmem_radix_release(struct resource *resource)
        mutex_unlock(&hmm_devmem_lock);
 }
 
-static void hmm_devmem_release(struct device *dev, void *data)
+static void hmm_devmem_release(void *data)
 {
        struct hmm_devmem *devmem = data;
        struct resource *resource = devmem->resource;
@@ -824,11 +825,6 @@ static void hmm_devmem_release(struct device *dev, void *data)
        struct zone *zone;
        struct page *page;
 
-       if (percpu_ref_tryget_live(&devmem->ref)) {
-               dev_WARN(dev, "%s: page mapping is still live!\n", __func__);
-               percpu_ref_put(&devmem->ref);
-       }
-
        /* pages are dead and unused, undo the arch mapping */
        start_pfn = (resource->start & ~(PA_SECTION_SIZE - 1)) >> PAGE_SHIFT;
        npages = ALIGN(resource_size(resource), PA_SECTION_SIZE) >> PAGE_SHIFT;
@@ -959,19 +955,6 @@ error:
        return ret;
 }
 
-static int hmm_devmem_match(struct device *dev, void *data, void *match_data)
-{
-       struct hmm_devmem *devmem = data;
-
-       return devmem->resource == match_data;
-}
-
-static void hmm_devmem_pages_remove(struct hmm_devmem *devmem)
-{
-       devres_release(devmem->device, &hmm_devmem_release,
-                      &hmm_devmem_match, devmem->resource);
-}
-
 /*
  * hmm_devmem_add() - hotplug ZONE_DEVICE memory for device memory
  *
@@ -999,8 +982,7 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 
        static_branch_enable(&device_private_key);
 
-       devmem = devres_alloc_node(&hmm_devmem_release, sizeof(*devmem),
-                                  GFP_KERNEL, dev_to_node(device));
+       devmem = devm_kzalloc(device, sizeof(*devmem), GFP_KERNEL);
        if (!devmem)
                return ERR_PTR(-ENOMEM);
 
@@ -1014,11 +996,11 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
        ret = percpu_ref_init(&devmem->ref, &hmm_devmem_ref_release,
                              0, GFP_KERNEL);
        if (ret)
-               goto error_percpu_ref;
+               return ERR_PTR(ret);
 
-       ret = devm_add_action(device, hmm_devmem_ref_exit, &devmem->ref);
+       ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit, &devmem->ref);
        if (ret)
-               goto error_devm_add_action;
+               return ERR_PTR(ret);
 
        size = ALIGN(size, PA_SECTION_SIZE);
        addr = min((unsigned long)iomem_resource.end,
@@ -1038,16 +1020,12 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 
                devmem->resource = devm_request_mem_region(device, addr, size,
                                                           dev_name(device));
-               if (!devmem->resource) {
-                       ret = -ENOMEM;
-                       goto error_no_resource;
-               }
+               if (!devmem->resource)
+                       return ERR_PTR(-ENOMEM);
                break;
        }
-       if (!devmem->resource) {
-               ret = -ERANGE;
-               goto error_no_resource;
-       }
+       if (!devmem->resource)
+               return ERR_PTR(-ERANGE);
 
        devmem->resource->desc = IORES_DESC_DEVICE_PRIVATE_MEMORY;
        devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT;
@@ -1056,28 +1034,13 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 
        ret = hmm_devmem_pages_create(devmem);
        if (ret)
-               goto error_pages;
-
-       devres_add(device, devmem);
+               return ERR_PTR(ret);
 
-       ret = devm_add_action(device, hmm_devmem_ref_kill, &devmem->ref);
-       if (ret) {
-               hmm_devmem_remove(devmem);
+       ret = devm_add_action_or_reset(device, hmm_devmem_release, devmem);
+       if (ret)
                return ERR_PTR(ret);
-       }
 
        return devmem;
-
-error_pages:
-       devm_release_mem_region(device, devmem->resource->start,
-                               resource_size(devmem->resource));
-error_no_resource:
-error_devm_add_action:
-       hmm_devmem_ref_kill(&devmem->ref);
-       hmm_devmem_ref_exit(&devmem->ref);
-error_percpu_ref:
-       devres_free(devmem);
-       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(hmm_devmem_add);
 
@@ -1093,8 +1056,7 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 
        static_branch_enable(&device_private_key);
 
-       devmem = devres_alloc_node(&hmm_devmem_release, sizeof(*devmem),
-                                  GFP_KERNEL, dev_to_node(device));
+       devmem = devm_kzalloc(device, sizeof(*devmem), GFP_KERNEL);
        if (!devmem)
                return ERR_PTR(-ENOMEM);
 
@@ -1108,12 +1070,12 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
        ret = percpu_ref_init(&devmem->ref, &hmm_devmem_ref_release,
                              0, GFP_KERNEL);
        if (ret)
-               goto error_percpu_ref;
+               return ERR_PTR(ret);
 
-       ret = devm_add_action(device, hmm_devmem_ref_exit, &devmem->ref);
+       ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit,
+                       &devmem->ref);
        if (ret)
-               goto error_devm_add_action;
-
+               return ERR_PTR(ret);
 
        devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT;
        devmem->pfn_last = devmem->pfn_first +
@@ -1121,59 +1083,21 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 
        ret = hmm_devmem_pages_create(devmem);
        if (ret)
-               goto error_devm_add_action;
+               return ERR_PTR(ret);
 
-       devres_add(device, devmem);
+       ret = devm_add_action_or_reset(device, hmm_devmem_release, devmem);
+       if (ret)
+               return ERR_PTR(ret);
 
-       ret = devm_add_action(device, hmm_devmem_ref_kill, &devmem->ref);
-       if (ret) {
-               hmm_devmem_remove(devmem);
+       ret = devm_add_action_or_reset(device, hmm_devmem_ref_kill,
+                       &devmem->ref);
+       if (ret)
                return ERR_PTR(ret);
-       }
 
        return devmem;
-
-error_devm_add_action:
-       hmm_devmem_ref_kill(&devmem->ref);
-       hmm_devmem_ref_exit(&devmem->ref);
-error_percpu_ref:
-       devres_free(devmem);
-       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(hmm_devmem_add_resource);
 
-/*
- * hmm_devmem_remove() - remove device memory (kill and free ZONE_DEVICE)
- *
- * @devmem: hmm_devmem struct use to track and manage the ZONE_DEVICE memory
- *
- * This will hot-unplug memory that was hotplugged by hmm_devmem_add on behalf
- * of the device driver. It will free struct page and remove the resource that
- * reserved the physical address range for this device memory.
- */
-void hmm_devmem_remove(struct hmm_devmem *devmem)
-{
-       resource_size_t start, size;
-       struct device *device;
-       bool cdm = false;
-
-       if (!devmem)
-               return;
-
-       device = devmem->device;
-       start = devmem->resource->start;
-       size = resource_size(devmem->resource);
-
-       cdm = devmem->resource->desc == IORES_DESC_DEVICE_PUBLIC_MEMORY;
-       hmm_devmem_ref_kill(&devmem->ref);
-       hmm_devmem_ref_exit(&devmem->ref);
-       hmm_devmem_pages_remove(devmem);
-
-       if (!cdm)
-               devm_release_mem_region(device, start, size);
-}
-EXPORT_SYMBOL(hmm_devmem_remove);
-
 /*
  * A device driver that wants to handle multiple devices memory through a
  * single fake device can use hmm_device to do so. This is purely a helper