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/mutex.h>
15 #include <linux/kdev_t.h>
16 #include <linux/kobject.h>
17 #include <linux/kobj_map.h>
26 int (*lock
)(dev_t
, void *);
32 int kobj_map(struct kobj_map
*domain
, dev_t dev
, unsigned long range
,
33 struct module
*module
, kobj_probe_t
*probe
,
34 int (*lock
)(dev_t
, void *), void *data
)
36 unsigned n
= MAJOR(dev
+ range
- 1) - MAJOR(dev
) + 1;
37 unsigned index
= MAJOR(dev
);
44 p
= kmalloc(sizeof(struct probe
) * n
, GFP_KERNEL
);
49 for (i
= 0; i
< n
; i
++, p
++) {
57 mutex_lock(domain
->lock
);
58 for (i
= 0, p
-= n
; i
< n
; i
++, p
++, index
++) {
59 struct probe
**s
= &domain
->probes
[index
% 255];
60 while (*s
&& (*s
)->range
< range
)
65 mutex_unlock(domain
->lock
);
69 void kobj_unmap(struct kobj_map
*domain
, dev_t dev
, unsigned long range
)
71 unsigned n
= MAJOR(dev
+ range
- 1) - MAJOR(dev
) + 1;
72 unsigned index
= MAJOR(dev
);
74 struct probe
*found
= NULL
;
79 mutex_lock(domain
->lock
);
80 for (i
= 0; i
< n
; i
++, index
++) {
82 for (s
= &domain
->probes
[index
% 255]; *s
; s
= &(*s
)->next
) {
84 if (p
->dev
== dev
&& p
->range
== range
) {
92 mutex_unlock(domain
->lock
);
96 struct kobject
*kobj_lookup(struct kobj_map
*domain
, dev_t dev
, int *index
)
100 unsigned long best
= ~0UL;
103 mutex_lock(domain
->lock
);
104 for (p
= domain
->probes
[MAJOR(dev
) % 255]; p
; p
= p
->next
) {
105 struct kobject
*(*probe
)(dev_t
, int *, void *);
106 struct module
*owner
;
109 if (p
->dev
> dev
|| p
->dev
+ p
->range
- 1 < dev
)
111 if (p
->range
- 1 >= best
)
113 if (!try_module_get(p
->owner
))
119 *index
= dev
- p
->dev
;
120 if (p
->lock
&& p
->lock(dev
, data
) < 0) {
124 mutex_unlock(domain
->lock
);
125 kobj
= probe(dev
, index
, data
);
126 /* Currently ->owner protects _only_ ->probe() itself. */
132 mutex_unlock(domain
->lock
);
136 struct kobj_map
*kobj_map_init(kobj_probe_t
*base_probe
, struct mutex
*lock
)
138 struct kobj_map
*p
= kmalloc(sizeof(struct kobj_map
), GFP_KERNEL
);
139 struct probe
*base
= kzalloc(sizeof(*base
), GFP_KERNEL
);
142 if ((p
== NULL
) || (base
== NULL
)) {
150 base
->get
= base_probe
;
151 for (i
= 0; i
< 255; i
++)