aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ppc64/kernel/Makefile2
-rw-r--r--arch/ppc64/kernel/XmPciLpEvent.c183
-rw-r--r--arch/ppc64/kernel/iSeries_irq.c170
3 files changed, 169 insertions, 186 deletions
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index ada9be84ddee..ebf9b3cbf33d 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -21,7 +21,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o
21 21
22obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) 22obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y)
23 23
24obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o XmPciLpEvent.o \ 24obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
25 HvCall.o HvLpConfig.o LparData.o \ 25 HvCall.o HvLpConfig.o LparData.o \
26 iSeries_setup.o ItLpQueue.o hvCall.o \ 26 iSeries_setup.o ItLpQueue.o hvCall.o \
27 mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ 27 mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
diff --git a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c
deleted file mode 100644
index 3db530744831..000000000000
--- a/arch/ppc64/kernel/XmPciLpEvent.c
+++ /dev/null
@@ -1,183 +0,0 @@
1/*
2 * File XmPciLpEvent.c created by Wayne Holm on Mon Jan 15 2001.
3 *
4 * This module handles PCI interrupt events sent by the iSeries Hypervisor.
5 */
6#include <linux/config.h>
7#include <linux/pci.h>
8#include <linux/init.h>
9#include <linux/threads.h>
10#include <linux/smp.h>
11#include <linux/param.h>
12#include <linux/string.h>
13#include <linux/bootmem.h>
14#include <linux/ide.h>
15
16#include <asm/iSeries/HvTypes.h>
17#include <asm/iSeries/HvLpEvent.h>
18#include <asm/iSeries/HvCallPci.h>
19#include <asm/iSeries/iSeries_irq.h>
20#include <asm/ppcdebug.h>
21
22static long Pci_Interrupt_Count;
23static long Pci_Event_Count;
24
25enum XmPciLpEvent_Subtype {
26 XmPciLpEvent_BusCreated = 0, // PHB has been created
27 XmPciLpEvent_BusError = 1, // PHB has failed
28 XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
29 XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
30 XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
31 XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
32 XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
33 XmPciLpEvent_BridgeError = 21, // Bridge Error
34 XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
35};
36
37struct XmPciLpEvent_BusInterrupt {
38 HvBusNumber busNumber;
39 HvSubBusNumber subBusNumber;
40};
41
42struct XmPciLpEvent_NodeInterrupt {
43 HvBusNumber busNumber;
44 HvSubBusNumber subBusNumber;
45 HvAgentId deviceId;
46};
47
48struct XmPciLpEvent {
49 struct HvLpEvent hvLpEvent;
50
51 union {
52 u64 alignData; // Align on an 8-byte boundary
53
54 struct {
55 u32 fisr;
56 HvBusNumber busNumber;
57 HvSubBusNumber subBusNumber;
58 HvAgentId deviceId;
59 } slotInterrupt;
60
61 struct XmPciLpEvent_BusInterrupt busFailed;
62 struct XmPciLpEvent_BusInterrupt busRecovered;
63 struct XmPciLpEvent_BusInterrupt busCreated;
64
65 struct XmPciLpEvent_NodeInterrupt nodeFailed;
66 struct XmPciLpEvent_NodeInterrupt nodeRecovered;
67
68 } eventData;
69
70};
71
72static void intReceived(struct XmPciLpEvent *eventParm,
73 struct pt_regs *regsParm)
74{
75 int irq;
76
77 ++Pci_Interrupt_Count;
78#if 0
79 PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n");
80#endif
81
82 switch (eventParm->hvLpEvent.xSubtype) {
83 case XmPciLpEvent_SlotInterrupt:
84 irq = eventParm->hvLpEvent.xCorrelationToken;
85 /* Dispatch the interrupt handlers for this irq */
86 ppc_irq_dispatch_handler(regsParm, irq);
87 HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
88 eventParm->eventData.slotInterrupt.subBusNumber,
89 eventParm->eventData.slotInterrupt.deviceId);
90 break;
91 /* Ignore error recovery events for now */
92 case XmPciLpEvent_BusCreated:
93 printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n",
94 eventParm->eventData.busCreated.busNumber);
95 break;
96 case XmPciLpEvent_BusError:
97 case XmPciLpEvent_BusFailed:
98 printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n",
99 eventParm->eventData.busFailed.busNumber);
100 break;
101 case XmPciLpEvent_BusRecovered:
102 case XmPciLpEvent_UnQuiesceBus:
103 printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n",
104 eventParm->eventData.busRecovered.busNumber);
105 break;
106 case XmPciLpEvent_NodeFailed:
107 case XmPciLpEvent_BridgeError:
108 printk(KERN_INFO
109 "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n",
110 eventParm->eventData.nodeFailed.busNumber,
111 eventParm->eventData.nodeFailed.subBusNumber,
112 eventParm->eventData.nodeFailed.deviceId);
113 break;
114 case XmPciLpEvent_NodeRecovered:
115 printk(KERN_INFO
116 "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n",
117 eventParm->eventData.nodeRecovered.busNumber,
118 eventParm->eventData.nodeRecovered.subBusNumber,
119 eventParm->eventData.nodeRecovered.deviceId);
120 break;
121 default:
122 printk(KERN_ERR
123 "XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
124 eventParm->hvLpEvent.xSubtype);
125 break;
126 }
127}
128
129static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
130 struct pt_regs *regsParm)
131{
132#ifdef CONFIG_PCI
133#if 0
134 PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n",
135 eventParm->xType);
136#endif
137 ++Pci_Event_Count;
138
139 if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
140 switch (eventParm->xFlags.xFunction) {
141 case HvLpEvent_Function_Int:
142 intReceived((struct XmPciLpEvent *)eventParm, regsParm);
143 break;
144 case HvLpEvent_Function_Ack:
145 printk(KERN_ERR
146 "XmPciLpEvent.c: unexpected ack received\n");
147 break;
148 default:
149 printk(KERN_ERR
150 "XmPciLpEvent.c: unexpected event function %d\n",
151 (int)eventParm->xFlags.xFunction);
152 break;
153 }
154 } else if (eventParm)
155 printk(KERN_ERR
156 "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",
157 (int)eventParm->xType);
158 else
159 printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
160#endif
161}
162
163/* This should be called sometime prior to buswalk (init_IRQ would be good) */
164int XmPciLpEvent_init()
165{
166 int xRc;
167
168 PPCDBG(PPCDBG_BUSWALK,
169 "XmPciLpEvent_init, Register Event type 0x%04X\n",
170 HvLpEvent_Type_PciIo);
171
172 xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
173 &XmPciLpEvent_handler);
174 if (xRc == 0) {
175 xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
176 if (xRc != 0)
177 printk(KERN_ERR "XmPciLpEvent.c: open event path "
178 "failed with rc 0x%x\n", xRc);
179 } else
180 printk(KERN_ERR "XmPciLpEvent.c: register handler "
181 "failed with rc 0x%x\n", xRc);
182 return xRc;
183}
diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
index 41902e358e76..96a1f8cd67e7 100644
--- a/arch/ppc64/kernel/iSeries_irq.c
+++ b/arch/ppc64/kernel/iSeries_irq.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * This module supports the iSeries PCI bus interrupt handling 2 * This module supports the iSeries PCI bus interrupt handling
3 * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp> 3 * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
4 * Copyright (C) 2004-2005 IBM Corporation
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -22,6 +23,7 @@
22 * Created, December 13, 2000 by Wayne Holm 23 * Created, December 13, 2000 by Wayne Holm
23 * End Change Activity 24 * End Change Activity
24 */ 25 */
26#include <linux/config.h>
25#include <linux/pci.h> 27#include <linux/pci.h>
26#include <linux/init.h> 28#include <linux/init.h>
27#include <linux/threads.h> 29#include <linux/threads.h>
@@ -30,11 +32,12 @@
30#include <linux/string.h> 32#include <linux/string.h>
31#include <linux/bootmem.h> 33#include <linux/bootmem.h>
32#include <linux/ide.h> 34#include <linux/ide.h>
33
34#include <linux/irq.h> 35#include <linux/irq.h>
35#include <linux/spinlock.h> 36#include <linux/spinlock.h>
36#include <asm/ppcdebug.h>
37 37
38#include <asm/ppcdebug.h>
39#include <asm/iSeries/HvTypes.h>
40#include <asm/iSeries/HvLpEvent.h>
38#include <asm/iSeries/HvCallPci.h> 41#include <asm/iSeries/HvCallPci.h>
39#include <asm/iSeries/HvCallXm.h> 42#include <asm/iSeries/HvCallXm.h>
40#include <asm/iSeries/iSeries_irq.h> 43#include <asm/iSeries/iSeries_irq.h>
@@ -46,6 +49,169 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
46/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ 49/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */
47static int next_virtual_irq = 2; 50static int next_virtual_irq = 2;
48 51
52static long Pci_Interrupt_Count;
53static long Pci_Event_Count;
54
55enum XmPciLpEvent_Subtype {
56 XmPciLpEvent_BusCreated = 0, // PHB has been created
57 XmPciLpEvent_BusError = 1, // PHB has failed
58 XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
59 XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
60 XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
61 XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
62 XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
63 XmPciLpEvent_BridgeError = 21, // Bridge Error
64 XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
65};
66
67struct XmPciLpEvent_BusInterrupt {
68 HvBusNumber busNumber;
69 HvSubBusNumber subBusNumber;
70};
71
72struct XmPciLpEvent_NodeInterrupt {
73 HvBusNumber busNumber;
74 HvSubBusNumber subBusNumber;
75 HvAgentId deviceId;
76};
77
78struct XmPciLpEvent {
79 struct HvLpEvent hvLpEvent;
80
81 union {
82 u64 alignData; // Align on an 8-byte boundary
83
84 struct {
85 u32 fisr;
86 HvBusNumber busNumber;
87 HvSubBusNumber subBusNumber;
88 HvAgentId deviceId;
89 } slotInterrupt;
90
91 struct XmPciLpEvent_BusInterrupt busFailed;
92 struct XmPciLpEvent_BusInterrupt busRecovered;
93 struct XmPciLpEvent_BusInterrupt busCreated;
94
95 struct XmPciLpEvent_NodeInterrupt nodeFailed;
96 struct XmPciLpEvent_NodeInterrupt nodeRecovered;
97
98 } eventData;
99
100};
101
102static void intReceived(struct XmPciLpEvent *eventParm,
103 struct pt_regs *regsParm)
104{
105 int irq;
106
107 ++Pci_Interrupt_Count;
108#if 0
109 PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n");
110#endif
111
112 switch (eventParm->hvLpEvent.xSubtype) {
113 case XmPciLpEvent_SlotInterrupt:
114 irq = eventParm->hvLpEvent.xCorrelationToken;
115 /* Dispatch the interrupt handlers for this irq */
116 ppc_irq_dispatch_handler(regsParm, irq);
117 HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
118 eventParm->eventData.slotInterrupt.subBusNumber,
119 eventParm->eventData.slotInterrupt.deviceId);
120 break;
121 /* Ignore error recovery events for now */
122 case XmPciLpEvent_BusCreated:
123 printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n",
124 eventParm->eventData.busCreated.busNumber);
125 break;
126 case XmPciLpEvent_BusError:
127 case XmPciLpEvent_BusFailed:
128 printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n",
129 eventParm->eventData.busFailed.busNumber);
130 break;
131 case XmPciLpEvent_BusRecovered:
132 case XmPciLpEvent_UnQuiesceBus:
133 printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n",
134 eventParm->eventData.busRecovered.busNumber);
135 break;
136 case XmPciLpEvent_NodeFailed:
137 case XmPciLpEvent_BridgeError:
138 printk(KERN_INFO
139 "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n",
140 eventParm->eventData.nodeFailed.busNumber,
141 eventParm->eventData.nodeFailed.subBusNumber,
142 eventParm->eventData.nodeFailed.deviceId);
143 break;
144 case XmPciLpEvent_NodeRecovered:
145 printk(KERN_INFO
146 "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n",
147 eventParm->eventData.nodeRecovered.busNumber,
148 eventParm->eventData.nodeRecovered.subBusNumber,
149 eventParm->eventData.nodeRecovered.deviceId);
150 break;
151 default:
152 printk(KERN_ERR
153 "XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
154 eventParm->hvLpEvent.xSubtype);
155 break;
156 }
157}
158
159static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
160 struct pt_regs *regsParm)
161{
162#ifdef CONFIG_PCI
163#if 0
164 PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n",
165 eventParm->xType);
166#endif
167 ++Pci_Event_Count;
168
169 if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
170 switch (eventParm->xFlags.xFunction) {
171 case HvLpEvent_Function_Int:
172 intReceived((struct XmPciLpEvent *)eventParm, regsParm);
173 break;
174 case HvLpEvent_Function_Ack:
175 printk(KERN_ERR
176 "XmPciLpEvent.c: unexpected ack received\n");
177 break;
178 default:
179 printk(KERN_ERR
180 "XmPciLpEvent.c: unexpected event function %d\n",
181 (int)eventParm->xFlags.xFunction);
182 break;
183 }
184 } else if (eventParm)
185 printk(KERN_ERR
186 "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",
187 (int)eventParm->xType);
188 else
189 printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
190#endif
191}
192
193/* This should be called sometime prior to buswalk (init_IRQ would be good) */
194int XmPciLpEvent_init()
195{
196 int xRc;
197
198 PPCDBG(PPCDBG_BUSWALK,
199 "XmPciLpEvent_init, Register Event type 0x%04X\n",
200 HvLpEvent_Type_PciIo);
201
202 xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
203 &XmPciLpEvent_handler);
204 if (xRc == 0) {
205 xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
206 if (xRc != 0)
207 printk(KERN_ERR "XmPciLpEvent.c: open event path "
208 "failed with rc 0x%x\n", xRc);
209 } else
210 printk(KERN_ERR "XmPciLpEvent.c: register handler "
211 "failed with rc 0x%x\n", xRc);
212 return xRc;
213}
214
49/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ 215/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */
50void __init iSeries_init_IRQ(void) 216void __init iSeries_init_IRQ(void)
51{ 217{