1 // SPDX-License-Identifier: GPL-2.0
3 * linux/drivers/base/map.c
5 * (C) Copyright Al Viro 2002,2003
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_array(n
, sizeof(struct probe
), GFP_KERNEL
);
48 for (i
= 0; i
< n
; i
++, p
++) {
56 mutex_lock(domain
->lock
);
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
)
64 mutex_unlock(domain
->lock
);
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
;
78 mutex_lock(domain
->lock
);
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
) {
91 mutex_unlock(domain
->lock
);
95 struct kobject
*kobj_lookup(struct kobj_map
*domain
, dev_t dev
, int *index
)
99 unsigned long best
= ~0UL;
102 mutex_lock(domain
->lock
);
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) {
123 mutex_unlock(domain
->lock
);
124 kobj
= probe(dev
, index
, data
);
125 /* Currently ->owner protects _only_ ->probe() itself. */
131 mutex_unlock(domain
->lock
);
135 struct kobj_map
*kobj_map_init(kobj_probe_t
*base_probe
, struct mutex
*lock
)
137 struct kobj_map
*p
= kmalloc(sizeof(struct kobj_map
), GFP_KERNEL
);
138 struct probe
*base
= kzalloc(sizeof(*base
), GFP_KERNEL
);
141 if ((p
== NULL
) || (base
== NULL
)) {
149 base
->get
= base_probe
;
150 for (i
= 0; i
< 255; i
++)