Blame view
drivers/dax/pmem.c
4.09 KB
ab68f2622 /dev/dax, pmem: d... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* * Copyright(c) 2016 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ #include <linux/percpu-refcount.h> #include <linux/memremap.h> #include <linux/module.h> #include <linux/pfn_t.h> #include "../nvdimm/pfn.h" #include "../nvdimm/nd.h" |
7b6be8444 dax: refactor dax... |
19 |
#include "device-dax.h" |
ab68f2622 /dev/dax, pmem: d... |
20 21 22 23 24 25 |
struct dax_pmem { struct device *dev; struct percpu_ref ref; struct completion cmp; }; |
ccdb07f62 dax: cleanup need... |
26 |
static struct dax_pmem *to_dax_pmem(struct percpu_ref *ref) |
ab68f2622 /dev/dax, pmem: d... |
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
{ return container_of(ref, struct dax_pmem, ref); } static void dax_pmem_percpu_release(struct percpu_ref *ref) { struct dax_pmem *dax_pmem = to_dax_pmem(ref); dev_dbg(dax_pmem->dev, "%s ", __func__); complete(&dax_pmem->cmp); } static void dax_pmem_percpu_exit(void *data) { struct percpu_ref *ref = data; struct dax_pmem *dax_pmem = to_dax_pmem(ref); dev_dbg(dax_pmem->dev, "%s ", __func__); |
713897038 mm, zone_device: ... |
47 |
wait_for_completion(&dax_pmem->cmp); |
ab68f2622 /dev/dax, pmem: d... |
48 |
percpu_ref_exit(ref); |
ab68f2622 /dev/dax, pmem: d... |
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
} static void dax_pmem_percpu_kill(void *data) { struct percpu_ref *ref = data; struct dax_pmem *dax_pmem = to_dax_pmem(ref); dev_dbg(dax_pmem->dev, "%s ", __func__); percpu_ref_kill(ref); } static int dax_pmem_probe(struct device *dev) { |
ab68f2622 /dev/dax, pmem: d... |
63 64 |
void *addr; struct resource res; |
bbb3be170 device-dax: fix s... |
65 |
int rc, id, region_id; |
ab68f2622 /dev/dax, pmem: d... |
66 |
struct nd_pfn_sb *pfn_sb; |
5f0694b30 device-dax: renam... |
67 |
struct dev_dax *dev_dax; |
ab68f2622 /dev/dax, pmem: d... |
68 |
struct dax_pmem *dax_pmem; |
ab68f2622 /dev/dax, pmem: d... |
69 70 71 72 73 74 75 76 77 78 79 80 81 |
struct nd_namespace_io *nsio; struct dax_region *dax_region; struct nd_namespace_common *ndns; struct nd_dax *nd_dax = to_nd_dax(dev); struct nd_pfn *nd_pfn = &nd_dax->nd_pfn; struct vmem_altmap __altmap, *altmap = NULL; ndns = nvdimm_namespace_common_probe(dev); if (IS_ERR(ndns)) return PTR_ERR(ndns); nsio = to_nd_namespace_io(&ndns->dev); /* parse the 'pfn' info block via ->rw_bytes */ |
6a84fb4b4 device-dax: check... |
82 83 84 |
rc = devm_nsio_enable(dev, nsio); if (rc) return rc; |
ab68f2622 /dev/dax, pmem: d... |
85 86 87 88 89 90 91 92 |
altmap = nvdimm_setup_pfn(nd_pfn, &res, &__altmap); if (IS_ERR(altmap)) return PTR_ERR(altmap); devm_nsio_disable(dev, nsio); pfn_sb = nd_pfn->pfn_sb; if (!devm_request_mem_region(dev, nsio->res.start, |
450c6633e libnvdimm: use co... |
93 94 |
resource_size(&nsio->res), dev_name(&ndns->dev))) { |
ab68f2622 /dev/dax, pmem: d... |
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
dev_warn(dev, "could not reserve region %pR ", &nsio->res); return -EBUSY; } dax_pmem = devm_kzalloc(dev, sizeof(*dax_pmem), GFP_KERNEL); if (!dax_pmem) return -ENOMEM; dax_pmem->dev = dev; init_completion(&dax_pmem->cmp); rc = percpu_ref_init(&dax_pmem->ref, dax_pmem_percpu_release, 0, GFP_KERNEL); if (rc) return rc; |
d1c8e0c52 dax: use devm_add... |
110 111 112 |
rc = devm_add_action_or_reset(dev, dax_pmem_percpu_exit, &dax_pmem->ref); if (rc) |
ab68f2622 /dev/dax, pmem: d... |
113 |
return rc; |
ab68f2622 /dev/dax, pmem: d... |
114 115 116 117 |
addr = devm_memremap_pages(dev, &res, &dax_pmem->ref, altmap); if (IS_ERR(addr)) return PTR_ERR(addr); |
d1c8e0c52 dax: use devm_add... |
118 119 120 |
rc = devm_add_action_or_reset(dev, dax_pmem_percpu_kill, &dax_pmem->ref); if (rc) |
ab68f2622 /dev/dax, pmem: d... |
121 |
return rc; |
ab68f2622 /dev/dax, pmem: d... |
122 |
|
d0e584556 dax: fix device-d... |
123 124 |
/* adjust the dax_region resource to the start of data */ res.start += le64_to_cpu(pfn_sb->dataoff); |
bbb3be170 device-dax: fix s... |
125 126 127 128 129 |
rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", ®ion_id, &id); if (rc != 2) return -EINVAL; dax_region = alloc_dax_region(dev, region_id, &res, |
ab68f2622 /dev/dax, pmem: d... |
130 131 132 133 134 |
le32_to_cpu(pfn_sb->align), addr, PFN_DEV|PFN_MAP); if (!dax_region) return -ENOMEM; /* TODO: support for subdividing a dax region... */ |
bbb3be170 device-dax: fix s... |
135 |
dev_dax = devm_create_dev_dax(dax_region, id, &res, 1); |
ab68f2622 /dev/dax, pmem: d... |
136 |
|
5f0694b30 device-dax: renam... |
137 |
/* child dev_dax instances now own the lifetime of the dax_region */ |
ab68f2622 /dev/dax, pmem: d... |
138 |
dax_region_put(dax_region); |
5f0694b30 device-dax: renam... |
139 |
return PTR_ERR_OR_ZERO(dev_dax); |
ab68f2622 /dev/dax, pmem: d... |
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
} static struct nd_device_driver dax_pmem_driver = { .probe = dax_pmem_probe, .drv = { .name = "dax_pmem", }, .type = ND_DRIVER_DAX_PMEM, }; static int __init dax_pmem_init(void) { return nd_driver_register(&dax_pmem_driver); } module_init(dax_pmem_init); static void __exit dax_pmem_exit(void) { driver_unregister(&dax_pmem_driver.drv); } module_exit(dax_pmem_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Intel Corporation"); MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DAX_PMEM); |