// SPDX-License-Identifier: GPL-2.0+/* * IBM Hot Plug Controller Driver * * Written By: Irene Zubarev, IBM Corporation * * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2001,2002 IBM Corp. * * All rights reserved. * * Send feedback to <gregkh@us.ibm.com> * */ #include <linux/module.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/list.h>#include <linux/init.h>#include "ibmphp.h" static int flags = 0; /* for testing */ static void update_resources(struct bus_node *bus_cur, int type, int rangeno);static int once_over(void);static int remove_ranges(struct bus_node *, struct bus_node *);static int update_bridge_ranges(struct bus_node **);static int add_bus_range(int type, struct range_node *, struct bus_node *);static void fix_resources(struct bus_node *);static struct bus_node *find_bus_wprev(u8, struct bus_node **, u8); static LIST_HEAD(gbuses); static struct bus_node * __init alloc_error_bus(struct ebda_pci_rsrc *curr, u8 busno, int flag){ struct bus_node *newbus; if (!(curr) && !(flag)) { err("NULL pointer passed\n"); return NULL; } newbus = kzalloc_obj(struct bus_node); if (!newbus) return NULL; if (flag) newbus->busno = busno; else newbus->busno = curr->bus_num; list_add_tail(&newbus->bus_list, &gbuses); return newbus;} static struct resource_node * __init alloc_resources(struct ebda_pci_rsrc *curr){ struct resource_node *rs; if (!curr) { err("NULL passed to allocate\n"); return NULL; } rs = kzalloc_obj(struct resource_node); if (!rs) return NULL; rs->busno = curr->bus_num; rs->devfunc = curr->dev_fun; rs->start = curr->start_addr; rs->end = curr->end_addr; rs->len = curr->end_addr - curr->start_addr + 1; return rs;} static int __init alloc_bus_range(struct bus_node **new_bus, struct range_node **new_range, struct ebda_pci_rsrc *curr, int flag, u8 first_bus){ struct bus_node *newbus; struct range_node *newrange; u8 num_ranges = 0; if (first_bus) { newbus = kzalloc_obj(struct bus_node); if (!newbus) return -ENOMEM; newbus->busno = curr->bus_num; } else { newbus = *new_bus; switch (flag) { case MEM: num_ranges = newbus->noMemRanges; break; case PFMEM: num_ranges = newbus->noPFMemRanges; break; case IO: num_ranges = newbus->noIORanges; break; } } newrange = kzalloc_obj(struct range_node); if (!newrange) { if (first_bus) kfree(newbus); return -ENOMEM; } newrange->start = curr->start_addr; newrange->end = curr->end_addr; if (first_bus || (!num_ranges)) newrange->rangeno = 1; else { /* need to insert our range */ add_bus_range(flag, newrange, newbus); debug("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end); } switch (flag) { case MEM: newbus->rangeMem = newrange; if (first_bus) newbus->noMemRanges = 1; else { debug("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end); ++newbus->noMemRanges; fix_resources(newbus); } break; case IO: newbus->rangeIO = newrange; if (first_bus) newbus->noIORanges = 1; else { debug("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end); ++newbus->noIORanges; fix_resources(newbus); } break; case PFMEM: newbus->rangePFMem = newrange; if (first_bus) newbus->noPFMemRanges = 1; else { debug("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); ++newbus->noPFMemRanges; fix_resources(newbus); } break; } *new_bus = newbus; *new_range = newrange; return 0;} /* Notes: * 1. The ranges are ordered. The buses are not ordered. (First come) * * 2. If cannot allocate out of PFMem range, allocate from Mem ranges. PFmemFromMem * are not sorted. (no need since use mem node). To not change the entire code, we * also add mem node whenever this case happens so as not to change * ibmphp_check_mem_resource etc(and since it really is taking Mem resource) */ /***************************************************************************** * This is the Resource Management initialization function. It will go through * the Resource list taken from EBDA and fill in this module's data structures * * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES, * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW * * Input: ptr to the head of the resource list from EBDA * Output: 0, -1 or error codes ***************************************************************************/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) */} /******************************************************************************** * This function adds a range into a sorted list of ranges per bus for a particular * range type, it then calls another routine to update the range numbers on the * pci devices' resources for the appropriate resource * * Input: type of the resource, range to add, current bus * Output: 0 or -1, bus and range ptrs ********************************************************************************/static int add_bus_range(int type, struct range_node *range, struct bus_node *bus_cur){ struct range_node *range_cur = NULL; struct range_node *range_prev; int count = 0, i_init; int noRanges = 0; switch (type) { case MEM: range_cur = bus_cur->rangeMem; noRanges = bus_cur->noMemRanges; break; case PFMEM: range_cur = bus_cur->rangePFMem; noRanges = bus_cur->noPFMemRanges; break; case IO: range_cur = bus_cur->rangeIO; noRanges = bus_cur->noIORanges; break; } range_prev = NULL; while (range_cur) { if (range->start < range_cur->start) break; range_prev = range_cur; range_cur = range_cur->next; count = count + 1; } if (!count) { /* our range will go at the beginning of the list */ switch (type) { case MEM: bus_cur->rangeMem = range; break; case PFMEM: bus_cur->rangePFMem = range; break; case IO: bus_cur->rangeIO = range; break; } range->next = range_cur; range->rangeno = 1; i_init = 0; } else if (!range_cur) { /* our range will go at the end of the list */ range->next = NULL; range_prev->next = range; range->rangeno = range_prev->rangeno + 1; return 0; } else { /* the range is in the middle */ range_prev->next = range; range->next = range_cur; range->rangeno = range_cur->rangeno; i_init = range_prev->rangeno; } for (count = i_init; count < noRanges; ++count) { ++range_cur->rangeno; range_cur = range_cur->next; } update_resources(bus_cur, type, i_init + 1); return 0;} /******************************************************************************* * This routine goes through the list of resources of type 'type' and updates * the range numbers that they correspond to. It was called from add_bus_range fnc * * Input: bus, type of the resource, the rangeno starting from which to update ******************************************************************************/static void update_resources(struct bus_node *bus_cur, int type, int rangeno){ struct resource_node *res = NULL; u8 eol = 0; /* end of list indicator */ switch (type) { case MEM: if (bus_cur->firstMem) res = bus_cur->firstMem; break; case PFMEM: if (bus_cur->firstPFMem) res = bus_cur->firstPFMem; break; case IO: if (bus_cur->firstIO) res = bus_cur->firstIO; break; } if (res) { while (res) { if (res->rangeno == rangeno) break; if (res->next) res = res->next; else if (res->nextRange) res = res->nextRange; else { eol = 1; break; } } if (!eol) { /* found the range */ while (res) { ++res->rangeno; res = res->next; } } }} static void fix_me(struct resource_node *res, struct bus_node *bus_cur, struct range_node *range){ char *str = ""; switch (res->type) { case IO: str = "io"; break; case MEM: str = "mem"; break; case PFMEM: str = "pfmem"; break; }Lines 1–500 of 2118. Load more
// SPDX-License-Identifier: GPL-2.0+ /* * IBM Hot Plug Controller Driver * * Written By: Irene Zubarev, IBM Corporation * * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2001,2002 IBM Corp. * * All rights reserved. * * Send feedback to <gregkh@us.ibm.com> * */ #include <linux/module.h> #include <linux/slab.h> #include <linux/pci.h> #include <linux/list.h> #include <linux/init.h> #include "ibmphp.h" static int flags = 0; /* for testing */ static void update_resources(struct bus_node *bus_cur, int type, int rangeno); static int once_over(void); static int remove_ranges(struct bus_node *, struct bus_node *); static int update_bridge_ranges(struct bus_node **); static int add_bus_range(int type, struct range_node *, struct bus_node *); static void fix_resources(struct bus_node *); static struct bus_node *find_bus_wprev(u8, struct bus_node **, u8); static LIST_HEAD(gbuses); static struct bus_node * __init alloc_error_bus(struct ebda_pci_rsrc *curr, u8 busno, int flag) { struct bus_node *newbus; if (!(curr) && !(flag)) { err("NULL pointer passed\n"); return NULL; } newbus = kzalloc_obj(struct bus_node); if (!newbus) return NULL; if (flag) newbus->busno = busno; else newbus->busno = curr->bus_num; list_add_tail(&newbus->bus_list, &gbuses); return newbus; } static struct resource_node * __init alloc_resources(struct ebda_pci_rsrc *curr) { struct resource_node *rs; if (!curr) { err("NULL passed to allocate\n"); return NULL; } rs = kzalloc_obj(struct resource_node); if (!rs) return NULL; rs->busno = curr->bus_num; rs->devfunc = curr->dev_fun; rs->start = curr->start_addr; rs->end = curr->end_addr; rs->len = curr->end_addr - curr->start_addr + 1; return rs; } static int __init alloc_bus_range(struct bus_node **new_bus, struct range_node **new_range, struct ebda_pci_rsrc *curr, int flag, u8 first_bus) { struct bus_node *newbus; struct range_node *newrange; u8 num_ranges = 0; if (first_bus) { newbus = kzalloc_obj(struct bus_node); if (!newbus) return -ENOMEM; newbus->busno = curr->bus_num; } else { newbus = *new_bus; switch (flag) { case MEM: num_ranges = newbus->noMemRanges; break; case PFMEM: num_ranges = newbus->noPFMemRanges; break; case IO: num_ranges = newbus->noIORanges; break; } } newrange = kzalloc_obj(struct range_node); if (!newrange) { if (first_bus) kfree(newbus); return -ENOMEM; } newrange->start = curr->start_addr; newrange->end = curr->end_addr; if (first_bus || (!num_ranges)) newrange->rangeno = 1; else { /* need to insert our range */ add_bus_range(flag, newrange, newbus); debug("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end); } switch (flag) { case MEM: newbus->rangeMem = newrange; if (first_bus) newbus->noMemRanges = 1; else { debug("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end); ++newbus->noMemRanges; fix_resources(newbus); } break; case IO: newbus->rangeIO = newrange; if (first_bus) newbus->noIORanges = 1; else { debug("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end); ++newbus->noIORanges; fix_resources(newbus); } break; case PFMEM: newbus->rangePFMem = newrange; if (first_bus) newbus->noPFMemRanges = 1; else { debug("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); ++newbus->noPFMemRanges; fix_resources(newbus); } break; } *new_bus = newbus; *new_range = newrange; return 0; } /* Notes: * 1. The ranges are ordered. The buses are not ordered. (First come) * * 2. If cannot allocate out of PFMem range, allocate from Mem ranges. PFmemFromMem * are not sorted. (no need since use mem node). To not change the entire code, we * also add mem node whenever this case happens so as not to change * ibmphp_check_mem_resource etc(and since it really is taking Mem resource) */ /***************************************************************************** * This is the Resource Management initialization function. It will go through * the Resource list taken from EBDA and fill in this module's data structures * * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES, * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW * * Input: ptr to the head of the resource list from EBDA * Output: 0, -1 or error codes ***************************************************************************/ 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) */ } /******************************************************************************** * This function adds a range into a sorted list of ranges per bus for a particular * range type, it then calls another routine to update the range numbers on the * pci devices' resources for the appropriate resource * * Input: type of the resource, range to add, current bus * Output: 0 or -1, bus and range ptrs ********************************************************************************/ static int add_bus_range(int type, struct range_node *range, struct bus_node *bus_cur) { struct range_node *range_cur = NULL; struct range_node *range_prev; int count = 0, i_init; int noRanges = 0; switch (type) { case MEM: range_cur = bus_cur->rangeMem; noRanges = bus_cur->noMemRanges; break; case PFMEM: range_cur = bus_cur->rangePFMem; noRanges = bus_cur->noPFMemRanges; break; case IO: range_cur = bus_cur->rangeIO; noRanges = bus_cur->noIORanges; break; } range_prev = NULL; while (range_cur) { if (range->start < range_cur->start) break; range_prev = range_cur; range_cur = range_cur->next; count = count + 1; } if (!count) { /* our range will go at the beginning of the list */ switch (type) { case MEM: bus_cur->rangeMem = range; break; case PFMEM: bus_cur->rangePFMem = range; break; case IO: bus_cur->rangeIO = range; break; } range->next = range_cur; range->rangeno = 1; i_init = 0; } else if (!range_cur) { /* our range will go at the end of the list */ range->next = NULL; range_prev->next = range; range->rangeno = range_prev->rangeno + 1; return 0; } else { /* the range is in the middle */ range_prev->next = range; range->next = range_cur; range->rangeno = range_cur->rangeno; i_init = range_prev->rangeno; } for (count = i_init; count < noRanges; ++count) { ++range_cur->rangeno; range_cur = range_cur->next; } update_resources(bus_cur, type, i_init + 1); return 0; } /******************************************************************************* * This routine goes through the list of resources of type 'type' and updates * the range numbers that they correspond to. It was called from add_bus_range fnc * * Input: bus, type of the resource, the rangeno starting from which to update ******************************************************************************/ static void update_resources(struct bus_node *bus_cur, int type, int rangeno) { struct resource_node *res = NULL; u8 eol = 0; /* end of list indicator */ switch (type) { case MEM: if (bus_cur->firstMem) res = bus_cur->firstMem; break; case PFMEM: if (bus_cur->firstPFMem) res = bus_cur->firstPFMem; break; case IO: if (bus_cur->firstIO) res = bus_cur->firstIO; break; } if (res) { while (res) { if (res->rangeno == rangeno) break; if (res->next) res = res->next; else if (res->nextRange) res = res->nextRange; else { eol = 1; break; } } if (!eol) { /* found the range */ while (res) { ++res->rangeno; res = res->next; } } } } static void fix_me(struct resource_node *res, struct bus_node *bus_cur, struct range_node *range) { char *str = ""; switch (res->type) { case IO: str = "io"; break; case MEM: str = "mem"; break; case PFMEM: str = "pfmem"; break; }