diff options
-rw-r--r-- | drivers/dax/dax.h | 7 | ||||
-rw-r--r-- | drivers/nvdimm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 61 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.h | 7 | ||||
-rw-r--r-- | include/linux/dax.h | 6 | ||||
-rw-r--r-- | tools/testing/nvdimm/pmem-dax.c | 21 |
6 files changed, 70 insertions, 33 deletions
diff --git a/drivers/dax/dax.h b/drivers/dax/dax.h index 617bbc24be2b..f9e5feea742c 100644 --- a/drivers/dax/dax.h +++ b/drivers/dax/dax.h | |||
@@ -13,13 +13,6 @@ | |||
13 | #ifndef __DAX_H__ | 13 | #ifndef __DAX_H__ |
14 | #define __DAX_H__ | 14 | #define __DAX_H__ |
15 | struct dax_device; | 15 | struct dax_device; |
16 | struct dax_operations; | ||
17 | struct dax_device *alloc_dax(void *private, const char *host, | ||
18 | const struct dax_operations *ops); | ||
19 | void put_dax(struct dax_device *dax_dev); | ||
20 | bool dax_alive(struct dax_device *dax_dev); | ||
21 | void kill_dax(struct dax_device *dax_dev); | ||
22 | struct dax_device *inode_dax(struct inode *inode); | 16 | struct dax_device *inode_dax(struct inode *inode); |
23 | struct inode *dax_inode(struct dax_device *dax_dev); | 17 | struct inode *dax_inode(struct dax_device *dax_dev); |
24 | void *dax_get_private(struct dax_device *dax_dev); | ||
25 | #endif /* __DAX_H__ */ | 18 | #endif /* __DAX_H__ */ |
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig index 59e750183b7f..5bdd499b5f4f 100644 --- a/drivers/nvdimm/Kconfig +++ b/drivers/nvdimm/Kconfig | |||
@@ -20,6 +20,7 @@ if LIBNVDIMM | |||
20 | config BLK_DEV_PMEM | 20 | config BLK_DEV_PMEM |
21 | tristate "PMEM: Persistent memory block device support" | 21 | tristate "PMEM: Persistent memory block device support" |
22 | default LIBNVDIMM | 22 | default LIBNVDIMM |
23 | select DAX | ||
23 | select ND_BTT if BTT | 24 | select ND_BTT if BTT |
24 | select ND_PFN if NVDIMM_PFN | 25 | select ND_PFN if NVDIMM_PFN |
25 | help | 26 | help |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 5b536be5a12e..fbbcf8154eec 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/pfn_t.h> | 28 | #include <linux/pfn_t.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/pmem.h> | 30 | #include <linux/pmem.h> |
31 | #include <linux/dax.h> | ||
31 | #include <linux/nd.h> | 32 | #include <linux/nd.h> |
32 | #include "pmem.h" | 33 | #include "pmem.h" |
33 | #include "pfn.h" | 34 | #include "pfn.h" |
@@ -199,13 +200,13 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector, | |||
199 | } | 200 | } |
200 | 201 | ||
201 | /* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */ | 202 | /* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */ |
202 | __weak long pmem_direct_access(struct block_device *bdev, sector_t sector, | 203 | __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, |
203 | void **kaddr, pfn_t *pfn, long size) | 204 | long nr_pages, void **kaddr, pfn_t *pfn) |
204 | { | 205 | { |
205 | struct pmem_device *pmem = bdev->bd_queue->queuedata; | 206 | resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset; |
206 | resource_size_t offset = sector * 512 + pmem->data_offset; | ||
207 | 207 | ||
208 | if (unlikely(is_bad_pmem(&pmem->bb, sector, size))) | 208 | if (unlikely(is_bad_pmem(&pmem->bb, PFN_PHYS(pgoff) / 512, |
209 | PFN_PHYS(nr_pages)))) | ||
209 | return -EIO; | 210 | return -EIO; |
210 | *kaddr = pmem->virt_addr + offset; | 211 | *kaddr = pmem->virt_addr + offset; |
211 | *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags); | 212 | *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags); |
@@ -215,26 +216,51 @@ __weak long pmem_direct_access(struct block_device *bdev, sector_t sector, | |||
215 | * requested range. | 216 | * requested range. |
216 | */ | 217 | */ |
217 | if (unlikely(pmem->bb.count)) | 218 | if (unlikely(pmem->bb.count)) |
218 | return size; | 219 | return nr_pages; |
219 | return pmem->size - pmem->pfn_pad - offset; | 220 | return PHYS_PFN(pmem->size - pmem->pfn_pad - offset); |
221 | } | ||
222 | |||
223 | static long pmem_blk_direct_access(struct block_device *bdev, sector_t sector, | ||
224 | void **kaddr, pfn_t *pfn, long size) | ||
225 | { | ||
226 | struct pmem_device *pmem = bdev->bd_queue->queuedata; | ||
227 | |||
228 | return __pmem_direct_access(pmem, PHYS_PFN(sector * 512), | ||
229 | PHYS_PFN(size), kaddr, pfn); | ||
220 | } | 230 | } |
221 | 231 | ||
222 | static const struct block_device_operations pmem_fops = { | 232 | static const struct block_device_operations pmem_fops = { |
223 | .owner = THIS_MODULE, | 233 | .owner = THIS_MODULE, |
224 | .rw_page = pmem_rw_page, | 234 | .rw_page = pmem_rw_page, |
225 | .direct_access = pmem_direct_access, | 235 | .direct_access = pmem_blk_direct_access, |
226 | .revalidate_disk = nvdimm_revalidate_disk, | 236 | .revalidate_disk = nvdimm_revalidate_disk, |
227 | }; | 237 | }; |
228 | 238 | ||
239 | static long pmem_dax_direct_access(struct dax_device *dax_dev, | ||
240 | pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) | ||
241 | { | ||
242 | struct pmem_device *pmem = dax_get_private(dax_dev); | ||
243 | |||
244 | return __pmem_direct_access(pmem, pgoff, nr_pages, kaddr, pfn); | ||
245 | } | ||
246 | |||
247 | static const struct dax_operations pmem_dax_ops = { | ||
248 | .direct_access = pmem_dax_direct_access, | ||
249 | }; | ||
250 | |||
229 | static void pmem_release_queue(void *q) | 251 | static void pmem_release_queue(void *q) |
230 | { | 252 | { |
231 | blk_cleanup_queue(q); | 253 | blk_cleanup_queue(q); |
232 | } | 254 | } |
233 | 255 | ||
234 | static void pmem_release_disk(void *disk) | 256 | static void pmem_release_disk(void *__pmem) |
235 | { | 257 | { |
236 | del_gendisk(disk); | 258 | struct pmem_device *pmem = __pmem; |
237 | put_disk(disk); | 259 | |
260 | kill_dax(pmem->dax_dev); | ||
261 | put_dax(pmem->dax_dev); | ||
262 | del_gendisk(pmem->disk); | ||
263 | put_disk(pmem->disk); | ||
238 | } | 264 | } |
239 | 265 | ||
240 | static int pmem_attach_disk(struct device *dev, | 266 | static int pmem_attach_disk(struct device *dev, |
@@ -245,6 +271,7 @@ static int pmem_attach_disk(struct device *dev, | |||
245 | struct vmem_altmap __altmap, *altmap = NULL; | 271 | struct vmem_altmap __altmap, *altmap = NULL; |
246 | struct resource *res = &nsio->res; | 272 | struct resource *res = &nsio->res; |
247 | struct nd_pfn *nd_pfn = NULL; | 273 | struct nd_pfn *nd_pfn = NULL; |
274 | struct dax_device *dax_dev; | ||
248 | int nid = dev_to_node(dev); | 275 | int nid = dev_to_node(dev); |
249 | struct nd_pfn_sb *pfn_sb; | 276 | struct nd_pfn_sb *pfn_sb; |
250 | struct pmem_device *pmem; | 277 | struct pmem_device *pmem; |
@@ -325,6 +352,7 @@ static int pmem_attach_disk(struct device *dev, | |||
325 | disk = alloc_disk_node(0, nid); | 352 | disk = alloc_disk_node(0, nid); |
326 | if (!disk) | 353 | if (!disk) |
327 | return -ENOMEM; | 354 | return -ENOMEM; |
355 | pmem->disk = disk; | ||
328 | 356 | ||
329 | disk->fops = &pmem_fops; | 357 | disk->fops = &pmem_fops; |
330 | disk->queue = q; | 358 | disk->queue = q; |
@@ -336,9 +364,16 @@ static int pmem_attach_disk(struct device *dev, | |||
336 | return -ENOMEM; | 364 | return -ENOMEM; |
337 | nvdimm_badblocks_populate(nd_region, &pmem->bb, res); | 365 | nvdimm_badblocks_populate(nd_region, &pmem->bb, res); |
338 | disk->bb = &pmem->bb; | 366 | disk->bb = &pmem->bb; |
339 | device_add_disk(dev, disk); | ||
340 | 367 | ||
341 | if (devm_add_action_or_reset(dev, pmem_release_disk, disk)) | 368 | dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops); |
369 | if (!dax_dev) { | ||
370 | put_disk(disk); | ||
371 | return -ENOMEM; | ||
372 | } | ||
373 | pmem->dax_dev = dax_dev; | ||
374 | |||
375 | device_add_disk(dev, disk); | ||
376 | if (devm_add_action_or_reset(dev, pmem_release_disk, pmem)) | ||
342 | return -ENOMEM; | 377 | return -ENOMEM; |
343 | 378 | ||
344 | revalidate_disk(disk); | 379 | revalidate_disk(disk); |
diff --git a/drivers/nvdimm/pmem.h b/drivers/nvdimm/pmem.h index b4ee4f71b4a1..7f4dbd72a90a 100644 --- a/drivers/nvdimm/pmem.h +++ b/drivers/nvdimm/pmem.h | |||
@@ -5,8 +5,6 @@ | |||
5 | #include <linux/pfn_t.h> | 5 | #include <linux/pfn_t.h> |
6 | #include <linux/fs.h> | 6 | #include <linux/fs.h> |
7 | 7 | ||
8 | long pmem_direct_access(struct block_device *bdev, sector_t sector, | ||
9 | void **kaddr, pfn_t *pfn, long size); | ||
10 | /* this definition is in it's own header for tools/testing/nvdimm to consume */ | 8 | /* this definition is in it's own header for tools/testing/nvdimm to consume */ |
11 | struct pmem_device { | 9 | struct pmem_device { |
12 | /* One contiguous memory region per device */ | 10 | /* One contiguous memory region per device */ |
@@ -20,5 +18,10 @@ struct pmem_device { | |||
20 | /* trim size when namespace capacity has been section aligned */ | 18 | /* trim size when namespace capacity has been section aligned */ |
21 | u32 pfn_pad; | 19 | u32 pfn_pad; |
22 | struct badblocks bb; | 20 | struct badblocks bb; |
21 | struct dax_device *dax_dev; | ||
22 | struct gendisk *disk; | ||
23 | }; | 23 | }; |
24 | |||
25 | long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, | ||
26 | long nr_pages, void **kaddr, pfn_t *pfn); | ||
24 | #endif /* __NVDIMM_PMEM_H__ */ | 27 | #endif /* __NVDIMM_PMEM_H__ */ |
diff --git a/include/linux/dax.h b/include/linux/dax.h index 74ebb92b625a..39a0312c45c3 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h | |||
@@ -21,6 +21,12 @@ struct dax_operations { | |||
21 | int dax_read_lock(void); | 21 | int dax_read_lock(void); |
22 | void dax_read_unlock(int id); | 22 | void dax_read_unlock(int id); |
23 | struct dax_device *dax_get_by_host(const char *host); | 23 | struct dax_device *dax_get_by_host(const char *host); |
24 | struct dax_device *alloc_dax(void *private, const char *host, | ||
25 | const struct dax_operations *ops); | ||
26 | void put_dax(struct dax_device *dax_dev); | ||
27 | bool dax_alive(struct dax_device *dax_dev); | ||
28 | void kill_dax(struct dax_device *dax_dev); | ||
29 | void *dax_get_private(struct dax_device *dax_dev); | ||
24 | 30 | ||
25 | /* | 31 | /* |
26 | * We use lowest available bit in exceptional entry for locking, one bit for | 32 | * We use lowest available bit in exceptional entry for locking, one bit for |
diff --git a/tools/testing/nvdimm/pmem-dax.c b/tools/testing/nvdimm/pmem-dax.c index c9b8c48f85fc..b53596ad601b 100644 --- a/tools/testing/nvdimm/pmem-dax.c +++ b/tools/testing/nvdimm/pmem-dax.c | |||
@@ -15,13 +15,13 @@ | |||
15 | #include <pmem.h> | 15 | #include <pmem.h> |
16 | #include <nd.h> | 16 | #include <nd.h> |
17 | 17 | ||
18 | long pmem_direct_access(struct block_device *bdev, sector_t sector, | 18 | long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, |
19 | void **kaddr, pfn_t *pfn, long size) | 19 | long nr_pages, void **kaddr, pfn_t *pfn) |
20 | { | 20 | { |
21 | struct pmem_device *pmem = bdev->bd_queue->queuedata; | 21 | resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset; |
22 | resource_size_t offset = sector * 512 + pmem->data_offset; | ||
23 | 22 | ||
24 | if (unlikely(is_bad_pmem(&pmem->bb, sector, size))) | 23 | if (unlikely(is_bad_pmem(&pmem->bb, PFN_PHYS(pgoff) / 512, |
24 | PFN_PHYS(nr_pages)))) | ||
25 | return -EIO; | 25 | return -EIO; |
26 | 26 | ||
27 | /* | 27 | /* |
@@ -34,11 +34,10 @@ long pmem_direct_access(struct block_device *bdev, sector_t sector, | |||
34 | *kaddr = pmem->virt_addr + offset; | 34 | *kaddr = pmem->virt_addr + offset; |
35 | page = vmalloc_to_page(pmem->virt_addr + offset); | 35 | page = vmalloc_to_page(pmem->virt_addr + offset); |
36 | *pfn = page_to_pfn_t(page); | 36 | *pfn = page_to_pfn_t(page); |
37 | dev_dbg_ratelimited(disk_to_dev(bdev->bd_disk)->parent, | 37 | pr_debug_ratelimited("%s: pmem: %p pgoff: %#lx pfn: %#lx\n", |
38 | "%s: sector: %#llx pfn: %#lx\n", __func__, | 38 | __func__, pmem, pgoff, page_to_pfn(page)); |
39 | (unsigned long long) sector, page_to_pfn(page)); | ||
40 | 39 | ||
41 | return PAGE_SIZE; | 40 | return 1; |
42 | } | 41 | } |
43 | 42 | ||
44 | *kaddr = pmem->virt_addr + offset; | 43 | *kaddr = pmem->virt_addr + offset; |
@@ -49,6 +48,6 @@ long pmem_direct_access(struct block_device *bdev, sector_t sector, | |||
49 | * requested range. | 48 | * requested range. |
50 | */ | 49 | */ |
51 | if (unlikely(pmem->bb.count)) | 50 | if (unlikely(pmem->bb.count)) |
52 | return size; | 51 | return nr_pages; |
53 | return pmem->size - pmem->pfn_pad - offset; | 52 | return PHYS_PFN(pmem->size - pmem->pfn_pad - offset); |
54 | } | 53 | } |