⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resource.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * insert_resource - Inserts a resource in the resource tree * @parent: parent of the new resource * @new: new resource to insert * * Returns 0 on success, -EBUSY if the resource can't be inserted. * * This function is equivalent to request_resource when no conflict * happens. If a conflict happens, and the conflicting resources * entirely fit within the range of the new resource, then the new * resource is inserted and the conflicting resources become children of * the new resource. */int insert_resource(struct resource *parent, struct resource *new){	int result;	struct resource *first, *next;	write_lock(&resource_lock);	for (;; parent = first) {	 	result = 0;		first = __request_resource(parent, new);		if (!first)			goto out;		result = -EBUSY;		if (first == parent)			goto out;		if ((first->start > new->start) || (first->end < new->end))			break;		if ((first->start == new->start) && (first->end == new->end))			break;	}	for (next = first; ; next = next->sibling) {		/* Partial overlap? Bad, and unfixable */		if (next->start < new->start || next->end > new->end)			goto out;		if (!next->sibling)			break;		if (next->sibling->start > new->end)			break;	}	result = 0;	new->parent = parent;	new->sibling = next->sibling;	new->child = first;	next->sibling = NULL;	for (next = first; next; next = next->sibling)		next->parent = new;	if (parent->child == first) {		parent->child = new;	} else {		next = parent->child;		while (next->sibling != first)			next = next->sibling;		next->sibling = new;	} out:	write_unlock(&resource_lock);	return result;}/** * adjust_resource - modify a resource's start and size * @res: resource to modify * @start: new start value * @size: new size * * Given an existing resource, change its start and size to match the * arguments.  Returns 0 on success, -EBUSY if it can't fit. * Existing children of the resource are assumed to be immutable. */int adjust_resource(struct resource *res, resource_size_t start, resource_size_t size){	struct resource *tmp, *parent = res->parent;	resource_size_t end = start + size - 1;	int result = -EBUSY;	write_lock(&resource_lock);	if ((start < parent->start) || (end > parent->end))		goto out;	for (tmp = res->child; tmp; tmp = tmp->sibling) {		if ((tmp->start < start) || (tmp->end > end))			goto out;	}	if (res->sibling && (res->sibling->start <= end))		goto out;	tmp = parent->child;	if (tmp != res) {		while (tmp->sibling != res)			tmp = tmp->sibling;		if (start <= tmp->end)			goto out;	}	res->start = start;	res->end = end;	result = 0; out:	write_unlock(&resource_lock);	return result;}EXPORT_SYMBOL(adjust_resource);/* * This is compatibility stuff for IO resources. * * Note how this, unlike the above, knows about * the IO flag meanings (busy etc). * * request_region creates a new busy region. * * check_region returns non-zero if the area is already busy. * * release_region releases a matching busy region. *//** * __request_region - create a new busy resource region * @parent: parent resource descriptor * @start: resource start address * @n: resource region size * @name: reserving caller's ID string */struct resource * __request_region(struct resource *parent,				   resource_size_t start, resource_size_t n,				   const char *name){	struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);	if (res) {		res->name = name;		res->start = start;		res->end = start + n - 1;		res->flags = IORESOURCE_BUSY;		write_lock(&resource_lock);		for (;;) {			struct resource *conflict;			conflict = __request_resource(parent, res);			if (!conflict)				break;			if (conflict != parent) {				parent = conflict;				if (!(conflict->flags & IORESOURCE_BUSY))					continue;			}			/* Uhhuh, that didn't work out.. */			kfree(res);			res = NULL;			break;		}		write_unlock(&resource_lock);	}	return res;}EXPORT_SYMBOL(__request_region);/** * __check_region - check if a resource region is busy or free * @parent: parent resource descriptor * @start: resource start address * @n: resource region size * * Returns 0 if the region is free at the moment it is checked, * returns %-EBUSY if the region is busy. * * NOTE: * This function is deprecated because its use is racy. * Even if it returns 0, a subsequent call to request_region() * may fail because another driver etc. just allocated the region. * Do NOT use it.  It will be removed from the kernel. */int __check_region(struct resource *parent, resource_size_t start,			resource_size_t n){	struct resource * res;	res = __request_region(parent, start, n, "check-region");	if (!res)		return -EBUSY;	release_resource(res);	kfree(res);	return 0;}EXPORT_SYMBOL(__check_region);/** * __release_region - release a previously reserved resource region * @parent: parent resource descriptor * @start: resource start address * @n: resource region size * * The described resource region must match a currently busy region. */void __release_region(struct resource *parent, resource_size_t start,			resource_size_t n){	struct resource **p;	resource_size_t end;	p = &parent->child;	end = start + n - 1;	write_lock(&resource_lock);	for (;;) {		struct resource *res = *p;		if (!res)			break;		if (res->start <= start && res->end >= end) {			if (!(res->flags & IORESOURCE_BUSY)) {				p = &res->child;				continue;			}			if (res->start != start || res->end != end)				break;			*p = res->sibling;			write_unlock(&resource_lock);			kfree(res);			return;		}		p = &res->sibling;	}	write_unlock(&resource_lock);	printk(KERN_WARNING "Trying to free nonexistent resource "		"<%016llx-%016llx>\n", (unsigned long long)start,		(unsigned long long)end);}EXPORT_SYMBOL(__release_region);/* * Managed region resource */struct region_devres {	struct resource *parent;	resource_size_t start;	resource_size_t n;};static void devm_region_release(struct device *dev, void *res){	struct region_devres *this = res;	__release_region(this->parent, this->start, this->n);}static int devm_region_match(struct device *dev, void *res, void *match_data){	struct region_devres *this = res, *match = match_data;	return this->parent == match->parent &&		this->start == match->start && this->n == match->n;}struct resource * __devm_request_region(struct device *dev,				struct resource *parent, resource_size_t start,				resource_size_t n, const char *name){	struct region_devres *dr = NULL;	struct resource *res;	dr = devres_alloc(devm_region_release, sizeof(struct region_devres),			  GFP_KERNEL);	if (!dr)		return NULL;	dr->parent = parent;	dr->start = start;	dr->n = n;	res = __request_region(parent, start, n, name);	if (res)		devres_add(dev, dr);	else		devres_free(dr);	return res;}EXPORT_SYMBOL(__devm_request_region);void __devm_release_region(struct device *dev, struct resource *parent,			   resource_size_t start, resource_size_t n){	struct region_devres match_data = { parent, start, n };	__release_region(parent, start, n);	WARN_ON(devres_destroy(dev, devm_region_release, devm_region_match,			       &match_data));}EXPORT_SYMBOL(__devm_release_region);/* * Called from init/main.c to reserve IO ports. */#define MAXRESERVE 4static int __init reserve_setup(char *str){	static int reserved;	static struct resource reserve[MAXRESERVE];	for (;;) {		int io_start, io_num;		int x = reserved;		if (get_option (&str, &io_start) != 2)			break;		if (get_option (&str, &io_num)   == 0)			break;		if (x < MAXRESERVE) {			struct resource *res = reserve + x;			res->name = "reserved";			res->start = io_start;			res->end = io_start + io_num - 1;			res->flags = IORESOURCE_BUSY;			res->child = NULL;			if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)				reserved = x+1;		}	}	return 1;}__setup("reserve=", reserve_setup);

⌨️ 快捷键说明

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