/alps/kmm

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/kmm

« back to all changes in this revision

Viewing changes to mod.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-12-02 18:03:58 UTC
  • Revision ID: csa@suren.me-20151202180358-3k401zf10ltlpj0m
Initial import

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