Loading drivers/dax/dax.c +94 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,73 @@ struct dax_dev { struct resource res[0]; }; static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dax_region *dax_region; ssize_t rc = -ENXIO; device_lock(dev); dax_region = dev_get_drvdata(dev); if (dax_region) rc = sprintf(buf, "%d\n", dax_region->id); device_unlock(dev); return rc; } static DEVICE_ATTR_RO(id); static ssize_t region_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dax_region *dax_region; ssize_t rc = -ENXIO; device_lock(dev); dax_region = dev_get_drvdata(dev); if (dax_region) rc = sprintf(buf, "%llu\n", (unsigned long long) resource_size(&dax_region->res)); device_unlock(dev); return rc; } static struct device_attribute dev_attr_region_size = __ATTR(size, 0444, region_size_show, NULL); static ssize_t align_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dax_region *dax_region; ssize_t rc = -ENXIO; device_lock(dev); dax_region = dev_get_drvdata(dev); if (dax_region) rc = sprintf(buf, "%u\n", dax_region->align); device_unlock(dev); return rc; } static DEVICE_ATTR_RO(align); static struct attribute *dax_region_attributes[] = { &dev_attr_region_size.attr, &dev_attr_align.attr, &dev_attr_id.attr, NULL, }; static const struct attribute_group dax_region_attribute_group = { .name = "dax_region", .attrs = dax_region_attributes, }; static const struct attribute_group *dax_region_attribute_groups[] = { &dax_region_attribute_group, NULL, }; static struct inode *dax_alloc_inode(struct super_block *sb) { return kmem_cache_alloc(dax_cache, GFP_KERNEL); Loading Loading @@ -200,12 +267,31 @@ void dax_region_put(struct dax_region *dax_region) } EXPORT_SYMBOL_GPL(dax_region_put); static void dax_region_unregister(void *region) { struct dax_region *dax_region = region; sysfs_remove_groups(&dax_region->dev->kobj, dax_region_attribute_groups); dax_region_put(dax_region); } struct dax_region *alloc_dax_region(struct device *parent, int region_id, struct resource *res, unsigned int align, void *addr, unsigned long pfn_flags) { struct dax_region *dax_region; /* * The DAX core assumes that it can store its private data in * parent->driver_data. This WARN is a reminder / safeguard for * developers of device-dax drivers. */ if (dev_get_drvdata(parent)) { dev_WARN(parent, "dax core failed to setup private data\n"); return NULL; } if (!IS_ALIGNED(res->start, align) || !IS_ALIGNED(resource_size(res), align)) return NULL; Loading @@ -214,6 +300,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, if (!dax_region) return NULL; dev_set_drvdata(parent, dax_region); memcpy(&dax_region->res, res, sizeof(*res)); dax_region->pfn_flags = pfn_flags; kref_init(&dax_region->kref); Loading @@ -222,7 +309,14 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, dax_region->align = align; dax_region->dev = parent; dax_region->base = addr; if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) { kfree(dax_region); return NULL;; } kref_get(&dax_region->kref); if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region)) return NULL; return dax_region; } EXPORT_SYMBOL_GPL(alloc_dax_region); Loading drivers/dax/pmem.c +2 −1 Original line number Diff line number Diff line Loading @@ -89,7 +89,8 @@ static int dax_pmem_probe(struct device *dev) pfn_sb = nd_pfn->pfn_sb; if (!devm_request_mem_region(dev, nsio->res.start, resource_size(&nsio->res), dev_name(dev))) { resource_size(&nsio->res), dev_name(&ndns->dev))) { dev_warn(dev, "could not reserve region %pR\n", &nsio->res); return -EBUSY; } Loading drivers/nvdimm/claim.c +32 −14 Original line number Diff line number Diff line Loading @@ -22,9 +22,8 @@ void __nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns) { struct nd_namespace_common *ndns = *_ndns; dev_WARN_ONCE(dev, !mutex_is_locked(&ndns->dev.mutex) || ndns->claim != dev, "%s: invalid claim\n", __func__); lockdep_assert_held(&ndns->dev.mutex); dev_WARN_ONCE(dev, ndns->claim != dev, "%s: invalid claim\n", __func__); ndns->claim = NULL; *_ndns = NULL; put_device(&ndns->dev); Loading @@ -49,9 +48,8 @@ bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, { if (attach->claim) return false; dev_WARN_ONCE(dev, !mutex_is_locked(&attach->dev.mutex) || *_ndns, "%s: invalid claim\n", __func__); lockdep_assert_held(&attach->dev.mutex); dev_WARN_ONCE(dev, *_ndns, "%s: invalid claim\n", __func__); attach->claim = dev; *_ndns = attach; get_device(&attach->dev); Loading Loading @@ -226,6 +224,12 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, resource_size_t offset, void *buf, size_t size, int rw) { struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); sector_t sector = offset >> 9; int rc = 0; if (unlikely(!size)) return 0; if (unlikely(offset + size > nsio->size)) { dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); Loading @@ -233,17 +237,31 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, } if (rw == READ) { unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align))) if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) return -EIO; return memcpy_from_pmem(buf, nsio->addr + offset, size); } else { } if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) { if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)) { long cleared; cleared = nvdimm_clear_poison(&ndns->dev, offset, size); if (cleared < size) rc = -EIO; if (cleared > 0 && cleared / 512) { cleared /= 512; badblocks_clear(&nsio->bb, sector, cleared); } invalidate_pmem(nsio->addr + offset, size); } else rc = -EIO; } memcpy_to_pmem(nsio->addr + offset, buf, size); nvdimm_flush(to_nd_region(ndns->dev.parent)); } return 0; return rc; } int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) Loading @@ -253,7 +271,7 @@ int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) nsio->size = resource_size(res); if (!devm_request_mem_region(dev, res->start, resource_size(res), dev_name(dev))) { dev_name(&ndns->dev))) { dev_warn(dev, "could not reserve region %pR\n", res); return -EBUSY; } Loading drivers/nvdimm/core.c +0 −29 Original line number Diff line number Diff line Loading @@ -317,35 +317,6 @@ ssize_t nd_sector_size_store(struct device *dev, const char *buf, } } void __nd_iostat_start(struct bio *bio, unsigned long *start) { struct gendisk *disk = bio->bi_bdev->bd_disk; const int rw = bio_data_dir(bio); int cpu = part_stat_lock(); *start = jiffies; part_round_stats(cpu, &disk->part0); part_stat_inc(cpu, &disk->part0, ios[rw]); part_stat_add(cpu, &disk->part0, sectors[rw], bio_sectors(bio)); part_inc_in_flight(&disk->part0, rw); part_stat_unlock(); } EXPORT_SYMBOL(__nd_iostat_start); void nd_iostat_end(struct bio *bio, unsigned long start) { struct gendisk *disk = bio->bi_bdev->bd_disk; unsigned long duration = jiffies - start; const int rw = bio_data_dir(bio); int cpu = part_stat_lock(); part_stat_add(cpu, &disk->part0, ticks[rw], duration); part_round_stats(cpu, &disk->part0); part_dec_in_flight(&disk->part0, rw); part_stat_unlock(); } EXPORT_SYMBOL(nd_iostat_end); static ssize_t commands_show(struct device *dev, struct device_attribute *attr, char *buf) { Loading drivers/nvdimm/dimm.c +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ static int nvdimm_probe(struct device *dev) nd_label_copy(ndd, to_next_namespace_index(ndd), to_current_namespace_index(ndd)); rc = nd_label_reserve_dpa(ndd); if (ndd->ns_current >= 0) nvdimm_set_aliasing(dev); nvdimm_bus_unlock(dev); if (rc) Loading Loading
drivers/dax/dax.c +94 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,73 @@ struct dax_dev { struct resource res[0]; }; static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dax_region *dax_region; ssize_t rc = -ENXIO; device_lock(dev); dax_region = dev_get_drvdata(dev); if (dax_region) rc = sprintf(buf, "%d\n", dax_region->id); device_unlock(dev); return rc; } static DEVICE_ATTR_RO(id); static ssize_t region_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dax_region *dax_region; ssize_t rc = -ENXIO; device_lock(dev); dax_region = dev_get_drvdata(dev); if (dax_region) rc = sprintf(buf, "%llu\n", (unsigned long long) resource_size(&dax_region->res)); device_unlock(dev); return rc; } static struct device_attribute dev_attr_region_size = __ATTR(size, 0444, region_size_show, NULL); static ssize_t align_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dax_region *dax_region; ssize_t rc = -ENXIO; device_lock(dev); dax_region = dev_get_drvdata(dev); if (dax_region) rc = sprintf(buf, "%u\n", dax_region->align); device_unlock(dev); return rc; } static DEVICE_ATTR_RO(align); static struct attribute *dax_region_attributes[] = { &dev_attr_region_size.attr, &dev_attr_align.attr, &dev_attr_id.attr, NULL, }; static const struct attribute_group dax_region_attribute_group = { .name = "dax_region", .attrs = dax_region_attributes, }; static const struct attribute_group *dax_region_attribute_groups[] = { &dax_region_attribute_group, NULL, }; static struct inode *dax_alloc_inode(struct super_block *sb) { return kmem_cache_alloc(dax_cache, GFP_KERNEL); Loading Loading @@ -200,12 +267,31 @@ void dax_region_put(struct dax_region *dax_region) } EXPORT_SYMBOL_GPL(dax_region_put); static void dax_region_unregister(void *region) { struct dax_region *dax_region = region; sysfs_remove_groups(&dax_region->dev->kobj, dax_region_attribute_groups); dax_region_put(dax_region); } struct dax_region *alloc_dax_region(struct device *parent, int region_id, struct resource *res, unsigned int align, void *addr, unsigned long pfn_flags) { struct dax_region *dax_region; /* * The DAX core assumes that it can store its private data in * parent->driver_data. This WARN is a reminder / safeguard for * developers of device-dax drivers. */ if (dev_get_drvdata(parent)) { dev_WARN(parent, "dax core failed to setup private data\n"); return NULL; } if (!IS_ALIGNED(res->start, align) || !IS_ALIGNED(resource_size(res), align)) return NULL; Loading @@ -214,6 +300,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, if (!dax_region) return NULL; dev_set_drvdata(parent, dax_region); memcpy(&dax_region->res, res, sizeof(*res)); dax_region->pfn_flags = pfn_flags; kref_init(&dax_region->kref); Loading @@ -222,7 +309,14 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, dax_region->align = align; dax_region->dev = parent; dax_region->base = addr; if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) { kfree(dax_region); return NULL;; } kref_get(&dax_region->kref); if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region)) return NULL; return dax_region; } EXPORT_SYMBOL_GPL(alloc_dax_region); Loading
drivers/dax/pmem.c +2 −1 Original line number Diff line number Diff line Loading @@ -89,7 +89,8 @@ static int dax_pmem_probe(struct device *dev) pfn_sb = nd_pfn->pfn_sb; if (!devm_request_mem_region(dev, nsio->res.start, resource_size(&nsio->res), dev_name(dev))) { resource_size(&nsio->res), dev_name(&ndns->dev))) { dev_warn(dev, "could not reserve region %pR\n", &nsio->res); return -EBUSY; } Loading
drivers/nvdimm/claim.c +32 −14 Original line number Diff line number Diff line Loading @@ -22,9 +22,8 @@ void __nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns) { struct nd_namespace_common *ndns = *_ndns; dev_WARN_ONCE(dev, !mutex_is_locked(&ndns->dev.mutex) || ndns->claim != dev, "%s: invalid claim\n", __func__); lockdep_assert_held(&ndns->dev.mutex); dev_WARN_ONCE(dev, ndns->claim != dev, "%s: invalid claim\n", __func__); ndns->claim = NULL; *_ndns = NULL; put_device(&ndns->dev); Loading @@ -49,9 +48,8 @@ bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, { if (attach->claim) return false; dev_WARN_ONCE(dev, !mutex_is_locked(&attach->dev.mutex) || *_ndns, "%s: invalid claim\n", __func__); lockdep_assert_held(&attach->dev.mutex); dev_WARN_ONCE(dev, *_ndns, "%s: invalid claim\n", __func__); attach->claim = dev; *_ndns = attach; get_device(&attach->dev); Loading Loading @@ -226,6 +224,12 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, resource_size_t offset, void *buf, size_t size, int rw) { struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); sector_t sector = offset >> 9; int rc = 0; if (unlikely(!size)) return 0; if (unlikely(offset + size > nsio->size)) { dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); Loading @@ -233,17 +237,31 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, } if (rw == READ) { unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align))) if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) return -EIO; return memcpy_from_pmem(buf, nsio->addr + offset, size); } else { } if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) { if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)) { long cleared; cleared = nvdimm_clear_poison(&ndns->dev, offset, size); if (cleared < size) rc = -EIO; if (cleared > 0 && cleared / 512) { cleared /= 512; badblocks_clear(&nsio->bb, sector, cleared); } invalidate_pmem(nsio->addr + offset, size); } else rc = -EIO; } memcpy_to_pmem(nsio->addr + offset, buf, size); nvdimm_flush(to_nd_region(ndns->dev.parent)); } return 0; return rc; } int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) Loading @@ -253,7 +271,7 @@ int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) nsio->size = resource_size(res); if (!devm_request_mem_region(dev, res->start, resource_size(res), dev_name(dev))) { dev_name(&ndns->dev))) { dev_warn(dev, "could not reserve region %pR\n", res); return -EBUSY; } Loading
drivers/nvdimm/core.c +0 −29 Original line number Diff line number Diff line Loading @@ -317,35 +317,6 @@ ssize_t nd_sector_size_store(struct device *dev, const char *buf, } } void __nd_iostat_start(struct bio *bio, unsigned long *start) { struct gendisk *disk = bio->bi_bdev->bd_disk; const int rw = bio_data_dir(bio); int cpu = part_stat_lock(); *start = jiffies; part_round_stats(cpu, &disk->part0); part_stat_inc(cpu, &disk->part0, ios[rw]); part_stat_add(cpu, &disk->part0, sectors[rw], bio_sectors(bio)); part_inc_in_flight(&disk->part0, rw); part_stat_unlock(); } EXPORT_SYMBOL(__nd_iostat_start); void nd_iostat_end(struct bio *bio, unsigned long start) { struct gendisk *disk = bio->bi_bdev->bd_disk; unsigned long duration = jiffies - start; const int rw = bio_data_dir(bio); int cpu = part_stat_lock(); part_stat_add(cpu, &disk->part0, ticks[rw], duration); part_round_stats(cpu, &disk->part0); part_dec_in_flight(&disk->part0, rw); part_stat_unlock(); } EXPORT_SYMBOL(nd_iostat_end); static ssize_t commands_show(struct device *dev, struct device_attribute *attr, char *buf) { Loading
drivers/nvdimm/dimm.c +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ static int nvdimm_probe(struct device *dev) nd_label_copy(ndd, to_next_namespace_index(ndd), to_current_namespace_index(ndd)); rc = nd_label_reserve_dpa(ndd); if (ndd->ns_current >= 0) nvdimm_set_aliasing(dev); nvdimm_bus_unlock(dev); if (rc) Loading