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