int __init ibmphp_rsrc_init()

in hotplug/ibmphp_res.c [180:358]


int __init ibmphp_rsrc_init(void)
{
	struct ebda_pci_rsrc *curr;
	struct range_node *newrange = NULL;
	struct bus_node *newbus = NULL;
	struct bus_node *bus_cur;
	struct bus_node *bus_prev;
	struct resource_node *new_io = NULL;
	struct resource_node *new_mem = NULL;
	struct resource_node *new_pfmem = NULL;
	int rc;

	list_for_each_entry(curr, &ibmphp_ebda_pci_rsrc_head,
			    ebda_pci_rsrc_list) {
		if (!(curr->rsrc_type & PCIDEVMASK)) {
			/* EBDA still lists non PCI devices, so ignore... */
			debug("this is not a PCI DEVICE in rsrc_init, please take care\n");
			// continue;
		}

		/* this is a primary bus resource */
		if (curr->rsrc_type & PRIMARYBUSMASK) {
			/* memory */
			if ((curr->rsrc_type & RESTYPE) == MMASK) {
				/* no bus structure exists in place yet */
				if (list_empty(&gbuses)) {
					rc = alloc_bus_range(&newbus, &newrange, curr, MEM, 1);
					if (rc)
						return rc;
					list_add_tail(&newbus->bus_list, &gbuses);
					debug("gbuses = NULL, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
				} else {
					bus_cur = find_bus_wprev(curr->bus_num, &bus_prev, 1);
					/* found our bus */
					if (bus_cur) {
						rc = alloc_bus_range(&bus_cur, &newrange, curr, MEM, 0);
						if (rc)
							return rc;
					} else {
						/* went through all the buses and didn't find ours, need to create a new bus node */
						rc = alloc_bus_range(&newbus, &newrange, curr, MEM, 1);
						if (rc)
							return rc;

						list_add_tail(&newbus->bus_list, &gbuses);
						debug("New Bus, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
					}
				}
			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
				/* prefetchable memory */
				if (list_empty(&gbuses)) {
					/* no bus structure exists in place yet */
					rc = alloc_bus_range(&newbus, &newrange, curr, PFMEM, 1);
					if (rc)
						return rc;
					list_add_tail(&newbus->bus_list, &gbuses);
					debug("gbuses = NULL, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
				} else {
					bus_cur = find_bus_wprev(curr->bus_num, &bus_prev, 1);
					if (bus_cur) {
						/* found our bus */
						rc = alloc_bus_range(&bus_cur, &newrange, curr, PFMEM, 0);
						if (rc)
							return rc;
					} else {
						/* went through all the buses and didn't find ours, need to create a new bus node */
						rc = alloc_bus_range(&newbus, &newrange, curr, PFMEM, 1);
						if (rc)
							return rc;
						list_add_tail(&newbus->bus_list, &gbuses);
						debug("1st Bus, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
					}
				}
			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
				/* IO */
				if (list_empty(&gbuses)) {
					/* no bus structure exists in place yet */
					rc = alloc_bus_range(&newbus, &newrange, curr, IO, 1);
					if (rc)
						return rc;
					list_add_tail(&newbus->bus_list, &gbuses);
					debug("gbuses = NULL, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
				} else {
					bus_cur = find_bus_wprev(curr->bus_num, &bus_prev, 1);
					if (bus_cur) {
						rc = alloc_bus_range(&bus_cur, &newrange, curr, IO, 0);
						if (rc)
							return rc;
					} else {
						/* went through all the buses and didn't find ours, need to create a new bus node */
						rc = alloc_bus_range(&newbus, &newrange, curr, IO, 1);
						if (rc)
							return rc;
						list_add_tail(&newbus->bus_list, &gbuses);
						debug("1st Bus, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
					}
				}

			} else {
				;	/* type is reserved  WHAT TO DO IN THIS CASE???
					   NOTHING TO DO??? */
			}
		} else {
			/* regular pci device resource */
			if ((curr->rsrc_type & RESTYPE) == MMASK) {
				/* Memory resource */
				new_mem = alloc_resources(curr);
				if (!new_mem)
					return -ENOMEM;
				new_mem->type = MEM;
				/*
				 * if it didn't find the bus, means PCI dev
				 * came b4 the Primary Bus info, so need to
				 * create a bus rangeno becomes a problem...
				 * assign a -1 and then update once the range
				 * actually appears...
				 */
				if (ibmphp_add_resource(new_mem) < 0) {
					newbus = alloc_error_bus(curr, 0, 0);
					if (!newbus)
						return -ENOMEM;
					newbus->firstMem = new_mem;
					++newbus->needMemUpdate;
					new_mem->rangeno = -1;
				}
				debug("Memory resource for device %x, bus %x, [%x - %x]\n", new_mem->devfunc, new_mem->busno, new_mem->start, new_mem->end);

			} else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
				/* PFMemory resource */
				new_pfmem = alloc_resources(curr);
				if (!new_pfmem)
					return -ENOMEM;
				new_pfmem->type = PFMEM;
				new_pfmem->fromMem = 0;
				if (ibmphp_add_resource(new_pfmem) < 0) {
					newbus = alloc_error_bus(curr, 0, 0);
					if (!newbus)
						return -ENOMEM;
					newbus->firstPFMem = new_pfmem;
					++newbus->needPFMemUpdate;
					new_pfmem->rangeno = -1;
				}

				debug("PFMemory resource for device %x, bus %x, [%x - %x]\n", new_pfmem->devfunc, new_pfmem->busno, new_pfmem->start, new_pfmem->end);
			} else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
				/* IO resource */
				new_io = alloc_resources(curr);
				if (!new_io)
					return -ENOMEM;
				new_io->type = IO;

				/*
				 * if it didn't find the bus, means PCI dev
				 * came b4 the Primary Bus info, so need to
				 * create a bus rangeno becomes a problem...
				 * Can assign a -1 and then update once the
				 * range actually appears...
				 */
				if (ibmphp_add_resource(new_io) < 0) {
					newbus = alloc_error_bus(curr, 0, 0);
					if (!newbus)
						return -ENOMEM;
					newbus->firstIO = new_io;
					++newbus->needIOUpdate;
					new_io->rangeno = -1;
				}
				debug("IO resource for device %x, bus %x, [%x - %x]\n", new_io->devfunc, new_io->busno, new_io->start, new_io->end);
			}
		}
	}

	list_for_each_entry(bus_cur, &gbuses, bus_list) {
		/* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */
		rc = update_bridge_ranges(&bus_cur);
		if (rc)
			return rc;
	}
	return once_over();	/* This is to align ranges (so no -1) */
}