1
2
3
4#include <linux/module.h>
5#include <linux/kmod.h>
6#include <linux/spinlock.h>
7#include <linux/list.h>
8#include <linux/slab.h>
9
10
11
12
13
14
15
16static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
17static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
18static int kmalloc_failed;
19
20struct inter_module_entry {
21 struct list_head list;
22 const char *im_name;
23 struct module *owner;
24 const void *userdata;
25};
26
27
28
29
30
31
32
33
34
35
36
37void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
38{
39 struct list_head *tmp;
40 struct inter_module_entry *ime, *ime_new;
41
42 if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
43
44 printk(KERN_ERR
45 "Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
46 im_name);
47 kmalloc_failed = 1;
48 return;
49 }
50 memset(ime_new, 0, sizeof(*ime_new));
51 ime_new->im_name = im_name;
52 ime_new->owner = owner;
53 ime_new->userdata = userdata;
54
55 spin_lock(&ime_lock);
56 list_for_each(tmp, &ime_list) {
57 ime = list_entry(tmp, struct inter_module_entry, list);
58 if (strcmp(ime->im_name, im_name) == 0) {
59 spin_unlock(&ime_lock);
60 kfree(ime_new);
61
62 printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
63 BUG();
64 }
65 }
66 list_add(&(ime_new->list), &ime_list);
67 spin_unlock(&ime_lock);
68}
69
70
71
72
73
74
75
76
77
78void inter_module_unregister(const char *im_name)
79{
80 struct list_head *tmp;
81 struct inter_module_entry *ime;
82
83 spin_lock(&ime_lock);
84 list_for_each(tmp, &ime_list) {
85 ime = list_entry(tmp, struct inter_module_entry, list);
86 if (strcmp(ime->im_name, im_name) == 0) {
87 list_del(&(ime->list));
88 spin_unlock(&ime_lock);
89 kfree(ime);
90 return;
91 }
92 }
93 spin_unlock(&ime_lock);
94 if (kmalloc_failed) {
95 printk(KERN_ERR
96 "inter_module_unregister: no entry for '%s', "
97 "probably caused by previous kmalloc failure\n",
98 im_name);
99 return;
100 }
101 else {
102
103 printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
104 BUG();
105 }
106}
107
108
109
110
111
112
113
114
115
116const void *inter_module_get(const char *im_name)
117{
118 struct list_head *tmp;
119 struct inter_module_entry *ime;
120 const void *result = NULL;
121
122 spin_lock(&ime_lock);
123 list_for_each(tmp, &ime_list) {
124 ime = list_entry(tmp, struct inter_module_entry, list);
125 if (strcmp(ime->im_name, im_name) == 0) {
126 if (try_module_get(ime->owner))
127 result = ime->userdata;
128 break;
129 }
130 }
131 spin_unlock(&ime_lock);
132 return(result);
133}
134
135
136
137
138
139
140
141
142const void *inter_module_get_request(const char *im_name, const char *modname)
143{
144 const void *result = inter_module_get(im_name);
145 if (!result) {
146 request_module("%s", modname);
147 result = inter_module_get(im_name);
148 }
149 return(result);
150}
151
152
153
154
155
156
157
158
159void inter_module_put(const char *im_name)
160{
161 struct list_head *tmp;
162 struct inter_module_entry *ime;
163
164 spin_lock(&ime_lock);
165 list_for_each(tmp, &ime_list) {
166 ime = list_entry(tmp, struct inter_module_entry, list);
167 if (strcmp(ime->im_name, im_name) == 0) {
168 if (ime->owner)
169 module_put(ime->owner);
170 spin_unlock(&ime_lock);
171 return;
172 }
173 }
174 spin_unlock(&ime_lock);
175 printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
176 BUG();
177}
178
179EXPORT_SYMBOL(inter_module_register);
180EXPORT_SYMBOL(inter_module_unregister);
181EXPORT_SYMBOL(inter_module_get);
182EXPORT_SYMBOL(inter_module_get_request);
183EXPORT_SYMBOL(inter_module_put);
184