diff options
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r-- | drivers/nvdimm/Kconfig | 2 | ||||
-rw-r--r-- | drivers/nvdimm/badrange.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/btt.c | 36 | ||||
-rw-r--r-- | drivers/nvdimm/bus.c | 29 | ||||
-rw-r--r-- | drivers/nvdimm/claim.c | 20 | ||||
-rw-r--r-- | drivers/nvdimm/core.c | 31 | ||||
-rw-r--r-- | drivers/nvdimm/dax_devs.c | 4 | ||||
-rw-r--r-- | drivers/nvdimm/e820.c | 4 | ||||
-rw-r--r-- | drivers/nvdimm/label.c | 3 | ||||
-rw-r--r-- | drivers/nvdimm/namespace_devs.c | 43 | ||||
-rw-r--r-- | drivers/nvdimm/nd-core.h | 4 | ||||
-rw-r--r-- | drivers/nvdimm/nd.h | 10 | ||||
-rw-r--r-- | drivers/nvdimm/nd_virtio.c | 12 | ||||
-rw-r--r-- | drivers/nvdimm/of_pmem.c | 7 | ||||
-rw-r--r-- | drivers/nvdimm/pfn_devs.c | 9 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 60 | ||||
-rw-r--r-- | drivers/nvdimm/region_devs.c | 43 | ||||
-rw-r--r-- | drivers/nvdimm/virtio_pmem.c | 25 |
18 files changed, 143 insertions, 201 deletions
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig index 77b06d54cc62..fde3e17c836c 100644 --- a/drivers/nvdimm/Kconfig +++ b/drivers/nvdimm/Kconfig @@ -24,7 +24,7 @@ config BLK_DEV_PMEM select ND_PFN if NVDIMM_PFN help Memory ranges for PMEM are described by either an NFIT - (NVDIMM Firmware Interface Table, see CONFIG_NFIT_ACPI), a + (NVDIMM Firmware Interface Table, see CONFIG_ACPI_NFIT), 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 diff --git a/drivers/nvdimm/badrange.c b/drivers/nvdimm/badrange.c index a002ea6fdd84..ee478ccde7c6 100644 --- a/drivers/nvdimm/badrange.c +++ b/drivers/nvdimm/badrange.c @@ -167,7 +167,7 @@ static void set_badblock(struct badblocks *bb, sector_t s, int num) dev_dbg(bb->dev, "Found a bad range (0x%llx, 0x%llx)\n", (u64) s * 512, (u64) num * 512); /* this isn't an error as the hardware will still throw an exception */ - if (badblocks_set(bb, s, num, 1)) + if (!badblocks_set(bb, s, num, 1)) dev_info_once(bb->dev, "%s: failed for sector %llx\n", __func__, (u64) s); } diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index bb3726b622ad..423dcd190906 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -6,6 +6,7 @@ #include <linux/highmem.h> #include <linux/debugfs.h> #include <linux/blkdev.h> +#include <linux/blk-integrity.h> #include <linux/pagemap.h> #include <linux/module.h> #include <linux/device.h> @@ -750,7 +751,7 @@ static struct arena_info *alloc_arena(struct btt *btt, size_t size, u64 logsize, mapsize, datasize; u64 available = size; - arena = kzalloc(sizeof(struct arena_info), GFP_KERNEL); + arena = kzalloc(sizeof(*arena), GFP_KERNEL); if (!arena) return NULL; arena->nd_btt = btt->nd_btt; @@ -977,7 +978,7 @@ static int btt_arena_write_layout(struct arena_info *arena) if (ret) return ret; - super = kzalloc(sizeof(struct btt_sb), GFP_NOIO); + super = kzalloc(sizeof(*super), GFP_NOIO); if (!super) return -ENOMEM; @@ -1496,28 +1497,28 @@ static int btt_blk_init(struct btt *btt) { struct nd_btt *nd_btt = btt->nd_btt; struct nd_namespace_common *ndns = nd_btt->ndns; - int rc = -ENOMEM; + struct queue_limits lim = { + .logical_block_size = btt->sector_size, + .max_hw_sectors = UINT_MAX, + .max_integrity_segments = 1, + .features = BLK_FEAT_SYNCHRONOUS, + }; + int rc; - btt->btt_disk = blk_alloc_disk(NUMA_NO_NODE); - if (!btt->btt_disk) - return -ENOMEM; + if (btt_meta_size(btt) && IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) { + lim.integrity.tuple_size = btt_meta_size(btt); + lim.integrity.tag_size = btt_meta_size(btt); + } + + btt->btt_disk = blk_alloc_disk(&lim, NUMA_NO_NODE); + if (IS_ERR(btt->btt_disk)) + return PTR_ERR(btt->btt_disk); nvdimm_namespace_disk_name(ndns, btt->btt_disk->disk_name); btt->btt_disk->first_minor = 0; btt->btt_disk->fops = &btt_fops; btt->btt_disk->private_data = btt; - blk_queue_logical_block_size(btt->btt_disk->queue, btt->sector_size); - blk_queue_max_hw_sectors(btt->btt_disk->queue, UINT_MAX); - blk_queue_flag_set(QUEUE_FLAG_NONROT, btt->btt_disk->queue); - blk_queue_flag_set(QUEUE_FLAG_SYNCHRONOUS, btt->btt_disk->queue); - - if (btt_meta_size(btt)) { - rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt)); - if (rc) - goto out_cleanup_disk; - } - set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9); rc = device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL); if (rc) @@ -1715,6 +1716,7 @@ static void __exit nd_btt_exit(void) MODULE_ALIAS_ND_DEVICE(ND_DEVICE_BTT); MODULE_AUTHOR("Vishal Verma <vishal.l.verma@linux.intel.com>"); +MODULE_DESCRIPTION("NVDIMM Block Translation Table"); MODULE_LICENSE("GPL v2"); module_init(nd_btt_init); module_exit(nd_btt_exit); diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index ef3d0f83318b..0ccf4a9e523a 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -25,9 +25,12 @@ int nvdimm_major; static int nvdimm_bus_major; -static struct class *nd_class; static DEFINE_IDA(nd_ida); +static const struct class nd_class = { + .name = "nd", +}; + static int to_nd_device_type(const struct device *dev) { if (is_nvdimm(dev)) @@ -269,9 +272,9 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, } EXPORT_SYMBOL_GPL(nvdimm_clear_poison); -static int nvdimm_bus_match(struct device *dev, struct device_driver *drv); +static int nvdimm_bus_match(struct device *dev, const struct device_driver *drv); -static struct bus_type nvdimm_bus_type = { +static const struct bus_type nvdimm_bus_type = { .name = "nd", .uevent = nvdimm_bus_uevent, .match = nvdimm_bus_match, @@ -465,9 +468,9 @@ static struct nd_device_driver nd_bus_driver = { }, }; -static int nvdimm_bus_match(struct device *dev, struct device_driver *drv) +static int nvdimm_bus_match(struct device *dev, const struct device_driver *drv) { - struct nd_device_driver *nd_drv = to_nd_device_driver(drv); + const struct nd_device_driver *nd_drv = to_nd_device_driver(drv); if (is_nvdimm_bus(dev) && nd_drv == &nd_bus_driver) return true; @@ -742,7 +745,7 @@ int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus) device_initialize(dev); lockdep_set_class(&dev->mutex, &nvdimm_ndctl_key); device_set_pm_not_required(dev); - dev->class = nd_class; + dev->class = &nd_class; dev->parent = &nvdimm_bus->dev; dev->devt = devt; dev->release = ndctl_release; @@ -765,7 +768,7 @@ err: void nvdimm_bus_destroy_ndctl(struct nvdimm_bus *nvdimm_bus) { - device_destroy(nd_class, MKDEV(nvdimm_bus_major, nvdimm_bus->id)); + device_destroy(&nd_class, MKDEV(nvdimm_bus_major, nvdimm_bus->id)); } static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = { @@ -1209,7 +1212,7 @@ enum nd_ioctl_mode { DIMM_IOCTL, }; -static int match_dimm(struct device *dev, void *data) +static int match_dimm(struct device *dev, const void *data) { long id = (long) data; @@ -1320,11 +1323,9 @@ int __init nvdimm_bus_init(void) goto err_dimm_chrdev; nvdimm_major = rc; - nd_class = class_create("nd"); - if (IS_ERR(nd_class)) { - rc = PTR_ERR(nd_class); + rc = class_register(&nd_class); + if (rc) goto err_class; - } rc = driver_register(&nd_bus_driver.drv); if (rc) @@ -1333,7 +1334,7 @@ int __init nvdimm_bus_init(void) return 0; err_nd_bus: - class_destroy(nd_class); + class_unregister(&nd_class); err_class: unregister_chrdev(nvdimm_major, "dimmctl"); err_dimm_chrdev: @@ -1347,7 +1348,7 @@ int __init nvdimm_bus_init(void) void nvdimm_bus_exit(void) { driver_unregister(&nd_bus_driver.drv); - class_destroy(nd_class); + class_unregister(&nd_class); unregister_chrdev(nvdimm_bus_major, "ndctl"); unregister_chrdev(nvdimm_major, "dimmctl"); bus_unregister(&nvdimm_bus_type); diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c index 030dbde6b088..51614651d2e7 100644 --- a/drivers/nvdimm/claim.c +++ b/drivers/nvdimm/claim.c @@ -56,24 +56,6 @@ bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, return true; } -bool nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, - struct nd_namespace_common **_ndns) -{ - bool claimed; - - nvdimm_bus_lock(&attach->dev); - claimed = __nd_attach_ndns(dev, attach, _ndns); - nvdimm_bus_unlock(&attach->dev); - return claimed; -} - -static int namespace_match(struct device *dev, void *data) -{ - char *name = data; - - return strcmp(name, dev_name(dev)) == 0; -} - static bool is_idle(struct device *dev, struct nd_namespace_common *ndns) { struct nd_region *nd_region = to_nd_region(dev->parent); @@ -168,7 +150,7 @@ ssize_t nd_namespace_store(struct device *dev, goto out; } - found = device_find_child(dev->parent, name, namespace_match); + found = device_find_child_by_name(dev->parent, name); if (!found) { dev_dbg(dev, "'%s' not found under %s\n", name, dev_name(dev->parent)); diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index d91799b71d23..eaa796629c27 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c @@ -7,7 +7,6 @@ #include <linux/export.h> #include <linux/module.h> #include <linux/blkdev.h> -#include <linux/blk-integrity.h> #include <linux/device.h> #include <linux/ctype.h> #include <linux/ndctl.h> @@ -508,35 +507,6 @@ int nvdimm_bus_add_badrange(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) } EXPORT_SYMBOL_GPL(nvdimm_bus_add_badrange); -#ifdef CONFIG_BLK_DEV_INTEGRITY -int nd_integrity_init(struct gendisk *disk, unsigned long meta_size) -{ - struct blk_integrity bi; - - if (meta_size == 0) - return 0; - - memset(&bi, 0, sizeof(bi)); - - bi.tuple_size = meta_size; - bi.tag_size = meta_size; - - blk_integrity_register(disk, &bi); - blk_queue_max_integrity_segments(disk->queue, 1); - - return 0; -} -EXPORT_SYMBOL(nd_integrity_init); - -#else /* CONFIG_BLK_DEV_INTEGRITY */ -int nd_integrity_init(struct gendisk *disk, unsigned long meta_size) -{ - return 0; -} -EXPORT_SYMBOL(nd_integrity_init); - -#endif - static __init int libnvdimm_init(void) { int rc; @@ -570,6 +540,7 @@ static __exit void libnvdimm_exit(void) nvdimm_devs_exit(); } +MODULE_DESCRIPTION("NVDIMM (Non-Volatile Memory Device) core"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Intel Corporation"); subsys_initcall(libnvdimm_init); diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c index 6b4922de3047..37b743acbb7b 100644 --- a/drivers/nvdimm/dax_devs.c +++ b/drivers/nvdimm/dax_devs.c @@ -106,12 +106,12 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns) nvdimm_bus_lock(&ndns->dev); nd_dax = nd_dax_alloc(nd_region); - nd_pfn = &nd_dax->nd_pfn; - dax_dev = nd_pfn_devinit(nd_pfn, ndns); + dax_dev = nd_dax_devinit(nd_dax, ndns); nvdimm_bus_unlock(&ndns->dev); if (!dax_dev) return -ENOMEM; pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); + nd_pfn = &nd_dax->nd_pfn; nd_pfn->pfn_sb = pfn_sb; rc = nd_pfn_validate(nd_pfn, DAX_SIG); dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : "<none>"); diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c index 4cd18be9d0e9..41c67dfa8015 100644 --- a/drivers/nvdimm/e820.c +++ b/drivers/nvdimm/e820.c @@ -9,12 +9,11 @@ #include <linux/module.h> #include <linux/numa.h> -static int e820_pmem_remove(struct platform_device *pdev) +static void e820_pmem_remove(struct platform_device *pdev) { struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev); nvdimm_bus_unregister(nvdimm_bus); - return 0; } static int e820_register_one(struct resource *res, void *data) @@ -69,5 +68,6 @@ static struct platform_driver e820_pmem_driver = { module_platform_driver(e820_pmem_driver); MODULE_ALIAS("platform:e820_pmem*"); +MODULE_DESCRIPTION("NVDIMM support for e820 type-12 memory"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Intel Corporation"); diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index 082253a3a956..04f4a049599a 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c @@ -442,7 +442,8 @@ int nd_label_data_init(struct nvdimm_drvdata *ndd) if (ndd->data) return 0; - if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0) { + if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0 || + ndd->nsarea.config_size == 0) { dev_dbg(ndd->dev, "failed to init config data area: (%u:%u)\n", ndd->nsarea.max_xfer, ndd->nsarea.config_size); return -ENXIO; diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index d6d558f94d6b..55cfbf1e0a95 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -1612,9 +1612,6 @@ static int select_pmem_id(struct nd_region *nd_region, const uuid_t *pmem_id) { int i; - if (!pmem_id) - return -ENODEV; - for (i = 0; i < nd_region->ndr_mappings; i++) { struct nd_mapping *nd_mapping = &nd_region->mapping[i]; struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); @@ -1790,9 +1787,6 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region, case -EINVAL: dev_dbg(&nd_region->dev, "invalid label(s)\n"); break; - case -ENODEV: - dev_dbg(&nd_region->dev, "label not found\n"); - break; default: dev_dbg(&nd_region->dev, "unexpected err: %d\n", rc); break; @@ -1937,12 +1931,16 @@ static int cmp_dpa(const void *a, const void *b) static struct device **scan_labels(struct nd_region *nd_region) { int i, count = 0; - struct device *dev, **devs = NULL; + struct device *dev, **devs; struct nd_label_ent *label_ent, *e; struct nd_mapping *nd_mapping = &nd_region->mapping[0]; struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); resource_size_t map_end = nd_mapping->start + nd_mapping->size - 1; + devs = kcalloc(2, sizeof(dev), GFP_KERNEL); + if (!devs) + return NULL; + /* "safe" because create_namespace_pmem() might list_move() label_ent */ list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) { struct nd_namespace_label *nd_label = label_ent->label; @@ -1961,12 +1959,14 @@ static struct device **scan_labels(struct nd_region *nd_region) goto err; if (i < count) continue; - __devs = kcalloc(count + 2, sizeof(dev), GFP_KERNEL); - if (!__devs) - goto err; - memcpy(__devs, devs, sizeof(dev) * count); - kfree(devs); - devs = __devs; + if (count) { + __devs = kcalloc(count + 2, sizeof(dev), GFP_KERNEL); + if (!__devs) + goto err; + memcpy(__devs, devs, sizeof(dev) * count); + kfree(devs); + devs = __devs; + } dev = create_namespace_pmem(nd_region, nd_mapping, nd_label); if (IS_ERR(dev)) { @@ -1974,9 +1974,6 @@ static struct device **scan_labels(struct nd_region *nd_region) case -EAGAIN: /* skip invalid labels */ continue; - case -ENODEV: - /* fallthrough to seed creation */ - break; default: goto err; } @@ -1993,11 +1990,6 @@ static struct device **scan_labels(struct nd_region *nd_region) /* Publish a zero-sized namespace for userspace to configure. */ nd_mapping_free_labels(nd_mapping); - - devs = kcalloc(2, sizeof(dev), GFP_KERNEL); - if (!devs) - goto err; - nspm = kzalloc(sizeof(*nspm), GFP_KERNEL); if (!nspm) goto err; @@ -2036,11 +2028,10 @@ static struct device **scan_labels(struct nd_region *nd_region) return devs; err: - if (devs) { - for (i = 0; devs[i]; i++) - namespace_pmem_release(devs[i]); - kfree(devs); - } + for (i = 0; devs[i]; i++) + namespace_pmem_release(devs[i]); + kfree(devs); + return NULL; } diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h index 86976a9e8a15..bfc6bfeb6e24 100644 --- a/drivers/nvdimm/nd-core.h +++ b/drivers/nvdimm/nd-core.h @@ -127,8 +127,6 @@ resource_size_t nd_region_allocatable_dpa(struct nd_region *nd_region); resource_size_t nd_pmem_available_dpa(struct nd_region *nd_region, struct nd_mapping *nd_mapping); resource_size_t nd_region_available_dpa(struct nd_region *nd_region); -int nd_region_conflict(struct nd_region *nd_region, resource_size_t start, - resource_size_t size); resource_size_t nvdimm_allocated_dpa(struct nvdimm_drvdata *ndd, struct nd_label_id *label_id); int nvdimm_num_label_slots(struct nvdimm_drvdata *ndd); @@ -136,8 +134,6 @@ void get_ndd(struct nvdimm_drvdata *ndd); resource_size_t __nvdimm_namespace_capacity(struct nd_namespace_common *ndns); void nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns); void __nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns); -bool nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, - struct nd_namespace_common **_ndns); bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, struct nd_namespace_common **_ndns); ssize_t nd_namespace_store(struct device *dev, diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index ae2078eb6a62..cc5c8f3f81e8 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -489,7 +489,6 @@ enum nd_async_mode { ND_ASYNC, }; -int nd_integrity_init(struct gendisk *disk, unsigned long meta_size); void wait_nvdimm_bus_probe_idle(struct device *dev); void nd_device_register(struct device *dev); void nd_device_unregister(struct device *dev, enum nd_async_mode mode); @@ -601,6 +600,13 @@ struct nd_dax *to_nd_dax(struct device *dev); int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns); bool is_nd_dax(const struct device *dev); struct device *nd_dax_create(struct nd_region *nd_region); +static inline struct device *nd_dax_devinit(struct nd_dax *nd_dax, + struct nd_namespace_common *ndns) +{ + if (!nd_dax) + return NULL; + return nd_pfn_devinit(&nd_dax->nd_pfn, ndns); +} #else static inline int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns) @@ -667,7 +673,7 @@ static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, { if (bb->count) { sector_t first_bad; - int num_bad; + sector_t num_bad; return !!badblocks_check(bb, sector, len / 512, &first_bad, &num_bad); diff --git a/drivers/nvdimm/nd_virtio.c b/drivers/nvdimm/nd_virtio.c index 1f8c667c6f1e..c3f07be4aa22 100644 --- a/drivers/nvdimm/nd_virtio.c +++ b/drivers/nvdimm/nd_virtio.c @@ -44,6 +44,15 @@ static int virtio_pmem_flush(struct nd_region *nd_region) unsigned long flags; int err, err1; + /* + * Don't bother to submit the request to the device if the device is + * not activated. + */ + if (vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_NEEDS_RESET) { + dev_info(&vdev->dev, "virtio pmem device needs a reset\n"); + return -EIO; + } + might_sleep(); req_data = kmalloc(sizeof(*req_data), GFP_KERNEL); if (!req_data) @@ -88,7 +97,7 @@ static int virtio_pmem_flush(struct nd_region *nd_region) dev_info(&vdev->dev, "failed to send command to virtio pmem device\n"); err = -EIO; } else { - /* A host repsonse results in "host_ack" getting called */ + /* A host response results in "host_ack" getting called */ wait_event(req_data->host_acked, req_data->done); err = le32_to_cpu(req_data->resp.ret); } @@ -123,4 +132,5 @@ int async_pmem_flush(struct nd_region *nd_region, struct bio *bio) return 0; }; EXPORT_SYMBOL_GPL(async_pmem_flush); +MODULE_DESCRIPTION("Virtio Persistent Memory Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c index d3fca0ab6290..68bddab3fb46 100644 --- a/drivers/nvdimm/of_pmem.c +++ b/drivers/nvdimm/of_pmem.c @@ -47,7 +47,7 @@ static int of_pmem_region_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, priv); - is_volatile = !!of_find_property(np, "volatile", NULL); + is_volatile = of_property_read_bool(np, "volatile"); dev_dbg(&pdev->dev, "Registering %s regions from %pOF\n", is_volatile ? "volatile" : "non-volatile", np); @@ -84,14 +84,12 @@ static int of_pmem_region_probe(struct platform_device *pdev) return 0; } -static int of_pmem_region_remove(struct platform_device *pdev) +static void of_pmem_region_remove(struct platform_device *pdev) { struct of_pmem_private *priv = platform_get_drvdata(pdev); nvdimm_bus_unregister(priv->bus); kfree(priv); - - return 0; } static const struct of_device_id of_pmem_region_match[] = { @@ -111,5 +109,6 @@ static struct platform_driver of_pmem_region_driver = { module_platform_driver(of_pmem_region_driver); MODULE_DEVICE_TABLE(of, of_pmem_region_match); +MODULE_DESCRIPTION("NVDIMM Device Tree support"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("IBM Corporation"); diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 586348125b61..8f3e816e805d 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -367,9 +367,10 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn) struct nd_namespace_common *ndns = nd_pfn->ndns; void *zero_page = page_address(ZERO_PAGE(0)); struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; - int num_bad, meta_num, rc, bb_present; + int meta_num, rc, bb_present; sector_t first_bad, meta_start; struct nd_namespace_io *nsio; + sector_t num_bad; if (nd_pfn->mode != PFN_MODE_PMEM) return 0; @@ -394,7 +395,7 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn) bb_present = badblocks_check(&nd_region->bb, meta_start, meta_num, &first_bad, &num_bad); if (bb_present) { - dev_dbg(&nd_pfn->dev, "meta: %x badblocks at %llx\n", + dev_dbg(&nd_pfn->dev, "meta: %llx badblocks at %llx\n", num_bad, first_bad); nsoff = ALIGN_DOWN((nd_region->ndr_start + (first_bad << 9)) - nsio->res.start, @@ -413,7 +414,7 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn) } if (rc) { dev_err(&nd_pfn->dev, - "error clearing %x badblocks at %llx\n", + "error clearing %llx badblocks at %llx\n", num_bad, first_bad); return rc; } @@ -539,7 +540,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) if (!nd_pfn->uuid) { /* - * When probing a namepace via nd_pfn_probe() the uuid + * When probing a namespace via nd_pfn_probe() the uuid * is NULL (see: nd_pfn_devinit()) we init settings from * pfn_sb */ diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 4e8fdcb3f1c8..aa50006b7616 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -249,7 +249,7 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, unsigned int num = PFN_PHYS(nr_pages) >> SECTOR_SHIFT; struct badblocks *bb = &pmem->bb; sector_t first_bad; - int num_bad; + sector_t num_bad; if (kaddr) *kaddr = pmem->virt_addr + offset; @@ -316,7 +316,7 @@ static long pmem_dax_direct_access(struct dax_device *dax_dev, * range, filesystem turns the normal pwrite to a dax_recovery_write. * * The recovery write consists of clearing media poison, clearing page - * HWPoison bit, reenable page-wide read-write permission, flush the + * HWPoison bit, re-enable page-wide read-write permission, flush the * caches and finally write. A competing pread thread will be held * off during the recovery process since data read back might not be * valid, and this is achieved by clearing the badblock records after @@ -451,6 +451,13 @@ static int pmem_attach_disk(struct device *dev, { struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); struct nd_region *nd_region = to_nd_region(dev->parent); + struct queue_limits lim = { + .logical_block_size = pmem_sector_size(ndns), + .physical_block_size = PAGE_SIZE, + .max_hw_sectors = UINT_MAX, + .features = BLK_FEAT_WRITE_CACHE | + BLK_FEAT_SYNCHRONOUS, + }; int nid = dev_to_node(dev), fua; struct resource *res = &nsio->res; struct range bb_range; @@ -458,7 +465,6 @@ static int pmem_attach_disk(struct device *dev, struct dax_device *dax_dev; struct nd_pfn_sb *pfn_sb; struct pmem_device *pmem; - struct request_queue *q; struct gendisk *disk; void *addr; int rc; @@ -490,6 +496,10 @@ static int pmem_attach_disk(struct device *dev, dev_warn(dev, "unable to guarantee persistence of writes\n"); fua = 0; } + if (fua) + lim.features |= BLK_FEAT_FUA; + if (is_nd_pfn(dev) || pmem_should_map_pages(dev)) + lim.features |= BLK_FEAT_DAX; if (!devm_request_mem_region(dev, res->start, resource_size(res), dev_name(&ndns->dev))) { @@ -497,14 +507,13 @@ static int pmem_attach_disk(struct device *dev, return -EBUSY; } - disk = blk_alloc_disk(nid); - if (!disk) - return -ENOMEM; - q = disk->queue; + disk = blk_alloc_disk(&lim, nid); + if (IS_ERR(disk)) + return PTR_ERR(disk); pmem->disk = disk; pmem->pgmap.owner = pmem; - pmem->pfn_flags = PFN_DEV; + pmem->pfn_flags = 0; if (is_nd_pfn(dev)) { pmem->pgmap.type = MEMORY_DEVICE_FS_DAX; pmem->pgmap.ops = &fsdax_pagemap_ops; @@ -513,7 +522,6 @@ static int pmem_attach_disk(struct device *dev, pmem->data_offset = le64_to_cpu(pfn_sb->dataoff); pmem->pfn_pad = resource_size(res) - range_len(&pmem->pgmap.range); - pmem->pfn_flags |= PFN_MAP; bb_range = pmem->pgmap.range; bb_range.start += pmem->data_offset; } else if (pmem_should_map_pages(dev)) { @@ -523,7 +531,6 @@ static int pmem_attach_disk(struct device *dev, pmem->pgmap.type = MEMORY_DEVICE_FS_DAX; pmem->pgmap.ops = &fsdax_pagemap_ops; addr = devm_memremap_pages(dev, &pmem->pgmap); - pmem->pfn_flags |= PFN_MAP; bb_range = pmem->pgmap.range; } else { addr = devm_memremap(dev, pmem->phys_addr, @@ -538,15 +545,6 @@ static int pmem_attach_disk(struct device *dev, } pmem->virt_addr = addr; - blk_queue_write_cache(q, true, fua); - blk_queue_physical_block_size(q, PAGE_SIZE); - blk_queue_logical_block_size(q, pmem_sector_size(ndns)); - blk_queue_max_hw_sectors(q, UINT_MAX); - blk_queue_flag_set(QUEUE_FLAG_NONROT, q); - blk_queue_flag_set(QUEUE_FLAG_SYNCHRONOUS, q); - if (pmem->pfn_flags & PFN_MAP) - blk_queue_flag_set(QUEUE_FLAG_DAX, q); - disk->fops = &pmem_fops; disk->private_data = pmem; nvdimm_namespace_disk_name(ndns, disk->disk_name); @@ -560,18 +558,19 @@ static int pmem_attach_disk(struct device *dev, dax_dev = alloc_dax(pmem, &pmem_dax_ops); if (IS_ERR(dax_dev)) { rc = PTR_ERR(dax_dev); - goto out; + if (rc != -EOPNOTSUPP) + goto out; + } else { + set_dax_nocache(dax_dev); + set_dax_nomc(dax_dev); + if (is_nvdimm_sync(nd_region)) + set_dax_synchronous(dax_dev); + pmem->dax_dev = dax_dev; + rc = dax_add_host(dax_dev, disk); + if (rc) + goto out_cleanup_dax; + dax_write_cache(dax_dev, nvdimm_has_cache(nd_region)); } - set_dax_nocache(dax_dev); - set_dax_nomc(dax_dev); - if (is_nvdimm_sync(nd_region)) - set_dax_synchronous(dax_dev); - rc = dax_add_host(dax_dev, disk); - if (rc) - goto out_cleanup_dax; - dax_write_cache(dax_dev, nvdimm_has_cache(nd_region)); - pmem->dax_dev = dax_dev; - rc = device_add_disk(dev, disk, pmem_attribute_groups); if (rc) goto out_remove_host; @@ -765,4 +764,5 @@ static struct nd_device_driver nd_pmem_driver = { module_nd_driver(nd_pmem_driver); MODULE_AUTHOR("Ross Zwisler <ross.zwisler@linux.intel.com>"); +MODULE_DESCRIPTION("NVDIMM Persistent Memory Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 9e4f7ff024a0..de1ee5ebc851 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -1229,45 +1229,4 @@ bool is_nvdimm_sync(struct nd_region *nd_region) } EXPORT_SYMBOL_GPL(is_nvdimm_sync); -struct conflict_context { - struct nd_region *nd_region; - resource_size_t start, size; -}; - -static int region_conflict(struct device *dev, void *data) -{ - struct nd_region *nd_region; - struct conflict_context *ctx = data; - resource_size_t res_end, region_end, region_start; - - if (!is_memory(dev)) - return 0; - - nd_region = to_nd_region(dev); - if (nd_region == ctx->nd_region) - return 0; - - res_end = ctx->start + ctx->size; - region_start = nd_region->ndr_start; - region_end = region_start + nd_region->ndr_size; - if (ctx->start >= region_start && ctx->start < region_end) - return -EBUSY; - if (res_end > region_start && res_end <= region_end) - return -EBUSY; - return 0; -} - -int nd_region_conflict(struct nd_region *nd_region, resource_size_t start, - resource_size_t size) -{ - struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev); - struct conflict_context ctx = { - .nd_region = nd_region, - .start = start, - .size = size, - }; - - return device_for_each_child(&nvdimm_bus->dev, &ctx, region_conflict); -} - -MODULE_IMPORT_NS(DEVMEM); +MODULE_IMPORT_NS("DEVMEM"); diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c index 4ceced5cefcf..2396d19ce549 100644 --- a/drivers/nvdimm/virtio_pmem.c +++ b/drivers/nvdimm/virtio_pmem.c @@ -143,6 +143,28 @@ static void virtio_pmem_remove(struct virtio_device *vdev) virtio_reset_device(vdev); } +static int virtio_pmem_freeze(struct virtio_device *vdev) +{ + vdev->config->del_vqs(vdev); + virtio_reset_device(vdev); + + return 0; +} + +static int virtio_pmem_restore(struct virtio_device *vdev) +{ + int ret; + + ret = init_vq(vdev->priv); + if (ret) { + dev_err(&vdev->dev, "failed to initialize virtio pmem's vq\n"); + return ret; + } + virtio_device_ready(vdev); + + return 0; +} + static unsigned int features[] = { VIRTIO_PMEM_F_SHMEM_REGION, }; @@ -151,11 +173,12 @@ static struct virtio_driver virtio_pmem_driver = { .feature_table = features, .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, .id_table = id_table, .validate = virtio_pmem_validate, .probe = virtio_pmem_probe, .remove = virtio_pmem_remove, + .freeze = virtio_pmem_freeze, + .restore = virtio_pmem_restore, }; module_virtio_driver(virtio_pmem_driver); |