in hotplug/ibmphp_res.c [757:915]
int ibmphp_remove_resource(struct resource_node *res)
{
struct bus_node *bus_cur;
struct resource_node *res_cur = NULL;
struct resource_node *res_prev;
struct resource_node *mem_cur;
char *type = "";
if (!res) {
err("resource to remove is NULL\n");
return -ENODEV;
}
bus_cur = find_bus_wprev(res->busno, NULL, 0);
if (!bus_cur) {
err("cannot find corresponding bus of the io resource to remove bailing out...\n");
return -ENODEV;
}
switch (res->type) {
case IO:
res_cur = bus_cur->firstIO;
type = "io";
break;
case MEM:
res_cur = bus_cur->firstMem;
type = "mem";
break;
case PFMEM:
res_cur = bus_cur->firstPFMem;
type = "pfmem";
break;
default:
err("unknown type for resource to remove\n");
return -EINVAL;
}
res_prev = NULL;
while (res_cur) {
if ((res_cur->start == res->start) && (res_cur->end == res->end))
break;
res_prev = res_cur;
if (res_cur->next)
res_cur = res_cur->next;
else
res_cur = res_cur->nextRange;
}
if (!res_cur) {
if (res->type == PFMEM) {
/*
* case where pfmem might be in the PFMemFromMem list
* so will also need to remove the corresponding mem
* entry
*/
res_cur = bus_cur->firstPFMemFromMem;
res_prev = NULL;
while (res_cur) {
if ((res_cur->start == res->start) && (res_cur->end == res->end)) {
mem_cur = bus_cur->firstMem;
while (mem_cur) {
if ((mem_cur->start == res_cur->start)
&& (mem_cur->end == res_cur->end))
break;
if (mem_cur->next)
mem_cur = mem_cur->next;
else
mem_cur = mem_cur->nextRange;
}
if (!mem_cur) {
err("cannot find corresponding mem node for pfmem...\n");
return -EINVAL;
}
ibmphp_remove_resource(mem_cur);
if (!res_prev)
bus_cur->firstPFMemFromMem = res_cur->next;
else
res_prev->next = res_cur->next;
kfree(res_cur);
return 0;
}
res_prev = res_cur;
if (res_cur->next)
res_cur = res_cur->next;
else
res_cur = res_cur->nextRange;
}
if (!res_cur) {
err("cannot find pfmem to delete...\n");
return -EINVAL;
}
} else {
err("the %s resource is not in the list to be deleted...\n", type);
return -EINVAL;
}
}
if (!res_prev) {
/* first device to be deleted */
if (res_cur->next) {
switch (res->type) {
case IO:
bus_cur->firstIO = res_cur->next;
break;
case MEM:
bus_cur->firstMem = res_cur->next;
break;
case PFMEM:
bus_cur->firstPFMem = res_cur->next;
break;
}
} else if (res_cur->nextRange) {
switch (res->type) {
case IO:
bus_cur->firstIO = res_cur->nextRange;
break;
case MEM:
bus_cur->firstMem = res_cur->nextRange;
break;
case PFMEM:
bus_cur->firstPFMem = res_cur->nextRange;
break;
}
} else {
switch (res->type) {
case IO:
bus_cur->firstIO = NULL;
break;
case MEM:
bus_cur->firstMem = NULL;
break;
case PFMEM:
bus_cur->firstPFMem = NULL;
break;
}
}
kfree(res_cur);
return 0;
} else {
if (res_cur->next) {
if (res_prev->rangeno == res_cur->rangeno)
res_prev->next = res_cur->next;
else
res_prev->nextRange = res_cur->next;
} else if (res_cur->nextRange) {
res_prev->next = NULL;
res_prev->nextRange = res_cur->nextRange;
} else {
res_prev->next = NULL;
res_prev->nextRange = NULL;
}
kfree(res_cur);
return 0;
}
return 0;
}