/alps/bar_resolve

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/bar_resolve
1 by Suren A. Chilingaryan
Test application for resolving user-space BAR addresses
1
#include <linux/init.h>
2
#include <linux/module.h>
3
#include <linux/device.h>
4
#include <linux/types.h>
5
#include <linux/cdev.h>
6
#include <linux/fs.h>
7
#include <linux/slab.h>
2 by Suren A. Chilingaryan
Finalyze the sample
8
#include <linux/semaphore.h>
1 by Suren A. Chilingaryan
Test application for resolving user-space BAR addresses
9
10
11
#include "mod.h"
12
#include "dev.h"
13
#include "debug.h"
14
#include "sysfs.h"
15
16
17
MODULE_LICENSE("GPL v2");
18
MODULE_AUTHOR("Suren A. Chilingaryan <csa@suren.me>");
19
MODULE_DESCRIPTION("Testing module");
20
MODULE_VERSION("0.0.1");
21
22
int test_minors = TEST_MINORS;
23
24
module_param(test_minors, int, S_IRUGO);
25
26
27
static dev_t test_devno;			/**< major number */
2 by Suren A. Chilingaryan
Finalyze the sample
28
static test_dev_t **test_devs = NULL;	        /**< per-device context */
29
static DEFINE_SEMAPHORE(test_devs_mtx);            /**< mutex protecting creation/destruction of devices */
1 by Suren A. Chilingaryan
Test application for resolving user-space BAR addresses
30
static struct class *test_class;		/**< device class */
31
32
static void test_module_destroy_cdev(test_dev_t *test)
33
{
34
    if (test->dev) {
35
	test_sysfs_free(test);
36
	device_destroy(test_class, test->devno);
37
    }
38
    cdev_del(&test->cdev);
39
    kfree(test);
40
}
41
42
static int test_module_setup_cdev(void)
43
{
44
    int i;
45
    int err = 0;
46
    dev_t devno;
47
    test_dev_t *test;
48
49
    test = kmalloc(sizeof(test_dev_t), GFP_KERNEL);
50
    if (!test) {
51
	mod_info("Couldn't allocate memory. Device is not created.\n");
52
	return -ENOMEM;
53
    }
54
55
    cdev_init(&test->cdev, test_get_fops());
56
    test->cdev.owner = THIS_MODULE;
57
    test->cdev.ops = test_get_fops();
58
2 by Suren A. Chilingaryan
Finalyze the sample
59
    down(&test_devs_mtx);
1 by Suren A. Chilingaryan
Test application for resolving user-space BAR addresses
60
    for (i = 0; i < test_minors; i++) {
61
	if (!test_devs[i])
62
	    break;
63
    }
64
65
    if (i == test_minors) {
66
	mod_info("No free minor numbers left");
67
	err = -EBUSY;
68
	goto fail;
69
    }
70
71
    devno = MKDEV(MAJOR(test_devno), MINOR(test_devno) + i);
72
    test->devno = devno;
73
74
    err = cdev_add(&test->cdev, devno, 1);
75
    if (err) {
76
	mod_info("Error %d adding device kmm%d", err, i);
77
	goto fail;
78
    }
79
80
    test->dev = device_create(test_class, NULL, devno, test, TEST_NODE_FMT, MINOR(test_devno) + i);
81
    if (!test->dev) {
82
	mod_info("Error creating /dev/%s%d\n", TEST_NODE, MINOR(test_devno) + i);
83
	goto fail;
84
    }
85
    dev_set_drvdata(test->dev, test);
86
87
    test_devs[i] = test;
2 by Suren A. Chilingaryan
Finalyze the sample
88
    up(&test_devs_mtx);
1 by Suren A. Chilingaryan
Test application for resolving user-space BAR addresses
89
90
    err = test_sysfs_init(test);
91
    if (err) goto fail_sysfs;
92
93
    mod_info("Device /dev/%s%d added\n", TEST_NODE, MINOR(test_devno) + i);
94
95
    return 0;
96
97
fail:
2 by Suren A. Chilingaryan
Finalyze the sample
98
    up(&test_devs_mtx);
1 by Suren A. Chilingaryan
Test application for resolving user-space BAR addresses
99
fail_sysfs:
100
    test_module_destroy_cdev(test);
101
    return err;
102
}
103
104
105
static void test_module_cleanup(void)
106
{
107
    int i;
108
109
    if (test_devs) {
110
	for (i = 0; i < test_minors; i++) {
111
	    if (test_devs[i])
112
		test_module_destroy_cdev(test_devs[i]);
113
	}
114
	kfree(test_devs);
115
    }
116
117
118
    if (test_class)
119
    	class_destroy(test_class);
120
121
    unregister_chrdev_region(test_devno, test_minors);
122
}
123
124
static int __init test_module_init(void)
125
{
126
    int err;
127
128
    if ((err = alloc_chrdev_region(&test_devno, 0, test_minors, TEST_NODE))) {
129
	mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
130
	goto alloc_chrdev_fail;
131
    }
132
133
    test_class = class_create(THIS_MODULE, TEST_NODE);
134
    if (IS_ERR(test_class)) {
135
	mod_info("No sysfs support. Module not loaded.\n");
136
	goto fail;
137
    }
138
139
    test_devs = kmalloc(test_minors * sizeof(test_dev_t*), GFP_KERNEL);
140
    if (!test_devs) {
141
	mod_info("Couldn't allocate memory. Module not loaded.\n");
142
	err = -ENOMEM;
143
    }
144
    memset(test_devs, 0, test_minors * sizeof(test_dev_t*));
145
146
    mod_info("Major %d allocated to node '%s'\n", MAJOR(test_devno), TEST_NODE);
147
148
    err = test_module_setup_cdev();
149
    if (err) goto fail;
150
151
152
    return 0;
153
154
fail:
155
    test_module_cleanup();
156
alloc_chrdev_fail:
157
    return err;
158
}
159
160
161
static void __exit test_module_exit(void)
162
{
163
    test_module_cleanup();
164
}
165
166
module_init(test_module_init);
167
module_exit(test_module_exit);