Skip to content

Commit 89ec9f2

Browse files
committed
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>
1 parent 9567da0 commit 89ec9f2

File tree

5 files changed

+90
-79
lines changed

5 files changed

+90
-79
lines changed

drivers/dax/bus.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */
3+
#include <linux/memremap.h>
34
#include <linux/device.h>
45
#include <linux/slab.h>
56
#include <linux/dax.h>
@@ -206,7 +207,8 @@ static void unregister_dev_dax(void *dev)
206207
put_device(dev);
207208
}
208209

209-
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
210+
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
211+
struct dev_pagemap *pgmap)
210212
{
211213
struct device *parent = dax_region->dev;
212214
struct dax_device *dax_dev;
@@ -222,6 +224,8 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
222224
if (!dev_dax)
223225
return ERR_PTR(-ENOMEM);
224226

227+
memcpy(&dev_dax->pgmap, pgmap, sizeof(*pgmap));
228+
225229
/*
226230
* No 'host' or dax_operations since there is no access to this
227231
* device outside of mmap of the resulting character device.

drivers/dax/bus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ struct dax_region;
1010
void dax_region_put(struct dax_region *dax_region);
1111
struct dax_region *alloc_dax_region(struct device *parent, int region_id,
1212
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);
1415
int __dax_driver_register(struct device_driver *drv,
1516
struct module *module, const char *mod_name);
1617
#define dax_driver_register(driver) \

drivers/dax/dax-private.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,22 @@ struct dax_region {
4242
};
4343

4444
/**
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.
4647
* @region - parent region
4748
* @dax_dev - core dax functionality
4849
* @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)
4953
*/
5054
struct dev_dax {
5155
struct dax_region *region;
5256
struct dax_device *dax_dev;
5357
struct device dev;
58+
struct dev_pagemap pgmap;
59+
struct percpu_ref ref;
60+
struct completion cmp;
5461
};
5562

5663
static inline struct dev_dax *to_dev_dax(struct device *dev)

drivers/dax/device.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/* Copyright(c) 2016-2018 Intel Corporation. All rights reserved. */
3+
#include <linux/memremap.h>
34
#include <linux/pagemap.h>
45
#include <linux/module.h>
56
#include <linux/device.h>
@@ -13,6 +14,38 @@
1314
#include "dax-private.h"
1415
#include "bus.h"
1516

17+
static struct dev_dax *ref_to_dev_dax(struct percpu_ref *ref)
18+
{
19+
return container_of(ref, struct dev_dax, ref);
20+
}
21+
22+
static void dev_dax_percpu_release(struct percpu_ref *ref)
23+
{
24+
struct dev_dax *dev_dax = ref_to_dev_dax(ref);
25+
26+
dev_dbg(&dev_dax->dev, "%s\n", __func__);
27+
complete(&dev_dax->cmp);
28+
}
29+
30+
static void dev_dax_percpu_exit(void *data)
31+
{
32+
struct percpu_ref *ref = data;
33+
struct dev_dax *dev_dax = ref_to_dev_dax(ref);
34+
35+
dev_dbg(&dev_dax->dev, "%s\n", __func__);
36+
wait_for_completion(&dev_dax->cmp);
37+
percpu_ref_exit(ref);
38+
}
39+
40+
static void dev_dax_percpu_kill(struct percpu_ref *data)
41+
{
42+
struct percpu_ref *ref = data;
43+
struct dev_dax *dev_dax = ref_to_dev_dax(ref);
44+
45+
dev_dbg(&dev_dax->dev, "%s\n", __func__);
46+
percpu_ref_kill(ref);
47+
}
48+
1649
static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
1750
const char *func)
1851
{
@@ -416,10 +449,38 @@ static int dev_dax_probe(struct device *dev)
416449
{
417450
struct dev_dax *dev_dax = to_dev_dax(dev);
418451
struct dax_device *dax_dev = dev_dax->dax_dev;
452+
struct resource *res = &dev_dax->region->res;
419453
struct inode *inode;
420454
struct cdev *cdev;
455+
void *addr;
421456
int rc;
422457

458+
/* 1:1 map region resource range to device-dax instance range */
459+
if (!devm_request_mem_region(dev, res->start, resource_size(res),
460+
dev_name(dev))) {
461+
dev_warn(dev, "could not reserve region %pR\n", res);
462+
return -EBUSY;
463+
}
464+
465+
init_completion(&dev_dax->cmp);
466+
rc = percpu_ref_init(&dev_dax->ref, dev_dax_percpu_release, 0,
467+
GFP_KERNEL);
468+
if (rc)
469+
return rc;
470+
471+
rc = devm_add_action_or_reset(dev, dev_dax_percpu_exit, &dev_dax->ref);
472+
if (rc)
473+
return rc;
474+
475+
dev_dax->pgmap.ref = &dev_dax->ref;
476+
dev_dax->pgmap.kill = dev_dax_percpu_kill;
477+
addr = devm_memremap_pages(dev, &dev_dax->pgmap);
478+
if (IS_ERR(addr)) {
479+
devm_remove_action(dev, dev_dax_percpu_exit, &dev_dax->ref);
480+
percpu_ref_exit(&dev_dax->ref);
481+
return PTR_ERR(addr);
482+
}
483+
423484
inode = dax_inode(dax_dev);
424485
cdev = inode->i_cdev;
425486
cdev_init(cdev, &dax_fops);

drivers/dax/pmem.c

Lines changed: 14 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -18,54 +18,16 @@
1818
#include "../nvdimm/nd.h"
1919
#include "bus.h"
2020

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-
5921
static int dax_pmem_probe(struct device *dev)
6022
{
61-
void *addr;
6223
struct resource res;
6324
int rc, id, region_id;
25+
resource_size_t offset;
6426
struct nd_pfn_sb *pfn_sb;
6527
struct dev_dax *dev_dax;
66-
struct dax_pmem *dax_pmem;
6728
struct nd_namespace_io *nsio;
6829
struct dax_region *dax_region;
30+
struct dev_pagemap pgmap = { 0 };
6931
struct nd_namespace_common *ndns;
7032
struct nd_dax *nd_dax = to_nd_dax(dev);
7133
struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
@@ -75,61 +37,37 @@ static int dax_pmem_probe(struct device *dev)
7537
return PTR_ERR(ndns);
7638
nsio = to_nd_namespace_io(&ndns->dev);
7739

78-
dax_pmem = devm_kzalloc(dev, sizeof(*dax_pmem), GFP_KERNEL);
79-
if (!dax_pmem)
80-
return -ENOMEM;
81-
8240
/* parse the 'pfn' info block via ->rw_bytes */
8341
rc = devm_nsio_enable(dev, nsio);
8442
if (rc)
8543
return rc;
86-
rc = nvdimm_setup_pfn(nd_pfn, &dax_pmem->pgmap);
44+
rc = nvdimm_setup_pfn(nd_pfn, &pgmap);
8745
if (rc)
8846
return rc;
8947
devm_nsio_disable(dev, nsio);
9048

91-
pfn_sb = nd_pfn->pfn_sb;
92-
93-
if (!devm_request_mem_region(dev, nsio->res.start,
94-
resource_size(&nsio->res),
49+
/* reserve the metadata area, device-dax will reserve the data */
50+
pfn_sb = nd_pfn->pfn_sb;
51+
offset = le64_to_cpu(pfn_sb->dataoff);
52+
if (!devm_request_mem_region(dev, nsio->res.start, offset,
9553
dev_name(&ndns->dev))) {
96-
dev_warn(dev, "could not reserve region %pR\n", &nsio->res);
97-
return -EBUSY;
98-
}
99-
100-
dax_pmem->dev = dev;
101-
init_completion(&dax_pmem->cmp);
102-
rc = percpu_ref_init(&dax_pmem->ref, dax_pmem_percpu_release, 0,
103-
GFP_KERNEL);
104-
if (rc)
105-
return rc;
106-
107-
rc = devm_add_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
108-
if (rc) {
109-
percpu_ref_exit(&dax_pmem->ref);
110-
return rc;
111-
}
112-
113-
dax_pmem->pgmap.ref = &dax_pmem->ref;
114-
dax_pmem->pgmap.kill = dax_pmem_percpu_kill;
115-
addr = devm_memremap_pages(dev, &dax_pmem->pgmap);
116-
if (IS_ERR(addr))
117-
return PTR_ERR(addr);
118-
119-
/* adjust the dax_region resource to the start of data */
120-
memcpy(&res, &dax_pmem->pgmap.res, sizeof(res));
121-
res.start += le64_to_cpu(pfn_sb->dataoff);
54+
dev_warn(dev, "could not reserve metadata\n");
55+
return -EBUSY;
56+
}
12257

12358
rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id);
12459
if (rc != 2)
12560
return -EINVAL;
12661

62+
/* adjust the dax_region resource to the start of data */
63+
memcpy(&res, &pgmap.res, sizeof(res));
64+
res.start += offset;
12765
dax_region = alloc_dax_region(dev, region_id, &res,
12866
le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP);
12967
if (!dax_region)
13068
return -ENOMEM;
13169

132-
dev_dax = devm_create_dev_dax(dax_region, id);
70+
dev_dax = devm_create_dev_dax(dax_region, id, &pgmap);
13371

13472
/* child dev_dax instances now own the lifetime of the dax_region */
13573
dax_region_put(dax_region);

0 commit comments

Comments
 (0)