Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / fs / char_dev.c
1 /*
2  *  linux/fs/char_dev.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6
7 #include <linux/config.h>
8 #include <linux/init.h>
9 #include <linux/fs.h>
10 #include <linux/slab.h>
11 #include <linux/string.h>
12
13 #include <linux/major.h>
14 #include <linux/errno.h>
15 #include <linux/module.h>
16 #include <linux/smp_lock.h>
17 #include <linux/devfs_fs_kernel.h>
18
19 #include <linux/kobject.h>
20 #include <linux/kobj_map.h>
21 #include <linux/cdev.h>
22
23 #ifdef CONFIG_KMOD
24 #include <linux/kmod.h>
25 #endif
26
27 static struct kobj_map *cdev_map;
28
29 /* degrade to linked list for small systems */
30 #define MAX_PROBE_HASH (CONFIG_BASE_SMALL ? 1 : 255)
31
32 static DECLARE_MUTEX(chrdevs_lock);
33
34 static struct char_device_struct {
35         struct char_device_struct *next;
36         unsigned int major;
37         unsigned int baseminor;
38         int minorct;
39         const char *name;
40         struct file_operations *fops;
41         struct cdev *cdev;              /* will die */
42 } *chrdevs[MAX_PROBE_HASH];
43
44 /* index in the above */
45 static inline int major_to_index(int major)
46 {
47         return major % MAX_PROBE_HASH;
48 }
49
50 /* get char device names in somewhat random order */
51 int get_chrdev_list(char *page)
52 {
53         struct char_device_struct *cd;
54         int i, len;
55
56         len = sprintf(page, "Character devices:\n");
57
58         down(&chrdevs_lock);
59         for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
60                 for (cd = chrdevs[i]; cd; cd = cd->next)
61                         len += sprintf(page+len, "%3d %s\n",
62                                        cd->major, cd->name);
63         }
64         up(&chrdevs_lock);
65
66         return len;
67 }
68
69 /*
70  * Register a single major with a specified minor range.
71  *
72  * If major == 0 this functions will dynamically allocate a major and return
73  * its number.
74  *
75  * If major > 0 this function will attempt to reserve the passed range of
76  * minors and will return zero on success.
77  *
78  * Returns a -ve errno on failure.
79  */
80 static struct char_device_struct *
81 __register_chrdev_region(unsigned int major, unsigned int baseminor,
82                            int minorct, const char *name)
83 {
84         struct char_device_struct *cd, **cp;
85         int ret = 0;
86         int i;
87
88         cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL);
89         if (cd == NULL)
90                 return ERR_PTR(-ENOMEM);
91
92         memset(cd, 0, sizeof(struct char_device_struct));
93
94         down(&chrdevs_lock);
95
96         /* temporary */
97         if (major == 0) {
98                 for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
99                         if (chrdevs[i] == NULL)
100                                 break;
101                 }
102
103                 if (i == 0) {
104                         ret = -EBUSY;
105                         goto out;
106                 }
107                 major = i;
108                 ret = major;
109         }
110
111         cd->major = major;
112         cd->baseminor = baseminor;
113         cd->minorct = minorct;
114         cd->name = name;
115
116         i = major_to_index(major);
117
118         for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
119                 if ((*cp)->major > major ||
120                     ((*cp)->major == major && (*cp)->baseminor >= baseminor))
121                         break;
122         if (*cp && (*cp)->major == major &&
123             (*cp)->baseminor < baseminor + minorct) {
124                 ret = -EBUSY;
125                 goto out;
126         }
127         cd->next = *cp;
128         *cp = cd;
129         up(&chrdevs_lock);
130         return cd;
131 out:
132         up(&chrdevs_lock);
133         kfree(cd);
134         return ERR_PTR(ret);
135 }
136
137 static struct char_device_struct *
138 __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
139 {
140         struct char_device_struct *cd = NULL, **cp;
141         int i = major_to_index(major);
142
143         up(&chrdevs_lock);
144         for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
145                 if ((*cp)->major == major &&
146                     (*cp)->baseminor == baseminor &&
147                     (*cp)->minorct == minorct)
148                         break;
149         if (*cp) {
150                 cd = *cp;
151                 *cp = cd->next;
152         }
153         up(&chrdevs_lock);
154         return cd;
155 }
156
157 int register_chrdev_region(dev_t from, unsigned count, const char *name)
158 {
159         struct char_device_struct *cd;
160         dev_t to = from + count;
161         dev_t n, next;
162
163         for (n = from; n < to; n = next) {
164                 next = MKDEV(MAJOR(n)+1, 0);
165                 if (next > to)
166                         next = to;
167                 cd = __register_chrdev_region(MAJOR(n), MINOR(n),
168                                next - n, name);
169                 if (IS_ERR(cd))
170                         goto fail;
171         }
172         return 0;
173 fail:
174         to = n;
175         for (n = from; n < to; n = next) {
176                 next = MKDEV(MAJOR(n)+1, 0);
177                 kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
178         }
179         return PTR_ERR(cd);
180 }
181
182 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
183                         const char *name)
184 {
185         struct char_device_struct *cd;
186         cd = __register_chrdev_region(0, baseminor, count, name);
187         if (IS_ERR(cd))
188                 return PTR_ERR(cd);
189         *dev = MKDEV(cd->major, cd->baseminor);
190         return 0;
191 }
192
193 int register_chrdev(unsigned int major, const char *name,
194                     struct file_operations *fops)
195 {
196         struct char_device_struct *cd;
197         struct cdev *cdev;
198         char *s;
199         int err = -ENOMEM;
200
201         cd = __register_chrdev_region(major, 0, 256, name);
202         if (IS_ERR(cd))
203                 return PTR_ERR(cd);
204         
205         cdev = cdev_alloc();
206         if (!cdev)
207                 goto out2;
208
209         cdev->owner = fops->owner;
210         cdev->ops = fops;
211         kobject_set_name(&cdev->kobj, "%s", name);
212         for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/'))
213                 *s = '!';
214                 
215         err = cdev_add(cdev, MKDEV(cd->major, 0), 256);
216         if (err)
217                 goto out;
218
219         cd->cdev = cdev;
220
221         return major ? 0 : cd->major;
222 out:
223         kobject_put(&cdev->kobj);
224 out2:
225         kfree(__unregister_chrdev_region(cd->major, 0, 256));
226         return err;
227 }
228
229 void unregister_chrdev_region(dev_t from, unsigned count)
230 {
231         dev_t to = from + count;
232         dev_t n, next;
233
234         for (n = from; n < to; n = next) {
235                 next = MKDEV(MAJOR(n)+1, 0);
236                 if (next > to)
237                         next = to;
238                 kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
239         }
240 }
241
242 int unregister_chrdev(unsigned int major, const char *name)
243 {
244         struct char_device_struct *cd;
245         cd = __unregister_chrdev_region(major, 0, 256);
246         if (cd && cd->cdev)
247                 cdev_del(cd->cdev);
248         kfree(cd);
249         return 0;
250 }
251
252 static DEFINE_SPINLOCK(cdev_lock);
253
254 static struct kobject *cdev_get(struct cdev *p)
255 {
256         struct module *owner = p->owner;
257         struct kobject *kobj;
258
259         if (owner && !try_module_get(owner))
260                 return NULL;
261         kobj = kobject_get(&p->kobj);
262         if (!kobj)
263                 module_put(owner);
264         return kobj;
265 }
266
267 void cdev_put(struct cdev *p)
268 {
269         if (p) {
270                 kobject_put(&p->kobj);
271                 module_put(p->owner);
272         }
273 }
274
275 /*
276  * Called every time a character special file is opened
277  */
278 int chrdev_open(struct inode * inode, struct file * filp)
279 {
280         struct cdev *p;
281         struct cdev *new = NULL;
282         int ret = 0;
283
284         spin_lock(&cdev_lock);
285         p = inode->i_cdev;
286         if (!p) {
287                 struct kobject *kobj;
288                 int idx;
289                 spin_unlock(&cdev_lock);
290                 kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
291                 if (!kobj)
292                         return -ENXIO;
293                 new = container_of(kobj, struct cdev, kobj);
294                 spin_lock(&cdev_lock);
295                 p = inode->i_cdev;
296                 if (!p) {
297                         inode->i_cdev = p = new;
298                         inode->i_cindex = idx;
299                         list_add(&inode->i_devices, &p->list);
300                         new = NULL;
301                 } else if (!cdev_get(p))
302                         ret = -ENXIO;
303         } else if (!cdev_get(p))
304                 ret = -ENXIO;
305         spin_unlock(&cdev_lock);
306         cdev_put(new);
307         if (ret)
308                 return ret;
309         filp->f_op = fops_get(p->ops);
310         if (!filp->f_op) {
311                 cdev_put(p);
312                 return -ENXIO;
313         }
314         if (filp->f_op->open) {
315                 lock_kernel();
316                 ret = filp->f_op->open(inode,filp);
317                 unlock_kernel();
318         }
319         if (ret)
320                 cdev_put(p);
321         return ret;
322 }
323
324 void cd_forget(struct inode *inode)
325 {
326         spin_lock(&cdev_lock);
327         list_del_init(&inode->i_devices);
328         inode->i_cdev = NULL;
329         spin_unlock(&cdev_lock);
330 }
331
332 void cdev_purge(struct cdev *cdev)
333 {
334         spin_lock(&cdev_lock);
335         while (!list_empty(&cdev->list)) {
336                 struct inode *inode;
337                 inode = container_of(cdev->list.next, struct inode, i_devices);
338                 list_del_init(&inode->i_devices);
339                 inode->i_cdev = NULL;
340         }
341         spin_unlock(&cdev_lock);
342 }
343
344 /*
345  * Dummy default file-operations: the only thing this does
346  * is contain the open that then fills in the correct operations
347  * depending on the special file...
348  */
349 struct file_operations def_chr_fops = {
350         .open = chrdev_open,
351 };
352
353 static struct kobject *exact_match(dev_t dev, int *part, void *data)
354 {
355         struct cdev *p = data;
356         return &p->kobj;
357 }
358
359 static int exact_lock(dev_t dev, void *data)
360 {
361         struct cdev *p = data;
362         return cdev_get(p) ? 0 : -1;
363 }
364
365 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
366 {
367         p->dev = dev;
368         p->count = count;
369         return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
370 }
371
372 static void cdev_unmap(dev_t dev, unsigned count)
373 {
374         kobj_unmap(cdev_map, dev, count);
375 }
376
377 void cdev_del(struct cdev *p)
378 {
379         cdev_unmap(p->dev, p->count);
380         kobject_put(&p->kobj);
381 }
382
383
384 static void cdev_default_release(struct kobject *kobj)
385 {
386         struct cdev *p = container_of(kobj, struct cdev, kobj);
387         cdev_purge(p);
388 }
389
390 static void cdev_dynamic_release(struct kobject *kobj)
391 {
392         struct cdev *p = container_of(kobj, struct cdev, kobj);
393         cdev_purge(p);
394         kfree(p);
395 }
396
397 static struct kobj_type ktype_cdev_default = {
398         .release        = cdev_default_release,
399 };
400
401 static struct kobj_type ktype_cdev_dynamic = {
402         .release        = cdev_dynamic_release,
403 };
404
405 struct cdev *cdev_alloc(void)
406 {
407         struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL);
408         if (p) {
409                 memset(p, 0, sizeof(struct cdev));
410                 p->kobj.ktype = &ktype_cdev_dynamic;
411                 INIT_LIST_HEAD(&p->list);
412                 kobject_init(&p->kobj);
413         }
414         return p;
415 }
416
417 void cdev_init(struct cdev *cdev, struct file_operations *fops)
418 {
419         memset(cdev, 0, sizeof *cdev);
420         INIT_LIST_HEAD(&cdev->list);
421         cdev->kobj.ktype = &ktype_cdev_default;
422         kobject_init(&cdev->kobj);
423         cdev->ops = fops;
424 }
425
426 static struct kobject *base_probe(dev_t dev, int *part, void *data)
427 {
428         if (request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0)
429                 /* Make old-style 2.4 aliases work */
430                 request_module("char-major-%d", MAJOR(dev));
431         return NULL;
432 }
433
434 void __init chrdev_init(void)
435 {
436         cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
437 }
438
439
440 /* Let modules do char dev stuff */
441 EXPORT_SYMBOL(register_chrdev_region);
442 EXPORT_SYMBOL(unregister_chrdev_region);
443 EXPORT_SYMBOL(alloc_chrdev_region);
444 EXPORT_SYMBOL(cdev_init);
445 EXPORT_SYMBOL(cdev_alloc);
446 EXPORT_SYMBOL(cdev_del);
447 EXPORT_SYMBOL(cdev_add);
448 EXPORT_SYMBOL(register_chrdev);
449 EXPORT_SYMBOL(unregister_chrdev);