Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }