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

device-dax, tools/testing/nvdimm: enable device-dax with mock resources

Provide a replacement pgoff_to_phys() that translates an nfit_test
resource (allocated by vmalloc()) to a pfn.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

authored by

Dave Jiang and committed by
Dan Williams
efebc711 006358b3

+118 -47
+61
drivers/dax/dax-private.h
··· 1 + /* 2 + * Copyright(c) 2016 Intel Corporation. All rights reserved. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of version 2 of the GNU General Public License as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but 9 + * WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 + * General Public License for more details. 12 + */ 13 + #ifndef __DAX_PRIVATE_H__ 14 + #define __DAX_PRIVATE_H__ 15 + 16 + #include <linux/device.h> 17 + #include <linux/cdev.h> 18 + 19 + /** 20 + * struct dax_region - mapping infrastructure for dax devices 21 + * @id: kernel-wide unique region for a memory range 22 + * @base: linear address corresponding to @res 23 + * @kref: to pin while other agents have a need to do lookups 24 + * @dev: parent device backing this region 25 + * @align: allocation and mapping alignment for child dax devices 26 + * @res: physical address range of the region 27 + * @pfn_flags: identify whether the pfns are paged back or not 28 + */ 29 + struct dax_region { 30 + int id; 31 + struct ida ida; 32 + void *base; 33 + struct kref kref; 34 + struct device *dev; 35 + unsigned int align; 36 + struct resource res; 37 + unsigned long pfn_flags; 38 + }; 39 + 40 + /** 41 + * struct dax_dev - subdivision of a dax region 42 + * @region - parent region 43 + * @inode - inode 44 + * @dev - device backing the character device 45 + * @cdev - core chardev data 46 + * @alive - !alive + srcu grace period == no new mappings can be established 47 + * @id - child id in the region 48 + * @num_resources - number of physical address extents in this device 49 + * @res - array of physical address ranges 50 + */ 51 + struct dax_dev { 52 + struct dax_region *region; 53 + struct inode *inode; 54 + struct device dev; 55 + struct cdev cdev; 56 + bool alive; 57 + int id; 58 + int num_resources; 59 + struct resource res[0]; 60 + }; 61 + #endif
+6 -46
drivers/dax/dax.c
··· 22 22 #include <linux/dax.h> 23 23 #include <linux/fs.h> 24 24 #include <linux/mm.h> 25 + #include "dax-private.h" 25 26 #include "dax.h" 26 27 27 28 static dev_t dax_devt; ··· 35 34 static struct kmem_cache *dax_cache __read_mostly; 36 35 static struct super_block *dax_superblock __read_mostly; 37 36 MODULE_PARM_DESC(nr_dax, "max number of device-dax instances"); 38 - 39 - /** 40 - * struct dax_region - mapping infrastructure for dax devices 41 - * @id: kernel-wide unique region for a memory range 42 - * @base: linear address corresponding to @res 43 - * @kref: to pin while other agents have a need to do lookups 44 - * @dev: parent device backing this region 45 - * @align: allocation and mapping alignment for child dax devices 46 - * @res: physical address range of the region 47 - * @pfn_flags: identify whether the pfns are paged back or not 48 - */ 49 - struct dax_region { 50 - int id; 51 - struct ida ida; 52 - void *base; 53 - struct kref kref; 54 - struct device *dev; 55 - unsigned int align; 56 - struct resource res; 57 - unsigned long pfn_flags; 58 - }; 59 - 60 - /** 61 - * struct dax_dev - subdivision of a dax region 62 - * @region - parent region 63 - * @dev - device backing the character device 64 - * @cdev - core chardev data 65 - * @alive - !alive + srcu grace period == no new mappings can be established 66 - * @id - child id in the region 67 - * @num_resources - number of physical address extents in this device 68 - * @res - array of physical address ranges 69 - */ 70 - struct dax_dev { 71 - struct dax_region *region; 72 - struct inode *inode; 73 - struct device dev; 74 - struct cdev cdev; 75 - bool alive; 76 - int id; 77 - int num_resources; 78 - struct resource res[0]; 79 - }; 80 37 81 38 static ssize_t id_show(struct device *dev, 82 39 struct device_attribute *attr, char *buf) ··· 356 397 return 0; 357 398 } 358 399 359 - static phys_addr_t pgoff_to_phys(struct dax_dev *dax_dev, pgoff_t pgoff, 400 + /* see "strong" declaration in tools/testing/nvdimm/dax-dev.c */ 401 + __weak phys_addr_t dax_pgoff_to_phys(struct dax_dev *dax_dev, pgoff_t pgoff, 360 402 unsigned long size) 361 403 { 362 404 struct resource *res; ··· 402 442 if (fault_size != dax_region->align) 403 443 return VM_FAULT_SIGBUS; 404 444 405 - phys = pgoff_to_phys(dax_dev, vmf->pgoff, PAGE_SIZE); 445 + phys = dax_pgoff_to_phys(dax_dev, vmf->pgoff, PAGE_SIZE); 406 446 if (phys == -1) { 407 447 dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__, 408 448 vmf->pgoff); ··· 457 497 return VM_FAULT_SIGBUS; 458 498 459 499 pgoff = linear_page_index(vmf->vma, pmd_addr); 460 - phys = pgoff_to_phys(dax_dev, pgoff, PMD_SIZE); 500 + phys = dax_pgoff_to_phys(dax_dev, pgoff, PMD_SIZE); 461 501 if (phys == -1) { 462 502 dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__, 463 503 pgoff); ··· 508 548 return VM_FAULT_SIGBUS; 509 549 510 550 pgoff = linear_page_index(vmf->vma, pud_addr); 511 - phys = pgoff_to_phys(dax_dev, pgoff, PUD_SIZE); 551 + phys = dax_pgoff_to_phys(dax_dev, pgoff, PUD_SIZE); 512 552 if (phys == -1) { 513 553 dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__, 514 554 pgoff);
+2 -1
tools/testing/nvdimm/Kbuild
··· 28 28 obj-$(CONFIG_ND_BLK) += nd_blk.o 29 29 obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o 30 30 obj-$(CONFIG_ACPI_NFIT) += nfit.o 31 - obj-$(CONFIG_DEV_DAX) += dax.o 31 + obj-$(CONFIG_DEV_DAX) += dax.o dax-dev.o 32 32 obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o 33 33 34 34 nfit-y := $(ACPI_SRC)/core.o ··· 49 49 nd_e820-y += config_check.o 50 50 51 51 dax-y := $(DAX_SRC)/dax.o 52 + dax-y += dax-dev.o 52 53 dax-y += config_check.o 53 54 54 55 dax_pmem-y := $(DAX_SRC)/pmem.o
+49
tools/testing/nvdimm/dax-dev.c
··· 1 + /* 2 + * Copyright (c) 2016, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + */ 13 + #include "test/nfit_test.h" 14 + #include <linux/mm.h> 15 + #include "../../../drivers/dax/dax-private.h" 16 + 17 + phys_addr_t dax_pgoff_to_phys(struct dax_dev *dax_dev, pgoff_t pgoff, 18 + unsigned long size) 19 + { 20 + struct resource *res; 21 + phys_addr_t addr; 22 + int i; 23 + 24 + for (i = 0; i < dax_dev->num_resources; i++) { 25 + res = &dax_dev->res[i]; 26 + addr = pgoff * PAGE_SIZE + res->start; 27 + if (addr >= res->start && addr <= res->end) 28 + break; 29 + pgoff -= PHYS_PFN(resource_size(res)); 30 + } 31 + 32 + if (i < dax_dev->num_resources) { 33 + res = &dax_dev->res[i]; 34 + if (addr + size - 1 <= res->end) { 35 + if (get_nfit_res(addr)) { 36 + struct page *page; 37 + 38 + if (dax_dev->region->align > PAGE_SIZE) 39 + return -1; 40 + 41 + page = vmalloc_to_page((void *)addr); 42 + return PFN_PHYS(page_to_pfn(page)); 43 + } else 44 + return addr; 45 + } 46 + } 47 + 48 + return -1; 49 + }