Skip to content

Commit

Permalink
Merge branch 'for-4.10/libnvdimm' into libnvdimm-for-next
Browse files Browse the repository at this point in the history
  • Loading branch information
djbw committed Dec 17, 2016
2 parents 325896f + d7fe1a6 commit c44ef85
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 80 deletions.
94 changes: 94 additions & 0 deletions drivers/dax/dax.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion drivers/dax/pmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
46 changes: 32 additions & 14 deletions drivers/nvdimm/claim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -226,24 +224,44 @@ 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");
return -EFAULT;
}

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 {
memcpy_to_pmem(nsio->addr + offset, buf, size);
nvdimm_flush(to_nd_region(ndns->dev.parent));
}

return 0;
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 rc;
}

int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio)
Expand All @@ -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;
}
Expand Down
29 changes: 0 additions & 29 deletions drivers/nvdimm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 2 additions & 0 deletions drivers/nvdimm/dimm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions drivers/nvdimm/dimm_devs.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
return rc;
}

void nvdimm_set_aliasing(struct device *dev)
{
struct nvdimm *nvdimm = to_nvdimm(dev);

nvdimm->flags |= NDD_ALIASING;
}

static void nvdimm_release(struct device *dev)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
Expand Down
12 changes: 1 addition & 11 deletions drivers/nvdimm/e820.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,8 @@ static struct platform_driver e820_pmem_driver = {
},
};

static __init int e820_pmem_init(void)
{
return platform_driver_register(&e820_pmem_driver);
}

static __exit void e820_pmem_exit(void)
{
platform_driver_unregister(&e820_pmem_driver);
}
module_platform_driver(e820_pmem_driver);

MODULE_ALIAS("platform:e820_pmem*");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Intel Corporation");
module_init(e820_pmem_init);
module_exit(e820_pmem_exit);
2 changes: 1 addition & 1 deletion drivers/nvdimm/label.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
}

for_each_dpa_resource(ndd, res)
if (strncmp(res->name, "pmem", 3) == 0)
if (strncmp(res->name, "pmem", 4) == 0)
count++;
WARN_ON_ONCE(!count);

Expand Down
8 changes: 4 additions & 4 deletions drivers/nvdimm/namespace_devs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,7 @@ static ssize_t size_show(struct device *dev,
return sprintf(buf, "%llu\n", (unsigned long long)
nvdimm_namespace_capacity(to_ndns(dev)));
}
static DEVICE_ATTR(size, S_IRUGO, size_show, size_store);
static DEVICE_ATTR(size, 0444, size_show, size_store);

static u8 *namespace_to_uuid(struct device *dev)
{
Expand Down Expand Up @@ -1456,7 +1456,7 @@ static umode_t namespace_visible(struct kobject *kobj,

if (is_namespace_pmem(dev) || is_namespace_blk(dev)) {
if (a == &dev_attr_size.attr)
return S_IWUSR | S_IRUGO;
return 0644;

if (is_namespace_pmem(dev) && a == &dev_attr_sector_size.attr)
return 0;
Expand Down Expand Up @@ -1653,7 +1653,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
u64 hw_start, hw_end, pmem_start, pmem_end;
struct nd_label_ent *label_ent;

WARN_ON(!mutex_is_locked(&nd_mapping->lock));
lockdep_assert_held(&nd_mapping->lock);
list_for_each_entry(label_ent, &nd_mapping->labels, list) {
nd_label = label_ent->label;
if (!nd_label)
Expand Down Expand Up @@ -1997,7 +1997,7 @@ struct device *create_namespace_blk(struct nd_region *nd_region,
struct nd_mapping *nd_mapping = &nd_region->mapping[0];
struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
struct nd_namespace_blk *nsblk;
char *name[NSLABEL_NAME_LEN];
char name[NSLABEL_NAME_LEN];
struct device *dev = NULL;
struct resource *res;

Expand Down
12 changes: 10 additions & 2 deletions drivers/nvdimm/nd.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
void *buf, size_t len);
long nvdimm_clear_poison(struct device *dev, phys_addr_t phys,
unsigned int len);
void nvdimm_set_aliasing(struct device *dev);
struct nd_btt *to_nd_btt(struct device *dev);

struct nd_gen_sb {
Expand Down Expand Up @@ -377,10 +378,17 @@ static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
if (!blk_queue_io_stat(disk->queue))
return false;

__nd_iostat_start(bio, start);
*start = jiffies;
generic_start_io_acct(bio_data_dir(bio),
bio_sectors(bio), &disk->part0);
return true;
}
void nd_iostat_end(struct bio *bio, unsigned long start);
static inline void nd_iostat_end(struct bio *bio, unsigned long start)
{
struct gendisk *disk = bio->bi_bdev->bd_disk;

generic_end_io_acct(bio_data_dir(bio), &disk->part0, start);
}
static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector,
unsigned int len)
{
Expand Down
2 changes: 1 addition & 1 deletion drivers/nvdimm/pfn_devs.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static ssize_t align_show(struct device *dev,
{
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);

return sprintf(buf, "%lx\n", nd_pfn->align);
return sprintf(buf, "%ld\n", nd_pfn->align);
}

static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf)
Expand Down
Loading

0 comments on commit c44ef85

Please sign in to comment.