^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) * Compaq Hot Plug Controller Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1995,2001 Compaq Computer Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2001 IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Send feedback to <greg@kroah.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^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) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pci_hotplug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "../pci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "cpqphp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "cpqphp_nvram.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u8 cpqhp_nic_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u8 cpqhp_disk_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static u16 unused_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * detect_HRT_floating_pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * find the Hot Plug Resource Table in the specified region of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) void __iomem *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) void __iomem *endp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u8 temp1, temp2, temp3, temp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) endp = (end - sizeof(struct hrt) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) for (fp = begin; fp <= endp; fp += 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) temp1 = readb(fp + SIG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) temp2 = readb(fp + SIG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) temp3 = readb(fp + SIG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) temp4 = readb(fp + SIG3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (temp1 == '$' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) temp2 == 'H' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) temp3 == 'R' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) temp4 == 'T') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) fp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) dbg("Discovered Hotplug Resource Table at %p\n", fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct pci_bus *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pci_lock_rescan_remove();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (func->pci_dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) func->pci_dev = pci_get_domain_bus_and_slot(0, func->bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) func->function));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* No pci device, we need to create it then */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (func->pci_dev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) dbg("INFO: pci_dev still null\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) num = pci_scan_slot(ctrl->pci_dev->bus, PCI_DEVFN(func->device, func->function));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) pci_bus_add_devices(ctrl->pci_dev->bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) func->pci_dev = pci_get_domain_bus_and_slot(0, func->bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) func->function));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (func->pci_dev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dbg("ERROR: pci_dev still null\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) pci_hp_add_bridge(func->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) child = func->pci_dev->subordinate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) pci_bus_add_devices(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pci_dev_put(func->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) pci_unlock_rescan_remove();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int cpqhp_unconfigure_device(struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) pci_lock_rescan_remove();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) for (j = 0; j < 8 ; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct pci_dev *temp = pci_get_domain_bus_and_slot(0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) func->bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) PCI_DEVFN(func->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) j));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (temp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) pci_dev_put(temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) pci_stop_and_remove_bus_device(temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pci_unlock_rescan_remove();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u32 vendID = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (vendID == 0xffffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return pci_bus_read_config_dword(bus, devfn, offset, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * cpqhp_set_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * @bus_num: bus number of PCI device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * @dev_num: device number of PCI device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * @slot: pointer to u8 where slot number will be returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (cpqhp_legacy_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct pci_dev *fakedev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct pci_bus *fakebus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u16 temp_word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) fakedev = kmalloc(sizeof(*fakedev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) fakebus = kmalloc(sizeof(*fakebus), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!fakedev || !fakebus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) kfree(fakedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) kfree(fakebus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) fakedev->devfn = dev_num << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) fakedev->bus = fakebus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) fakebus->number = bus_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dbg("%s: dev %d, bus %d, pin %d, num %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) __func__, dev_num, bus_num, int_pin, irq_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) rc = pcibios_set_irq_routing(fakedev, int_pin - 1, irq_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) kfree(fakedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) kfree(fakebus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) dbg("%s: rc %d\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return !rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* set the Edge Level Control Register (ELCR) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) temp_word = inb(0x4d0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) temp_word |= inb(0x4d1) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) temp_word |= 0x01 << irq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* This should only be for x86 as it sets the Edge Level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Control Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) outb((u8) (temp_word & 0xFF), 0x4d0); outb((u8) ((temp_word &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 0xFF00) >> 8), 0x4d1); rc = 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u16 tdevice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u32 work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u8 tbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ctrl->pci_bus->number = bus_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) for (tdevice = 0; tdevice < 0xFF; tdevice++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* Scan for access first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Yep we got one. Not a bridge ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *dev_num = tdevice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) dbg("found it !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^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) for (tdevice = 0; tdevice < 0xFF; tdevice++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Scan for access first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Yep we got one. bridge ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* XXX: no recursion, wtf? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int loop, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) u32 work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) u8 tbus, tdevice, tslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) len = cpqhp_routing_table_length();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) for (loop = 0; loop < len; ++loop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) tbus = cpqhp_routing_table->slots[loop].bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) tdevice = cpqhp_routing_table->slots[loop].devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) tslot = cpqhp_routing_table->slots[loop].slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (tslot == slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *bus_num = tbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) *dev_num = tdevice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ctrl->pci_bus->number = tbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) pci_bus_read_config_dword(ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (!nobridge || (work == 0xffffffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) pci_bus_read_config_dword(ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) pci_bus_read_config_byte(ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) dbg("Scan bus for Non Bridge: bus %d\n", tbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) *bus_num = tbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* plain (bridges allowed) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* More PCI configuration routines; this time centered around hotplug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * cpqhp_save_config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Reads configuration for all slots in a PCI bus and saves info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * Note: For non-hot plug buses, the slot # saved is the device #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * returns 0 if success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) long rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u8 class_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) u8 header_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u32 ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u8 secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct pci_func *new_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int sub_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int FirstSupported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int LastSupported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int max_functions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) u8 DevError;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int device = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int cloop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int stop_it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) u16 devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* Decide which slots are supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (is_hot_plug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * is_hot_plug is the slot mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) FirstSupported = is_hot_plug >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) FirstSupported = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) LastSupported = 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* Save PCI configuration space for all devices in supported slots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ctrl->pci_bus->number = busnumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) for (device = FirstSupported; device <= LastSupported; device++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ID = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (ID == 0xFFFFFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (is_hot_plug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Setup slot structure with entry for empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) new_slot = cpqhp_slot_create(busnumber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (new_slot == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) new_slot->bus = (u8) busnumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) new_slot->device = (u8) device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) new_slot->function = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) new_slot->is_a_board = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) new_slot->presence_save = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) new_slot->switch_save = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* If multi-function device, set max_functions to 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (header_type & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) max_functions = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) max_functions = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) function = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) DevError = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* Recurse the subordinate bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * get the subordinate bus number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) sub_bus = (int) secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* Save secondary bus cfg spc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * with this recursive call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) rc = cpqhp_save_config(ctrl, sub_bus, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ctrl->pci_bus->number = busnumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) new_slot = cpqhp_slot_find(busnumber, device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) while (new_slot &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) (new_slot->function != (u8) function))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) new_slot = cpqhp_slot_find(busnumber, device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!new_slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* Setup slot structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) new_slot = cpqhp_slot_create(busnumber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (new_slot == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) new_slot->bus = (u8) busnumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) new_slot->device = (u8) device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) new_slot->function = (u8) function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) new_slot->is_a_board = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) new_slot->switch_save = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* In case of unsupported board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) new_slot->status = DevError;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) devfn = (new_slot->device << 3) | new_slot->function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) new_slot->pci_dev = pci_get_domain_bus_and_slot(0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) new_slot->bus, devfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) for (cloop = 0; cloop < 0x20; cloop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) &(new_slot->config_space[cloop]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) pci_dev_put(new_slot->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) function++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) stop_it = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* this loop skips to the next present function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * reading in Class Code and Header type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) while ((function < max_functions) && (!stop_it)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (ID == 0xFFFFFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) function++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) stop_it++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) } while (function < max_functions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) } /* End of FOR loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * cpqhp_save_slot_config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * Saves configuration info for all PCI devices in a given slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * including subordinate buses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * returns 0 if success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int cpqhp_save_slot_config(struct controller *ctrl, struct pci_func *new_slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) long rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) u8 class_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) u8 header_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) u32 ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) u8 secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int sub_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int max_functions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int function = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int cloop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int stop_it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ID = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) ctrl->pci_bus->number = new_slot->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (ID == 0xFFFFFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (header_type & 0x80) /* Multi-function device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) max_functions = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) max_functions = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) while (function < max_functions) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* Recurse the subordinate bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sub_bus = (int) secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* Save the config headers for the secondary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) rc = cpqhp_save_config(ctrl, sub_bus, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ctrl->pci_bus->number = new_slot->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) new_slot->status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) for (cloop = 0; cloop < 0x20; cloop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) &(new_slot->config_space[cloop]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) function++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) stop_it = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* this loop skips to the next present function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * reading in the Class Code and the Header type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) while ((function < max_functions) && (!stop_it)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (ID == 0xFFFFFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) function++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) stop_it++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * cpqhp_save_base_addr_length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * Saves the length of all base address registers for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * specified slot. this is for hot plug REPLACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * returns 0 if success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u8 cloop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) u8 header_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) u8 secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int sub_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) u32 temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) u32 base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u32 rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct pci_func *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct pci_bus *pci_bus = ctrl->pci_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) while (func != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) pci_bus->number = func->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) devfn = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* Check for Bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) sub_bus = (int) secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) next = cpqhp_slot_list[sub_bus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) while (next != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) rc = cpqhp_save_base_addr_length(ctrl, next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) next = next->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) pci_bus->number = func->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* FIXME: this loop is duplicated in the non-bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * case. The two could be rolled together Figure out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * IO and memory base lengths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) temp_register = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* If this register is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (base & 0x01L) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* IO base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * set base = amount of IO space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) base = base & 0xFFFFFFFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) base = (~base) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* memory base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) base = base & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) base = (~base) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) base = 0x0L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* Save information in slot structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) func->base_length[(cloop - 0x10) >> 2] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) func->base_type[(cloop - 0x10) >> 2] = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) } /* End of base register loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) } else if ((header_type & 0x7F) == 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /* Figure out IO and memory base lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) temp_register = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* If this register is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (base & 0x01L) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* IO base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * base = amount of IO space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) base = base & 0xFFFFFFFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) base = (~base) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* memory base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * base = amount of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * space requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) base = base & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) base = (~base) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) base = 0x0L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* Save information in slot structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) func->base_length[(cloop - 0x10) >> 2] = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) func->base_type[(cloop - 0x10) >> 2] = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) } /* End of base register loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) } else { /* Some other unknown header type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* find the next device in this slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * cpqhp_save_used_resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * Stores used resource information for existing boards. this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * for boards that were in the system when this driver was loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * this function is for hot plug ADD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * returns 0 if success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) u8 cloop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) u8 header_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) u8 secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) u8 temp_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) u8 b_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) u8 b_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) u16 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) u16 save_command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) u16 w_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) u16 w_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) u32 temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) u32 save_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) u32 base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct pci_resource *mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct pci_resource *p_mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct pci_resource *io_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct pci_resource *bus_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct pci_bus *pci_bus = ctrl->pci_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) while ((func != NULL) && func->is_a_board) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) pci_bus->number = func->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) devfn = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* Save the command register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* disable card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) command = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* Check for Bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* Clear Bridge Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) command = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (!bus_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) bus_node->base = secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) bus_node->length = temp_byte - secondary_bus + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) bus_node->next = func->bus_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) func->bus_head = bus_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* Save IO base and Limit registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &b_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &b_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if ((b_base <= b_length) && (save_command & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) io_node = kmalloc(sizeof(*io_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (!io_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) io_node->base = (b_base & 0xF0) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) io_node->length = (b_length - b_base + 0x10) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) io_node->next = func->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) func->io_head = io_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* Save memory base and Limit registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if ((w_base <= w_length) && (save_command & 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (!mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) mem_node->base = w_base << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) mem_node->length = (w_length - w_base + 0x10) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) mem_node->next = func->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) func->mem_head = mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* Save prefetchable memory base and Limit registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if ((w_base <= w_length) && (save_command & 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (!p_mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) p_mem_node->base = w_base << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) p_mem_node->length = (w_length - w_base + 0x10) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) p_mem_node->next = func->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) func->p_mem_head = p_mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* Figure out IO and memory base lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) temp_register = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) temp_register = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* If this register is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (((base & 0x03L) == 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) && (save_command & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* IO base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * set temp_register = amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * of IO space requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) temp_register = base & 0xFFFFFFFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) temp_register = (~temp_register) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) io_node = kmalloc(sizeof(*io_node),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (!io_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) io_node->base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) save_base & (~0x03L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) io_node->length = temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) io_node->next = func->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) func->io_head = io_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (((base & 0x0BL) == 0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) && (save_command & 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /* prefetchable memory base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) temp_register = base & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) temp_register = (~temp_register) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) p_mem_node = kmalloc(sizeof(*p_mem_node),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (!p_mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) p_mem_node->base = save_base & (~0x0FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) p_mem_node->length = temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) p_mem_node->next = func->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) func->p_mem_head = p_mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (((base & 0x0BL) == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) && (save_command & 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* prefetchable memory base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) temp_register = base & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) temp_register = (~temp_register) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) mem_node = kmalloc(sizeof(*mem_node),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (!mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) mem_node->base = save_base & (~0x0FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) mem_node->length = temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) mem_node->next = func->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) func->mem_head = mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) } /* End of base register loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /* Standard header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) } else if ((header_type & 0x7F) == 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /* Figure out IO and memory base lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) temp_register = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) temp_register = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /* If this register is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (((base & 0x03L) == 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) && (save_command & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* IO base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * set temp_register = amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * of IO space requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) temp_register = base & 0xFFFFFFFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) temp_register = (~temp_register) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) io_node = kmalloc(sizeof(*io_node),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (!io_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) io_node->base = save_base & (~0x01L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) io_node->length = temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) io_node->next = func->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) func->io_head = io_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (((base & 0x0BL) == 0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) && (save_command & 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* prefetchable memory base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) temp_register = base & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) temp_register = (~temp_register) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) p_mem_node = kmalloc(sizeof(*p_mem_node),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (!p_mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) p_mem_node->base = save_base & (~0x0FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) p_mem_node->length = temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) p_mem_node->next = func->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) func->p_mem_head = p_mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (((base & 0x0BL) == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) && (save_command & 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) /* prefetchable memory base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) temp_register = base & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) temp_register = (~temp_register) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) mem_node = kmalloc(sizeof(*mem_node),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (!mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) mem_node->base = save_base & (~0x0FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) mem_node->length = temp_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) mem_node->next = func->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) func->mem_head = mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) } /* End of base register loop */
^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) /* find the next device in this slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * cpqhp_configure_board
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * Copies saved configuration information to one slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * this is called recursively for bridge devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * this is for hot plug REPLACE!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * returns 0 if success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) int cloop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) u8 header_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) u8 secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int sub_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct pci_func *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) u32 rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct pci_bus *pci_bus = ctrl->pci_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) while (func != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) pci_bus->number = func->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) devfn = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* Start at the top of config space so that the control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * registers are programmed last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) for (cloop = 0x3C; cloop > 0; cloop -= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) pci_bus_write_config_dword(pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) /* If this is a bridge device, restore subordinate devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) sub_bus = (int) secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) next = cpqhp_slot_list[sub_bus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) while (next != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) rc = cpqhp_configure_board(ctrl, next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) next = next->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* Check all the base Address Registers to make sure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * they are the same. If not, the board is different.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) for (cloop = 16; cloop < 40; cloop += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (temp != func->config_space[cloop >> 2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) dbg("Config space compare failure!!! offset = %x\n", cloop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop >> 2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) func->configured = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^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) * cpqhp_valid_replace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) * this function checks to see if a board is the same as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * one it is replacing. this check will detect if the device's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * vendor or device id's are the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * returns 0 if the board is the same nonzero otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) u8 cloop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) u8 header_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) u8 secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) u32 temp_register = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) u32 base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) u32 rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct pci_func *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) struct pci_bus *pci_bus = ctrl->pci_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) unsigned int devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (!func->is_a_board)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return(ADD_NOT_SUPPORTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) while (func != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) pci_bus->number = func->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) devfn = PCI_DEVFN(func->device, func->function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) pci_bus_read_config_dword(pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /* No adapter present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (temp_register == 0xFFFFFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return(NO_ADAPTER_PRESENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (temp_register != func->config_space[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) return(ADAPTER_NOT_SAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* Check for same revision number and class code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) pci_bus_read_config_dword(pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* Adapter not the same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (temp_register != func->config_space[0x08 >> 2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return(ADAPTER_NOT_SAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* Check for Bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* In order to continue checking, we must program the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * bus registers in the bridge to respond to accesses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * for its subordinate bus(es)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) temp_register = func->config_space[0x18 >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) pci_bus_write_config_dword(pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) secondary_bus = (temp_register >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) next = cpqhp_slot_list[secondary_bus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) while (next != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) rc = cpqhp_valid_replace(ctrl, next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) next = next->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /* Check to see if it is a standard config header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /* Check subsystem vendor and ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) pci_bus_read_config_dword(pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (temp_register != func->config_space[0x2C >> 2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) /* If it's a SMART-2 and the register isn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * filled in, ignore the difference because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * they just have an old rev of the firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (!((func->config_space[0] == 0xAE100E11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) && (temp_register == 0x00L)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return(ADAPTER_NOT_SAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) /* Figure out IO and memory base lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) temp_register = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* If this register is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (base & 0x01L) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) /* IO base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * set base = amount of IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * space requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) base = base & 0xFFFFFFFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) base = (~base) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /* memory base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) base = base & 0xFFFFFFF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) base = (~base) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) base = 0x0L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* Check information in slot structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (func->base_length[(cloop - 0x10) >> 2] != base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return(ADAPTER_NOT_SAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (func->base_type[(cloop - 0x10) >> 2] != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return(ADAPTER_NOT_SAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) } /* End of base register loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) } /* End of (type 0 config space) else */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /* this is not a type 0 or 1 config space header so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * we don't know how to do it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return(DEVICE_TYPE_NOT_SUPPORTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /* Get the next function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) func = cpqhp_slot_find(func->bus, func->device, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return 0;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * cpqhp_find_available_resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * Finds available memory, IO, and IRQ resources for programming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * devices which may be added to the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * this function is for hot plug ADD!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * returns 0 if success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) u8 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) u8 populated_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) u8 bridged_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) void __iomem *one_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) void __iomem *rom_resource_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct pci_func *func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) int i = 10, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) u32 temp_dword, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct pci_resource *mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) struct pci_resource *p_mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) struct pci_resource *io_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct pci_resource *bus_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) dbg("rom_resource_table = %p\n", rom_resource_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (rom_resource_table == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) /* Sum all resources and setup resource maps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) dbg("unused_IRQ = %x\n", unused_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) while (unused_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (unused_IRQ & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) cpqhp_disk_irq = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) unused_IRQ = unused_IRQ >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) temp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) dbg("cpqhp_disk_irq= %d\n", cpqhp_disk_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) unused_IRQ = unused_IRQ >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) temp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) while (unused_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (unused_IRQ & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) cpqhp_nic_irq = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) unused_IRQ = unused_IRQ >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) temp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) dbg("cpqhp_nic_irq= %d\n", cpqhp_nic_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) unused_IRQ = readl(rom_resource_table + PCIIRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (!cpqhp_nic_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) cpqhp_nic_irq = ctrl->cfgspc_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (!cpqhp_disk_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) cpqhp_disk_irq = ctrl->cfgspc_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) rc = compaq_nvram_load(rom_start, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) one_slot = rom_resource_table + sizeof(struct hrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) dbg("number_of_entries = %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (!readb(one_slot + SECONDARY_BUS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) dbg("dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) while (i && readb(one_slot + SECONDARY_BUS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) u8 dev_func = readb(one_slot + DEV_FUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) u8 primary_bus = readb(one_slot + PRIMARY_BUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) u8 max_bus = readb(one_slot + MAX_BUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) u16 io_base = readw(one_slot + IO_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) u16 io_length = readw(one_slot + IO_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) u16 mem_base = readw(one_slot + MEM_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) u16 mem_length = readw(one_slot + MEM_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) primary_bus, secondary_bus, max_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /* If this entry isn't for our controller's bus, ignore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (primary_bus != ctrl->bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) one_slot += sizeof(struct slot_rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) /* find out if this entry is for an occupied slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) ctrl->pci_bus->number = primary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) pci_bus_read_config_dword(ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) dbg("temp_D_word = %x\n", temp_dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (temp_dword != 0xFFFFFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) func = cpqhp_slot_find(primary_bus, dev_func >> 3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) while (func && (func->function != (dev_func & 0x07))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) dbg("func = %p (bus, dev, fun) = (%d, %d, %d)\n", func, primary_bus, dev_func >> 3, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /* If we can't find a match, skip this table entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (!func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) one_slot += sizeof(struct slot_rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) /* this may not work and shouldn't be used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (secondary_bus != primary_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) bridged_slot = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) bridged_slot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) populated_slot = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) populated_slot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) bridged_slot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) /* If we've got a valid IO base, use it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) temp_dword = io_base + io_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if ((io_base) && (temp_dword < 0x10000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) io_node = kmalloc(sizeof(*io_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (!io_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) io_node->base = io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) io_node->length = io_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) dbg("found io_node(base, length) = %x, %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) io_node->base, io_node->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) dbg("populated slot =%d \n", populated_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (!populated_slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) io_node->next = ctrl->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) ctrl->io_head = io_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) io_node->next = func->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) func->io_head = io_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) /* If we've got a valid memory base, use it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) temp_dword = mem_base + mem_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if ((mem_base) && (temp_dword < 0x10000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (!mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) mem_node->base = mem_base << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) mem_node->length = mem_length << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) dbg("found mem_node(base, length) = %x, %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) mem_node->base, mem_node->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) dbg("populated slot =%d \n", populated_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (!populated_slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) mem_node->next = ctrl->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) ctrl->mem_head = mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) mem_node->next = func->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) func->mem_head = mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) }
^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) /* If we've got a valid prefetchable memory base, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) * the base + length isn't greater than 0xFFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) temp_dword = pre_mem_base + pre_mem_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if ((pre_mem_base) && (temp_dword < 0x10000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (!p_mem_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) p_mem_node->base = pre_mem_base << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) p_mem_node->length = pre_mem_length << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) dbg("found p_mem_node(base, length) = %x, %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) p_mem_node->base, p_mem_node->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) dbg("populated slot =%d \n", populated_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (!populated_slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) p_mem_node->next = ctrl->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) ctrl->p_mem_head = p_mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) p_mem_node->next = func->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) func->p_mem_head = p_mem_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) /* If we've got a valid bus number, use it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * The second condition is to ignore bus numbers on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * populated slots that don't have PCI-PCI bridges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (secondary_bus && (secondary_bus != primary_bus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (!bus_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) bus_node->base = secondary_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) bus_node->length = max_bus - secondary_bus + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) dbg("found bus_node(base, length) = %x, %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) bus_node->base, bus_node->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) dbg("populated slot =%d \n", populated_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (!populated_slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) bus_node->next = ctrl->bus_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) ctrl->bus_head = bus_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) bus_node->next = func->bus_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) func->bus_head = bus_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) one_slot += sizeof(struct slot_rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) /* If all of the following fail, we don't have any resources for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * hot plug add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) * cpqhp_return_board_resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * this routine returns all resources allocated to a board to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * the available pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * returns 0 if success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) int cpqhp_return_board_resources(struct pci_func *func, struct resource_lists *resources)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) struct pci_resource *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) struct pci_resource *t_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) dbg("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (!func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) node = func->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) func->io_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) while (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) t_node = node->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) return_resource(&(resources->io_head), node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) node = t_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) node = func->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) func->mem_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) while (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) t_node = node->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) return_resource(&(resources->mem_head), node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) node = t_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) node = func->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) func->p_mem_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) while (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) t_node = node->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) return_resource(&(resources->p_mem_head), node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) node = t_node;
^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) node = func->bus_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) func->bus_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) while (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) t_node = node->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return_resource(&(resources->bus_head), node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) node = t_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) rc |= cpqhp_resource_sort_and_combine(&(resources->mem_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) rc |= cpqhp_resource_sort_and_combine(&(resources->p_mem_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) rc |= cpqhp_resource_sort_and_combine(&(resources->io_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) rc |= cpqhp_resource_sort_and_combine(&(resources->bus_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * cpqhp_destroy_resource_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) * Puts node back in the resource list pointed to by head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) void cpqhp_destroy_resource_list(struct resource_lists *resources)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) struct pci_resource *res, *tres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) res = resources->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) resources->io_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) kfree(tres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) res = resources->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) resources->mem_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) kfree(tres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) res = resources->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) resources->p_mem_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) kfree(tres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) res = resources->bus_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) resources->bus_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) kfree(tres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) * cpqhp_destroy_board_resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) * Puts node back in the resource list pointed to by head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) void cpqhp_destroy_board_resources(struct pci_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) struct pci_resource *res, *tres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) res = func->io_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) func->io_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) kfree(tres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) res = func->mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) func->mem_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) kfree(tres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) res = func->p_mem_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) func->p_mem_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) kfree(tres);
^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) res = func->bus_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) func->bus_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) while (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) tres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) res = res->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) kfree(tres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }