Skip to content

Commit 9567da0

Browse files
committed
device-dax: Introduce bus + driver model
In support of multiple device-dax instances per device-dax-region and allowing the 'kmem' driver to attach to dax-instances instead of the current device-node access, convert the dax sub-system from a class to a bus. Recall that the kmem driver takes reserved / special purpose memories and assigns them to be managed by the core-mm. Aside from the fact the device-dax instances are registered and probed on a bus, two other lifetime-management changes are made: 1/ Delay attaching a cdev until driver probe time 2/ A new run_dax() helper is introduced to allow restoring dax-operation after a kill_dax() event. So, at driver ->probe() time we run_dax() and at ->remove() time we kill_dax() and invalidate all mappings. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 51cf784 commit 9567da0

File tree

5 files changed

+203
-87
lines changed

5 files changed

+203
-87
lines changed

drivers/dax/bus.c

Lines changed: 125 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,33 @@
66
#include "dax-private.h"
77
#include "bus.h"
88

9+
static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
10+
{
11+
/*
12+
* We only ever expect to handle device-dax instances, i.e. the
13+
* @type argument to MODULE_ALIAS_DAX_DEVICE() is always zero
14+
*/
15+
return add_uevent_var(env, "MODALIAS=" DAX_DEVICE_MODALIAS_FMT, 0);
16+
}
17+
18+
static int dax_bus_match(struct device *dev, struct device_driver *drv);
19+
20+
static struct bus_type dax_bus_type = {
21+
.name = "dax",
22+
.uevent = dax_bus_uevent,
23+
.match = dax_bus_match,
24+
};
25+
26+
static int dax_bus_match(struct device *dev, struct device_driver *drv)
27+
{
28+
/*
29+
* The drivers that can register on the 'dax' bus are private to
30+
* drivers/dax/ so any device and driver on the bus always
31+
* match.
32+
*/
33+
return 1;
34+
}
35+
936
/*
1037
* Rely on the fact that drvdata is set before the attributes are
1138
* registered, and that the attributes are unregistered before drvdata
@@ -142,11 +169,10 @@ static const struct attribute_group dev_dax_attribute_group = {
142169
.attrs = dev_dax_attributes,
143170
};
144171

145-
const struct attribute_group *dax_attribute_groups[] = {
172+
static const struct attribute_group *dax_attribute_groups[] = {
146173
&dev_dax_attribute_group,
147174
NULL,
148175
};
149-
EXPORT_SYMBOL_GPL(dax_attribute_groups);
150176

151177
void kill_dev_dax(struct dev_dax *dev_dax)
152178
{
@@ -158,17 +184,108 @@ void kill_dev_dax(struct dev_dax *dev_dax)
158184
}
159185
EXPORT_SYMBOL_GPL(kill_dev_dax);
160186

161-
void unregister_dev_dax(void *dev)
187+
static void dev_dax_release(struct device *dev)
162188
{
163189
struct dev_dax *dev_dax = to_dev_dax(dev);
190+
struct dax_region *dax_region = dev_dax->region;
164191
struct dax_device *dax_dev = dev_dax->dax_dev;
165-
struct inode *inode = dax_inode(dax_dev);
166-
struct cdev *cdev = inode->i_cdev;
167192

168-
dev_dbg(dev, "trace\n");
193+
dax_region_put(dax_region);
194+
put_dax(dax_dev);
195+
kfree(dev_dax);
196+
}
197+
198+
static void unregister_dev_dax(void *dev)
199+
{
200+
struct dev_dax *dev_dax = to_dev_dax(dev);
201+
202+
dev_dbg(dev, "%s\n", __func__);
169203

170204
kill_dev_dax(dev_dax);
171-
cdev_device_del(cdev, dev);
205+
device_del(dev);
172206
put_device(dev);
173207
}
174-
EXPORT_SYMBOL_GPL(unregister_dev_dax);
208+
209+
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
210+
{
211+
struct device *parent = dax_region->dev;
212+
struct dax_device *dax_dev;
213+
struct dev_dax *dev_dax;
214+
struct inode *inode;
215+
struct device *dev;
216+
int rc = -ENOMEM;
217+
218+
if (id < 0)
219+
return ERR_PTR(-EINVAL);
220+
221+
dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL);
222+
if (!dev_dax)
223+
return ERR_PTR(-ENOMEM);
224+
225+
/*
226+
* No 'host' or dax_operations since there is no access to this
227+
* device outside of mmap of the resulting character device.
228+
*/
229+
dax_dev = alloc_dax(dev_dax, NULL, NULL);
230+
if (!dax_dev)
231+
goto err;
232+
233+
/* a device_dax instance is dead while the driver is not attached */
234+
kill_dax(dax_dev);
235+
236+
/* from here on we're committed to teardown via dax_dev_release() */
237+
dev = &dev_dax->dev;
238+
device_initialize(dev);
239+
240+
dev_dax->dax_dev = dax_dev;
241+
dev_dax->region = dax_region;
242+
kref_get(&dax_region->kref);
243+
244+
inode = dax_inode(dax_dev);
245+
dev->devt = inode->i_rdev;
246+
dev->bus = &dax_bus_type;
247+
dev->parent = parent;
248+
dev->groups = dax_attribute_groups;
249+
dev->release = dev_dax_release;
250+
dev_set_name(dev, "dax%d.%d", dax_region->id, id);
251+
252+
rc = device_add(dev);
253+
if (rc) {
254+
kill_dev_dax(dev_dax);
255+
put_device(dev);
256+
return ERR_PTR(rc);
257+
}
258+
259+
rc = devm_add_action_or_reset(dax_region->dev, unregister_dev_dax, dev);
260+
if (rc)
261+
return ERR_PTR(rc);
262+
263+
return dev_dax;
264+
265+
err:
266+
kfree(dev_dax);
267+
268+
return ERR_PTR(rc);
269+
}
270+
EXPORT_SYMBOL_GPL(devm_create_dev_dax);
271+
272+
int __dax_driver_register(struct device_driver *drv,
273+
struct module *module, const char *mod_name)
274+
{
275+
drv->owner = module;
276+
drv->name = mod_name;
277+
drv->mod_name = mod_name;
278+
drv->bus = &dax_bus_type;
279+
return driver_register(drv);
280+
}
281+
EXPORT_SYMBOL_GPL(__dax_driver_register);
282+
283+
int __init dax_bus_init(void)
284+
{
285+
return bus_register(&dax_bus_type);
286+
}
287+
288+
void __exit dax_bus_exit(void)
289+
{
290+
bus_unregister(&dax_bus_type);
291+
}

drivers/dax/bus.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,21 @@ void dax_region_put(struct dax_region *dax_region);
1111
struct dax_region *alloc_dax_region(struct device *parent, int region_id,
1212
struct resource *res, unsigned int align, unsigned long flags);
1313
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id);
14+
int __dax_driver_register(struct device_driver *drv,
15+
struct module *module, const char *mod_name);
16+
#define dax_driver_register(driver) \
17+
__dax_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
1418
void kill_dev_dax(struct dev_dax *dev_dax);
19+
20+
/*
21+
* While run_dax() is potentially a generic operation that could be
22+
* defined in include/linux/dax.h we don't want to grow any users
23+
* outside of drivers/dax/
24+
*/
25+
void run_dax(struct dax_device *dax_dev);
26+
27+
#define MODULE_ALIAS_DAX_DEVICE(type) \
28+
MODULE_ALIAS("dax:t" __stringify(type) "*")
29+
#define DAX_DEVICE_MODALIAS_FMT "dax:t%d"
30+
1531
#endif /* __DAX_BUS_H__ */

drivers/dax/dax-private.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
struct dax_device;
2121
struct dax_device *inode_dax(struct inode *inode);
2222
struct inode *dax_inode(struct dax_device *dax_dev);
23-
24-
/* temporary until devm_create_dax_dev moves to bus.c */
25-
extern const struct attribute_group *dax_attribute_groups[];
26-
void unregister_dev_dax(void *dev);
23+
int dax_bus_init(void);
24+
void dax_bus_exit(void);
2725

2826
/**
2927
* struct dax_region - mapping infrastructure for dax devices

drivers/dax/device.c

Lines changed: 32 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include "dax-private.h"
1414
#include "bus.h"
1515

16-
static struct class *dax_class;
17-
1816
static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
1917
const char *func)
2018
{
@@ -404,93 +402,64 @@ static const struct file_operations dax_fops = {
404402
.mmap_supported_flags = MAP_SYNC,
405403
};
406404

407-
static void dev_dax_release(struct device *dev)
405+
static void dev_dax_cdev_del(void *cdev)
408406
{
409-
struct dev_dax *dev_dax = to_dev_dax(dev);
410-
struct dax_region *dax_region = dev_dax->region;
411-
struct dax_device *dax_dev = dev_dax->dax_dev;
407+
cdev_del(cdev);
408+
}
412409

413-
dax_region_put(dax_region);
414-
put_dax(dax_dev);
415-
kfree(dev_dax);
410+
static void dev_dax_kill(void *dev_dax)
411+
{
412+
kill_dev_dax(dev_dax);
416413
}
417414

418-
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
415+
static int dev_dax_probe(struct device *dev)
419416
{
420-
struct device *parent = dax_region->dev;
421-
struct dax_device *dax_dev;
422-
struct dev_dax *dev_dax;
417+
struct dev_dax *dev_dax = to_dev_dax(dev);
418+
struct dax_device *dax_dev = dev_dax->dax_dev;
423419
struct inode *inode;
424-
struct device *dev;
425420
struct cdev *cdev;
426421
int rc;
427422

428-
dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL);
429-
if (!dev_dax)
430-
return ERR_PTR(-ENOMEM);
431-
432-
/*
433-
* No 'host' or dax_operations since there is no access to this
434-
* device outside of mmap of the resulting character device.
435-
*/
436-
dax_dev = alloc_dax(dev_dax, NULL, NULL);
437-
if (!dax_dev) {
438-
rc = -ENOMEM;
439-
goto err;
440-
}
441-
442-
/* from here on we're committed to teardown via dax_dev_release() */
443-
dev = &dev_dax->dev;
444-
device_initialize(dev);
445-
446423
inode = dax_inode(dax_dev);
447424
cdev = inode->i_cdev;
448425
cdev_init(cdev, &dax_fops);
449-
cdev->owner = parent->driver->owner;
450-
451-
dev_dax->dax_dev = dax_dev;
452-
dev_dax->region = dax_region;
453-
kref_get(&dax_region->kref);
454-
455-
dev->devt = inode->i_rdev;
456-
dev->class = dax_class;
457-
dev->parent = parent;
458-
dev->groups = dax_attribute_groups;
459-
dev->release = dev_dax_release;
460-
dev_set_name(dev, "dax%d.%d", dax_region->id, id);
461-
462-
rc = cdev_device_add(cdev, dev);
463-
if (rc) {
464-
kill_dev_dax(dev_dax);
465-
put_device(dev);
466-
return ERR_PTR(rc);
467-
}
468-
469-
rc = devm_add_action_or_reset(dax_region->dev, unregister_dev_dax, dev);
426+
cdev->owner = dev->driver->owner;
427+
cdev_set_parent(cdev, &dev->kobj);
428+
rc = cdev_add(cdev, dev->devt, 1);
470429
if (rc)
471-
return ERR_PTR(rc);
430+
return rc;
472431

473-
return dev_dax;
432+
rc = devm_add_action_or_reset(dev, dev_dax_cdev_del, cdev);
433+
if (rc)
434+
return rc;
474435

475-
err:
476-
kfree(dev_dax);
436+
run_dax(dax_dev);
437+
return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
438+
}
477439

478-
return ERR_PTR(rc);
440+
static int dev_dax_remove(struct device *dev)
441+
{
442+
/* all probe actions are unwound by devm */
443+
return 0;
479444
}
480-
EXPORT_SYMBOL_GPL(devm_create_dev_dax);
445+
446+
static struct device_driver device_dax_driver = {
447+
.probe = dev_dax_probe,
448+
.remove = dev_dax_remove,
449+
};
481450

482451
static int __init dax_init(void)
483452
{
484-
dax_class = class_create(THIS_MODULE, "dax");
485-
return PTR_ERR_OR_ZERO(dax_class);
453+
return dax_driver_register(&device_dax_driver);
486454
}
487455

488456
static void __exit dax_exit(void)
489457
{
490-
class_destroy(dax_class);
458+
driver_unregister(&device_dax_driver);
491459
}
492460

493461
MODULE_AUTHOR("Intel Corporation");
494462
MODULE_LICENSE("GPL v2");
495-
subsys_initcall(dax_init);
463+
module_init(dax_init);
496464
module_exit(dax_exit);
465+
MODULE_ALIAS_DAX_DEVICE(0);

0 commit comments

Comments
 (0)