aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dax/bus.c145
-rw-r--r--drivers/dax/bus.h10
-rw-r--r--drivers/dax/device.c11
3 files changed, 156 insertions, 10 deletions
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index 69aae2cbd45f..17af6fbc3be5 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -2,11 +2,21 @@
2/* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */ 2/* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */
3#include <linux/memremap.h> 3#include <linux/memremap.h>
4#include <linux/device.h> 4#include <linux/device.h>
5#include <linux/mutex.h>
6#include <linux/list.h>
5#include <linux/slab.h> 7#include <linux/slab.h>
6#include <linux/dax.h> 8#include <linux/dax.h>
7#include "dax-private.h" 9#include "dax-private.h"
8#include "bus.h" 10#include "bus.h"
9 11
12static DEFINE_MUTEX(dax_bus_lock);
13
14#define DAX_NAME_LEN 30
15struct dax_id {
16 struct list_head list;
17 char dev_name[DAX_NAME_LEN];
18};
19
10static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 20static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
11{ 21{
12 /* 22 /*
@@ -16,22 +26,115 @@ static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
16 return add_uevent_var(env, "MODALIAS=" DAX_DEVICE_MODALIAS_FMT, 0); 26 return add_uevent_var(env, "MODALIAS=" DAX_DEVICE_MODALIAS_FMT, 0);
17} 27}
18 28
29static struct dax_device_driver *to_dax_drv(struct device_driver *drv)
30{
31 return container_of(drv, struct dax_device_driver, drv);
32}
33
34static struct dax_id *__dax_match_id(struct dax_device_driver *dax_drv,
35 const char *dev_name)
36{
37 struct dax_id *dax_id;
38
39 lockdep_assert_held(&dax_bus_lock);
40
41 list_for_each_entry(dax_id, &dax_drv->ids, list)
42 if (sysfs_streq(dax_id->dev_name, dev_name))
43 return dax_id;
44 return NULL;
45}
46
47static int dax_match_id(struct dax_device_driver *dax_drv, struct device *dev)
48{
49 int match;
50
51 mutex_lock(&dax_bus_lock);
52 match = !!__dax_match_id(dax_drv, dev_name(dev));
53 mutex_unlock(&dax_bus_lock);
54
55 return match;
56}
57
58static ssize_t do_id_store(struct device_driver *drv, const char *buf,
59 size_t count, bool add)
60{
61 struct dax_device_driver *dax_drv = to_dax_drv(drv);
62 unsigned int region_id, id;
63 char devname[DAX_NAME_LEN];
64 struct dax_id *dax_id;
65 ssize_t rc = count;
66 int fields;
67
68 fields = sscanf(buf, "dax%d.%d", &region_id, &id);
69 if (fields != 2)
70 return -EINVAL;
71 sprintf(devname, "dax%d.%d", region_id, id);
72 if (!sysfs_streq(buf, devname))
73 return -EINVAL;
74
75 mutex_lock(&dax_bus_lock);
76 dax_id = __dax_match_id(dax_drv, buf);
77 if (!dax_id) {
78 if (add) {
79 dax_id = kzalloc(sizeof(*dax_id), GFP_KERNEL);
80 if (dax_id) {
81 strncpy(dax_id->dev_name, buf, DAX_NAME_LEN);
82 list_add(&dax_id->list, &dax_drv->ids);
83 } else
84 rc = -ENOMEM;
85 } else
86 /* nothing to remove */;
87 } else if (!add) {
88 list_del(&dax_id->list);
89 kfree(dax_id);
90 } else
91 /* dax_id already added */;
92 mutex_unlock(&dax_bus_lock);
93 return rc;
94}
95
96static ssize_t new_id_store(struct device_driver *drv, const char *buf,
97 size_t count)
98{
99 return do_id_store(drv, buf, count, true);
100}
101static DRIVER_ATTR_WO(new_id);
102
103static ssize_t remove_id_store(struct device_driver *drv, const char *buf,
104 size_t count)
105{
106 return do_id_store(drv, buf, count, false);
107}
108static DRIVER_ATTR_WO(remove_id);
109
110static struct attribute *dax_drv_attrs[] = {
111 &driver_attr_new_id.attr,
112 &driver_attr_remove_id.attr,
113 NULL,
114};
115ATTRIBUTE_GROUPS(dax_drv);
116
19static int dax_bus_match(struct device *dev, struct device_driver *drv); 117static int dax_bus_match(struct device *dev, struct device_driver *drv);
20 118
21static struct bus_type dax_bus_type = { 119static struct bus_type dax_bus_type = {
22 .name = "dax", 120 .name = "dax",
23 .uevent = dax_bus_uevent, 121 .uevent = dax_bus_uevent,
24 .match = dax_bus_match, 122 .match = dax_bus_match,
123 .drv_groups = dax_drv_groups,
25}; 124};
26 125
27static int dax_bus_match(struct device *dev, struct device_driver *drv) 126static int dax_bus_match(struct device *dev, struct device_driver *drv)
28{ 127{
128 struct dax_device_driver *dax_drv = to_dax_drv(drv);
129
29 /* 130 /*
30 * The drivers that can register on the 'dax' bus are private to 131 * All but the 'device-dax' driver, which has 'match_always'
31 * drivers/dax/ so any device and driver on the bus always 132 * set, requires an exact id match.
32 * match.
33 */ 133 */
34 return 1; 134 if (dax_drv->match_always)
135 return 1;
136
137 return dax_match_id(dax_drv, dev);
35} 138}
36 139
37/* 140/*
@@ -273,17 +376,49 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
273} 376}
274EXPORT_SYMBOL_GPL(devm_create_dev_dax); 377EXPORT_SYMBOL_GPL(devm_create_dev_dax);
275 378
276int __dax_driver_register(struct device_driver *drv, 379static int match_always_count;
380
381int __dax_driver_register(struct dax_device_driver *dax_drv,
277 struct module *module, const char *mod_name) 382 struct module *module, const char *mod_name)
278{ 383{
384 struct device_driver *drv = &dax_drv->drv;
385 int rc = 0;
386
387 INIT_LIST_HEAD(&dax_drv->ids);
279 drv->owner = module; 388 drv->owner = module;
280 drv->name = mod_name; 389 drv->name = mod_name;
281 drv->mod_name = mod_name; 390 drv->mod_name = mod_name;
282 drv->bus = &dax_bus_type; 391 drv->bus = &dax_bus_type;
392
393 /* there can only be one default driver */
394 mutex_lock(&dax_bus_lock);
395 match_always_count += dax_drv->match_always;
396 if (match_always_count > 1) {
397 match_always_count--;
398 WARN_ON(1);
399 rc = -EINVAL;
400 }
401 mutex_unlock(&dax_bus_lock);
402 if (rc)
403 return rc;
283 return driver_register(drv); 404 return driver_register(drv);
284} 405}
285EXPORT_SYMBOL_GPL(__dax_driver_register); 406EXPORT_SYMBOL_GPL(__dax_driver_register);
286 407
408void dax_driver_unregister(struct dax_device_driver *dax_drv)
409{
410 struct dax_id *dax_id, *_id;
411
412 mutex_lock(&dax_bus_lock);
413 match_always_count -= dax_drv->match_always;
414 list_for_each_entry_safe(dax_id, _id, &dax_drv->ids, list) {
415 list_del(&dax_id->list);
416 kfree(dax_id);
417 }
418 mutex_unlock(&dax_bus_lock);
419}
420EXPORT_SYMBOL_GPL(dax_driver_unregister);
421
287int __init dax_bus_init(void) 422int __init dax_bus_init(void)
288{ 423{
289 return bus_register(&dax_bus_type); 424 return bus_register(&dax_bus_type);
diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
index e08e0c394983..395ab812367c 100644
--- a/drivers/dax/bus.h
+++ b/drivers/dax/bus.h
@@ -12,10 +12,18 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
12 struct resource *res, unsigned int align, unsigned long flags); 12 struct resource *res, unsigned int align, unsigned long flags);
13struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id, 13struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
14 struct dev_pagemap *pgmap); 14 struct dev_pagemap *pgmap);
15int __dax_driver_register(struct device_driver *drv, 15
16struct dax_device_driver {
17 struct device_driver drv;
18 struct list_head ids;
19 int match_always;
20};
21
22int __dax_driver_register(struct dax_device_driver *dax_drv,
16 struct module *module, const char *mod_name); 23 struct module *module, const char *mod_name);
17#define dax_driver_register(driver) \ 24#define dax_driver_register(driver) \
18 __dax_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) 25 __dax_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
26void dax_driver_unregister(struct dax_device_driver *dax_drv);
19void kill_dev_dax(struct dev_dax *dev_dax); 27void kill_dev_dax(struct dev_dax *dev_dax);
20 28
21/* 29/*
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index 6ad964d7b077..ad3120395f7a 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -504,9 +504,12 @@ static int dev_dax_remove(struct device *dev)
504 return 0; 504 return 0;
505} 505}
506 506
507static struct device_driver device_dax_driver = { 507static struct dax_device_driver device_dax_driver = {
508 .probe = dev_dax_probe, 508 .drv = {
509 .remove = dev_dax_remove, 509 .probe = dev_dax_probe,
510 .remove = dev_dax_remove,
511 },
512 .match_always = 1,
510}; 513};
511 514
512static int __init dax_init(void) 515static int __init dax_init(void)
@@ -516,7 +519,7 @@ static int __init dax_init(void)
516 519
517static void __exit dax_exit(void) 520static void __exit dax_exit(void)
518{ 521{
519 driver_unregister(&device_dax_driver); 522 dax_driver_unregister(&device_dax_driver);
520} 523}
521 524
522MODULE_AUTHOR("Intel Corporation"); 525MODULE_AUTHOR("Intel Corporation");