-
Notifications
You must be signed in to change notification settings - Fork 54.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
device-dax: Start defining a dax bus model
Towards eliminating the dax_class, move the dax-device-attribute enabling to a new bus.c file in the core. The amount of code thrash of sub-sequent patches is reduced as no logic changes are made, just pure code movement. A temporary export of unregister_dex_dax() and dax_attribute_groups is needed to preserve compilation, but those symbols become static again in a follow-on patch. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
- Loading branch information
Showing
10 changed files
with
210 additions
and
224 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */ | ||
#include <linux/device.h> | ||
#include <linux/slab.h> | ||
#include <linux/dax.h> | ||
#include "dax-private.h" | ||
#include "bus.h" | ||
|
||
/* | ||
* Rely on the fact that drvdata is set before the attributes are | ||
* registered, and that the attributes are unregistered before drvdata | ||
* is cleared to assume that drvdata is always valid. | ||
*/ | ||
static ssize_t id_show(struct device *dev, | ||
struct device_attribute *attr, char *buf) | ||
{ | ||
struct dax_region *dax_region = dev_get_drvdata(dev); | ||
|
||
return sprintf(buf, "%d\n", dax_region->id); | ||
} | ||
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 = dev_get_drvdata(dev); | ||
|
||
return sprintf(buf, "%llu\n", (unsigned long long) | ||
resource_size(&dax_region->res)); | ||
} | ||
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 = dev_get_drvdata(dev); | ||
|
||
return sprintf(buf, "%u\n", dax_region->align); | ||
} | ||
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 void dax_region_free(struct kref *kref) | ||
{ | ||
struct dax_region *dax_region; | ||
|
||
dax_region = container_of(kref, struct dax_region, kref); | ||
kfree(dax_region); | ||
} | ||
|
||
void dax_region_put(struct dax_region *dax_region) | ||
{ | ||
kref_put(&dax_region->kref, dax_region_free); | ||
} | ||
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, | ||
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; | ||
|
||
dax_region = kzalloc(sizeof(*dax_region), GFP_KERNEL); | ||
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); | ||
dax_region->id = region_id; | ||
dax_region->align = align; | ||
dax_region->dev = parent; | ||
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); | ||
|
||
static ssize_t size_show(struct device *dev, | ||
struct device_attribute *attr, char *buf) | ||
{ | ||
struct dev_dax *dev_dax = to_dev_dax(dev); | ||
unsigned long long size = resource_size(&dev_dax->region->res); | ||
|
||
return sprintf(buf, "%llu\n", size); | ||
} | ||
static DEVICE_ATTR_RO(size); | ||
|
||
static struct attribute *dev_dax_attributes[] = { | ||
&dev_attr_size.attr, | ||
NULL, | ||
}; | ||
|
||
static const struct attribute_group dev_dax_attribute_group = { | ||
.attrs = dev_dax_attributes, | ||
}; | ||
|
||
const struct attribute_group *dax_attribute_groups[] = { | ||
&dev_dax_attribute_group, | ||
NULL, | ||
}; | ||
EXPORT_SYMBOL_GPL(dax_attribute_groups); | ||
|
||
void kill_dev_dax(struct dev_dax *dev_dax) | ||
{ | ||
struct dax_device *dax_dev = dev_dax->dax_dev; | ||
struct inode *inode = dax_inode(dax_dev); | ||
|
||
kill_dax(dax_dev); | ||
unmap_mapping_range(inode->i_mapping, 0, 0, 1); | ||
} | ||
EXPORT_SYMBOL_GPL(kill_dev_dax); | ||
|
||
void unregister_dev_dax(void *dev) | ||
{ | ||
struct dev_dax *dev_dax = to_dev_dax(dev); | ||
struct dax_device *dax_dev = dev_dax->dax_dev; | ||
struct inode *inode = dax_inode(dax_dev); | ||
struct cdev *cdev = inode->i_cdev; | ||
|
||
dev_dbg(dev, "trace\n"); | ||
|
||
kill_dev_dax(dev_dax); | ||
cdev_device_del(cdev, dev); | ||
put_device(dev); | ||
} | ||
EXPORT_SYMBOL_GPL(unregister_dev_dax); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */ | ||
#ifndef __DAX_BUS_H__ | ||
#define __DAX_BUS_H__ | ||
struct device; | ||
struct dev_dax; | ||
struct resource; | ||
struct dax_device; | ||
struct dax_region; | ||
void dax_region_put(struct dax_region *dax_region); | ||
struct dax_region *alloc_dax_region(struct device *parent, int region_id, | ||
struct resource *res, unsigned int align, unsigned long flags); | ||
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id); | ||
void kill_dev_dax(struct dev_dax *dev_dax); | ||
#endif /* __DAX_BUS_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.