^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 "ibmphp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int configure_device(struct pci_func *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int configure_bridge(struct pci_func **, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static struct res_needed *scan_behind_bridge(struct pci_func *, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int add_new_bus(struct bus_node *, struct resource_node *, struct resource_node *, struct resource_node *, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static u8 find_sec_number(u8 primary_busno, u8 slotno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * NOTE..... If BIOS doesn't provide default routing, we assign:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 9 for SCSI, 10 for LAN adapters, and 11 for everything else.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * If adapter is bridged, then we assign 11 to it and devices behind it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * We also assign the same irq numbers for multi function devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * These are PIC mode, so shouldn't matter n.e.ways (hopefully)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void assign_alt_irq(struct pci_func *cur_func, u8 class_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) for (j = 0; j < 4; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (cur_func->irq[j] == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) switch (class_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case PCI_BASE_CLASS_STORAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) cur_func->irq[j] = SCSI_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case PCI_BASE_CLASS_NETWORK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cur_func->irq[j] = LAN_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) cur_func->irq[j] = OTHER_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Configures the device to be added (will allocate needed resources if it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * can), the device can be a bridge or a regular pci device, can also be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * multi-functional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Input: function to be added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * TO DO: The error case with Multifunction device or multi function bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * if there is an error, will need to go through all previous functions and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * unconfigure....or can add some code into unconfigure_card....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int ibmphp_configure_card(struct pci_func *func, u8 slotno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u16 vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u32 class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u8 class_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u8 hdr_type, device, sec_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u8 function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct pci_func *newfunc; /* for multi devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct pci_func *cur_func, *prev_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int rc, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int cleanup_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u8 flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u8 valid_device = 0x00; /* to see if we are able to read from card any device info at all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) debug("inside configure_card, func->busno = %x\n", func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) device = func->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) cur_func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* We only get bus and device from IRQ routing table. So at this point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * func->busno is correct, and func->device contains only device (at the 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * highest bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* For every function on the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for (function = 0x00; function < 0x08; function++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned int devfn = PCI_DEVFN(device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ibmphp_pci_bus->number = cur_func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) cur_func->function = function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) debug("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->function = %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) cur_func->busno, cur_func->device, cur_func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) debug("vendor_id is %x\n", vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* found correct device!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) debug("found valid device, vendor_id = %x\n", vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ++valid_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* header: x x x x x x x x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * |_=> 0 = single function device, 1 = multi-function device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) class_code = class >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) debug("hrd_type = %x, class = %x, class_code %x\n", hdr_type, class, class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) class >>= 8; /* to take revision out, class = class.subclass.prog i/f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (class == PCI_CLASS_NOT_DEFINED_VGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) err("The device %x is VGA compatible and as is not supported for hot plugging. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) "Please choose another device.\n", cur_func->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) } else if (class == PCI_CLASS_DISPLAY_VGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) err("The device %x is not supported for hot plugging. Please choose another device.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) cur_func->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) switch (hdr_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case PCI_HEADER_TYPE_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) debug("single device case.... vendor id = %x, hdr_type = %x, class = %x\n", vendor_id, hdr_type, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) assign_alt_irq(cur_func, class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) rc = configure_device(cur_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* We need to do this in case some other BARs were properly inserted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err("was not able to configure devfunc %x on bus %x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cur_func->device, cur_func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) cleanup_count = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) cur_func->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) function = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case PCI_HEADER_TYPE_MULTIDEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) assign_alt_irq(cur_func, class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) rc = configure_device(cur_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* We need to do this in case some other BARs were properly inserted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) err("was not able to configure devfunc %x on bus %x...bailing out\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) cur_func->device, cur_func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) cleanup_count = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!newfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) newfunc->busno = cur_func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) newfunc->device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) cur_func->next = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) cur_func = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) for (j = 0; j < 4; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) newfunc->irq[j] = cur_func->irq[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case PCI_HEADER_TYPE_MULTIBRIDGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) class >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (class != PCI_CLASS_BRIDGE_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) err("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. Please insert another card.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) cur_func->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) assign_alt_irq(cur_func, class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) rc = configure_bridge(&cur_func, slotno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (rc == -ENODEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) err("You chose to insert Single Bridge, or nested bridges, this is not supported...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) err("Bus %x, devfunc %x\n", cur_func->busno, cur_func->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* We need to do this in case some other BARs were properly inserted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) err("was not able to hot-add PPB properly.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) cleanup_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (func->devices[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (!newfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) newfunc->busno = sec_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) newfunc->device = (u8) i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (j = 0; j < 4; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) newfunc->irq[j] = cur_func->irq[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) prev_func->next = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) cur_func->next = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) rc = ibmphp_configure_card(newfunc, slotno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* This could only happen if kmalloc failed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* We need to do this in case bridge itself got configured properly, but devices behind it failed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) cleanup_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!newfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) newfunc->busno = cur_func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) newfunc->device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) for (j = 0; j < 4; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) newfunc->irq[j] = cur_func->irq[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) prev_func->next = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) cur_func = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case PCI_HEADER_TYPE_BRIDGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) class >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) debug("class now is %x\n", class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (class != PCI_CLASS_BRIDGE_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) err("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. Please insert another card.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) cur_func->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) assign_alt_irq(cur_func, class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) debug("cur_func->busno b4 configure_bridge is %x\n", cur_func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) rc = configure_bridge(&cur_func, slotno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (rc == -ENODEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) err("You chose to insert Single Bridge, or nested bridges, this is not supported...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) err("Bus %x, devfunc %x\n", cur_func->busno, cur_func->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* We need to do this in case some other BARs were properly inserted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) err("was not able to hot-add PPB properly.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) cleanup_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) debug("cur_func->busno = %x, device = %x, function = %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) cur_func->busno, device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) debug("after configuring bridge..., sec_number = %x\n", sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (func->devices[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) debug("inside for loop, device is %x\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!newfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) newfunc->busno = sec_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) newfunc->device = (u8) i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) for (j = 0; j < 4; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) newfunc->irq[j] = cur_func->irq[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) for (prev_func = cur_func; prev_func->next; prev_func = prev_func->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) prev_func->next = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) cur_func->next = newfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) rc = ibmphp_configure_card(newfunc, slotno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* Again, this case should not happen... For complete paranoia, will need to call remove_bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* We need to do this in case some other BARs were properly inserted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) func->bus = 1; /* To indicate to the unconfigure function that this is a PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) cleanup_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) function = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) err("MAJOR PROBLEM!!!!, header type not supported? %x\n", hdr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) } /* end of switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) } /* end of valid device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) } /* end of for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!valid_device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) err("Cannot find any valid devices on the card. Or unable to read from card.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) for (i = 0; i < cleanup_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (cur_func->io[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) ibmphp_remove_resource(cur_func->io[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) cur_func->io[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) } else if (cur_func->pfmem[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ibmphp_remove_resource(cur_func->pfmem[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) cur_func->pfmem[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) } else if (cur_func->mem[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ibmphp_remove_resource(cur_func->mem[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) cur_func->mem[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * This function configures the pci BARs of a single device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * Input: pointer to the pci_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * Output: configured PCI, 0, or error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int configure_device(struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u32 bar[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) u32 address[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) PCI_BASE_ADDRESS_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) PCI_BASE_ADDRESS_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) PCI_BASE_ADDRESS_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) PCI_BASE_ADDRESS_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) PCI_BASE_ADDRESS_4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) PCI_BASE_ADDRESS_5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u8 irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int len[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct resource_node *io[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct resource_node *mem[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct resource_node *mem_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct resource_node *pfmem[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) debug("%s - inside\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) devfn = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) ibmphp_pci_bus->number = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) for (count = 0; address[count]; count++) { /* for 6 BARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* not sure if i need this. per scott, said maybe need * something like this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if devices don't adhere 100% to the spec, so don't want to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) to the reserved bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) pcibios_read_config_byte(cur_func->busno, cur_func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) PCI_BASE_ADDRESS_0 + 4 * count, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (tmp & 0x01) // IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) pcibios_write_config_dword(cur_func->busno, cur_func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) else // Memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) pcibios_write_config_dword(cur_func->busno, cur_func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!bar[count]) /* This BAR is not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) debug("Device %x BAR %d wants %x\n", func->device, count, bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* This is IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) debug("inside IO SPACE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) len[count] = bar[count] & 0xFFFFFFFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) debug("len[count] in IO %x, count %d\n", len[count], count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!io[count])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) io[count]->type = IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) io[count]->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) io[count]->devfunc = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) io[count]->len = len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (ibmphp_check_resource(io[count], 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ibmphp_add_resource(io[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) func->io[count] = io[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) err("cannot allocate requested io for bus %x device %x function %x len %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) func->busno, func->device, func->function, len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) kfree(io[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], func->io[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* _______________This is for debugging purposes only_____________________ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) debug("b4 writing, the IO address is %x\n", func->io[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) debug("after writing.... the start address is %x\n", bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* _________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* This is Memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* pfmem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) debug("PFMEM SPACE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) len[count] = bar[count] & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) debug("len[count] in PFMEM %x, count %d\n", len[count], count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!pfmem[count])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) pfmem[count]->type = PFMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) pfmem[count]->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) pfmem[count]->devfunc = PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) pfmem[count]->len = len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) pfmem[count]->fromMem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (ibmphp_check_resource(pfmem[count], 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ibmphp_add_resource(pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) func->pfmem[count] = pfmem[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (!mem_tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) kfree(pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) mem_tmp->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) mem_tmp->busno = pfmem[count]->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) mem_tmp->devfunc = pfmem[count]->devfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) mem_tmp->len = pfmem[count]->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) debug("there's no pfmem... going into mem.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (ibmphp_check_resource(mem_tmp, 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ibmphp_add_resource(mem_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) pfmem[count]->fromMem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) pfmem[count]->rangeno = mem_tmp->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) pfmem[count]->start = mem_tmp->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) pfmem[count]->end = mem_tmp->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ibmphp_add_pfmem_from_mem(pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) func->pfmem[count] = pfmem[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) err("cannot allocate requested pfmem for bus %x, device %x, len %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) func->busno, func->device, len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) kfree(mem_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) kfree(pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /*_______________This is for debugging purposes only______________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) debug("b4 writing, start address is %x\n", func->pfmem[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) debug("after writing, start address is %x\n", bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /*_________________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) debug("inside the mem 64 case, count %d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* regular memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) debug("REGULAR MEM SPACE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) len[count] = bar[count] & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) debug("len[count] in Mem %x, count %d\n", len[count], count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!mem[count])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) mem[count]->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) mem[count]->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) mem[count]->devfunc = PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) mem[count]->len = len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (ibmphp_check_resource(mem[count], 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ibmphp_add_resource(mem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) func->mem[count] = mem[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) err("cannot allocate requested mem for bus %x, device %x, len %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) func->busno, func->device, len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) kfree(mem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], func->mem[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* _______________________This is for debugging purposes only _______________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) debug("b4 writing, start address is %x\n", func->mem[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) debug("after writing, the address is %x\n", bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* __________________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) debug("inside mem 64 case, reg. mem, count %d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) } /* end of mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) } /* end of for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) func->bus = 0; /* To indicate that this is not a PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if ((irq > 0x00) && (irq < 0x05))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * This routine configures a PCI-2-PCI bridge and the functions behind it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * Parameters: pci_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static int configure_bridge(struct pci_func **func_passed, u8 slotno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) u8 sec_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u8 io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) u16 pfmem_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) u32 bar[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) u32 len[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) u8 flag_io = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) u8 flag_mem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) u8 flag_pfmem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u8 need_io_upper = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) u8 need_pfmem_upper = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct res_needed *amount_needed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct resource_node *io = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct resource_node *bus_io[2] = {NULL, NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct resource_node *mem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) struct resource_node *bus_mem[2] = {NULL, NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct resource_node *mem_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) struct resource_node *pfmem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct resource_node *bus_pfmem[2] = {NULL, NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct bus_node *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) u32 address[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) PCI_BASE_ADDRESS_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) PCI_BASE_ADDRESS_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct pci_func *func = *func_passed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) u8 irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) debug("%s - enter\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) devfn = PCI_DEVFN(func->function, func->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ibmphp_pci_bus->number = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) /* Configuring necessary info for the bridge so that we could see the devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * behind it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* _____________________For debugging purposes only __________________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) pci_bus_config_byte(ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) debug("primary # written into the bridge is %x\n", pri_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ___________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* in EBDA, only get allocated 1 additional bus # per slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) sec_number = find_sec_number(func->busno, slotno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (sec_number == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) err("cannot allocate secondary bus number for the bridged device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) debug("after find_sec_number, the number we got is %x\n", sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) debug("AFTER FIND_SEC_NUMBER, func->busno IS %x\n", func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* __________________For debugging purposes only __________________________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) debug("sec_number after write/read is %x\n", sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) ________________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* __________________For debugging purposes only ____________________________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) debug("subordinate number after write/read is %x\n", sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) __________________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_SEC_LATENCY_TIMER, LATENCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) debug("func->busno is %x\n", func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) debug("sec_number after writing is %x\n", sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) !!!!!!!!!!!!!!!NEED TO ADD!!! FAST BACK-TO-BACK ENABLE!!!!!!!!!!!!!!!!!!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /* First we need to allocate mem/io for the bridge itself in case it needs it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) for (count = 0; address[count]; count++) { /* for 2 BARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (!bar[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* This BAR is not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) debug("so we come here then, eh?, count = %d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) // tmp_bar = bar[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) debug("Bar %d wants %x\n", count, bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /* This is IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) len[count] = bar[count] & 0xFFFFFFFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) debug("len[count] in IO = %x\n", len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (!bus_io[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) bus_io[count]->type = IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) bus_io[count]->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) bus_io[count]->devfunc = PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) bus_io[count]->len = len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (ibmphp_check_resource(bus_io[count], 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ibmphp_add_resource(bus_io[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) func->io[count] = bus_io[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) err("cannot allocate requested io for bus %x, device %x, len %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) func->busno, func->device, len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) kfree(bus_io[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], func->io[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /* This is Memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* pfmem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) len[count] = bar[count] & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) debug("len[count] in PFMEM = %x\n", len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!bus_pfmem[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) bus_pfmem[count]->type = PFMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) bus_pfmem[count]->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) bus_pfmem[count]->devfunc = PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) bus_pfmem[count]->len = len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) bus_pfmem[count]->fromMem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (ibmphp_check_resource(bus_pfmem[count], 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ibmphp_add_resource(bus_pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) func->pfmem[count] = bus_pfmem[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (!mem_tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) mem_tmp->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) mem_tmp->busno = bus_pfmem[count]->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) mem_tmp->devfunc = bus_pfmem[count]->devfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) mem_tmp->len = bus_pfmem[count]->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (ibmphp_check_resource(mem_tmp, 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ibmphp_add_resource(mem_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) bus_pfmem[count]->fromMem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) bus_pfmem[count]->rangeno = mem_tmp->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ibmphp_add_pfmem_from_mem(bus_pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) func->pfmem[count] = bus_pfmem[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) err("cannot allocate requested pfmem for bus %x, device %x, len %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) func->busno, func->device, len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) kfree(mem_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) kfree(bus_pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /* regular memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) len[count] = bar[count] & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) debug("len[count] in Memory is %x\n", len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (!bus_mem[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) bus_mem[count]->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) bus_mem[count]->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) bus_mem[count]->devfunc = PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) bus_mem[count]->len = len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (ibmphp_check_resource(bus_mem[count], 0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ibmphp_add_resource(bus_mem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) func->mem[count] = bus_mem[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) err("cannot allocate requested mem for bus %x, device %x, len %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) func->busno, func->device, len[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) kfree(bus_mem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], func->mem[count]->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) } /* end of mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) } /* end of for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* Now need to see how much space the devices behind the bridge needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) amount_needed = scan_behind_bridge(func, sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (amount_needed == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ibmphp_pci_bus->number = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) debug("after coming back from scan_behind_bridge\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) debug("amount_needed->not_correct = %x\n", amount_needed->not_correct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) debug("amount_needed->io = %x\n", amount_needed->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) debug("amount_needed->mem = %x\n", amount_needed->mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) debug("amount_needed->pfmem = %x\n", amount_needed->pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (amount_needed->not_correct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) debug("amount_needed is not correct\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) for (count = 0; address[count]; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* for 2 BARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (bus_io[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ibmphp_remove_resource(bus_io[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) func->io[count] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) } else if (bus_pfmem[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) ibmphp_remove_resource(bus_pfmem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) func->pfmem[count] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) } else if (bus_mem[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) ibmphp_remove_resource(bus_mem[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) func->mem[count] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) kfree(amount_needed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (!amount_needed->io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) debug("it doesn't want IO?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) flag_io = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) debug("it wants %x IO behind the bridge\n", amount_needed->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) io = kzalloc(sizeof(*io), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (!io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) io->type = IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) io->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) io->devfunc = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) io->len = amount_needed->io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (ibmphp_check_resource(io, 1) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) debug("were we able to add io\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) ibmphp_add_resource(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) flag_io = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (!amount_needed->mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) debug("it doesn't want n.e.memory?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) flag_mem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) debug("it wants %x memory behind the bridge\n", amount_needed->mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) mem = kzalloc(sizeof(*mem), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (!mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) mem->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) mem->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) mem->devfunc = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mem->len = amount_needed->mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (ibmphp_check_resource(mem, 1) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ibmphp_add_resource(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) flag_mem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) debug("were we able to add mem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (!amount_needed->pfmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) debug("it doesn't want n.e.pfmem mem?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) flag_pfmem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) debug("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (!pfmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) pfmem->type = PFMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pfmem->busno = func->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) pfmem->devfunc = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) pfmem->len = amount_needed->pfmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) pfmem->fromMem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (ibmphp_check_resource(pfmem, 1) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) ibmphp_add_resource(pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) flag_pfmem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (!mem_tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) mem_tmp->type = MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) mem_tmp->busno = pfmem->busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) mem_tmp->devfunc = pfmem->devfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) mem_tmp->len = pfmem->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (ibmphp_check_resource(mem_tmp, 1) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ibmphp_add_resource(mem_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) pfmem->fromMem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) pfmem->rangeno = mem_tmp->rangeno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) ibmphp_add_pfmem_from_mem(pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) flag_pfmem = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) debug("b4 if (flag_io && flag_mem && flag_pfmem)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) debug("flag_io = %x, flag_mem = %x, flag_pfmem = %x\n", flag_io, flag_mem, flag_pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (flag_io && flag_mem && flag_pfmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* If on bootup, there was a bridged card in this slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * then card was removed and ibmphp got unloaded and loaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * back again, there's no way for us to remove the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * struct, so no need to kmalloc, can use existing node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) bus = ibmphp_find_res_bus(sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (!bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) bus = kzalloc(sizeof(*bus), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (!bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) bus->busno = sec_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) debug("b4 adding new bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) rc = add_new_bus(bus, io, mem, pfmem, func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) } else if (!(bus->rangeIO) && !(bus->rangeMem) && !(bus->rangePFMem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) rc = add_new_bus(bus, io, mem, pfmem, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) err("expected bus structure not empty?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) retval = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (rc == -ENOMEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) ibmphp_remove_bus(bus, func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) kfree(amount_needed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) retval = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_IO_BASE, &io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &pfmem_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) debug("io 32\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) need_io_upper = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) debug("pfmem 64\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) need_pfmem_upper = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (bus->noIORanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00 | bus->rangeIO->start >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00 | bus->rangeIO->end >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* _______________This is for debugging purposes only ____________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_IO_BASE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) debug("io_base = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) debug("io_limit = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (need_io_upper) { /* since can't support n.e.ways */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (bus->noMemRanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0x0000 | bus->rangeMem->start >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000 | bus->rangeMem->end >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /* ____________________This is for debugging purposes only ________________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) debug("mem_base = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) debug("mem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) __________________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (bus->noPFMemRanges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0x0000 | bus->rangePFMem->start >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000 | bus->rangePFMem->end >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) /* __________________________This is for debugging purposes only _______________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) debug("pfmem_base = %x", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) debug("pfmem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ______________________________________________________________________________________*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (need_pfmem_upper) { /* since can't support n.e.ways */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) debug("b4 writing control information\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if ((irq > 0x00) && (irq < 0x05))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_PARITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) pci_bus_write_config_byte(ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) pci_bus_write_config_word(ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (amount_needed->devices[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) debug("device where devices[i] is 1 = %x\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) func->devices[i] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) func->bus = 1; /* For unconfiguring, to indicate it's PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) func_passed = &func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) debug("func->busno b4 returning is %x\n", func->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) debug("func->busno b4 returning in the other structure is %x\n", (*func_passed)->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) kfree(amount_needed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) err("Configuring bridge was unsuccessful...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) mem_tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) retval = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) kfree(amount_needed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (pfmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) ibmphp_remove_resource(pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ibmphp_remove_resource(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ibmphp_remove_resource(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) for (i = 0; i < 2; i++) { /* for 2 BARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (bus_io[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) ibmphp_remove_resource(bus_io[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) func->io[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) } else if (bus_pfmem[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ibmphp_remove_resource(bus_pfmem[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) func->pfmem[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) } else if (bus_mem[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) ibmphp_remove_resource(bus_mem[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) func->mem[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) * This function adds up the amount of resources needed behind the PPB bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) * and passes it to the configure_bridge function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * Input: bridge function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * Output: amount of resources needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static struct res_needed *scan_behind_bridge(struct pci_func *func, u8 busno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) int count, len[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) u16 vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) u8 hdr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) u8 device, function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) int howmany = 0; /*this is to see if there are any devices behind the bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) u32 bar[6], class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) u32 address[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) PCI_BASE_ADDRESS_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) PCI_BASE_ADDRESS_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) PCI_BASE_ADDRESS_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) PCI_BASE_ADDRESS_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) PCI_BASE_ADDRESS_4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) PCI_BASE_ADDRESS_5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct res_needed *amount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) amount = kzalloc(sizeof(*amount), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (amount == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ibmphp_pci_bus->number = busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) debug("the bus_no behind the bridge is %x\n", busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) debug("scanning devices behind the bridge...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) for (device = 0; device < 32; device++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) amount->devices[device] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) for (function = 0; function < 8; function++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) devfn = PCI_DEVFN(device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) /* found correct device!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) howmany++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) debug("hdr_type behind the bridge is %x\n", hdr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) err("embedded bridges not supported for hot-plugging.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) amount->not_correct = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return amount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) class >>= 8; /* to take revision out, class = class.subclass.prog i/f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (class == PCI_CLASS_NOT_DEFINED_VGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) err("The device %x is VGA compatible and as is not supported for hot plugging. Please choose another device.\n", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) amount->not_correct = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) return amount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) } else if (class == PCI_CLASS_DISPLAY_VGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) err("The device %x is not supported for hot plugging. Please choose another device.\n", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) amount->not_correct = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return amount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) amount->devices[device] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) for (count = 0; address[count]; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) /* for 6 BARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, address[count], &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (tmp & 0x01) // IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) else // MEMORY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) debug("what is bar[count]? %x, count = %d\n", bar[count], count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!bar[count]) /* This BAR is not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) //tmp_bar = bar[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) debug("count %d device %x function %x wants %x resources\n", count, device, function, bar[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /* This is IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) len[count] = bar[count] & 0xFFFFFFFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) amount->io += len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) /* This is Memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) /* pfmem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) len[count] = bar[count] & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) amount->pfmem += len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /* regular memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) len[count] = bar[count] & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) len[count] = ~len[count] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) amount->mem += len[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) } /* end for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) } /* end if (valid) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) } /* end for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) } /* end for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (!howmany)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) amount->not_correct = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) amount->not_correct = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if ((amount->io) && (amount->io < IOBRIDGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) amount->io = IOBRIDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if ((amount->mem) && (amount->mem < MEMBRIDGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) amount->mem = MEMBRIDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if ((amount->pfmem) && (amount->pfmem < MEMBRIDGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) amount->pfmem = MEMBRIDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return amount;
^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) /* The following 3 unconfigure_boot_ routines deal with the case when we had the card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * upon bootup in the system, since we don't allocate func to such case, we need to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * the start addresses from pci config space and then find the corresponding entries in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * our resource lists. The functions return either 0, -ENODEV, or -1 (general failure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) * Change: we also call these functions even if we configured the card ourselves (i.e., not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) * the bootup case), since it should work same way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static int unconfigure_boot_device(u8 busno, u8 device, u8 function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) u32 start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) u32 address[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) PCI_BASE_ADDRESS_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) PCI_BASE_ADDRESS_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) PCI_BASE_ADDRESS_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) PCI_BASE_ADDRESS_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) PCI_BASE_ADDRESS_4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) PCI_BASE_ADDRESS_5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) struct resource_node *io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct resource_node *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) struct resource_node *pfmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) struct bus_node *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) u32 end_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) u32 temp_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) u32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) u32 tmp_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) debug("%s - enter\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) bus = ibmphp_find_res_bus(busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (!bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) debug("cannot find corresponding bus.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) devfn = PCI_DEVFN(device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) ibmphp_pci_bus->number = busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) for (count = 0; address[count]; count++) { /* for 6 BARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &start_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /* We can do this here, b/c by that time the device driver of the card has been stopped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], start_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) debug("start_address is %x\n", start_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) debug("busno, device, function %x %x %x\n", busno, device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (!size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /* This BAR is not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) debug("is this bar no implemented?, count = %d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) tmp_address = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (start_address & PCI_BASE_ADDRESS_SPACE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) /* This is IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) start_address &= PCI_BASE_ADDRESS_IO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) size = size & 0xFFFFFFFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) size = ~size + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) end_address = start_address + size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (ibmphp_find_resource(bus, start_address, &io, IO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) goto report_search_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) debug("io->start = %x\n", io->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) temp_end = io->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) start_address = io->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) ibmphp_remove_resource(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /* This is needed b/c of the old I/O restrictions in the BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) while (temp_end < end_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (ibmphp_find_resource(bus, start_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) &io, IO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) goto report_search_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) debug("io->start = %x\n", io->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) temp_end = io->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) start_address = io->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) ibmphp_remove_resource(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) /* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) /* This is Memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) /* pfmem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) debug("start address of pfmem is %x\n", start_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) start_address &= PCI_BASE_ADDRESS_MEM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (ibmphp_find_resource(bus, start_address, &pfmem, PFMEM) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) err("cannot find corresponding PFMEM resource to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (pfmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) debug("pfmem->start = %x\n", pfmem->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) ibmphp_remove_resource(pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) /* regular memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) debug("start address of mem is %x\n", start_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) start_address &= PCI_BASE_ADDRESS_MEM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (ibmphp_find_resource(bus, start_address, &mem, MEM) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) err("cannot find corresponding MEM resource to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) debug("mem->start = %x\n", mem->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) ibmphp_remove_resource(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) } /* end of mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) } /* end of for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) report_search_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) err("cannot find corresponding IO resource to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return -EIO;
^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) static int unconfigure_boot_bridge(u8 busno, u8 device, u8 function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) int bus_no, pri_no, sub_no, sec_no = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) u32 start_address, tmp_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) u8 sec_number, sub_number, pri_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) struct resource_node *io = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) struct resource_node *mem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) struct resource_node *pfmem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) struct bus_node *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) u32 address[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) PCI_BASE_ADDRESS_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) PCI_BASE_ADDRESS_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) devfn = PCI_DEVFN(device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) ibmphp_pci_bus->number = busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) bus_no = (int) busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) debug("busno is %x\n", busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) debug("%s - busno = %x, primary_number = %x\n", __func__, busno, pri_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) debug("sec_number is %x\n", sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) sec_no = (int) sec_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) pri_no = (int) pri_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (pri_no != bus_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) err("primary numbers in our structures and pci config space don't match.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sub_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) sub_no = (int) sub_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) debug("sub_no is %d, sec_no is %d\n", sub_no, sec_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) if (sec_no != sub_number) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) err("there're more buses behind this bridge. Hot removal is not supported. Please choose another card\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) bus = ibmphp_find_res_bus(sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (!bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) err("cannot find Bus structure for the bridged device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) debug("bus->busno is %x\n", bus->busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) debug("sec_number is %x\n", sec_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) ibmphp_remove_bus(bus, busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) for (count = 0; address[count]; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) /* for 2 BARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &start_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (!start_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) /* This BAR is not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) tmp_address = start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if (start_address & PCI_BASE_ADDRESS_SPACE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) /* This is IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) start_address &= PCI_BASE_ADDRESS_IO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (ibmphp_find_resource(bus, start_address, &io, IO) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) err("cannot find corresponding IO resource to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) debug("io->start = %x\n", io->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) ibmphp_remove_resource(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /* This is Memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) /* pfmem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) start_address &= PCI_BASE_ADDRESS_MEM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (ibmphp_find_resource(bus, start_address, &pfmem, PFMEM) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) err("cannot find corresponding PFMEM resource to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (pfmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) debug("pfmem->start = %x\n", pfmem->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) ibmphp_remove_resource(pfmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) /* regular memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) start_address &= PCI_BASE_ADDRESS_MEM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (ibmphp_find_resource(bus, start_address, &mem, MEM) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) err("cannot find corresponding MEM resource to remove\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) debug("mem->start = %x\n", mem->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) ibmphp_remove_resource(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) /* takes up another dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) } /* end of mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) } /* end of for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) debug("%s - exiting, returning success\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) static int unconfigure_boot_card(struct slot *slot_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) u16 vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) u32 class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) u8 hdr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) u8 device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) u8 busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) u8 function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) debug("%s - enter\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) device = slot_cur->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) busno = slot_cur->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) debug("b4 for loop, device is %x\n", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) /* For every function on the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) for (function = 0x0; function < 0x08; function++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) devfn = PCI_DEVFN(device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) ibmphp_pci_bus->number = busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) pci_bus_read_config_word(ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (vendor_id != PCI_VENDOR_ID_NOTVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /* found correct device!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) ++valid_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) debug("%s - found correct device\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) /* header: x x x x x x x x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * |_=> 0 = single function device, 1 = multi-function device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) pci_bus_read_config_byte(ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) pci_bus_read_config_dword(ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) debug("hdr_type %x, class %x\n", hdr_type, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) class >>= 8; /* to take revision out, class = class.subclass.prog i/f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (class == PCI_CLASS_NOT_DEFINED_VGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) err("The device %x function %x is VGA compatible and is not supported for hot removing. Please choose another device.\n", device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) } else if (class == PCI_CLASS_DISPLAY_VGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) err("The device %x function %x is not supported for hot removing. Please choose another device.\n", device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) switch (hdr_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) case PCI_HEADER_TYPE_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) rc = unconfigure_boot_device(busno, device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) err("was not able to unconfigure device %x func %x on bus %x. bailing out...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) device, function, busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) function = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) case PCI_HEADER_TYPE_MULTIDEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) rc = unconfigure_boot_device(busno, device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) err("was not able to unconfigure device %x func %x on bus %x. bailing out...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) device, function, busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) case PCI_HEADER_TYPE_BRIDGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) class >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (class != PCI_CLASS_BRIDGE_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) err("This device %x function %x is not PCI-to-PCI bridge, and is not supported for hot-removing. Please try another card.\n", device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) rc = unconfigure_boot_bridge(busno, device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) err("was not able to hot-remove PPB properly.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) function = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) case PCI_HEADER_TYPE_MULTIBRIDGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) class >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) if (class != PCI_CLASS_BRIDGE_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) err("This device %x function %x is not PCI-to-PCI bridge, and is not supported for hot-removing. Please try another card.\n", device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) rc = unconfigure_boot_bridge(busno, device, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) err("was not able to hot-remove PPB properly.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) err("MAJOR PROBLEM!!!! Cannot read device's header\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) } /* end of switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) } /* end of valid device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) } /* end of for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (!valid_device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) err("Could not find device to unconfigure. Or could not read the card.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * free the resources of the card (multi, single, or bridged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) * Parameters: slot, flag to say if this is for removing entire module or just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) * unconfiguring the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) * TO DO: will probably need to add some code in case there was some resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) * to remove it... this is from when we have errors in the configure_card...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) * !!!!!!!!!!!!!!!!!!!!!!!!!FOR BUSES!!!!!!!!!!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) * Returns: 0, -1, -ENODEV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) int ibmphp_unconfigure_card(struct slot **slot_cur, int the_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) struct slot *sl = *slot_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) struct pci_func *cur_func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) struct pci_func *temp_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) debug("%s - enter\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (!the_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) /* Need to unconfigure the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) rc = unconfigure_boot_card(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) if ((rc == -ENODEV) || (rc == -EIO) || (rc == -EINVAL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) /* In all other cases, will still need to get rid of func structure if it exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) if (sl->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) cur_func = sl->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) while (cur_func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /* TO DO: WILL MOST LIKELY NEED TO GET RID OF THE BUS STRUCTURE FROM RESOURCES AS WELL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (cur_func->bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) /* in other words, it's a PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) count = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (cur_func->io[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) debug("io[%d] exists\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (the_end > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) ibmphp_remove_resource(cur_func->io[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) cur_func->io[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) if (cur_func->mem[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) debug("mem[%d] exists\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (the_end > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) ibmphp_remove_resource(cur_func->mem[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) cur_func->mem[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) if (cur_func->pfmem[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) debug("pfmem[%d] exists\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) if (the_end > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) ibmphp_remove_resource(cur_func->pfmem[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) cur_func->pfmem[i] = 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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) temp_func = cur_func->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) kfree(cur_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) cur_func = temp_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) sl->func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) *slot_cur = sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) debug("%s - exit\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * add a new bus resulting from hot-plugging a PPB bridge with devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) * Input: bus and the amount of resources needed (we know we can assign those,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) * since they've been checked already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) * Output: bus added to the correct spot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) * 0, -1, error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) static int add_new_bus(struct bus_node *bus, struct resource_node *io, struct resource_node *mem, struct resource_node *pfmem, u8 parent_busno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) struct range_node *io_range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) struct range_node *mem_range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) struct range_node *pfmem_range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) struct bus_node *cur_bus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) /* Trying to find the parent bus number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (parent_busno != 0xFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) cur_bus = ibmphp_find_res_bus(parent_busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) if (!cur_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) err("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) list_add(&bus->bus_list, &cur_bus->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) if (io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) io_range = kzalloc(sizeof(*io_range), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) if (!io_range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) io_range->start = io->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) io_range->end = io->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) io_range->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) bus->noIORanges = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) bus->rangeIO = io_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) if (mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) mem_range = kzalloc(sizeof(*mem_range), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) if (!mem_range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) mem_range->start = mem->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) mem_range->end = mem->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) mem_range->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) bus->noMemRanges = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) bus->rangeMem = mem_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (pfmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if (!pfmem_range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) pfmem_range->start = pfmem->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) pfmem_range->end = pfmem->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) pfmem_range->rangeno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) bus->noPFMemRanges = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) bus->rangePFMem = pfmem_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) * find the 1st available bus number for PPB to set as its secondary bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * Parameters: bus_number of the primary bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) * Returns: bus_number of the secondary bus or 0xff in case of failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) static u8 find_sec_number(u8 primary_busno, u8 slotno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) int min, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) u8 busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) struct bus_info *bus;
^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) bus = ibmphp_find_same_bus_num(primary_busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if (!bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) err("cannot get slot range of the bus from the BIOS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) max = bus->slot_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) min = bus->slot_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) if ((slotno > max) || (slotno < min)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) err("got the wrong range\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) busno = (u8) (slotno - (u8) min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) busno += primary_busno + 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) bus_cur = ibmphp_find_res_bus(busno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) /* either there is no such bus number, or there are no ranges, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) * can only happen if we removed the bridged device in previous load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * of the driver, and now only have the skeleton bus struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if ((!bus_cur) || (!(bus_cur->rangeIO) && !(bus_cur->rangeMem) && !(bus_cur->rangePFMem)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) return busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }