^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * IBM Hot Plug Controller Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written By: Irene Zubarev, IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2001,2002 IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Send feedback to <gregkh@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "ibmphp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int flags = 0; /* for testing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static void update_resources(struct bus_node *bus_cur, int type, int rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int once_over(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int remove_ranges(struct bus_node *, struct bus_node *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int update_bridge_ranges(struct bus_node **);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int add_bus_range(int type, struct range_node *, struct bus_node *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static void fix_resources(struct bus_node *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static struct bus_node *find_bus_wprev(u8, struct bus_node **, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static LIST_HEAD(gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static struct bus_node * __init alloc_error_bus(struct ebda_pci_rsrc *curr, u8 busno, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct bus_node *newbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!(curr) && !(flag)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) err("NULL pointer passed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (!newbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) newbus->busno = busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) newbus->busno = curr->bus_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) list_add_tail(&newbus->bus_list, &gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return newbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static struct resource_node * __init alloc_resources(struct ebda_pci_rsrc *curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct resource_node *rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!curr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) err("NULL passed to allocate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!rs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) rs->busno = curr->bus_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) rs->devfunc = curr->dev_fun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) rs->start = curr->start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) rs->end = curr->end_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) rs->len = curr->end_addr - curr->start_addr + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) 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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct bus_node *newbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct range_node *newrange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u8 num_ranges = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (first_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!newbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) newbus->busno = curr->bus_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) newbus = *new_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) switch (flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) num_ranges = newbus->noMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) num_ranges = newbus->noPFMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) num_ranges = newbus->noIORanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!newrange) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (first_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) kfree(newbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) newrange->start = curr->start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) newrange->end = curr->end_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (first_bus || (!num_ranges))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) newrange->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* need to insert our range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) add_bus_range(flag, newrange, newbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) debug("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) switch (flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) newbus->rangeMem = newrange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (first_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) newbus->noMemRanges = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) debug("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ++newbus->noMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) fix_resources(newbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) newbus->rangeIO = newrange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (first_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) newbus->noIORanges = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) debug("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ++newbus->noIORanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) fix_resources(newbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) newbus->rangePFMem = newrange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (first_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) newbus->noPFMemRanges = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) debug("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ++newbus->noPFMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) fix_resources(newbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) *new_bus = newbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *new_range = newrange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * 1. The ranges are ordered. The buses are not ordered. (First come)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * 2. If cannot allocate out of PFMem range, allocate from Mem ranges. PFmemFromMem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * are not sorted. (no need since use mem node). To not change the entire code, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * also add mem node whenever this case happens so as not to change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * ibmphp_check_mem_resource etc(and since it really is taking Mem resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * This is the Resource Management initialization function. It will go through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * the Resource list taken from EBDA and fill in this module's data structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * Input: ptr to the head of the resource list from EBDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * Output: 0, -1 or error codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int __init ibmphp_rsrc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct ebda_pci_rsrc *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct range_node *newrange = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct bus_node *newbus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct bus_node *bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct bus_node *bus_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct resource_node *new_io = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct resource_node *new_mem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct resource_node *new_pfmem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) list_for_each_entry(curr, &ibmphp_ebda_pci_rsrc_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ebda_pci_rsrc_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (!(curr->rsrc_type & PCIDEVMASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* EBDA still lists non PCI devices, so ignore... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) debug("this is not a PCI DEVICE in rsrc_init, please take care\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) // continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* this is a primary bus resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (curr->rsrc_type & PRIMARYBUSMASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if ((curr->rsrc_type & RESTYPE) == MMASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* no bus structure exists in place yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (list_empty(&gbuses)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) rc = alloc_bus_range(&newbus, &newrange, curr, MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) list_add_tail(&newbus->bus_list, &gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) debug("gbuses = NULL, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) bus_cur = find_bus_wprev(curr->bus_num, &bus_prev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* found our bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (bus_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) rc = alloc_bus_range(&bus_cur, &newrange, curr, MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* went through all the buses and didn't find ours, need to create a new bus node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) rc = alloc_bus_range(&newbus, &newrange, curr, MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) list_add_tail(&newbus->bus_list, &gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) debug("New Bus, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) } else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* prefetchable memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (list_empty(&gbuses)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* no bus structure exists in place yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) rc = alloc_bus_range(&newbus, &newrange, curr, PFMEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) list_add_tail(&newbus->bus_list, &gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) debug("gbuses = NULL, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) bus_cur = find_bus_wprev(curr->bus_num, &bus_prev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (bus_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* found our bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) rc = alloc_bus_range(&bus_cur, &newrange, curr, PFMEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* went through all the buses and didn't find ours, need to create a new bus node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) rc = alloc_bus_range(&newbus, &newrange, curr, PFMEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) list_add_tail(&newbus->bus_list, &gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) debug("1st Bus, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) } else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (list_empty(&gbuses)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* no bus structure exists in place yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) rc = alloc_bus_range(&newbus, &newrange, curr, IO, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) list_add_tail(&newbus->bus_list, &gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) debug("gbuses = NULL, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) bus_cur = find_bus_wprev(curr->bus_num, &bus_prev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (bus_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) rc = alloc_bus_range(&bus_cur, &newrange, curr, IO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* went through all the buses and didn't find ours, need to create a new bus node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) rc = alloc_bus_range(&newbus, &newrange, curr, IO, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) list_add_tail(&newbus->bus_list, &gbuses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) debug("1st Bus, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ; /* type is reserved WHAT TO DO IN THIS CASE???
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) NOTHING TO DO??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* regular pci device resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if ((curr->rsrc_type & RESTYPE) == MMASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Memory resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) new_mem = alloc_resources(curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!new_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) new_mem->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * if it didn't find the bus, means PCI dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * came b4 the Primary Bus info, so need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * create a bus rangeno becomes a problem...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * assign a -1 and then update once the range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * actually appears...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ibmphp_add_resource(new_mem) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) newbus = alloc_error_bus(curr, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!newbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) newbus->firstMem = new_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ++newbus->needMemUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) new_mem->rangeno = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) debug("Memory resource for device %x, bus %x, [%x - %x]\n", new_mem->devfunc, new_mem->busno, new_mem->start, new_mem->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) } else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* PFMemory resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) new_pfmem = alloc_resources(curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!new_pfmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) new_pfmem->type = PFMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) new_pfmem->fromMem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (ibmphp_add_resource(new_pfmem) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) newbus = alloc_error_bus(curr, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (!newbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) newbus->firstPFMem = new_pfmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ++newbus->needPFMemUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) new_pfmem->rangeno = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) debug("PFMemory resource for device %x, bus %x, [%x - %x]\n", new_pfmem->devfunc, new_pfmem->busno, new_pfmem->start, new_pfmem->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) } else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* IO resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) new_io = alloc_resources(curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!new_io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) new_io->type = IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * if it didn't find the bus, means PCI dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * came b4 the Primary Bus info, so need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * create a bus rangeno becomes a problem...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * Can assign a -1 and then update once the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * range actually appears...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (ibmphp_add_resource(new_io) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) newbus = alloc_error_bus(curr, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!newbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) newbus->firstIO = new_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ++newbus->needIOUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) new_io->rangeno = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) debug("IO resource for device %x, bus %x, [%x - %x]\n", new_io->devfunc, new_io->busno, new_io->start, new_io->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) list_for_each_entry(bus_cur, &gbuses, bus_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) rc = update_bridge_ranges(&bus_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return once_over(); /* This is to align ranges (so no -1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /********************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * This function adds a range into a sorted list of ranges per bus for a particular
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * range type, it then calls another routine to update the range numbers on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * pci devices' resources for the appropriate resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * Input: type of the resource, range to add, current bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Output: 0 or -1, bus and range ptrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ********************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int add_bus_range(int type, struct range_node *range, struct bus_node *bus_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct range_node *range_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct range_node *range_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) int count = 0, i_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int noRanges = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) range_cur = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) noRanges = bus_cur->noMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) range_cur = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) noRanges = bus_cur->noPFMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) range_cur = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) noRanges = bus_cur->noIORanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) range_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) while (range_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (range->start < range_cur->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) range_prev = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) count = count + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (!count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* our range will go at the beginning of the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) bus_cur->rangeMem = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) bus_cur->rangePFMem = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) bus_cur->rangeIO = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) range->next = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) range->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) i_init = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) } else if (!range_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* our range will go at the end of the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) range->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) range_prev->next = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) range->rangeno = range_prev->rangeno + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* the range is in the middle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) range_prev->next = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) range->next = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) range->rangeno = range_cur->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) i_init = range_prev->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) for (count = i_init; count < noRanges; ++count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ++range_cur->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) update_resources(bus_cur, type, i_init + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * This routine goes through the list of resources of type 'type' and updates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * the range numbers that they correspond to. It was called from add_bus_range fnc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * Input: bus, type of the resource, the rangeno starting from which to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static void update_resources(struct bus_node *bus_cur, int type, int rangeno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct resource_node *res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) u8 eol = 0; /* end of list indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (bus_cur->firstMem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) res = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (bus_cur->firstPFMem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) res = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (bus_cur->firstIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) res = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (res->rangeno == rangeno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (res->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) else if (res->nextRange)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) res = res->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) eol = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (!eol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* found the range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ++res->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static void fix_me(struct resource_node *res, struct bus_node *bus_cur, struct range_node *range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) char *str = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) str = "io";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) str = "mem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) str = "pfmem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (res->rangeno == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) while (range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if ((res->start >= range->start) && (res->end <= range->end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) res->rangeno = range->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) debug("%s->rangeno in fix_resources is %d\n", str, res->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) --bus_cur->needIOUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) --bus_cur->needMemUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) --bus_cur->needPFMemUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) range = range->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (res->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) res = res->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * This routine reassigns the range numbers to the resources that had a -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * This case can happen only if upon initialization, resources taken by pci dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * appear in EBDA before the resources allocated for that bus, since we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * know the range, we assign -1, and this routine is called after a new range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * is assigned to see the resources with unknown range belong to the added range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * Input: current bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * Output: none, list of resources for that bus are fixed if can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) *******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static void fix_resources(struct bus_node *bus_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct range_node *range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct resource_node *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) debug("%s - bus_cur->busno = %d\n", __func__, bus_cur->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (bus_cur->needIOUpdate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) res = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) range = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) fix_me(res, bus_cur, range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (bus_cur->needMemUpdate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) res = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) range = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) fix_me(res, bus_cur, range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (bus_cur->needPFMemUpdate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) res = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) range = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) fix_me(res, bus_cur, range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * This routine adds a resource to the list of resources to the appropriate bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * based on their resource type and sorted by their starting addresses. It assigns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * the ptrs to next and nextRange if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * Input: resource ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * Output: ptrs assigned (to the node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * 0 or -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) *******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) int ibmphp_add_resource(struct resource_node *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct resource_node *res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct resource_node *res_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) struct bus_node *bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct range_node *range_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct resource_node *res_start = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) debug("%s - enter\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) err("NULL passed to add\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) bus_cur = find_bus_wprev(res->busno, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (!bus_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /* didn't find a bus, something's wrong!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) debug("no bus in the system, either pci_dev's wrong or allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* Normal case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) range_cur = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) res_start = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) range_cur = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) res_start = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) range_cur = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) res_start = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) err("cannot read the type of the resource to add... problem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) while (range_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if ((res->start >= range_cur->start) && (res->end <= range_cur->end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) res->rangeno = range_cur->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * this is again the case of rangeno = -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (!range_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ++bus_cur->needIOUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ++bus_cur->needMemUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ++bus_cur->needPFMemUpdate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) res->rangeno = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) debug("The range is %d\n", res->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (!res_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) bus_cur->firstIO = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) bus_cur->firstMem = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) bus_cur->firstPFMem = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) res->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) res->nextRange = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) res_cur = res_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) res_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) debug("res_cur->rangeno is %d\n", res_cur->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (res_cur->rangeno >= res->rangeno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) res_prev = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (!res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /* at the end of the resource list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) debug("i should be here, [%x - %x]\n", res->start, res->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) res_prev->nextRange = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) res->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) res->nextRange = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) } else if (res_cur->rangeno == res->rangeno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /* in the same range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (res->start < res_cur->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) res_prev = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (!res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /* the last resource in this range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) res_prev->next = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) res->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) res->nextRange = res_prev->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) res_prev->nextRange = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) } else if (res->start < res_cur->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* at the beginning or middle of the range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (!res_prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) bus_cur->firstIO = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) bus_cur->firstMem = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) bus_cur->firstPFMem = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) } else if (res_prev->rangeno == res_cur->rangeno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) res_prev->next = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) res_prev->nextRange = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) res->next = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) res->nextRange = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* this is the case where it is 1st occurrence of the range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (!res_prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* at the beginning of the resource list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) res->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) res->nextRange = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) bus_cur->firstIO = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) res->nextRange = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) bus_cur->firstMem = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) res->nextRange = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) bus_cur->firstPFMem = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) } else if (res_cur->rangeno > res->rangeno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /* in the middle of the resource list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) res_prev->nextRange = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) res->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) res->nextRange = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) debug("%s - exit\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * This routine will remove the resource from the list of resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * Input: io, mem, and/or pfmem resource to be deleted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * Output: modified resource list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * 0 or error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) ****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int ibmphp_remove_resource(struct resource_node *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct bus_node *bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct resource_node *res_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct resource_node *res_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct resource_node *mem_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) char *type = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) err("resource to remove is NULL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) bus_cur = find_bus_wprev(res->busno, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (!bus_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) err("cannot find corresponding bus of the io resource to remove bailing out...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) res_cur = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) type = "io";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) res_cur = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) type = "mem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) res_cur = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) type = "pfmem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) err("unknown type for resource to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) res_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if ((res_cur->start == res->start) && (res_cur->end == res->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) res_prev = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (!res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (res->type == PFMEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * case where pfmem might be in the PFMemFromMem list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * so will also need to remove the corresponding mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) res_cur = bus_cur->firstPFMemFromMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) res_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if ((res_cur->start == res->start) && (res_cur->end == res->end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) mem_cur = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) while (mem_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if ((mem_cur->start == res_cur->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) && (mem_cur->end == res_cur->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (mem_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) mem_cur = mem_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) mem_cur = mem_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (!mem_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) err("cannot find corresponding mem node for pfmem...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ibmphp_remove_resource(mem_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (!res_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) bus_cur->firstPFMemFromMem = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) res_prev->next = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) kfree(res_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) res_prev = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (!res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) err("cannot find pfmem to delete...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) err("the %s resource is not in the list to be deleted...\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (!res_prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) /* first device to be deleted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (res_cur->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) bus_cur->firstIO = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) bus_cur->firstMem = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) bus_cur->firstPFMem = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) } else if (res_cur->nextRange) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) bus_cur->firstIO = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) bus_cur->firstMem = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) bus_cur->firstPFMem = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) bus_cur->firstIO = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) bus_cur->firstMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) bus_cur->firstPFMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) kfree(res_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (res_cur->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (res_prev->rangeno == res_cur->rangeno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) res_prev->next = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) res_prev->nextRange = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) } else if (res_cur->nextRange) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) res_prev->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) res_prev->nextRange = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) res_prev->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) res_prev->nextRange = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) kfree(res_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) static struct range_node *find_range(struct bus_node *bus_cur, struct resource_node *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct range_node *range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) range = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) range = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) range = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) err("cannot read resource type in find_range\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) while (range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (res->rangeno == range->rangeno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) range = range->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * This routine will check to make sure the io/mem/pfmem->len that the device asked for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * can fit w/i our list of available IO/MEM/PFMEM resources. If cannot, returns -EINVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * otherwise, returns 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * Input: resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * Output: the correct start and end address are inputted into the resource node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * 0 or -EINVAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int ibmphp_check_resource(struct resource_node *res, u8 bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct bus_node *bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) struct range_node *range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct resource_node *res_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct resource_node *res_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) u32 len_cur = 0, start_cur = 0, len_tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) int noranges = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) u32 tmp_start; /* this is to make sure start address is divisible by the length needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) u32 tmp_divide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) u8 flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /* The rules for bridges are different, 4K divisible for IO, 1M for (pf)mem*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (res->type == IO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) tmp_divide = IOBRIDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) tmp_divide = MEMBRIDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) tmp_divide = res->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) bus_cur = find_bus_wprev(res->busno, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (!bus_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* didn't find a bus, something's wrong!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) debug("no bus in the system, either pci_dev's wrong or allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) debug("%s - enter\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) debug("bus_cur->busno is %d\n", bus_cur->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /* This is a quick fix to not mess up with the code very much. i.e.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * 2000-2fff, len = 1000, but when we compare, we need it to be fff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) res->len -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) res_cur = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) noranges = bus_cur->noIORanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) res_cur = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) noranges = bus_cur->noMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) res_cur = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) noranges = bus_cur->noPFMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) err("wrong type of resource to check\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) res_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) range = find_range(bus_cur, res_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) debug("%s - rangeno = %d\n", __func__, res_cur->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (!range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) err("no range for the device exists... bailing out...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /* found our range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (!res_prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /* first time in the loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) len_tmp = res_cur->start - 1 - range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if ((res_cur->start != range->start) && (len_tmp >= res->len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) debug("len_tmp = %x\n", len_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if ((len_tmp < len_cur) || (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if ((range->start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* just perfect, starting address is divisible by length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) start_cur = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) /* Needs adjusting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) tmp_start = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if ((tmp_start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) start_cur = tmp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) tmp_start += tmp_divide - tmp_start % tmp_divide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (tmp_start >= res_cur->start - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (flag && len_cur == res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) debug("but we are not here, right?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (!res_cur->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* last device on the range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) len_tmp = range->end - (res_cur->end + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if ((range->end != res_cur->end) && (len_tmp >= res->len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) debug("len_tmp = %x\n", len_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if ((len_tmp < len_cur) || (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (((res_cur->end + 1) % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /* just perfect, starting address is divisible by length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) start_cur = res_cur->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) /* Needs adjusting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) tmp_start = res_cur->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) while ((len_tmp = range->end - tmp_start) >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if ((tmp_start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) start_cur = tmp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) tmp_start += tmp_divide - tmp_start % tmp_divide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (tmp_start >= range->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (flag && len_cur == res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (res_prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (res_prev->rangeno != res_cur->rangeno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) /* 1st device on this range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) len_tmp = res_cur->start - 1 - range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if ((res_cur->start != range->start) && (len_tmp >= res->len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if ((len_tmp < len_cur) || (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if ((range->start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* just perfect, starting address is divisible by length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) start_cur = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* Needs adjusting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) tmp_start = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if ((tmp_start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) start_cur = tmp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) tmp_start += tmp_divide - tmp_start % tmp_divide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (tmp_start >= res_cur->start - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (flag && len_cur == res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) /* in the same range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) len_tmp = res_cur->start - 1 - res_prev->end - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (len_tmp >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if ((len_tmp < len_cur) || (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (((res_prev->end + 1) % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) /* just perfect, starting address's divisible by length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) start_cur = res_prev->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /* Needs adjusting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) tmp_start = res_prev->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if ((tmp_start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) start_cur = tmp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) tmp_start += tmp_divide - tmp_start % tmp_divide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (tmp_start >= res_cur->start - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (flag && len_cur == res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) /* end if (res_prev) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) res_prev = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) } /* end of while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (!res_prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) /* 1st device ever */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /* need to find appropriate range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) range = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) range = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) range = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) while (range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) len_tmp = range->end - range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (len_tmp >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if ((len_tmp < len_cur) || (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if ((range->start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) /* just perfect, starting address's divisible by length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) start_cur = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /* Needs adjusting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) tmp_start = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) while ((len_tmp = range->end - tmp_start) >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if ((tmp_start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) start_cur = tmp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) tmp_start += tmp_divide - tmp_start % tmp_divide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (tmp_start >= range->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (flag && len_cur == res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) range = range->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) } /* end of while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if ((!range) && (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /* have gone through the list of devices and ranges and haven't found n.e.thing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) err("no appropriate range.. bailing out...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) } else if (len_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (!res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) debug("prev->rangeno = %d, noranges = %d\n", res_prev->rangeno, noranges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (res_prev->rangeno < noranges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* if there're more ranges out there to check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) switch (res->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) range = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) range = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) range = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) while (range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) len_tmp = range->end - range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (len_tmp >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if ((len_tmp < len_cur) || (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if ((range->start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /* just perfect, starting address's divisible by length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) start_cur = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /* Needs adjusting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) tmp_start = range->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) while ((len_tmp = range->end - tmp_start) >= res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if ((tmp_start % tmp_divide) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) len_cur = len_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) start_cur = tmp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) tmp_start += tmp_divide - tmp_start % tmp_divide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (tmp_start >= range->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (flag && len_cur == res->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) range = range->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) } /* end of while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if ((!range) && (len_cur == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) /* have gone through the list of devices and ranges and haven't found n.e.thing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) err("no appropriate range.. bailing out...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) } else if (len_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) /* no more ranges to check on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (len_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) res->start = start_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) res->len += 1; /* To restore the balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) res->end = res->start + res->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) /* have gone through the list of devices and haven't found n.e.thing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) err("no appropriate range.. bailing out...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) } /* end if (!res_cur) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) /********************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * This routine is called from remove_card if the card contained PPB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * It will remove all the resources on the bus as well as the bus itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * Input: Bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * Output: 0, -ENODEV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) ********************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) int ibmphp_remove_bus(struct bus_node *bus, u8 parent_busno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) struct resource_node *res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) struct resource_node *res_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) struct bus_node *prev_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) prev_bus = find_bus_wprev(parent_busno, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (!prev_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) debug("something terribly wrong. Cannot find parent bus to the one to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) debug("In ibmphp_remove_bus... prev_bus->busno is %x\n", prev_bus->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) rc = remove_ranges(bus, prev_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (bus->firstIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) res_cur = bus->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) bus->firstIO = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (bus->firstMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) res_cur = bus->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) bus->firstMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (bus->firstPFMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) res_cur = bus->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) bus->firstPFMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (bus->firstPFMemFromMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) res_cur = bus->firstPFMemFromMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) bus->firstPFMemFromMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) list_del(&bus->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) kfree(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * This routine deletes the ranges from a given bus, and the entries from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) * parent's bus in the resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * Input: current bus, previous bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) * Output: 0, -EINVAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) static int remove_ranges(struct bus_node *bus_cur, struct bus_node *bus_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) struct range_node *range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) struct range_node *range_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) struct resource_node *res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (bus_cur->noIORanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) range_cur = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) for (i = 0; i < bus_cur->noIORanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (ibmphp_find_resource(bus_prev, range_cur->start, &res, IO) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) ibmphp_remove_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) range_tmp = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) kfree(range_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) range_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) bus_cur->rangeIO = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (bus_cur->noMemRanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) range_cur = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) for (i = 0; i < bus_cur->noMemRanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) if (ibmphp_find_resource(bus_prev, range_cur->start, &res, MEM) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) ibmphp_remove_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) range_tmp = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) kfree(range_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) range_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) bus_cur->rangeMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (bus_cur->noPFMemRanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) range_cur = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) for (i = 0; i < bus_cur->noPFMemRanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (ibmphp_find_resource(bus_prev, range_cur->start, &res, PFMEM) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) ibmphp_remove_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) range_tmp = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) kfree(range_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) range_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) bus_cur->rangePFMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) * find the resource node in the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) * Input: Resource needed, start address of the resource, type of resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) int ibmphp_find_resource(struct bus_node *bus, u32 start_address, struct resource_node **res, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) struct resource_node *res_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) char *type = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (!bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) err("The bus passed in NULL to find resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) switch (flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) res_cur = bus->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) type = "io";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) res_cur = bus->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) type = "mem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) res_cur = bus->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) type = "pfmem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) err("wrong type of flag\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (res_cur->start == start_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) *res = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (!res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (flag == PFMEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) res_cur = bus->firstPFMemFromMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) if (res_cur->start == start_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) *res = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (!res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) debug("SOS...cannot find %s resource in the bus.\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) debug("SOS... cannot find %s resource in the bus.\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) if (*res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) debug("*res->start = %x\n", (*res)->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /***********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * This routine will free the resource structures used by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) * system. It is called from cleanup routine for the module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) * Parameters: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * Returns: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) ***********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) void ibmphp_free_resources(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) struct bus_node *bus_cur = NULL, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) struct bus_node *bus_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) struct range_node *range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) struct range_node *range_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) struct resource_node *res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) struct resource_node *res_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) flags = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) list_for_each_entry_safe(bus_cur, next, &gbuses, bus_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (bus_cur->noIORanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) range_cur = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) for (i = 0; i < bus_cur->noIORanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (!range_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) range_tmp = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) kfree(range_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) range_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (bus_cur->noMemRanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) range_cur = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) for (i = 0; i < bus_cur->noMemRanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) if (!range_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) range_tmp = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) kfree(range_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) range_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (bus_cur->noPFMemRanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) range_cur = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) for (i = 0; i < bus_cur->noPFMemRanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) if (!range_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) range_tmp = range_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) kfree(range_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) range_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) if (bus_cur->firstIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) res_cur = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) bus_cur->firstIO = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (bus_cur->firstMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) res_cur = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) bus_cur->firstMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) if (bus_cur->firstPFMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) res_cur = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (res_cur->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) res_cur = res_cur->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) bus_cur->firstPFMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (bus_cur->firstPFMemFromMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) res_cur = bus_cur->firstPFMemFromMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) while (res_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) res_tmp = res_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) res_cur = res_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) kfree(res_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) res_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) bus_cur->firstPFMemFromMem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) bus_tmp = bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) list_del(&bus_cur->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) kfree(bus_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) bus_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) /*********************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) * This function will go over the PFmem resources to check if the EBDA allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) * pfmem out of memory buckets of the bus. If so, it will change the range numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) * and a flag to indicate that this resource is out of memory. It will also move the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) * Pfmem out of the pfmem resource list to the PFMemFromMem list, and will create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * a new Mem node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) * This routine is called right after initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) *******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) static int __init once_over(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) struct resource_node *pfmem_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) struct resource_node *pfmem_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) struct resource_node *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) struct bus_node *bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) list_for_each_entry(bus_cur, &gbuses, bus_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) pfmem_cur->fromMem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (pfmem_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) pfmem_prev->next = pfmem_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) bus_cur->firstPFMem = pfmem_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) if (!bus_cur->firstPFMemFromMem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) pfmem_cur->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) /* we don't need to sort PFMemFromMem since we're using mem node for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) all the real work anyways, so just insert at the beginning of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) pfmem_cur->next = bus_cur->firstPFMemFromMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) bus_cur->firstPFMemFromMem = pfmem_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) if (!mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) mem->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) mem->busno = pfmem_cur->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) mem->devfunc = pfmem_cur->devfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) mem->start = pfmem_cur->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) mem->end = pfmem_cur->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) mem->len = pfmem_cur->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) if (ibmphp_add_resource(mem) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) err("Trouble...trouble... EBDA allocated pfmem from mem, but system doesn't display it has this space... unless not PCI device...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) pfmem_cur->rangeno = mem->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) } /* end for pfmem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) } /* end if */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) } /* end list_for_each bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) int ibmphp_add_pfmem_from_mem(struct resource_node *pfmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) struct bus_node *bus_cur = find_bus_wprev(pfmem->busno, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) if (!bus_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) err("cannot find bus of pfmem to add...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) if (bus_cur->firstPFMemFromMem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) pfmem->next = bus_cur->firstPFMemFromMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) pfmem->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) bus_cur->firstPFMemFromMem = pfmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) /* This routine just goes through the buses to see if the bus already exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) * It is called from ibmphp_find_sec_number, to find out a secondary bus number for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) * bridged cards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) * Parameters: bus_number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) * Returns: Bus pointer or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) struct bus_node *ibmphp_find_res_bus(u8 bus_number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) return find_bus_wprev(bus_number, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) static struct bus_node *find_bus_wprev(u8 bus_number, struct bus_node **prev, u8 flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) struct bus_node *bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) list_for_each_entry(bus_cur, &gbuses, bus_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) if (flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) *prev = list_prev_entry(bus_cur, bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) if (bus_cur->busno == bus_number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) return bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) void ibmphp_print_test(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) struct bus_node *bus_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) struct range_node *range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) struct resource_node *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) debug_pci("*****************START**********************\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) if ((!list_empty(&gbuses)) && flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) err("The GBUSES is not NULL?!?!?!?!?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) list_for_each_entry(bus_cur, &gbuses, bus_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) debug_pci ("This is bus # %d. There are\n", bus_cur->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) debug_pci ("IORanges = %d\t", bus_cur->noIORanges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) debug_pci ("The IO Ranges are as follows:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) if (bus_cur->rangeIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) range = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) for (i = 0; i < bus_cur->noIORanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) debug_pci("rangeno is %d\n", range->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) debug_pci("[%x - %x]\n", range->start, range->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) range = range->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) debug_pci("The Mem Ranges are as follows:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) if (bus_cur->rangeMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) range = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) for (i = 0; i < bus_cur->noMemRanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) debug_pci("rangeno is %d\n", range->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) debug_pci("[%x - %x]\n", range->start, range->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) range = range->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) debug_pci("The PFMem Ranges are as follows:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (bus_cur->rangePFMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) range = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) for (i = 0; i < bus_cur->noPFMemRanges; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) debug_pci("rangeno is %d\n", range->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) debug_pci("[%x - %x]\n", range->start, range->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) range = range->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) debug_pci("The resources on this bus are as follows\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) debug_pci("IO...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) if (bus_cur->firstIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) res = bus_cur->firstIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) debug_pci("The range # is %d\n", res->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) debug_pci("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) debug_pci("[%x - %x], len=%x\n", res->start, res->end, res->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if (res->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) else if (res->nextRange)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) res = res->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) debug_pci("Mem...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) if (bus_cur->firstMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) res = bus_cur->firstMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) debug_pci("The range # is %d\n", res->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) debug_pci("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) debug_pci("[%x - %x], len=%x\n", res->start, res->end, res->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (res->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) else if (res->nextRange)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) res = res->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) debug_pci("PFMem...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (bus_cur->firstPFMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) res = bus_cur->firstPFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) debug_pci("The range # is %d\n", res->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) debug_pci("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) debug_pci("[%x - %x], len=%x\n", res->start, res->end, res->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) if (res->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) else if (res->nextRange)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) res = res->nextRange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) debug_pci("PFMemFromMem...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (bus_cur->firstPFMemFromMem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) res = bus_cur->firstPFMemFromMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) debug_pci("The range # is %d\n", res->rangeno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) debug_pci("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) debug_pci("[%x - %x], len=%x\n", res->start, res->end, res->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) debug_pci("***********************END***********************\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) static int range_exists_already(struct range_node *range, struct bus_node *bus_cur, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) struct range_node *range_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) case IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) range_cur = bus_cur->rangeIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) case MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) range_cur = bus_cur->rangeMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) case PFMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) range_cur = bus_cur->rangePFMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) err("wrong type passed to find out if range already exists\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) while (range_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) if ((range_cur->start == range->start) && (range_cur->end == range->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) range_cur = range_cur->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) /* This routine will read the windows for any PPB we have and update the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) * range info for the secondary bus, and will also input this info into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) * primary bus, since BIOS doesn't. This is for PPB that are in the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) * on bootup. For bridged cards that were added during previous load of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) * driver, only the ranges and the bus structure are added, the devices are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) * added from NVRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) * Input: primary busno
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) * Returns: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) * Note: this function doesn't take into account IO restrictions etc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) * so will only work for bridges with no video/ISA devices behind them It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) * also will not work for onboard PPBs that can have more than 1 *bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) * behind them All these are TO DO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) * Also need to add more error checkings... (from fnc returns etc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) static int __init update_bridge_ranges(struct bus_node **bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) u8 sec_busno, device, function, hdr_type, start_io_address, end_io_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) u16 vendor_id, upper_io_start, upper_io_end, start_mem_address, end_mem_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) u32 start_address, end_address, upper_start, upper_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) struct bus_node *bus_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) struct bus_node *bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) struct resource_node *io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) struct resource_node *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) struct resource_node *pfmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) struct range_node *range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) bus_cur = *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) if (!bus_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) ibmphp_pci_bus->number = bus_cur->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) debug("inside %s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) debug("bus_cur->busno = %x\n", bus_cur->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) for (device = 0; device < 32; device++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) for (function = 0x00; function < 0x08; function++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) devfn = PCI_DEVFN(device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) /* found correct device!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) switch (hdr_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) case PCI_HEADER_TYPE_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) function = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) case PCI_HEADER_TYPE_MULTIDEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) case PCI_HEADER_TYPE_BRIDGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) function = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) case PCI_HEADER_TYPE_MULTIBRIDGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) /* We assume here that only 1 bus behind the bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) TO DO: add functionality for several:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) temp = secondary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) while (temp < subordinate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) temp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) bus_sec = find_bus_wprev(sec_busno, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) /* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) if (!bus_sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) bus_sec = alloc_error_bus(NULL, sec_busno, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) /* the rest will be populated during NVRAM call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_IO_BASE, &start_io_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &end_io_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, &upper_io_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, &upper_io_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) start_address = (start_io_address & PCI_IO_RANGE_MASK) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) start_address |= (upper_io_start << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) end_address = (end_io_address & PCI_IO_RANGE_MASK) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) end_address |= (upper_io_end << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if ((start_address) && (start_address <= end_address)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) if (!range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) range->start = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) range->end = end_address + 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) if (bus_sec->noIORanges > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (!range_exists_already(range, bus_sec, IO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) add_bus_range(IO, range, bus_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) ++bus_sec->noIORanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) kfree(range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) /* 1st IO Range on the bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) range->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) bus_sec->rangeIO = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) ++bus_sec->noIORanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) fix_resources(bus_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (ibmphp_find_resource(bus_cur, start_address, &io, IO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) io = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) if (!io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) kfree(range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) io->type = IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) io->busno = bus_cur->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) io->devfunc = ((device << 3) | (function & 0x7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) io->start = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) io->end = end_address + 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) io->len = io->end - io->start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) ibmphp_add_resource(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) if ((start_address) && (start_address <= end_address)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) if (!range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) range->start = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) range->end = end_address + 0xfffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) if (bus_sec->noMemRanges > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) if (!range_exists_already(range, bus_sec, MEM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) add_bus_range(MEM, range, bus_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) ++bus_sec->noMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) kfree(range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) /* 1st Mem Range on the bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) range->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) bus_sec->rangeMem = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) ++bus_sec->noMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) fix_resources(bus_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) if (ibmphp_find_resource(bus_cur, start_address, &mem, MEM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) if (!mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) kfree(range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) mem->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) mem->busno = bus_cur->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) mem->devfunc = ((device << 3) | (function & 0x7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) mem->start = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) mem->end = end_address + 0xfffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) mem->len = mem->end - mem->start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) ibmphp_add_resource(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &start_mem_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &end_mem_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, &upper_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, &upper_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) #if BITS_PER_LONG == 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) start_address |= ((long) upper_start) << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) end_address |= ((long) upper_end) << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) if ((start_address) && (start_address <= end_address)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (!range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) range->start = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) range->end = end_address + 0xfffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) if (bus_sec->noPFMemRanges > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) if (!range_exists_already(range, bus_sec, PFMEM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) add_bus_range(PFMEM, range, bus_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) ++bus_sec->noPFMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) kfree(range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) /* 1st PFMem Range on the bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) range->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) bus_sec->rangePFMem = range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) ++bus_sec->noPFMemRanges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) fix_resources(bus_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) if (ibmphp_find_resource(bus_cur, start_address, &pfmem, PFMEM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) if (!pfmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) kfree(range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) pfmem->type = PFMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) pfmem->busno = bus_cur->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) pfmem->devfunc = ((device << 3) | (function & 0x7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) pfmem->start = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) pfmem->end = end_address + 0xfffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) pfmem->len = pfmem->end - pfmem->start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) pfmem->fromMem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) ibmphp_add_resource(pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) } /* end of switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) } /* end if vendor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) } /* end for function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) } /* end for device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) bus = &bus_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) }