Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

device-dax: Move resource pinning+mapping into the common driver

Move the responsibility of calling devm_request_resource() and
devm_memremap_pages() into the common device-dax driver. This is another
preparatory step to allowing an alternate personality driver for a
device-dax range.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+90 -79
+5 -1
drivers/dax/bus.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */ 3 + #include <linux/memremap.h> 3 4 #include <linux/device.h> 4 5 #include <linux/slab.h> 5 6 #include <linux/dax.h> ··· 207 206 put_device(dev); 208 207 } 209 208 210 - struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id) 209 + struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id, 210 + struct dev_pagemap *pgmap) 211 211 { 212 212 struct device *parent = dax_region->dev; 213 213 struct dax_device *dax_dev; ··· 223 221 dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL); 224 222 if (!dev_dax) 225 223 return ERR_PTR(-ENOMEM); 224 + 225 + memcpy(&dev_dax->pgmap, pgmap, sizeof(*pgmap)); 226 226 227 227 /* 228 228 * No 'host' or dax_operations since there is no access to this
+2 -1
drivers/dax/bus.h
··· 10 10 void dax_region_put(struct dax_region *dax_region); 11 11 struct dax_region *alloc_dax_region(struct device *parent, int region_id, 12 12 struct resource *res, unsigned int align, unsigned long flags); 13 - struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id); 13 + struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id, 14 + struct dev_pagemap *pgmap); 14 15 int __dax_driver_register(struct device_driver *drv, 15 16 struct module *module, const char *mod_name); 16 17 #define dax_driver_register(driver) \
+8 -1
drivers/dax/dax-private.h
··· 42 42 }; 43 43 44 44 /** 45 - * struct dev_dax - instance data for a subdivision of a dax region 45 + * struct dev_dax - instance data for a subdivision of a dax region, and 46 + * data while the device is activated in the driver. 46 47 * @region - parent region 47 48 * @dax_dev - core dax functionality 48 49 * @dev - device core 50 + * @pgmap - pgmap for memmap setup / lifetime (driver owned) 51 + * @ref: pgmap reference count (driver owned) 52 + * @cmp: @ref final put completion (driver owned) 49 53 */ 50 54 struct dev_dax { 51 55 struct dax_region *region; 52 56 struct dax_device *dax_dev; 53 57 struct device dev; 58 + struct dev_pagemap pgmap; 59 + struct percpu_ref ref; 60 + struct completion cmp; 54 61 }; 55 62 56 63 static inline struct dev_dax *to_dev_dax(struct device *dev)
+61
drivers/dax/device.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright(c) 2016-2018 Intel Corporation. All rights reserved. */ 3 + #include <linux/memremap.h> 3 4 #include <linux/pagemap.h> 4 5 #include <linux/module.h> 5 6 #include <linux/device.h> ··· 13 12 #include <linux/mman.h> 14 13 #include "dax-private.h" 15 14 #include "bus.h" 15 + 16 + static struct dev_dax *ref_to_dev_dax(struct percpu_ref *ref) 17 + { 18 + return container_of(ref, struct dev_dax, ref); 19 + } 20 + 21 + static void dev_dax_percpu_release(struct percpu_ref *ref) 22 + { 23 + struct dev_dax *dev_dax = ref_to_dev_dax(ref); 24 + 25 + dev_dbg(&dev_dax->dev, "%s\n", __func__); 26 + complete(&dev_dax->cmp); 27 + } 28 + 29 + static void dev_dax_percpu_exit(void *data) 30 + { 31 + struct percpu_ref *ref = data; 32 + struct dev_dax *dev_dax = ref_to_dev_dax(ref); 33 + 34 + dev_dbg(&dev_dax->dev, "%s\n", __func__); 35 + wait_for_completion(&dev_dax->cmp); 36 + percpu_ref_exit(ref); 37 + } 38 + 39 + static void dev_dax_percpu_kill(struct percpu_ref *data) 40 + { 41 + struct percpu_ref *ref = data; 42 + struct dev_dax *dev_dax = ref_to_dev_dax(ref); 43 + 44 + dev_dbg(&dev_dax->dev, "%s\n", __func__); 45 + percpu_ref_kill(ref); 46 + } 16 47 17 48 static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma, 18 49 const char *func) ··· 449 416 { 450 417 struct dev_dax *dev_dax = to_dev_dax(dev); 451 418 struct dax_device *dax_dev = dev_dax->dax_dev; 419 + struct resource *res = &dev_dax->region->res; 452 420 struct inode *inode; 453 421 struct cdev *cdev; 422 + void *addr; 454 423 int rc; 424 + 425 + /* 1:1 map region resource range to device-dax instance range */ 426 + if (!devm_request_mem_region(dev, res->start, resource_size(res), 427 + dev_name(dev))) { 428 + dev_warn(dev, "could not reserve region %pR\n", res); 429 + return -EBUSY; 430 + } 431 + 432 + init_completion(&dev_dax->cmp); 433 + rc = percpu_ref_init(&dev_dax->ref, dev_dax_percpu_release, 0, 434 + GFP_KERNEL); 435 + if (rc) 436 + return rc; 437 + 438 + rc = devm_add_action_or_reset(dev, dev_dax_percpu_exit, &dev_dax->ref); 439 + if (rc) 440 + return rc; 441 + 442 + dev_dax->pgmap.ref = &dev_dax->ref; 443 + dev_dax->pgmap.kill = dev_dax_percpu_kill; 444 + addr = devm_memremap_pages(dev, &dev_dax->pgmap); 445 + if (IS_ERR(addr)) { 446 + devm_remove_action(dev, dev_dax_percpu_exit, &dev_dax->ref); 447 + percpu_ref_exit(&dev_dax->ref); 448 + return PTR_ERR(addr); 449 + } 455 450 456 451 inode = dax_inode(dax_dev); 457 452 cdev = inode->i_cdev;
+14 -76
drivers/dax/pmem.c
··· 18 18 #include "../nvdimm/nd.h" 19 19 #include "bus.h" 20 20 21 - struct dax_pmem { 22 - struct device *dev; 23 - struct percpu_ref ref; 24 - struct dev_pagemap pgmap; 25 - struct completion cmp; 26 - }; 27 - 28 - static struct dax_pmem *to_dax_pmem(struct percpu_ref *ref) 29 - { 30 - return container_of(ref, struct dax_pmem, ref); 31 - } 32 - 33 - static void dax_pmem_percpu_release(struct percpu_ref *ref) 34 - { 35 - struct dax_pmem *dax_pmem = to_dax_pmem(ref); 36 - 37 - dev_dbg(dax_pmem->dev, "trace\n"); 38 - complete(&dax_pmem->cmp); 39 - } 40 - 41 - static void dax_pmem_percpu_exit(void *data) 42 - { 43 - struct percpu_ref *ref = data; 44 - struct dax_pmem *dax_pmem = to_dax_pmem(ref); 45 - 46 - dev_dbg(dax_pmem->dev, "trace\n"); 47 - wait_for_completion(&dax_pmem->cmp); 48 - percpu_ref_exit(ref); 49 - } 50 - 51 - static void dax_pmem_percpu_kill(struct percpu_ref *ref) 52 - { 53 - struct dax_pmem *dax_pmem = to_dax_pmem(ref); 54 - 55 - dev_dbg(dax_pmem->dev, "trace\n"); 56 - percpu_ref_kill(ref); 57 - } 58 - 59 21 static int dax_pmem_probe(struct device *dev) 60 22 { 61 - void *addr; 62 23 struct resource res; 63 24 int rc, id, region_id; 25 + resource_size_t offset; 64 26 struct nd_pfn_sb *pfn_sb; 65 27 struct dev_dax *dev_dax; 66 - struct dax_pmem *dax_pmem; 67 28 struct nd_namespace_io *nsio; 68 29 struct dax_region *dax_region; 30 + struct dev_pagemap pgmap = { 0 }; 69 31 struct nd_namespace_common *ndns; 70 32 struct nd_dax *nd_dax = to_nd_dax(dev); 71 33 struct nd_pfn *nd_pfn = &nd_dax->nd_pfn; ··· 37 75 return PTR_ERR(ndns); 38 76 nsio = to_nd_namespace_io(&ndns->dev); 39 77 40 - dax_pmem = devm_kzalloc(dev, sizeof(*dax_pmem), GFP_KERNEL); 41 - if (!dax_pmem) 42 - return -ENOMEM; 43 - 44 78 /* parse the 'pfn' info block via ->rw_bytes */ 45 79 rc = devm_nsio_enable(dev, nsio); 46 80 if (rc) 47 81 return rc; 48 - rc = nvdimm_setup_pfn(nd_pfn, &dax_pmem->pgmap); 82 + rc = nvdimm_setup_pfn(nd_pfn, &pgmap); 49 83 if (rc) 50 84 return rc; 51 85 devm_nsio_disable(dev, nsio); 52 86 53 - pfn_sb = nd_pfn->pfn_sb; 54 - 55 - if (!devm_request_mem_region(dev, nsio->res.start, 56 - resource_size(&nsio->res), 87 + /* reserve the metadata area, device-dax will reserve the data */ 88 + pfn_sb = nd_pfn->pfn_sb; 89 + offset = le64_to_cpu(pfn_sb->dataoff); 90 + if (!devm_request_mem_region(dev, nsio->res.start, offset, 57 91 dev_name(&ndns->dev))) { 58 - dev_warn(dev, "could not reserve region %pR\n", &nsio->res); 59 - return -EBUSY; 60 - } 61 - 62 - dax_pmem->dev = dev; 63 - init_completion(&dax_pmem->cmp); 64 - rc = percpu_ref_init(&dax_pmem->ref, dax_pmem_percpu_release, 0, 65 - GFP_KERNEL); 66 - if (rc) 67 - return rc; 68 - 69 - rc = devm_add_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref); 70 - if (rc) { 71 - percpu_ref_exit(&dax_pmem->ref); 72 - return rc; 73 - } 74 - 75 - dax_pmem->pgmap.ref = &dax_pmem->ref; 76 - dax_pmem->pgmap.kill = dax_pmem_percpu_kill; 77 - addr = devm_memremap_pages(dev, &dax_pmem->pgmap); 78 - if (IS_ERR(addr)) 79 - return PTR_ERR(addr); 80 - 81 - /* adjust the dax_region resource to the start of data */ 82 - memcpy(&res, &dax_pmem->pgmap.res, sizeof(res)); 83 - res.start += le64_to_cpu(pfn_sb->dataoff); 92 + dev_warn(dev, "could not reserve metadata\n"); 93 + return -EBUSY; 94 + } 84 95 85 96 rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id); 86 97 if (rc != 2) 87 98 return -EINVAL; 88 99 100 + /* adjust the dax_region resource to the start of data */ 101 + memcpy(&res, &pgmap.res, sizeof(res)); 102 + res.start += offset; 89 103 dax_region = alloc_dax_region(dev, region_id, &res, 90 104 le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP); 91 105 if (!dax_region) 92 106 return -ENOMEM; 93 107 94 - dev_dax = devm_create_dev_dax(dax_region, id); 108 + dev_dax = devm_create_dev_dax(dax_region, id, &pgmap); 95 109 96 110 /* child dev_dax instances now own the lifetime of the dax_region */ 97 111 dax_region_put(dax_region);