int ibmphp_add_resource()

in hotplug/ibmphp_res.c [575:748]


int ibmphp_add_resource(struct resource_node *res)
{
	struct resource_node *res_cur;
	struct resource_node *res_prev;
	struct bus_node *bus_cur;
	struct range_node *range_cur = NULL;
	struct resource_node *res_start = NULL;

	debug("%s - enter\n", __func__);

	if (!res) {
		err("NULL passed to add\n");
		return -ENODEV;
	}

	bus_cur = find_bus_wprev(res->busno, NULL, 0);

	if (!bus_cur) {
		/* didn't find a bus, something's wrong!!! */
		debug("no bus in the system, either pci_dev's wrong or allocation failed\n");
		return -ENODEV;
	}

	/* Normal case */
	switch (res->type) {
		case IO:
			range_cur = bus_cur->rangeIO;
			res_start = bus_cur->firstIO;
			break;
		case MEM:
			range_cur = bus_cur->rangeMem;
			res_start = bus_cur->firstMem;
			break;
		case PFMEM:
			range_cur = bus_cur->rangePFMem;
			res_start = bus_cur->firstPFMem;
			break;
		default:
			err("cannot read the type of the resource to add... problem\n");
			return -EINVAL;
	}
	while (range_cur) {
		if ((res->start >= range_cur->start) && (res->end <= range_cur->end)) {
			res->rangeno = range_cur->rangeno;
			break;
		}
		range_cur = range_cur->next;
	}

	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	 * this is again the case of rangeno = -1
	 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	 */

	if (!range_cur) {
		switch (res->type) {
			case IO:
				++bus_cur->needIOUpdate;
				break;
			case MEM:
				++bus_cur->needMemUpdate;
				break;
			case PFMEM:
				++bus_cur->needPFMemUpdate;
				break;
		}
		res->rangeno = -1;
	}

	debug("The range is %d\n", res->rangeno);
	if (!res_start) {
		/* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */
		switch (res->type) {
			case IO:
				bus_cur->firstIO = res;
				break;
			case MEM:
				bus_cur->firstMem = res;
				break;
			case PFMEM:
				bus_cur->firstPFMem = res;
				break;
		}
		res->next = NULL;
		res->nextRange = NULL;
	} else {
		res_cur = res_start;
		res_prev = NULL;

		debug("res_cur->rangeno is %d\n", res_cur->rangeno);

		while (res_cur) {
			if (res_cur->rangeno >= res->rangeno)
				break;
			res_prev = res_cur;
			if (res_cur->next)
				res_cur = res_cur->next;
			else
				res_cur = res_cur->nextRange;
		}

		if (!res_cur) {
			/* at the end of the resource list */
			debug("i should be here, [%x - %x]\n", res->start, res->end);
			res_prev->nextRange = res;
			res->next = NULL;
			res->nextRange = NULL;
		} else if (res_cur->rangeno == res->rangeno) {
			/* in the same range */
			while (res_cur) {
				if (res->start < res_cur->start)
					break;
				res_prev = res_cur;
				res_cur = res_cur->next;
			}
			if (!res_cur) {
				/* the last resource in this range */
				res_prev->next = res;
				res->next = NULL;
				res->nextRange = res_prev->nextRange;
				res_prev->nextRange = NULL;
			} else if (res->start < res_cur->start) {
				/* at the beginning or middle of the range */
				if (!res_prev)	{
					switch (res->type) {
						case IO:
							bus_cur->firstIO = res;
							break;
						case MEM:
							bus_cur->firstMem = res;
							break;
						case PFMEM:
							bus_cur->firstPFMem = res;
							break;
					}
				} else if (res_prev->rangeno == res_cur->rangeno)
					res_prev->next = res;
				else
					res_prev->nextRange = res;

				res->next = res_cur;
				res->nextRange = NULL;
			}
		} else {
			/* this is the case where it is 1st occurrence of the range */
			if (!res_prev) {
				/* at the beginning of the resource list */
				res->next = NULL;
				switch (res->type) {
					case IO:
						res->nextRange = bus_cur->firstIO;
						bus_cur->firstIO = res;
						break;
					case MEM:
						res->nextRange = bus_cur->firstMem;
						bus_cur->firstMem = res;
						break;
					case PFMEM:
						res->nextRange = bus_cur->firstPFMem;
						bus_cur->firstPFMem = res;
						break;
				}
			} else if (res_cur->rangeno > res->rangeno) {
				/* in the middle of the resource list */
				res_prev->nextRange = res;
				res->next = NULL;
				res->nextRange = res_cur;
			}
		}
	}

	debug("%s - exit\n", __func__);
	return 0;
}