aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dax/dax.h7
-rw-r--r--drivers/nvdimm/Kconfig1
-rw-r--r--drivers/nvdimm/pmem.c61
-rw-r--r--drivers/nvdimm/pmem.h7
-rw-r--r--include/linux/dax.h6
-rw-r--r--tools/testing/nvdimm/pmem-dax.c21
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__
15struct dax_device; 15struct dax_device;
16struct dax_operations;
17struct dax_device *alloc_dax(void *private, const char *host,
18 const struct dax_operations *ops);
19void put_dax(struct dax_device *dax_dev);
20bool dax_alive(struct dax_device *dax_dev);
21void kill_dax(struct dax_device *dax_dev);
22struct dax_device *inode_dax(struct inode *inode); 16struct dax_device *inode_dax(struct inode *inode);
23struct inode *dax_inode(struct dax_device *dax_dev); 17struct inode *dax_inode(struct dax_device *dax_dev);
24void *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
20config BLK_DEV_PMEM 20config 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
223static 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
222static const struct block_device_operations pmem_fops = { 232static 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
239static 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
247static const struct dax_operations pmem_dax_ops = {
248 .direct_access = pmem_dax_direct_access,
249};
250
229static void pmem_release_queue(void *q) 251static void pmem_release_queue(void *q)
230{ 252{
231 blk_cleanup_queue(q); 253 blk_cleanup_queue(q);
232} 254}
233 255
234static void pmem_release_disk(void *disk) 256static 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
240static int pmem_attach_disk(struct device *dev, 266static 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
8long 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 */
11struct pmem_device { 9struct 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
25long __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 {
21int dax_read_lock(void); 21int dax_read_lock(void);
22void dax_read_unlock(int id); 22void dax_read_unlock(int id);
23struct dax_device *dax_get_by_host(const char *host); 23struct dax_device *dax_get_by_host(const char *host);
24struct dax_device *alloc_dax(void *private, const char *host,
25 const struct dax_operations *ops);
26void put_dax(struct dax_device *dax_dev);
27bool dax_alive(struct dax_device *dax_dev);
28void kill_dax(struct dax_device *dax_dev);
29void *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
18long pmem_direct_access(struct block_device *bdev, sector_t sector, 18long __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}