2 * linux/drivers/base/map.c
4 * (C) Copyright Al Viro 2002,2003
5 * Released under GPL v2.
7 * NOTE: data structure needs to be changed. It works, but for large dev_t
8 * it will be too slow. It is isolated, though, so these changes will be
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/kdev_t.h>
15 #include <linux/kobject.h>
16 #include <linux/kobj_map.h>
25 int (*lock
)(dev_t
, void *);
28 struct semaphore
*sem
;
31 int kobj_map(struct kobj_map
*domain
, dev_t dev
, unsigned long range
,
32 struct module
*module
, kobj_probe_t
*probe
,
33 int (*lock
)(dev_t
, void *), void *data
)
35 unsigned n
= MAJOR(dev
+ range
- 1) - MAJOR(dev
) + 1;
36 unsigned index
= MAJOR(dev
);
43 p
= kmalloc(sizeof(struct probe
) * n
, GFP_KERNEL
);
48 for (i
= 0; i
< n
; i
++, p
++) {
57 for (i
= 0, p
-= n
; i
< n
; i
++, p
++, index
++) {
58 struct probe
**s
= &domain
->probes
[index
% 255];
59 while (*s
&& (*s
)->range
< range
)
68 void kobj_unmap(struct kobj_map
*domain
, dev_t dev
, unsigned long range
)
70 unsigned n
= MAJOR(dev
+ range
- 1) - MAJOR(dev
) + 1;
71 unsigned index
= MAJOR(dev
);
73 struct probe
*found
= NULL
;
79 for (i
= 0; i
< n
; i
++, index
++) {
81 for (s
= &domain
->probes
[index
% 255]; *s
; s
= &(*s
)->next
) {
83 if (p
->dev
== dev
&& p
->range
== range
) {
95 struct kobject
*kobj_lookup(struct kobj_map
*domain
, dev_t dev
, int *index
)
99 unsigned long best
= ~0UL;
103 for (p
= domain
->probes
[MAJOR(dev
) % 255]; p
; p
= p
->next
) {
104 struct kobject
*(*probe
)(dev_t
, int *, void *);
105 struct module
*owner
;
108 if (p
->dev
> dev
|| p
->dev
+ p
->range
- 1 < dev
)
110 if (p
->range
- 1 >= best
)
112 if (!try_module_get(p
->owner
))
118 *index
= dev
- p
->dev
;
119 if (p
->lock
&& p
->lock(dev
, data
) < 0) {
124 kobj
= probe(dev
, index
, data
);
125 /* Currently ->owner protects _only_ ->probe() itself. */
135 struct kobj_map
*kobj_map_init(kobj_probe_t
*base_probe
, struct semaphore
*sem
)
137 struct kobj_map
*p
= kmalloc(sizeof(struct kobj_map
), GFP_KERNEL
);
138 struct probe
*base
= kmalloc(sizeof(struct probe
), GFP_KERNEL
);
141 if ((p
== NULL
) || (base
== NULL
)) {
147 memset(base
, 0, sizeof(struct probe
));
150 base
->get
= base_probe
;
151 for (i
= 0; i
< 255; i
++)