From c4f34fde6f3c7c71ea68909b900561a47c58e35f Mon Sep 17 00:00:00 2001 From: Andrew Morton <akpm@osdl.org> Date: Sun, 18 Jan 2004 18:21:55 -0800 Subject: [PATCH] [PATCH] ppc64: Get native PCI going on iSeries, from Paul Mackerras From: Anton Blanchard <anton@samba.org> Get native PCI going on iSeries, from Paul Mackerras --- arch/ppc64/kernel/iSeries_IoMmTable.c | 1 - arch/ppc64/kernel/iSeries_VpdInfo.c | 2 +- arch/ppc64/kernel/iSeries_irq.c | 196 +++------ arch/ppc64/kernel/iSeries_pci.c | 547 ++++++++++-------------- arch/ppc64/kernel/iSeries_pci_reset.c | 1 - arch/ppc64/kernel/irq.c | 2 + arch/ppc64/kernel/pci.c | 17 + include/asm-ppc64/iSeries/HvCallPci.h | 62 ++- include/asm-ppc64/iSeries/iSeries_pci.h | 108 ++--- include/asm-ppc64/irq.h | 5 - 10 files changed, 384 insertions(+), 557 deletions(-) diff --git a/arch/ppc64/kernel/iSeries_IoMmTable.c b/arch/ppc64/kernel/iSeries_IoMmTable.c index be01bd7a944e..8a5c77610ccf 100644 --- a/arch/ppc64/kernel/iSeries_IoMmTable.c +++ b/arch/ppc64/kernel/iSeries_IoMmTable.c @@ -31,7 +31,6 @@ #include <linux/pci.h> #include <linux/spinlock.h> #include <asm/ppcdebug.h> -#include <asm/flight_recorder.h> #include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/iSeries_pci.h> diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c index 462fc5ec7dbf..5173cee43a14 100644 --- a/arch/ppc64/kernel/iSeries_VpdInfo.c +++ b/arch/ppc64/kernel/iSeries_VpdInfo.c @@ -153,7 +153,7 @@ int device_Location(struct pci_dev *PciDev, char *BufPtr) struct iSeries_Device_Node *DevNode = (struct iSeries_Device_Node *)PciDev->sysdata; return sprintf(BufPtr, "PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s", - DevNode->DsaAddr.busNumber, DevNode->AgentId, + DevNode->DsaAddr.Dsa.busNumber, DevNode->AgentId, DevNode->Vendor, DevNode->Location); } diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c index e90991374ab8..7a6e3a0b2306 100644 --- a/arch/ppc64/kernel/iSeries_irq.c +++ b/arch/ppc64/kernel/iSeries_irq.c @@ -55,45 +55,13 @@ static hw_irq_controller iSeries_IRQ_handler = { .end = iSeries_end_IRQ }; -struct iSeries_irqEntry { - u32 dsa; - struct iSeries_irqEntry* next; -}; - -struct iSeries_irqAnchor { - u8 valid : 1; - u8 reserved : 7; - u16 entryCount; - struct iSeries_irqEntry* head; -}; - -static struct iSeries_irqAnchor iSeries_irqMap[NR_IRQS]; - -#if 0 -static void iSeries_init_irqMap(int irq); -#endif - void iSeries_init_irq_desc(irq_desc_t *desc) { - desc->handler = &iSeries_IRQ_handler; } /* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ void __init iSeries_init_IRQ(void) { -#if 0 - int i; - irq_desc_t *desc; - - for (i = 0; i < NR_IRQS; i++) { - desc = get_irq_desc(i); - desc->handler = &iSeries_IRQ_handler; - desc->status = 0; - desc->status |= IRQ_DISABLED; - desc->depth = 1; - iSeries_init_irqMap(i); - } -#endif /* Register PCI event handler and open an event path */ PPCDBG(PPCDBG_BUSWALK, "Register PCI event handler and open an event path\n"); @@ -101,35 +69,24 @@ void __init iSeries_init_IRQ(void) return; } -#if 0 -/* - * Called by iSeries_init_IRQ - * Prevent IRQs 0 and 255 from being used. IRQ 0 appears in - * uninitialized devices. IRQ 255 appears in the PCI interrupt - * line register if a PCI error occurs, - */ -static void __init iSeries_init_irqMap(int irq) -{ - iSeries_irqMap[irq].valid = ((irq == 0) || (irq == 255)) ? 0 : 1; - iSeries_irqMap[irq].entryCount = 0; - iSeries_irqMap[irq].head = NULL; -} -#endif - /* * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot * It calculates the irq value for the slot. + * Note that subBusNumber is always 0 (at the moment at least). */ int __init iSeries_allocate_IRQ(HvBusNumber busNumber, HvSubBusNumber subBusNumber, HvAgentId deviceId) { u8 idsel = (deviceId >> 4); - u8 function = deviceId & 0x0F; + u8 function = deviceId & 7; - return ((((busNumber - 1) * 16 + (idsel - 1) * 8 - + function) * 9 / 8) % 253) + 2; + return ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function + 1; } +#define IRQ_TO_BUS(irq) (((((irq) - 1) >> 6) & 0xff) + 1) +#define IRQ_TO_IDSEL(irq) (((((irq) - 1) >> 3) & 7) + 1) +#define IRQ_TO_FUNC(irq) (((irq) - 1) & 7) + /* * This is called out of iSeries_scan_slot to assign the EADS slot * to its IRQ number @@ -137,66 +94,33 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber, int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber, HvSubBusNumber subBusNumber, HvAgentId deviceId) { - int rc; - u32 dsa = (busNumber << 16) | (subBusNumber << 8) | deviceId; - struct iSeries_irqEntry *newEntry; - unsigned long flags; - irq_desc_t *desc = get_irq_desc(irq); + irq_desc_t *desc = get_real_irq_desc(irq); - if ((irq < 0) || (irq >= NR_IRQS)) + if (desc == NULL) return -1; - - newEntry = kmalloc(sizeof(*newEntry), GFP_KERNEL); - if (newEntry == NULL) - return -ENOMEM; - - newEntry->dsa = dsa; - newEntry->next = NULL; - /* - * Probably not necessary to lock the irq since allocation is only - * done during buswalk, but it should not hurt anything except a - * little performance to be smp safe. - */ - spin_lock_irqsave(&desc->lock, flags); - - if (iSeries_irqMap[irq].valid) { - /* Push the new element onto the irq stack */ - newEntry->next = iSeries_irqMap[irq].head; - iSeries_irqMap[irq].head = newEntry; - ++iSeries_irqMap[irq].entryCount; - rc = 0; - PPCDBG(PPCDBG_BUSWALK, "iSeries_assign_IRQ 0x%04X.%02X.%02X = 0x%04X\n", - busNumber, subBusNumber, deviceId, irq); - } else { - printk("PCI: Something is wrong with the iSeries_irqMap.\n"); - kfree(newEntry); - rc = -1; - } - spin_unlock_irqrestore(&desc->lock, flags); - return rc; + desc->handler = &iSeries_IRQ_handler; + return 0; } /* This is called by iSeries_activate_IRQs */ static unsigned int iSeries_startup_IRQ(unsigned int irq) { - struct iSeries_irqEntry *entry; - u32 bus, subBus, deviceId, function, mask; + u32 bus, deviceId, function, mask; + const u32 subBus = 0; - for (entry = iSeries_irqMap[irq].head; entry != NULL; - entry = entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - function = deviceId & 0x0F; - /* Link the IRQ number to the bridge */ - HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); - /* Unmask bridge interrupts in the FISR */ - mask = 0x01010000 << function; - HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_activate_IRQ 0x%02X.%02X.%02X Irq:0x%02X\n", + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + + /* Link the IRQ number to the bridge */ + HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); + + /* Unmask bridge interrupts in the FISR */ + mask = 0x01010000 << function; + HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_activate_IRQ 0x%02X.%02X.%02X Irq:0x%02X\n", bus, subBus, deviceId, irq); - } return 0; } @@ -223,22 +147,20 @@ void __init iSeries_activate_IRQs() /* this is not called anywhere currently */ static void iSeries_shutdown_IRQ(unsigned int irq) { - struct iSeries_irqEntry *entry; - u32 bus, subBus, deviceId, function, mask; + u32 bus, deviceId, function, mask; + const u32 subBus = 0; /* irq should be locked by the caller */ + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + + /* Invalidate the IRQ number in the bridge */ + HvCallXm_connectBusUnit(bus, subBus, deviceId, 0); - for (entry = iSeries_irqMap[irq].head; entry; entry = entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - function = deviceId & 0x0F; - /* Invalidate the IRQ number in the bridge */ - HvCallXm_connectBusUnit(bus, subBus, deviceId, 0); - /* Mask bridge interrupts in the FISR */ - mask = 0x01010000 << function; - HvCallPci_maskFisr(bus, subBus, deviceId, mask); - } + /* Mask bridge interrupts in the FISR */ + mask = 0x01010000 << function; + HvCallPci_maskFisr(bus, subBus, deviceId, mask); } /* @@ -247,21 +169,19 @@ static void iSeries_shutdown_IRQ(unsigned int irq) */ static void iSeries_disable_IRQ(unsigned int irq) { - struct iSeries_irqEntry *entry; - u32 bus, subBus, deviceId, mask; + u32 bus, deviceId, function, mask; + const u32 subBus = 0; /* The IRQ has already been locked by the caller */ - for (entry = iSeries_irqMap[irq].head; entry; entry = entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - /* Mask secondary INTA */ - mask = 0x80000000; - HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, - "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); - } + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + + /* Mask secondary INTA */ + mask = 0x80000000; + HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", + bus, subBus, deviceId, irq); } /* @@ -270,21 +190,19 @@ static void iSeries_disable_IRQ(unsigned int irq) */ static void iSeries_enable_IRQ(unsigned int irq) { - struct iSeries_irqEntry *entry; - u32 bus, subBus, deviceId, mask; + u32 bus, deviceId, function, mask; + const u32 subBus = 0; /* The IRQ has already been locked by the caller */ - for (entry = iSeries_irqMap[irq].head; entry; entry = entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - /* Unmask secondary INTA */ - mask = 0x80000000; - HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, - "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); - } + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + + /* Unmask secondary INTA */ + mask = 0x80000000; + HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", + bus, subBus, deviceId, irq); } /* diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c index 24e4b3eb05c5..148f5a7691ab 100644 --- a/arch/ppc64/kernel/iSeries_pci.c +++ b/arch/ppc64/kernel/iSeries_pci.c @@ -36,7 +36,6 @@ #include <asm/pci-bridge.h> #include <asm/ppcdebug.h> #include <asm/naca.h> -#include <asm/flight_recorder.h> #include <asm/pci_dma.h> #include <asm/iSeries/HvCallPci.h> @@ -50,16 +49,10 @@ #include "iSeries_IoMmTable.h" #include "pci.h" -extern struct pci_controller *hose_head; -extern struct pci_controller **hose_tail; -extern int global_phb_number; extern int panic_timeout; -extern struct device_node *allnodes; extern unsigned long iSeries_Base_Io_Memory; -extern struct pci_ops iSeries_pci_ops; -extern struct flightRecorder *PciFr; extern struct TceTable *tceTables[256]; extern void iSeries_MmIoTest(void); @@ -67,8 +60,7 @@ extern void iSeries_MmIoTest(void); /* * Forward declares of prototypes. */ -static struct iSeries_Device_Node *find_Device_Node(struct pci_dev *PciDev); -unsigned long find_and_init_phbs(void); +static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn); static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb); static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); @@ -90,7 +82,8 @@ static long Pci_Error_Count; static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ -static int Pci_Trace_Flag; + +static struct pci_ops iSeries_pci_ops; /* * Log Error infor in Flight Recorder to system Console. @@ -102,14 +95,11 @@ static int Pci_Trace_Flag; static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, int AgentId, int HvRc) { - if (HvRc != 0x0302) { - char ErrorString[128]; + if (HvRc == 0x0302) + return; - sprintf(ErrorString, "%s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", - Error_Text, Bus, SubBus, AgentId, HvRc); - PCIFR(ErrorString); - printk("PCI: %s\n", ErrorString); - } + printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", + Error_Text, Bus, SubBus, AgentId, HvRc); } #if 0 @@ -159,95 +149,68 @@ static void list_device_nodes(void) static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus, HvSubBusNumber SubBus, int AgentId, int Function) { - struct iSeries_Device_Node *DeviceNode; + struct iSeries_Device_Node *node; PPCDBG(PPCDBG_BUSWALK, "-build_device_node 0x%02X.%02X.%02X Function: %02X\n", Bus, SubBus, AgentId, Function); - DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); - if (DeviceNode == NULL) - return NULL; - - memset(DeviceNode, 0, sizeof(struct iSeries_Device_Node)); - list_add_tail(&DeviceNode->Device_List, &iSeries_Global_Device_List); - /* DeviceNode->DsaAddr = - ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); */ - ISERIES_BUS(DeviceNode) = Bus; - ISERIES_SUBBUS(DeviceNode) = SubBus; - DeviceNode->DsaAddr.deviceId = 0x10; - DeviceNode->DsaAddr.barNumber = 0; - DeviceNode->AgentId = AgentId; - DeviceNode->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); - DeviceNode->IoRetry = 0; - iSeries_Get_Location_Code(DeviceNode); - PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(DeviceNode), - ISERIES_DEVFUN(DeviceNode), DeviceNode); - return DeviceNode; -} - -/* - * Allocate pci_controller(phb) initialized common variables. - */ -static struct pci_controller *pci_alloc_pci_controllerX(char *model, - enum phb_types controller_type) -{ - struct pci_controller *hose; - - hose = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), - GFP_KERNEL); - if (hose == NULL) + node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); + if (node == NULL) return NULL; - memset(hose, 0, sizeof(struct pci_controller)); - if (strlen(model) < 8) - strcpy(hose->what, model); - else - memcpy(hose->what, model, 7); - hose->type = controller_type; - hose->global_number = global_phb_number; - global_phb_number++; - - *hose_tail = hose; - hose_tail = &hose->next; - return hose; + memset(node, 0, sizeof(struct iSeries_Device_Node)); + list_add_tail(&node->Device_List, &iSeries_Global_Device_List); +#if 0 + node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); +#endif + node->DsaAddr.DsaAddr = 0; + node->DsaAddr.Dsa.busNumber = Bus; + node->DsaAddr.Dsa.subBusNumber = SubBus; + node->DsaAddr.Dsa.deviceId = 0x10; + node->AgentId = AgentId; + node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); + node->IoRetry = 0; + iSeries_Get_Location_Code(node); + PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(node), + ISERIES_DEVFUN(node), node); + return node; } /* - * unsigned int __init find_and_init_phbs(void) + * unsigned long __init find_and_init_phbs(void) * * Description: * This function checks for all possible system PCI host bridges that connect * PCI buses. The system hypervisor is queried as to the guest partition - * ownership status. A pci_controller is build for any bus which is partially + * ownership status. A pci_controller is built for any bus which is partially * owned or fully owned by this guest partition. */ unsigned long __init find_and_init_phbs(void) { struct pci_controller *phb; - HvBusNumber BusNumber; + HvBusNumber bus; PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n"); /* Check all possible buses. */ - for (BusNumber = 0; BusNumber < 256; BusNumber++) { - int RtnCode = HvCallXm_testBus(BusNumber); - if (RtnCode == 0) { - phb = pci_alloc_pci_controllerX("PHB HV", - phb_type_hypervisor); + for (bus = 0; bus < 256; bus++) { + int ret = HvCallXm_testBus(bus); + if (ret == 0) { + printk("bus %d appears to exist\n", bus); + phb = pci_alloc_pci_controller(phb_type_hypervisor); if (phb == NULL) { - printk("PCI: Allocate pci_controller failed.\n"); PCIFR("Allocate pci_controller failed."); return -1; } - phb->pci_mem_offset = phb->local_number = BusNumber; - phb->first_busno = BusNumber; - phb->last_busno = BusNumber; + phb->pci_mem_offset = phb->local_number = bus; + phb->first_busno = bus; + phb->last_busno = bus; phb->ops = &iSeries_pci_ops; PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", - phb, BusNumber); - PCIFR("Create iSeries PHB controller: %04X", BusNumber); + phb, bus); + PCIFR("Create iSeries PHB controller: %04X", bus); /* Find and connect the devices. */ iSeries_Scan_PHBs_Slots(phb); @@ -256,9 +219,9 @@ unsigned long __init find_and_init_phbs(void) * Check for Unexpected Return code, a clue that something * has gone wrong. */ - else if (RtnCode != 0x0301) - PCIFR("Unexpected Return on Probe(0x%04X): 0x%04X", - BusNumber, RtnCode); + else if (ret != 0x0301) + printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", + bus, ret); } return 0; } @@ -267,17 +230,6 @@ unsigned long __init find_and_init_phbs(void) * iSeries_pcibios_init * * Chance to initialize and structures or variable before PCI Bus walk. - * - * <4>buswalk [swapper : iSeries_pcibios_init Entry. - * <4>buswalk [swapper : IoMmTable Initialized 0xC00000000034BD30 - * <4>buswalk [swapper : find_and_init_phbs Entry - * <4>buswalk [swapper : Create iSeries pci_controller:(0xC00000001F5C7000), Bus 0x0017 - * <4>buswalk [swapper : Connect EADs: 0x17.00.12 = 0x00 - * <4>buswalk [swapper : iSeries_assign_IRQ 0x0017.00.12 = 0x0091 - * <4>buswalk [swapper : - allocate and assign IRQ 0x17.00.12 = 0x91 - * <4>buswalk [swapper : - FoundDevice: 0x17.28.10 = 0x12AE - * <4>buswalk [swapper : - build_device_node 0x17.28.12 - * <4>buswalk [swapper : iSeries_pcibios_init Exit. */ void iSeries_pcibios_init(void) { @@ -293,8 +245,8 @@ void iSeries_pcibios_init(void) */ void __init pcibios_final_fixup(void) { - struct pci_dev *PciDev = NULL; - struct iSeries_Device_Node *DeviceNode; + struct pci_dev *pdev = NULL; + struct iSeries_Device_Node *node; char Buffer[256]; int DeviceCount = 0; @@ -303,24 +255,28 @@ void __init pcibios_final_fixup(void) /* Fix up at the device node and pci_dev relationship */ mf_displaySrc(0xC9000100); - while ((PciDev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, PciDev)) + printk("pcibios_final_fixup\n"); + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { - DeviceNode = find_Device_Node(PciDev); - if (DeviceNode != NULL) { + node = find_Device_Node(pdev->bus->number, pdev->devfn); + printk("pci dev %p (%x.%x), node %p\n", pdev, + pdev->bus->number, pdev->devfn, node); + + if (node != NULL) { ++DeviceCount; - PciDev->sysdata = (void *)DeviceNode; - DeviceNode->PciDev = PciDev; + pdev->sysdata = (void *)node; + node->PciDev = pdev; PPCDBG(PPCDBG_BUSWALK, - "PciDev 0x%p <==> DevNode 0x%p\n", - PciDev, DeviceNode); - iSeries_allocateDeviceBars(PciDev); - iSeries_Device_Information(PciDev, Buffer, + "pdev 0x%p <==> DevNode 0x%p\n", + pdev, node); + iSeries_allocateDeviceBars(pdev); + iSeries_Device_Information(pdev, Buffer, sizeof(Buffer)); printk("%d. %s\n", DeviceCount, Buffer); - create_pci_bus_tce_table((unsigned long)DeviceNode); + create_pci_bus_tce_table((unsigned long)node); } else printk("PCI: Device Tree not found for 0x%016lX\n", - (unsigned long)PciDev); + (unsigned long)pdev); } iSeries_IoMmTable_Status(); iSeries_activate_IRQs(); @@ -333,9 +289,9 @@ void pcibios_fixup_bus(struct pci_bus *PciBus) PciBus->number); } -void pcibios_fixup_resources(struct pci_dev *PciDev) +void pcibios_fixup_resources(struct pci_dev *pdev) { - PPCDBG(PPCDBG_BUSWALK, "fixup_resources PciDev %p\n", PciDev); + PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev); } /* @@ -344,11 +300,11 @@ void pcibios_fixup_resources(struct pci_dev *PciDev) static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) { struct HvCallPci_DeviceInfo *DevInfo; - HvBusNumber Bus = Phb->local_number; /* System Bus */ - HvSubBusNumber SubBus = 0; /* EADs is always 0. */ + HvBusNumber bus = Phb->local_number; /* System Bus */ + const HvSubBusNumber SubBus = 0; /* EADs is always 0. */ int HvRc = 0; - int IdSel = 1; - int MaxAgents = 8; + int IdSel; + const int MaxAgents = 8; DevInfo = (struct HvCallPci_DeviceInfo*) kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); @@ -358,24 +314,25 @@ static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) /* * Probe for EADs Bridges */ - for (IdSel=1; IdSel < MaxAgents; ++IdSel) { - HvRc = HvCallPci_getDeviceInfo(Bus, SubBus, IdSel, + for (IdSel = 1; IdSel < MaxAgents; ++IdSel) { + HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel, REALADDR(DevInfo), sizeof(struct HvCallPci_DeviceInfo)); if (HvRc == 0) { if (DevInfo->deviceType == HvCallPci_NodeDevice) - iSeries_Scan_EADs_Bridge(Bus, SubBus, IdSel); + iSeries_Scan_EADs_Bridge(bus, SubBus, IdSel); else - printk("PCI: Invalid System Configuration(0x%02X.\n", - DevInfo->deviceType); + printk("PCI: Invalid System Configuration(0x%02X)" + " for bus 0x%02x id 0x%02x.\n", + DevInfo->deviceType, bus, IdSel); } else - pci_Log_Error("getDeviceInfo",Bus, SubBus, IdSel,HvRc); + pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc); } kfree(DevInfo); } -static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, +static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus, int IdSel) { struct HvCallPci_BridgeInfo *BridgeInfo; @@ -391,26 +348,26 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, /* Note: hvSubBus and irq is always be 0 at this level! */ for (Function = 0; Function < 8; ++Function) { AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, 0); + HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0); if (HvRc == 0) { + printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, IdSel, Function, AgentId); /* Connect EADs: 0x18.00.12 = 0x00 */ PPCDBG(PPCDBG_BUSWALK, "PCI:Connect EADs: 0x%02X.%02X.%02X\n", - Bus, SubBus, AgentId); - PCIFR("Connect EADs: 0x%02X.%02X.%02X", - Bus, SubBus, AgentId); - HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId, + bus, SubBus, AgentId); + HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, REALADDR(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo)); if (HvRc == 0) { - PPCDBG(PPCDBG_BUSWALK, - "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", + printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n", BridgeInfo->busUnitInfo.deviceType, BridgeInfo->subBusNumber, BridgeInfo->maxAgents, BridgeInfo->maxSubBusNumber, BridgeInfo->logicalSlotNumber); - PCIFR("BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X", + PPCDBG(PPCDBG_BUSWALK, + "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", BridgeInfo->busUnitInfo.deviceType, BridgeInfo->subBusNumber, BridgeInfo->maxAgents, @@ -420,16 +377,14 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice) { /* Scan_Bridge_Slot...: 0x18.00.12 */ - iSeries_Scan_Bridge_Slot(Bus, - BridgeInfo); + iSeries_Scan_Bridge_Slot(bus, BridgeInfo); } else printk("PCI: Invalid Bridge Configuration(0x%02X)", BridgeInfo->busUnitInfo.deviceType); } - } - else if (HvRc != 0x000B) + } else if (HvRc != 0x000B) pci_Log_Error("EADs Connect", - Bus, SubBus, AgentId, HvRc); + bus, SubBus, AgentId, HvRc); } kfree(BridgeInfo); } @@ -440,20 +395,18 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *BridgeInfo) { - struct iSeries_Device_Node *DeviceNode; + struct iSeries_Device_Node *node; HvSubBusNumber SubBus = BridgeInfo->subBusNumber; u16 VendorId = 0; int HvRc = 0; u8 Irq = 0; int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); - HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); - int FirstSlotId = 0; /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ - Irq = iSeries_allocate_IRQ(Bus, 0, AgentId); - iSeries_assign_IRQ(Irq, Bus, 0, AgentId); + Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); + iSeries_assign_IRQ(Irq, Bus, 0, EADsIdSel); PPCDBG(PPCDBG_BUSWALK, "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", Bus, 0, AgentId, Irq); @@ -463,53 +416,42 @@ static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, */ for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { for (Function = 0; Function < 8; ++Function) { - AgentId = ISERIES_PCI_AGENTID(IdSel, Function); + HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, Irq); - if (HvRc == 0) { - HvRc = HvCallPci_configLoad16(Bus, SubBus, - AgentId, PCI_VENDOR_ID, - &VendorId); - if (HvRc == 0) { - /* FoundDevice: 0x18.28.10 = 0x12AE */ - PPCDBG(PPCDBG_BUSWALK, - "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n", - Bus, SubBus, AgentId, VendorId); - HvRc = HvCallPci_configStore8(Bus, - SubBus, AgentId, - PCI_INTERRUPT_LINE, Irq); - if (HvRc != 0) - pci_Log_Error("PciCfgStore Irq Failed!", - Bus, SubBus, - AgentId, HvRc); - ++DeviceCount; - DeviceNode = build_device_node(Bus, - SubBus, EADsIdSel, - Function); - DeviceNode->Vendor = VendorId; - DeviceNode->Irq = Irq; - DeviceNode->LogicalSlot = - BridgeInfo->logicalSlotNumber; - PCIFR("Device(%4d): 0x%02X.%02X.%02X 0x%02X 0x%04X", - DeviceCount, Bus, SubBus, - AgentId, - DeviceNode->LogicalSlot,DeviceNode->Vendor); - - /* - * On the first device/function, - * assign irq to slot - */ - if (Function == 0) { - FirstSlotId = AgentId; - /* AHT iSeries_assign_IRQ(Irq, - Bus, SubBus, AgentId); */ - } - } else - pci_Log_Error("Read Vendor", - Bus, SubBus, AgentId, HvRc); - } else + if (HvRc != 0) { pci_Log_Error("Connect Bus Unit", - Bus, SubBus, AgentId, HvRc); + Bus, SubBus, AgentId, HvRc); + continue; + } + printk("connected bus unit at bus %d subbus 0x%x agentid 0x%x (idsel=%d func=%d)\n", + Bus, SubBus, AgentId, IdSel, Function); + + HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, + PCI_VENDOR_ID, &VendorId); + if (HvRc != 0) { + pci_Log_Error("Read Vendor", + Bus, SubBus, AgentId, HvRc); + continue; + } + printk("read vendor ID: %x\n", VendorId); + + /* FoundDevice: 0x18.28.10 = 0x12AE */ + PPCDBG(PPCDBG_BUSWALK, + "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n", + Bus, SubBus, AgentId, VendorId); + HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, + PCI_INTERRUPT_LINE, Irq); + if (HvRc != 0) + pci_Log_Error("PciCfgStore Irq Failed!", + Bus, SubBus, AgentId, HvRc); + + ++DeviceCount; + node = build_device_node(Bus, SubBus, EADsIdSel, Function); + node->Vendor = VendorId; + node->Irq = Irq; + node->LogicalSlot = BridgeInfo->logicalSlotNumber; + } /* for (Function = 0; Function < 8; ++Function) */ } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ return HvRc; @@ -562,19 +504,16 @@ void *iSeries_memcpy_fromio(void *dest, void *source, size_t count) /* * Look down the chain to find the matching Device Device */ -static struct iSeries_Device_Node *find_Device_Node(struct pci_dev *PciDev) +static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn) { - struct list_head *Device_Node_Ptr = iSeries_Global_Device_List.next; - int Bus = PciDev->bus->number; - int DevFn = PciDev->devfn; + struct list_head *pos; - while (Device_Node_Ptr != &iSeries_Global_Device_List) { - struct iSeries_Device_Node *DevNode = - (struct iSeries_Device_Node*)Device_Node_Ptr; + list_for_each(pos, &iSeries_Global_Device_List) { + struct iSeries_Device_Node *node = + list_entry(pos, struct iSeries_Device_Node, Device_List); - if ((Bus == ISERIES_BUS(DevNode)) && (DevFn == DevNode->DevFn)) - return DevNode; - Device_Node_Ptr = Device_Node_Ptr->next; + if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn)) + return node; } return NULL; } @@ -585,90 +524,82 @@ static struct iSeries_Device_Node *find_Device_Node(struct pci_dev *PciDev) * Sanity Check Node PciDev to passed pci_dev * If none is found, returns a NULL which the client must handle. */ -static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *PciDev) +static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev) { - struct iSeries_Device_Node *Node; - - Node = (struct iSeries_Device_Node *)PciDev->sysdata; - if (Node == NULL) - Node = find_Device_Node(PciDev); - else if (Node->PciDev != PciDev) - Node = find_Device_Node(PciDev); - return Node; + struct iSeries_Device_Node *node; + + node = pdev->sysdata; + if (node == NULL || node->PciDev != pdev) + node = find_Device_Node(pdev->bus->number, pdev->devfn); + return node; } #endif /* - * Read PCI Config Space Code + * Config space read and write functions. + * For now at least, we look for the device node for the bus and devfn + * that we are asked to access. It may be possible to translate the devfn + * to a subbus and deviceid more directly. */ -#if 0 -/** BYTE ********************************************************************/ -int iSeries_Node_read_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8* ReadValue) -{ - u8 ReadData; - if(DevNode == NULL) { return 0x301; } - ++Pci_Cfg_Read_Count; - DevNode->ReturnCode = HvCallPci_configLoad8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,&ReadData); - if(Pci_Trace_Flag == 1) { - PCIFR("RCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: RCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "RCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - } - *ReadValue = ReadData; - return DevNode->ReturnCode; -} +static u64 hv_cfg_read_func[4] = { + HvCallPciConfigLoad8, HvCallPciConfigLoad16, + HvCallPciConfigLoad32, HvCallPciConfigLoad32 +}; -int iSeries_pci_read_config_byte(struct pci_dev* PciDev, int Offset, u8* ReadValue) { - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_read_config_byte( DevNode ,Offset,ReadValue); -} -#endif +static u64 hv_cfg_write_func[4] = { + HvCallPciConfigStore8, HvCallPciConfigStore16, + HvCallPciConfigStore32, HvCallPciConfigStore32 +}; +/* + * Read PCI config space + */ static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int size, u32 *val) { - return PCIBIOS_DEVICE_NOT_FOUND; -} + struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + u64 fn; + struct HvCallPci_LoadReturn ret; -/* - * Write PCI Config Space - */ -#if 0 -/** BYTE ********************************************************************/ -int iSeries_Node_write_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8 WriteData) -{ - ++Pci_Cfg_Write_Count; - DevNode->ReturnCode = HvCallPci_configStore8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,WriteData); - if(Pci_Trace_Flag == 1) { - PCIFR("WCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: WCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "WCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); + if (node == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + fn = hv_cfg_read_func[(size - 1) & 3]; + HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0); + + if (ret.rc != 0) { + *val = ~0; + return PCIBIOS_DEVICE_NOT_FOUND; /* or something */ } - return DevNode->ReturnCode; -} -int iSeries_pci_write_config_byte( struct pci_dev* PciDev,int Offset, u8 WriteValue) -{ - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_write_config_byte( DevNode,Offset,WriteValue); + *val = ret.value; + return 0; } -#endif + +/* + * Write PCI config space + */ static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int size, u32 val) { - return PCIBIOS_DEVICE_NOT_FOUND; + struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + u64 fn; + u64 ret; + + if (node == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + fn = hv_cfg_write_func[(size - 1) & 3]; + ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0); + + if (ret != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + return 0; } -struct pci_ops iSeries_pci_ops = { +static struct pci_ops iSeries_pci_ops = { .read = iSeries_pci_read_config, .write = iSeries_pci_write_config }; @@ -683,18 +614,15 @@ struct pci_ops iSeries_pci_ops = { * PCI: Device 23.90 ReadL Retry( 1) * PCI: Device 23.90 ReadL Retry Successful(1) */ -int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, - u64 RtnCode) +static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, + u64 ret) { - if (RtnCode != 0) { + if (ret != 0) { ++Pci_Error_Count; ++DevNode->IoRetry; - PCIFR("%s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X", - TextHdr, ISERIES_BUS(DevNode), DevNode->DevFn, - DevNode->IoRetry, (int)RtnCode); printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", - TextHdr, ISERIES_BUS(DevNode), DevNode->DevFn, - DevNode->IoRetry, (int)RtnCode); + TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, + DevNode->IoRetry, (int)ret); /* * Bump the retry and check for retry count exceeded. * If, Exceeded, panic the system. @@ -711,7 +639,7 @@ int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, /* If retry was in progress, log success and rest retry count */ if (DevNode->IoRetry > 0) { PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).", - TextHdr, ISERIES_BUS(DevNode), DevNode->DevFn, + TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, DevNode->IoRetry); DevNode->IoRetry = 0; } @@ -724,16 +652,16 @@ int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, * the exposure of being device global. */ static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, - union HvDsaMap *DsaPtr, u64 *BarOffsetPtr) + u64 *dsaptr, u64 *BarOffsetPtr) { unsigned long BaseIoAddr = (unsigned long)IoAddress - iSeries_Base_Io_Memory; long TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size; - struct iSeries_Device_Node *DevNode = *(iSeries_IoMmTable + TableIndex); + struct iSeries_Device_Node *DevNode = iSeries_IoMmTable[TableIndex]; if (DevNode != NULL) { - DsaPtr->DsaAddr = ISERIES_DSA(DevNode); - DsaPtr->Dsa.barNumber = *(iSeries_IoBarTable + TableIndex); + int barnum = iSeries_IoBarTable[TableIndex]; + *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24); *BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size; } else panic("PCI: Invalid PCI IoAddress detected!\n"); @@ -752,61 +680,51 @@ static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, u8 iSeries_Read_Byte(void *IoAddress) { u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; + u64 dsa; + struct HvCallPci_LoadReturn ret; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); do { ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad8, &Return, DsaData.DsaAddr, - BarOffset, 0); - } while (CheckReturnCode("RDB", DevNode, Return.rc) != 0); + HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); + } while (CheckReturnCode("RDB", DevNode, ret.rc) != 0); - if (Pci_Trace_Flag == 1) - PCIFR("RDB: IoAddress 0x%p = 0x%02X", IoAddress, - (u8)Return.value); - return (u8)Return.value; + return (u8)ret.value; } u16 iSeries_Read_Word(void *IoAddress) { u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; + u64 dsa; + struct HvCallPci_LoadReturn ret; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); do { ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad16, &Return, DsaData.DsaAddr, + HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, BarOffset, 0); - } while (CheckReturnCode("RDW", DevNode, Return.rc) != 0); + } while (CheckReturnCode("RDW", DevNode, ret.rc) != 0); - if (Pci_Trace_Flag == 1) - PCIFR("RDW: IoAddress 0x%p = 0x%04X", IoAddress, - swab16((u16)Return.value)); - return swab16((u16)Return.value); + return swab16((u16)ret.value); } u32 iSeries_Read_Long(void *IoAddress) { u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; + u64 dsa; + struct HvCallPci_LoadReturn ret; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); do { ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad32, &Return, DsaData.DsaAddr, + HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, BarOffset, 0); - } while (CheckReturnCode("RDL", DevNode, Return.rc) != 0); + } while (CheckReturnCode("RDL", DevNode, ret.rc) != 0); - if (Pci_Trace_Flag == 1) - PCIFR("RDL: IoAddress 0x%p = 0x%04X", IoAddress, - swab32((u32)Return.value)); - return swab32((u32)Return.value); + return swab32((u32)ret.value); } /* @@ -816,55 +734,46 @@ u32 iSeries_Read_Long(void *IoAddress) * iSeries_Write_Word = Write Word(16 bit) * iSeries_Write_Long = Write Long(32 bit) */ -void iSeries_Write_Byte(u8 Data, void *IoAddress) +void iSeries_Write_Byte(u8 data, void *IoAddress) { u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; + u64 dsa; + u64 rc; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); do { ++Pci_Io_Write_Count; - Return.rc = HvCall4(HvCallPciBarStore8, DsaData.DsaAddr, - BarOffset, Data, 0); - } while (CheckReturnCode("WWB", DevNode, Return.rc) != 0); - if (Pci_Trace_Flag == 1) - PCIFR("WWB: IoAddress 0x%p = 0x%02X", IoAddress, Data); + rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); + } while (CheckReturnCode("WWB", DevNode, rc) != 0); } -void iSeries_Write_Word(u16 Data, void *IoAddress) +void iSeries_Write_Word(u16 data, void *IoAddress) { u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; + u64 dsa; + u64 rc; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); do { ++Pci_Io_Write_Count; - Return.rc = HvCall4(HvCallPciBarStore16, DsaData.DsaAddr, - BarOffset, swab16(Data), 0); - } while (CheckReturnCode("WWW", DevNode, Return.rc) != 0); - if (Pci_Trace_Flag == 1) - PCIFR("WWW: IoAddress 0x%p = 0x%04X", IoAddress, Data); + rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); + } while (CheckReturnCode("WWW", DevNode, rc) != 0); } -void iSeries_Write_Long(u32 Data, void *IoAddress) +void iSeries_Write_Long(u32 data, void *IoAddress) { u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; + u64 dsa; + u64 rc; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); do { ++Pci_Io_Write_Count; - Return.rc = HvCall4(HvCallPciBarStore32, DsaData.DsaAddr, - BarOffset, swab32(Data), 0); - } while (CheckReturnCode("WWL", DevNode, Return.rc) != 0); - if (Pci_Trace_Flag == 1) - PCIFR("WWL: IoAddress 0x%p = 0x%08X", IoAddress, Data); + rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); + } while (CheckReturnCode("WWL", DevNode, rc) != 0); } void pcibios_name_device(struct pci_dev *dev) diff --git a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c index 404a05e56db1..31405862a207 100644 --- a/arch/ppc64/kernel/iSeries_pci_reset.c +++ b/arch/ppc64/kernel/iSeries_pci_reset.c @@ -36,7 +36,6 @@ #include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/HvTypes.h> #include <asm/iSeries/mf.h> -#include <asm/flight_recorder.h> #include <asm/pci.h> #include <asm/iSeries/iSeries_pci.h> diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 49a8db2cd7a9..f535e5a4205c 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -589,7 +589,9 @@ int do_IRQ(struct pt_regs *regs) return 1; /* lets ret_from_int know we can do checks */ } + #else /* CONFIG_PPC_ISERIES */ + int do_IRQ(struct pt_regs *regs) { int irq, first = 1; diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 86c2c6e7a3e7..147dc23d14cb 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -224,7 +224,11 @@ pci_alloc_pci_controller(enum phb_types controller_type) struct pci_controller *hose; char *model; +#ifdef CONFIG_PPC_ISERIES + hose = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); +#else hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller)); +#endif if(hose == NULL) { printk(KERN_ERR "PCI: Allocate pci_controller failed.\n"); return NULL; @@ -232,6 +236,11 @@ pci_alloc_pci_controller(enum phb_types controller_type) memset(hose, 0, sizeof(struct pci_controller)); switch(controller_type) { +#ifdef CONFIG_PPC_ISERIES + case phb_type_hypervisor: + model = "PHB HV"; + break; +#endif case phb_type_python: model = "PHB PY"; break; @@ -311,6 +320,7 @@ static int __init pcibios_init(void) hose->last_busno = bus->subordinate; } +#ifndef CONFIG_PPC_ISERIES if (pci_probe_only) pcibios_claim_of_setup(); else @@ -318,6 +328,7 @@ static int __init pcibios_init(void) pci_assign_unassigned_resources() is able to work correctly with [partially] allocated PCI tree. */ pci_assign_unassigned_resources(); +#endif /* Call machine dependent fixup */ pcibios_final_fixup(); @@ -375,9 +386,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) */ int pci_domain_nr(struct pci_bus *bus) { +#ifdef CONFIG_PPC_ISERIES + return 0; +#else struct pci_controller *hose = PCI_GET_PHB_PTR(bus); return hose->global_number; +#endif } EXPORT_SYMBOL(pci_domain_nr); @@ -385,11 +400,13 @@ EXPORT_SYMBOL(pci_domain_nr); /* Set the name of the bus as it appears in /proc/bus/pci */ int pci_name_bus(char *name, struct pci_bus *bus) { +#ifndef CONFIG_PPC_ISERIES struct pci_controller *hose = PCI_GET_PHB_PTR(bus); if (hose->buid) sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); else +#endif sprintf(name, "%02x", bus->number); return 0; diff --git a/include/asm-ppc64/iSeries/HvCallPci.h b/include/asm-ppc64/iSeries/HvCallPci.h index f4602966ebc8..6887b619288e 100644 --- a/include/asm-ppc64/iSeries/HvCallPci.h +++ b/include/asm-ppc64/iSeries/HvCallPci.h @@ -1,6 +1,6 @@ /************************************************************************/ /* Provides the Hypervisor PCI calls for iSeries Linux Parition. */ -/* Copyright (C) 20yy <Wayne G Holm> <IBM Corporation> */ +/* Copyright (C) 2001 <Wayne G Holm> <IBM Corporation> */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ @@ -21,40 +21,25 @@ /* Change Activity: */ /* Created, Jan 9, 2001 */ /************************************************************************/ -//============================================================================ -// Header File Id -// Name______________: HvCallPci.H -// -// Description_______: -// -// This file contains the "hypervisor call" interface which is used to -// drive the hypervisor from SLIC. -// -//============================================================================ + #ifndef _HVCALLPCI_H #define _HVCALLPCI_H -//------------------------------------------------------------------- -// Forward declarations -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// Standard Includes -//------------------------------------------------------------------- #include <asm/iSeries/HvCallSc.h> #include <asm/iSeries/HvTypes.h> -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -struct HvCallPci_DsaAddr { // make sure this struct size is 64-bits total - u16 busNumber; - u8 subBusNumber; - u8 deviceId; +/* + * DSA == Direct Select Address + * this struct must be 64 bits in total + */ +struct HvCallPci_DsaAddr { + u16 busNumber; /* PHB index? */ + u8 subBusNumber; /* PCI bus number? */ + u8 deviceId; /* device and function? */ u8 barNumber; u8 reserved[3]; }; + union HvDsaMap { u64 DsaAddr; struct HvCallPci_DsaAddr Dsa; @@ -65,12 +50,13 @@ struct HvCallPci_LoadReturn { u64 value; }; -enum HvCallPci_DeviceType {HvCallPci_NodeDevice = 1, - HvCallPci_SpDevice = 2, - HvCallPci_IopDevice = 3, - HvCallPci_BridgeDevice = 4, - HvCallPci_MultiFunctionDevice = 5, - HvCallPci_IoaDevice = 6 +enum HvCallPci_DeviceType { + HvCallPci_NodeDevice = 1, + HvCallPci_SpDevice = 2, + HvCallPci_IopDevice = 3, + HvCallPci_BridgeDevice = 4, + HvCallPci_MultiFunctionDevice = 5, + HvCallPci_IoaDevice = 6 }; @@ -138,9 +124,9 @@ enum HvCallPci_VpdType { #define HvCallPciGetBusUnitInfo HvCallPci + 50 //============================================================================ -static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber, - u8 deviceId, u32 offset, - u8 *value) +static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u8 *value) { struct HvCallPci_DsaAddr dsa; struct HvCallPci_LoadReturn retVal; @@ -160,9 +146,9 @@ static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber, return retVal.rc; } //============================================================================ -static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber, - u8 deviceId, u32 offset, - u16 *value) +static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u16 *value) { struct HvCallPci_DsaAddr dsa; struct HvCallPci_LoadReturn retVal; diff --git a/include/asm-ppc64/iSeries/iSeries_pci.h b/include/asm-ppc64/iSeries/iSeries_pci.h index a526d76e4fd9..652a0c660c40 100644 --- a/include/asm-ppc64/iSeries/iSeries_pci.h +++ b/include/asm-ppc64/iSeries/iSeries_pci.h @@ -1,10 +1,11 @@ #ifndef _ISERIES_64_PCI_H #define _ISERIES_64_PCI_H + /************************************************************************/ /* File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001. */ /************************************************************************/ /* Define some useful macros for the iSeries pci routines. */ -/* Copyright (C) 20yy Allan H Trautman, IBM Corporation */ +/* Copyright (C) 2001 Allan H Trautman, IBM Corporation */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ @@ -28,77 +29,81 @@ /* Ported to ppc64, May 25, 2001 */ /* End Change Activity */ /************************************************************************/ + #include <asm/iSeries/HvCallPci.h> struct pci_dev; /* For Forward Reference */ struct iSeries_Device_Node; + /************************************************************************/ -/* Gets iSeries Bus, SubBus, of DevFn using pci_dev* structure */ +/* Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure */ /************************************************************************/ -#define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.busNumber -#define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.subBusNumber -#define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.deviceId -#define ISERIES_DEVFUN(DevPtr) DevPtr->DevFn -#define ISERIES_DSA(DevPtr) (*(u64*)&DevPtr->DsaAddr) + +#define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.Dsa.busNumber +#define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.Dsa.subBusNumber +#define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.Dsa.deviceId +#define ISERIES_DSA(DevPtr) DevPtr->DsaAddr.DsaAddr +#define ISERIES_DEVFUN(DevPtr) DevPtr->DevFn #define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node*)PciDev->sysdata) #define EADsMaxAgents 7 -/************************************************************************************/ -/* Decodes Linux DevFn to iSeries DevFn, bridge device, or function. */ -/* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h */ -/************************************************************************************/ -#define ISERIES_DECODE_DEVFN(linuxdevfn) (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07)) -#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10)) -#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07) + +/************************************************************************/ +/* Decodes Linux DevFn to iSeries DevFn, bridge device, or function. */ +/* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h */ +/************************************************************************/ + #define ISERIES_PCI_AGENTID(idsel,func) ((idsel & 0x0F) << 4) | (func & 0x07) +#define ISERIES_ENCODE_DEVICE(agentid) ((0x10) | ((agentid&0x20)>>2) | (agentid&07)) #define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7) #define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7) -#define ISERIES_ENCODE_DEVICE(agentid) ((0x10) | ((agentid&0x20)>>2) | (agentid&07)) -/************************************************************************************/ -/* Converts Virtual Address to Real Address for Hypervisor calls */ -/************************************************************************************/ -#define REALADDR(virtaddr) (0x8000000000000000 | (virt_to_absolute((u64)virtaddr) )) +/* + * N.B. the ISERIES_DECODE_* macros are not used anywhere, and I think + * the 0x71 (at least) must be wrong - 0x78 maybe? -- paulus. + */ +#define ISERIES_DECODE_DEVFN(linuxdevfn) (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07)) +#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10)) +#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07) -/************************************************************************************/ -/* Define TRUE and FALSE Values for Al */ -/************************************************************************************/ -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif +/************************************************************************/ +/* Converts Virtual Address to Real Address for Hypervisor calls */ +/************************************************************************/ + +#define REALADDR(virtaddr) (0x8000000000000000 | (virt_to_absolute((u64)virtaddr) )) /************************************************************************/ /* iSeries Device Information */ /************************************************************************/ + struct iSeries_Device_Node { - struct list_head Device_List; /* Must be first for cast to wo*/ - struct pci_dev* PciDev; /* Pointer to pci_dev structure*/ - struct HvCallPci_DsaAddr DsaAddr;/* Direct Select Address */ - /* busNumber,subBusNumber, */ - /* deviceId, barNumber */ - HvAgentId AgentId; /* Hypervisor DevFn */ - int DevFn; /* Linux devfn */ - int BarOffset; - int Irq; /* Assigned IRQ */ - int ReturnCode; /* Return Code Holder */ - int IoRetry; /* Current Retry Count */ - int Flags; /* Possible flags(disable/bist)*/ - u16 Vendor; /* Vendor ID */ - u8 LogicalSlot; /* Hv Slot Index for Tces */ - struct TceTable* DevTceTable; /* Device TCE Table */ - u8 PhbId; /* Phb Card is on. */ - u16 Board; /* Board Number */ - u8 FrameId; /* iSeries spcn Frame Id */ - char CardLocation[4];/* Char format of planar vpd */ - char Location[20]; /* Frame 1, Card C10 */ + struct list_head Device_List; + struct pci_dev* PciDev; /* Pointer to pci_dev structure*/ + union HvDsaMap DsaAddr; /* Direct Select Address */ + /* busNumber,subBusNumber, */ + /* deviceId, barNumber */ + HvAgentId AgentId; /* Hypervisor DevFn */ + int DevFn; /* Linux devfn */ + int BarOffset; + int Irq; /* Assigned IRQ */ + int ReturnCode; /* Return Code Holder */ + int IoRetry; /* Current Retry Count */ + int Flags; /* Possible flags(disable/bist)*/ + u16 Vendor; /* Vendor ID */ + u8 LogicalSlot; /* Hv Slot Index for Tces */ + struct TceTable* DevTceTable; /* Device TCE Table */ + u8 PhbId; /* Phb Card is on. */ + u16 Board; /* Board Number */ + u8 FrameId; /* iSeries spcn Frame Id */ + char CardLocation[4];/* Char format of planar vpd */ + char Location[20]; /* Frame 1, Card C10 */ }; + /************************************************************************/ /* Location Data extracted from the VPD list and device info. */ /************************************************************************/ + struct LocationDataStruct { /* Location data structure for device */ u16 Bus; /* iSeries Bus Number 0x00*/ u16 Board; /* iSeries Board 0x02*/ @@ -108,17 +113,14 @@ struct LocationDataStruct { /* Location data structure for device */ u8 Card; char CardLocation[4]; }; + typedef struct LocationDataStruct LocationData; #define LOCATION_DATA_SIZE 48 -/************************************************************************/ -/* Flight Recorder tracing */ -/************************************************************************/ -extern int iSeries_Set_PciTraceFlag(int TraceFlag); -extern int iSeries_Get_PciTraceFlag(void); /************************************************************************/ /* Functions */ /************************************************************************/ + extern LocationData* iSeries_GetLocationData(struct pci_dev* PciDev); extern int iSeries_Device_Information(struct pci_dev*,char*, int); extern void iSeries_Get_Location_Code(struct iSeries_Device_Node*); diff --git a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h index 5de0cf694fa2..b8ee457ed0f8 100644 --- a/include/asm-ppc64/irq.h +++ b/include/asm-ppc64/irq.h @@ -41,11 +41,6 @@ static inline unsigned long virt_irq_to_real(unsigned long virt_irq) { return virt_irq_to_real_map[virt_irq]; } -/* - * This gets called from serial.c, which is now used on - * powermacs as well as prep/chrp boxes. - * Prep and chrp both have cascaded 8259 PICs. - */ static __inline__ int irq_canonicalize(int irq) { return irq; -- 2.30.9