map.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 157 行

C
157
字号
/* *  linux/drivers/base/map.c * * (C) Copyright Al Viro 2002,2003 *	Released under GPL v2. * * 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>#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];	struct rw_semaphore *sem;};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;	p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);	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;	}	down_write(domain->sem);	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;	}	up_write(domain->sem);	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;	down_write(domain->sem);	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;			}		}	}	up_write(domain->sem);	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:	down_read(domain->sem);	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;		}		up_read(domain->sem);		kobj = probe(dev, index, data);		/* Currently ->owner protects _only_ ->probe() itself. */		module_put(owner);		if (kobj)			return kobj;		goto retry;	}	up_read(domain->sem);	return NULL;}struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,		struct subsystem *s){	struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);	struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);	int i;	if ((p == NULL) || (base == NULL)) {		kfree(p);		kfree(base);		return NULL;	}	memset(base, 0, sizeof(struct probe));	base->dev = 1;	base->range = ~0;	base->get = base_probe;	for (i = 0; i < 255; i++)		p->probes[i] = base;	p->sem = &s->rwsem;	return p;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?