Home Home > GIT Browse > stable-xen
summaryrefslogtreecommitdiff
blob: f111bb4caa9bd535ee19a5ba4124c95aa1cd28f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <linux/err.h>
#include <linux/export.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <xen/driver_util.h>

static struct class *_get_xen_class(void)
{
	static struct class *xen_class;
	static DEFINE_MUTEX(xc_mutex);

	mutex_lock(&xc_mutex);
	if (IS_ERR_OR_NULL(xen_class))
		xen_class = class_create(THIS_MODULE, "xen");
	mutex_unlock(&xc_mutex);
	if (IS_ERR(xen_class))
		pr_err("failed to create xen sysfs class\n");

	return xen_class;
}

struct class *get_xen_class(void)
{
	struct class *class = _get_xen_class();

	return !IS_ERR(class) ? class : NULL;
}
EXPORT_SYMBOL_GPL(get_xen_class);

static void xcdev_release(struct device *dev)
{
	kfree(dev);
}

struct device *xen_class_device_create(struct device_type *type,
				       struct device *parent,
				       dev_t devt, void *drvdata,
				       const char *fmt, ...)
{
	struct device *dev;
	int err;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (dev) {
		va_list vargs;

		va_start(vargs, fmt);
		err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
		va_end(vargs);
	} else
		err = -ENOMEM;

	if (!err) {
		dev->devt = devt;
		dev->class = _get_xen_class();
		if (IS_ERR(dev->class))
			err = PTR_ERR(dev->class);
	}

	if (!err) {
		dev->type = type;
		dev->parent = parent;
		dev_set_drvdata(dev, drvdata);
		dev->release = xcdev_release;
		err = device_register(dev);
		if (!err)
			return dev;
		put_device(dev);
	} else
		kfree(dev);

	return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(xen_class_device_create);