0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/mutex.h>
0015 #include <linux/kdev_t.h>
0016 #include <linux/kobject.h>
0017 #include <linux/kobj_map.h>
0018
0019 struct kobj_map {
0020 struct probe {
0021 struct probe *next;
0022 dev_t dev;
0023 unsigned long range;
0024 struct module *owner;
0025 kobj_probe_t *get;
0026 int (*lock)(dev_t, void *);
0027 void *data;
0028 } *probes[255];
0029 struct mutex *lock;
0030 };
0031
0032 int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
0033 struct module *module, kobj_probe_t *probe,
0034 int (*lock)(dev_t, void *), void *data)
0035 {
0036 unsigned int n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
0037 unsigned int index = MAJOR(dev);
0038 unsigned int i;
0039 struct probe *p;
0040
0041 if (n > 255)
0042 n = 255;
0043
0044 p = kmalloc_array(n, sizeof(struct probe), GFP_KERNEL);
0045 if (p == NULL)
0046 return -ENOMEM;
0047
0048 for (i = 0; i < n; i++, p++) {
0049 p->owner = module;
0050 p->get = probe;
0051 p->lock = lock;
0052 p->dev = dev;
0053 p->range = range;
0054 p->data = data;
0055 }
0056 mutex_lock(domain->lock);
0057 for (i = 0, p -= n; i < n; i++, p++, index++) {
0058 struct probe **s = &domain->probes[index % 255];
0059 while (*s && (*s)->range < range)
0060 s = &(*s)->next;
0061 p->next = *s;
0062 *s = p;
0063 }
0064 mutex_unlock(domain->lock);
0065 return 0;
0066 }
0067
0068 void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
0069 {
0070 unsigned int n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
0071 unsigned int index = MAJOR(dev);
0072 unsigned int i;
0073 struct probe *found = NULL;
0074
0075 if (n > 255)
0076 n = 255;
0077
0078 mutex_lock(domain->lock);
0079 for (i = 0; i < n; i++, index++) {
0080 struct probe **s;
0081 for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
0082 struct probe *p = *s;
0083 if (p->dev == dev && p->range == range) {
0084 *s = p->next;
0085 if (!found)
0086 found = p;
0087 break;
0088 }
0089 }
0090 }
0091 mutex_unlock(domain->lock);
0092 kfree(found);
0093 }
0094
0095 struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
0096 {
0097 struct kobject *kobj;
0098 struct probe *p;
0099 unsigned long best = ~0UL;
0100
0101 retry:
0102 mutex_lock(domain->lock);
0103 for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
0104 struct kobject *(*probe)(dev_t, int *, void *);
0105 struct module *owner;
0106 void *data;
0107
0108 if (p->dev > dev || p->dev + p->range - 1 < dev)
0109 continue;
0110 if (p->range - 1 >= best)
0111 break;
0112 if (!try_module_get(p->owner))
0113 continue;
0114 owner = p->owner;
0115 data = p->data;
0116 probe = p->get;
0117 best = p->range - 1;
0118 *index = dev - p->dev;
0119 if (p->lock && p->lock(dev, data) < 0) {
0120 module_put(owner);
0121 continue;
0122 }
0123 mutex_unlock(domain->lock);
0124 kobj = probe(dev, index, data);
0125
0126 module_put(owner);
0127 if (kobj)
0128 return kobj;
0129 goto retry;
0130 }
0131 mutex_unlock(domain->lock);
0132 return NULL;
0133 }
0134
0135 struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock)
0136 {
0137 struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
0138 struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
0139 int i;
0140
0141 if ((p == NULL) || (base == NULL)) {
0142 kfree(p);
0143 kfree(base);
0144 return NULL;
0145 }
0146
0147 base->dev = 1;
0148 base->range = ~0;
0149 base->get = base_probe;
0150 for (i = 0; i < 255; i++)
0151 p->probes[i] = base;
0152 p->lock = lock;
0153 return p;
0154 }