Skip to content

Commit

Permalink
dax: add region 'id', 'size', and 'align' attributes
Browse files Browse the repository at this point in the history
While this information is available by looking at the nvdimm parent
device that may not always be the case when/if we add support for other
memory regions. Tooling should not depend on walking a given ancestor
topology that is not guaranteed by the device's class. For example, a
device-dax instance will always have a dax_region parent, but it may not
always have a libnvdimm "dax" device as a grandparent.

Reported-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
  • Loading branch information
djbw committed Dec 17, 2016
1 parent 868f036 commit d7fe1a6
Showing 1 changed file with 94 additions and 0 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

0 comments on commit d7fe1a6

Please sign in to comment.