From patchwork Sat Apr 18 01:36:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 6236241 Return-Path: X-Original-To: patchwork-linux-nvdimm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id F23F4BF4A6 for ; Sat, 18 Apr 2015 01:39:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C4D2420394 for ; Sat, 18 Apr 2015 01:39:00 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9108720398 for ; Sat, 18 Apr 2015 01:38:59 +0000 (UTC) Received: from ml01.vlan14.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 86A13813BD; Fri, 17 Apr 2015 18:38:59 -0700 (PDT) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by ml01.01.org (Postfix) with ESMTP id AB0DB81388 for ; Fri, 17 Apr 2015 18:38:58 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP; 17 Apr 2015 18:38:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,598,1422950400"; d="scan'208";a="557972300" Received: from dwillia2-desk3.jf.intel.com (HELO dwillia2-desk3.amr.corp.intel.com) ([10.23.232.36]) by orsmga003.jf.intel.com with ESMTP; 17 Apr 2015 18:38:58 -0700 From: Dan Williams To: linux-nvdimm@lists.01.org Date: Fri, 17 Apr 2015 21:36:18 -0400 Message-ID: <20150418013618.25237.99555.stgit@dwillia2-desk3.amr.corp.intel.com> In-Reply-To: <20150418013256.25237.96403.stgit@dwillia2-desk3.amr.corp.intel.com> References: <20150418013256.25237.96403.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.17.1-8-g92dd MIME-Version: 1.0 Cc: linux-kernel@vger.kernel.org, Andy Lutomirski , Jens Axboe , "H. Peter Anvin" , Christoph Hellwig , Ingo Molnar Subject: [Linux-nvdimm] [PATCH 12/21] nd_pmem: add NFIT support to the pmem driver X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP nd_pmem attaches to persistent memory regions and namespaces emitted by the nd subsystem, and, same as the original pmem driver, presents the system-physical-address range as a block device. Cc: Andy Lutomirski Cc: Boaz Harrosh Cc: H. Peter Anvin Cc: Jens Axboe Cc: Ingo Molnar Cc: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/block/Kconfig | 11 ------- drivers/block/Makefile | 1 - drivers/block/nd/Kconfig | 17 +++++++++++ drivers/block/nd/Makefile | 3 ++ drivers/block/nd/pmem.c | 72 +++++++++++++++++++++++++++++++++++++++------ 5 files changed, 83 insertions(+), 21 deletions(-) rename drivers/block/{pmem.c => nd/pmem.c} (81%) diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index dfe40e5ca9bd..1cef4ffb16c5 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -406,17 +406,6 @@ config BLK_DEV_RAM_DAX and will prevent RAM block device backing store memory from being allocated from highmem (only a problem for highmem systems). -config BLK_DEV_PMEM - tristate "Persistent memory block device support" - help - Saying Y here will allow you to use a contiguous range of reserved - memory as one or more persistent block devices. - - To compile this driver as a module, choose M here: the module will be - called 'pmem'. - - If unsure, say N. - config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 18b27bb9cd2d..3a2f15be66a3 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_PS3_VRAM) += ps3vram.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o -obj-$(CONFIG_BLK_DEV_PMEM) += pmem.o obj-$(CONFIG_BLK_DEV_LOOP) += loop.o obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o diff --git a/drivers/block/nd/Kconfig b/drivers/block/nd/Kconfig index 6c15d10bf4e0..38eae5f0ae4b 100644 --- a/drivers/block/nd/Kconfig +++ b/drivers/block/nd/Kconfig @@ -72,4 +72,21 @@ config NFIT_TEST Say N unless you are doing development of the 'nd' subsystem. +config BLK_DEV_PMEM + tristate "PMEM: Persistent memory block device support" + depends on ND_CORE || X86_PMEM_LEGACY + default ND_CORE + help + Memory ranges for PMEM are described by either an NFIT + (NVDIMM Firmware Interface Table, see CONFIG_NFIT_ACPI), a + non-standard OEM-specific E820 memory type (type-12, see + CONFIG_X86_PMEM_LEGACY), or it is manually specified by the + 'memmap=nn[KMG]!ss[KMG]' kernel command line (see + Documentation/kernel-parameters.txt). This driver converts + these persistent memory ranges into block devices that are + capable of DAX (direct-access) file system mappings. See + Documentation/blockdev/nd.txt for more details. + + Say Y if you want to use a NVDIMM described by NFIT + endif diff --git a/drivers/block/nd/Makefile b/drivers/block/nd/Makefile index 769ddc34f974..c0194d52e5ad 100644 --- a/drivers/block/nd/Makefile +++ b/drivers/block/nd/Makefile @@ -16,6 +16,7 @@ endif obj-$(CONFIG_ND_CORE) += nd.o obj-$(CONFIG_NFIT_ACPI) += nd_acpi.o +obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o nd_acpi-y := acpi.o @@ -26,3 +27,5 @@ nd-y += dimm.o nd-y += region_devs.o nd-y += region.o nd-y += namespace_devs.o + +nd_pmem-y := pmem.o diff --git a/drivers/block/pmem.c b/drivers/block/nd/pmem.c similarity index 81% rename from drivers/block/pmem.c rename to drivers/block/nd/pmem.c index eabf4a8d0085..cd83a9a98d89 100644 --- a/drivers/block/pmem.c +++ b/drivers/block/nd/pmem.c @@ -1,7 +1,7 @@ /* * Persistent Memory Driver * - * Copyright (c) 2014, Intel Corporation. + * Copyright (c) 2014-2015, Intel Corporation. * Copyright (c) 2015, Christoph Hellwig . * Copyright (c) 2015, Boaz Harrosh . * @@ -23,6 +23,7 @@ #include #include #include +#include #define PMEM_MINORS 16 @@ -34,10 +35,11 @@ struct pmem_device { phys_addr_t phys_addr; void *virt_addr; size_t size; + int id; }; static int pmem_major; -static atomic_t pmem_index; +static DEFINE_IDA(pmem_ida); static void pmem_do_bvec(struct pmem_device *pmem, struct page *page, unsigned int len, unsigned int off, int rw, @@ -122,20 +124,26 @@ static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res) { struct pmem_device *pmem; struct gendisk *disk; - int idx, err; + int err; err = -ENOMEM; pmem = kzalloc(sizeof(*pmem), GFP_KERNEL); if (!pmem) goto out; + pmem->id = ida_simple_get(&pmem_ida, 0, 0, GFP_KERNEL); + if (pmem->id < 0) { + err = pmem->id; + goto out_free_dev; + } + pmem->phys_addr = res->start; pmem->size = resource_size(res); err = -EINVAL; if (!request_mem_region(pmem->phys_addr, pmem->size, "pmem")) { dev_warn(dev, "could not reserve region [0x%pa:0x%zx]\n", &pmem->phys_addr, pmem->size); - goto out_free_dev; + goto out_free_ida; } /* @@ -159,15 +167,13 @@ static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res) if (!disk) goto out_free_queue; - idx = atomic_inc_return(&pmem_index) - 1; - disk->major = pmem_major; - disk->first_minor = PMEM_MINORS * idx; + disk->first_minor = PMEM_MINORS * pmem->id; disk->fops = &pmem_fops; disk->private_data = pmem; disk->queue = pmem->pmem_queue; disk->flags = GENHD_FL_EXT_DEVT; - sprintf(disk->disk_name, "pmem%d", idx); + sprintf(disk->disk_name, "pmem%d", pmem->id); disk->driverfs_dev = dev; set_capacity(disk, pmem->size >> 9); pmem->pmem_disk = disk; @@ -182,6 +188,8 @@ out_unmap: iounmap(pmem->virt_addr); out_release_region: release_mem_region(pmem->phys_addr, pmem->size); +out_free_ida: + ida_simple_remove(&pmem_ida, pmem->id); out_free_dev: kfree(pmem); out: @@ -195,6 +203,7 @@ static void pmem_free(struct pmem_device *pmem) blk_cleanup_queue(pmem->pmem_queue); iounmap(pmem->virt_addr); release_mem_region(pmem->phys_addr, pmem->size); + ida_simple_remove(&pmem_ida, pmem->id); kfree(pmem); } @@ -236,6 +245,39 @@ static struct platform_driver pmem_driver = { }, }; +static int nd_pmem_probe(struct device *dev) +{ + struct nd_namespace_io *nsio = to_nd_namespace_io(dev); + struct pmem_device *pmem; + + pmem = pmem_alloc(dev, &nsio->res); + if (IS_ERR(pmem)) + return PTR_ERR(pmem); + + dev_set_drvdata(dev, pmem); + + return 0; +} + +static int nd_pmem_remove(struct device *dev) +{ + struct pmem_device *pmem = dev_get_drvdata(dev); + + pmem_free(pmem); + return 0; +} + +MODULE_ALIAS("pmem"); +MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_IO); +static struct nd_device_driver nd_pmem_driver = { + .probe = nd_pmem_probe, + .remove = nd_pmem_remove, + .drv = { + .name = "pmem", + }, + .type = ND_DRIVER_NAMESPACE_IO, +}; + static int __init pmem_init(void) { int error; @@ -244,9 +286,20 @@ static int __init pmem_init(void) if (pmem_major < 0) return pmem_major; + error = nd_driver_register(&nd_pmem_driver); + if (error) + goto out_unregister_blkdev; + error = platform_driver_register(&pmem_driver); if (error) - unregister_blkdev(pmem_major, "pmem"); + goto out_unregister_nd; + + return 0; + + out_unregister_nd: + driver_unregister(&nd_pmem_driver.drv); + out_unregister_blkdev: + unregister_blkdev(pmem_major, "pmem"); return error; } module_init(pmem_init); @@ -254,6 +307,7 @@ module_init(pmem_init); static void pmem_exit(void) { platform_driver_unregister(&pmem_driver); + driver_unregister(&nd_pmem_driver.drv); unregister_blkdev(pmem_major, "pmem"); } module_exit(pmem_exit);