Blame view
drivers/base/map.c
3.3 KB
989d42e85 driver core: add ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 |
/* * linux/drivers/base/map.c * * (C) Copyright Al Viro 2002,2003 |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 12 13 |
* * NOTE: data structure needs to be changed. It works, but for large dev_t * it will be too slow. It is isolated, though, so these changes will be * local to that file. */ #include <linux/module.h> #include <linux/slab.h> |
58383af62 [PATCH] kobj_map ... |
14 |
#include <linux/mutex.h> |
1da177e4c Linux-2.6.12-rc2 |
15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <linux/kdev_t.h> #include <linux/kobject.h> #include <linux/kobj_map.h> struct kobj_map { struct probe { struct probe *next; dev_t dev; unsigned long range; struct module *owner; kobj_probe_t *get; int (*lock)(dev_t, void *); void *data; } *probes[255]; |
58383af62 [PATCH] kobj_map ... |
29 |
struct mutex *lock; |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 33 34 35 36 37 38 39 40 41 42 |
}; int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, struct module *module, kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data) { unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; unsigned index = MAJOR(dev); unsigned i; struct probe *p; if (n > 255) n = 255; |
2e4fabec5 drivers: base: ma... |
43 |
p = kmalloc_array(n, sizeof(struct probe), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 49 50 51 52 53 54 |
if (p == NULL) return -ENOMEM; for (i = 0; i < n; i++, p++) { p->owner = module; p->get = probe; p->lock = lock; p->dev = dev; p->range = range; p->data = data; } |
58383af62 [PATCH] kobj_map ... |
55 |
mutex_lock(domain->lock); |
1da177e4c Linux-2.6.12-rc2 |
56 57 58 59 60 61 62 |
for (i = 0, p -= n; i < n; i++, p++, index++) { struct probe **s = &domain->probes[index % 255]; while (*s && (*s)->range < range) s = &(*s)->next; p->next = *s; *s = p; } |
58383af62 [PATCH] kobj_map ... |
63 |
mutex_unlock(domain->lock); |
1da177e4c Linux-2.6.12-rc2 |
64 65 66 67 68 69 70 71 72 73 74 75 |
return 0; } void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) { unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; unsigned index = MAJOR(dev); unsigned i; struct probe *found = NULL; if (n > 255) n = 255; |
58383af62 [PATCH] kobj_map ... |
76 |
mutex_lock(domain->lock); |
1da177e4c Linux-2.6.12-rc2 |
77 78 79 80 81 82 83 84 85 86 87 88 |
for (i = 0; i < n; i++, index++) { struct probe **s; for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) { struct probe *p = *s; if (p->dev == dev && p->range == range) { *s = p->next; if (!found) found = p; break; } } } |
58383af62 [PATCH] kobj_map ... |
89 |
mutex_unlock(domain->lock); |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 93 94 95 96 97 98 99 |
kfree(found); } struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) { struct kobject *kobj; struct probe *p; unsigned long best = ~0UL; retry: |
58383af62 [PATCH] kobj_map ... |
100 |
mutex_lock(domain->lock); |
1da177e4c Linux-2.6.12-rc2 |
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) { struct kobject *(*probe)(dev_t, int *, void *); struct module *owner; void *data; if (p->dev > dev || p->dev + p->range - 1 < dev) continue; if (p->range - 1 >= best) break; if (!try_module_get(p->owner)) continue; owner = p->owner; data = p->data; probe = p->get; best = p->range - 1; *index = dev - p->dev; if (p->lock && p->lock(dev, data) < 0) { module_put(owner); continue; } |
58383af62 [PATCH] kobj_map ... |
121 |
mutex_unlock(domain->lock); |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 126 127 128 |
kobj = probe(dev, index, data); /* Currently ->owner protects _only_ ->probe() itself. */ module_put(owner); if (kobj) return kobj; goto retry; } |
58383af62 [PATCH] kobj_map ... |
129 |
mutex_unlock(domain->lock); |
1da177e4c Linux-2.6.12-rc2 |
130 131 |
return NULL; } |
58383af62 [PATCH] kobj_map ... |
132 |
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock) |
1da177e4c Linux-2.6.12-rc2 |
133 134 |
{ struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); |
4aed0644d [PATCH] drivers/b... |
135 |
struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 141 142 |
int i; if ((p == NULL) || (base == NULL)) { kfree(p); kfree(base); return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
143 144 145 146 147 |
base->dev = 1; base->range = ~0; base->get = base_probe; for (i = 0; i < 255; i++) p->probes[i] = base; |
58383af62 [PATCH] kobj_map ... |
148 |
p->lock = lock; |
1da177e4c Linux-2.6.12-rc2 |
149 150 |
return p; } |