/alps/bar_resolve

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/bar_resolve

« back to all changes in this revision

Viewing changes to mod.c

  • Committer: Suren A. Chilingaryan
  • Date: 2016-03-02 05:45:24 UTC
  • Revision ID: csa@suren.me-20160302054524-aqefho92o0ljk3eh
Test application for resolving user-space BAR addresses

Show diffs side-by-side

added added

removed removed

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