diff options
Diffstat (limited to 'arch/ppc64')
-rw-r--r-- | arch/ppc64/kernel/XmPciLpEvent.c | 105 | ||||
-rw-r--r-- | arch/ppc64/kernel/iSeries_irq.c | 155 |
2 files changed, 123 insertions, 137 deletions
diff --git a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c index 809c9bc6678..3db53074483 100644 --- a/arch/ppc64/kernel/XmPciLpEvent.c +++ b/arch/ppc64/kernel/XmPciLpEvent.c @@ -1,9 +1,8 @@ /* - * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001. + * File XmPciLpEvent.c created by Wayne Holm on Mon Jan 15 2001. * * This module handles PCI interrupt events sent by the iSeries Hypervisor. -*/ - + */ #include <linux/config.h> #include <linux/pci.h> #include <linux/init.h> @@ -17,22 +16,22 @@ #include <asm/iSeries/HvTypes.h> #include <asm/iSeries/HvLpEvent.h> #include <asm/iSeries/HvCallPci.h> -#include <asm/iSeries/XmPciLpEvent.h> +#include <asm/iSeries/iSeries_irq.h> #include <asm/ppcdebug.h> static long Pci_Interrupt_Count; static long Pci_Event_Count; enum XmPciLpEvent_Subtype { - XmPciLpEvent_BusCreated = 0, // PHB has been created - XmPciLpEvent_BusError = 1, // PHB has failed - XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus - XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed - XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered - XmPciLpEvent_BusRecovered = 12, // PHB has been recovered - XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing - XmPciLpEvent_BridgeError = 21, // Bridge Error - XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt + XmPciLpEvent_BusCreated = 0, // PHB has been created + XmPciLpEvent_BusError = 1, // PHB has failed + XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus + XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed + XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered + XmPciLpEvent_BusRecovered = 12, // PHB has been recovered + XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing + XmPciLpEvent_BridgeError = 21, // Bridge Error + XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt }; struct XmPciLpEvent_BusInterrupt { @@ -71,43 +70,6 @@ struct XmPciLpEvent { }; static void intReceived(struct XmPciLpEvent *eventParm, - struct pt_regs *regsParm); - -static void XmPciLpEvent_handler(struct HvLpEvent *eventParm, - struct pt_regs *regsParm) -{ -#ifdef CONFIG_PCI -#if 0 - PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n", - eventParm->xType); -#endif - ++Pci_Event_Count; - - if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) { - switch (eventParm->xFlags.xFunction) { - case HvLpEvent_Function_Int: - intReceived((struct XmPciLpEvent *)eventParm, regsParm); - break; - case HvLpEvent_Function_Ack: - printk(KERN_ERR - "XmPciLpEvent.c: unexpected ack received\n"); - break; - default: - printk(KERN_ERR - "XmPciLpEvent.c: unexpected event function %d\n", - (int)eventParm->xFlags.xFunction); - break; - } - } else if (eventParm) - printk(KERN_ERR - "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n", - (int)eventParm->xType); - else - printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n"); -#endif -} - -static void intReceived(struct XmPciLpEvent *eventParm, struct pt_regs *regsParm) { int irq; @@ -164,6 +126,39 @@ static void intReceived(struct XmPciLpEvent *eventParm, } } +static void XmPciLpEvent_handler(struct HvLpEvent *eventParm, + struct pt_regs *regsParm) +{ +#ifdef CONFIG_PCI +#if 0 + PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n", + eventParm->xType); +#endif + ++Pci_Event_Count; + + if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) { + switch (eventParm->xFlags.xFunction) { + case HvLpEvent_Function_Int: + intReceived((struct XmPciLpEvent *)eventParm, regsParm); + break; + case HvLpEvent_Function_Ack: + printk(KERN_ERR + "XmPciLpEvent.c: unexpected ack received\n"); + break; + default: + printk(KERN_ERR + "XmPciLpEvent.c: unexpected event function %d\n", + (int)eventParm->xFlags.xFunction); + break; + } + } else if (eventParm) + printk(KERN_ERR + "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n", + (int)eventParm->xType); + else + printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n"); +#endif +} /* This should be called sometime prior to buswalk (init_IRQ would be good) */ int XmPciLpEvent_init() @@ -179,12 +174,10 @@ int XmPciLpEvent_init() if (xRc == 0) { xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); if (xRc != 0) - printk(KERN_ERR - "XmPciLpEvent.c: open event path failed with rc 0x%x\n", - xRc); + printk(KERN_ERR "XmPciLpEvent.c: open event path " + "failed with rc 0x%x\n", xRc); } else - printk(KERN_ERR - "XmPciLpEvent.c: register handler failed with rc 0x%x\n", - xRc); + printk(KERN_ERR "XmPciLpEvent.c: register handler " + "failed with rc 0x%x\n", xRc); return xRc; } diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c index f831d259dbb..41902e358e7 100644 --- a/arch/ppc64/kernel/iSeries_irq.c +++ b/arch/ppc64/kernel/iSeries_irq.c @@ -1,27 +1,27 @@ -/************************************************************************/ -/* This module supports the iSeries PCI bus interrupt handling */ -/* Copyright (C) 20yy <Robert L Holtorf> <IBM Corp> */ -/* */ -/* 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 */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the: */ -/* Free Software Foundation, Inc., */ -/* 59 Temple Place, Suite 330, */ -/* Boston, MA 02111-1307 USA */ -/************************************************************************/ -/* Change Activity: */ -/* Created, December 13, 2000 by Wayne Holm */ -/* End Change Activity */ -/************************************************************************/ +/* + * This module supports the iSeries PCI bus interrupt handling + * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + * Change Activity: + * Created, December 13, 2000 by Wayne Holm + * End Change Activity + */ #include <linux/pci.h> #include <linux/init.h> #include <linux/threads.h> @@ -38,22 +38,6 @@ #include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/HvCallXm.h> #include <asm/iSeries/iSeries_irq.h> -#include <asm/iSeries/XmPciLpEvent.h> - -static unsigned int iSeries_startup_IRQ(unsigned int irq); -static void iSeries_shutdown_IRQ(unsigned int irq); -static void iSeries_enable_IRQ(unsigned int irq); -static void iSeries_disable_IRQ(unsigned int irq); -static void iSeries_end_IRQ(unsigned int irq); - -static hw_irq_controller iSeries_IRQ_handler = { - .typename = "iSeries irq controller", - .startup = iSeries_startup_IRQ, - .shutdown = iSeries_shutdown_IRQ, - .enable = iSeries_enable_IRQ, - .disable = iSeries_disable_IRQ, - .end = iSeries_end_IRQ -}; /* This maps virtual irq numbers to real irqs */ unsigned int virt_irq_to_real_map[NR_IRQS]; @@ -69,30 +53,32 @@ void __init iSeries_init_IRQ(void) XmPciLpEvent_init(); } +#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) +#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) +#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7) + /* - * 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). + * This will be called by device drivers (via enable_IRQ) + * to enable INTA in the bridge interrupt status register. */ -int __init iSeries_allocate_IRQ(HvBusNumber busNumber, - HvSubBusNumber subBusNumber, HvAgentId deviceId) +static void iSeries_enable_IRQ(unsigned int irq) { - unsigned int realirq, virtirq; - u8 idsel = (deviceId >> 4); - u8 function = deviceId & 7; + u32 bus, deviceId, function, mask; + const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; - virtirq = next_virtual_irq++; - realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; - virt_irq_to_real_map[virtirq] = realirq; + /* The IRQ has already been locked by the caller */ + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; - irq_desc[virtirq].handler = &iSeries_IRQ_handler; - return virtirq; + /* 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); } -#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) -#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) -#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7) - /* This is called by iSeries_activate_IRQs */ static unsigned int iSeries_startup_IRQ(unsigned int irq) { @@ -131,7 +117,7 @@ void __init iSeries_activate_IRQs() desc->handler->startup(irq); spin_unlock_irqrestore(&desc->lock, flags); } - } + } } /* this is not called anywhere currently */ @@ -173,29 +159,7 @@ static void iSeries_disable_IRQ(unsigned int irq) 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); -} - -/* - * This will be called by device drivers (via enable_IRQ) - * to enable INTA in the bridge interrupt status register. - */ -static void iSeries_enable_IRQ(unsigned int irq) -{ - u32 bus, deviceId, function, mask; - const u32 subBus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; - - /* The IRQ has already been locked by the caller */ - bus = REAL_IRQ_TO_BUS(rirq); - function = REAL_IRQ_TO_FUNC(rirq); - deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 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); + bus, subBus, deviceId, irq); } /* @@ -207,3 +171,32 @@ static void iSeries_enable_IRQ(unsigned int irq) static void iSeries_end_IRQ(unsigned int irq) { } + +static hw_irq_controller iSeries_IRQ_handler = { + .typename = "iSeries irq controller", + .startup = iSeries_startup_IRQ, + .shutdown = iSeries_shutdown_IRQ, + .enable = iSeries_enable_IRQ, + .disable = iSeries_disable_IRQ, + .end = iSeries_end_IRQ +}; + +/* + * 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) +{ + unsigned int realirq, virtirq; + u8 idsel = (deviceId >> 4); + u8 function = deviceId & 7; + + virtirq = next_virtual_irq++; + realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; + virt_irq_to_real_map[virtirq] = realirq; + + irq_desc[virtirq].handler = &iSeries_IRQ_handler; + return virtirq; +} |