[PATCH] ps3: missing exports
[linux-2.6] / arch / powerpc / platforms / iseries / irq.c
1 /*
2  * This module supports the iSeries PCI bus interrupt handling
3  * Copyright (C) 20yy  <Robert L Holtorf> <IBM Corp>
4  * Copyright (C) 2004-2005 IBM Corporation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the:
18  * Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330,
20  * Boston, MA  02111-1307  USA
21  *
22  * Change Activity:
23  *   Created, December 13, 2000 by Wayne Holm
24  * End Change Activity
25  */
26 #include <linux/pci.h>
27 #include <linux/init.h>
28 #include <linux/threads.h>
29 #include <linux/smp.h>
30 #include <linux/param.h>
31 #include <linux/string.h>
32 #include <linux/bootmem.h>
33 #include <linux/ide.h>
34 #include <linux/irq.h>
35 #include <linux/spinlock.h>
36
37 #include <asm/paca.h>
38 #include <asm/iseries/hv_types.h>
39 #include <asm/iseries/hv_lp_event.h>
40 #include <asm/iseries/hv_call_xm.h>
41 #include <asm/iseries/it_lp_queue.h>
42
43 #include "irq.h"
44 #include "pci.h"
45 #include "call_pci.h"
46 #include "smp.h"
47
48 #ifdef CONFIG_PCI
49
50 enum pci_event_type {
51         pe_bus_created          = 0,    /* PHB has been created */
52         pe_bus_error            = 1,    /* PHB has failed */
53         pe_bus_failed           = 2,    /* Msg to Secondary, Primary failed bus */
54         pe_node_failed          = 4,    /* Multi-adapter bridge has failed */
55         pe_node_recovered       = 5,    /* Multi-adapter bridge has recovered */
56         pe_bus_recovered        = 12,   /* PHB has been recovered */
57         pe_unquiese_bus         = 18,   /* Secondary bus unqiescing */
58         pe_bridge_error         = 21,   /* Bridge Error */
59         pe_slot_interrupt       = 22    /* Slot interrupt */
60 };
61
62 struct pci_event {
63         struct HvLpEvent event;
64         union {
65                 u64 __align;            /* Align on an 8-byte boundary */
66                 struct {
67                         u32             fisr;
68                         HvBusNumber     bus_number;
69                         HvSubBusNumber  sub_bus_number;
70                         HvAgentId       dev_id;
71                 } slot;
72                 struct {
73                         HvBusNumber     bus_number;
74                         HvSubBusNumber  sub_bus_number;
75                 } bus;
76                 struct {
77                         HvBusNumber     bus_number;
78                         HvSubBusNumber  sub_bus_number;
79                         HvAgentId       dev_id;
80                 } node;
81         } data;
82 };
83
84 static DEFINE_SPINLOCK(pending_irqs_lock);
85 static int num_pending_irqs;
86 static int pending_irqs[NR_IRQS];
87
88 static void int_received(struct pci_event *event)
89 {
90         int irq;
91
92         switch (event->event.xSubtype) {
93         case pe_slot_interrupt:
94                 irq = event->event.xCorrelationToken;
95                 if (irq < NR_IRQS) {
96                         spin_lock(&pending_irqs_lock);
97                         pending_irqs[irq]++;
98                         num_pending_irqs++;
99                         spin_unlock(&pending_irqs_lock);
100                 } else {
101                         printk(KERN_WARNING "int_received: bad irq number %d\n",
102                                         irq);
103                         HvCallPci_eoi(event->data.slot.bus_number,
104                                         event->data.slot.sub_bus_number,
105                                         event->data.slot.dev_id);
106                 }
107                 break;
108                 /* Ignore error recovery events for now */
109         case pe_bus_created:
110                 printk(KERN_INFO "int_received: system bus %d created\n",
111                         event->data.bus.bus_number);
112                 break;
113         case pe_bus_error:
114         case pe_bus_failed:
115                 printk(KERN_INFO "int_received: system bus %d failed\n",
116                         event->data.bus.bus_number);
117                 break;
118         case pe_bus_recovered:
119         case pe_unquiese_bus:
120                 printk(KERN_INFO "int_received: system bus %d recovered\n",
121                         event->data.bus.bus_number);
122                 break;
123         case pe_node_failed:
124         case pe_bridge_error:
125                 printk(KERN_INFO
126                         "int_received: multi-adapter bridge %d/%d/%d failed\n",
127                         event->data.node.bus_number,
128                         event->data.node.sub_bus_number,
129                         event->data.node.dev_id);
130                 break;
131         case pe_node_recovered:
132                 printk(KERN_INFO
133                         "int_received: multi-adapter bridge %d/%d/%d recovered\n",
134                         event->data.node.bus_number,
135                         event->data.node.sub_bus_number,
136                         event->data.node.dev_id);
137                 break;
138         default:
139                 printk(KERN_ERR
140                         "int_received: unrecognized event subtype 0x%x\n",
141                         event->event.xSubtype);
142                 break;
143         }
144 }
145
146 static void pci_event_handler(struct HvLpEvent *event)
147 {
148         if (event && (event->xType == HvLpEvent_Type_PciIo)) {
149                 if (hvlpevent_is_int(event))
150                         int_received((struct pci_event *)event);
151                 else
152                         printk(KERN_ERR
153                                 "pci_event_handler: unexpected ack received\n");
154         } else if (event)
155                 printk(KERN_ERR
156                         "pci_event_handler: Unrecognized PCI event type 0x%x\n",
157                         (int)event->xType);
158         else
159                 printk(KERN_ERR "pci_event_handler: NULL event received\n");
160 }
161
162 #define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
163 #define REAL_IRQ_TO_BUS(irq)    ((((irq) >> 6) & 0xff) + 1)
164 #define REAL_IRQ_TO_IDSEL(irq)  ((((irq) >> 3) & 7) + 1)
165 #define REAL_IRQ_TO_FUNC(irq)   ((irq) & 7)
166
167 /*
168  * This will be called by device drivers (via enable_IRQ)
169  * to enable INTA in the bridge interrupt status register.
170  */
171 static void iseries_enable_IRQ(unsigned int irq)
172 {
173         u32 bus, dev_id, function, mask;
174         const u32 sub_bus = 0;
175         unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
176
177         /* The IRQ has already been locked by the caller */
178         bus = REAL_IRQ_TO_BUS(rirq);
179         function = REAL_IRQ_TO_FUNC(rirq);
180         dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
181
182         /* Unmask secondary INTA */
183         mask = 0x80000000;
184         HvCallPci_unmaskInterrupts(bus, sub_bus, dev_id, mask);
185 }
186
187 /* This is called by iseries_activate_IRQs */
188 static unsigned int iseries_startup_IRQ(unsigned int irq)
189 {
190         u32 bus, dev_id, function, mask;
191         const u32 sub_bus = 0;
192         unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
193
194         bus = REAL_IRQ_TO_BUS(rirq);
195         function = REAL_IRQ_TO_FUNC(rirq);
196         dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
197
198         /* Link the IRQ number to the bridge */
199         HvCallXm_connectBusUnit(bus, sub_bus, dev_id, irq);
200
201         /* Unmask bridge interrupts in the FISR */
202         mask = 0x01010000 << function;
203         HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask);
204         iseries_enable_IRQ(irq);
205         return 0;
206 }
207
208 /*
209  * This is called out of iSeries_fixup to activate interrupt
210  * generation for usable slots
211  */
212 void __init iSeries_activate_IRQs()
213 {
214         int irq;
215         unsigned long flags;
216
217         for_each_irq (irq) {
218                 irq_desc_t *desc = get_irq_desc(irq);
219
220                 if (desc && desc->chip && desc->chip->startup) {
221                         spin_lock_irqsave(&desc->lock, flags);
222                         desc->chip->startup(irq);
223                         spin_unlock_irqrestore(&desc->lock, flags);
224                 }
225         }
226 }
227
228 /*  this is not called anywhere currently */
229 static void iseries_shutdown_IRQ(unsigned int irq)
230 {
231         u32 bus, dev_id, function, mask;
232         const u32 sub_bus = 0;
233         unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
234
235         /* irq should be locked by the caller */
236         bus = REAL_IRQ_TO_BUS(rirq);
237         function = REAL_IRQ_TO_FUNC(rirq);
238         dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
239
240         /* Invalidate the IRQ number in the bridge */
241         HvCallXm_connectBusUnit(bus, sub_bus, dev_id, 0);
242
243         /* Mask bridge interrupts in the FISR */
244         mask = 0x01010000 << function;
245         HvCallPci_maskFisr(bus, sub_bus, dev_id, mask);
246 }
247
248 /*
249  * This will be called by device drivers (via disable_IRQ)
250  * to disable INTA in the bridge interrupt status register.
251  */
252 static void iseries_disable_IRQ(unsigned int irq)
253 {
254         u32 bus, dev_id, function, mask;
255         const u32 sub_bus = 0;
256         unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
257
258         /* The IRQ has already been locked by the caller */
259         bus = REAL_IRQ_TO_BUS(rirq);
260         function = REAL_IRQ_TO_FUNC(rirq);
261         dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
262
263         /* Mask secondary INTA   */
264         mask = 0x80000000;
265         HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask);
266 }
267
268 static void iseries_end_IRQ(unsigned int irq)
269 {
270         unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
271
272         HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
273                 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
274 }
275
276 static struct irq_chip iseries_pic = {
277         .typename       = "iSeries irq controller",
278         .startup        = iseries_startup_IRQ,
279         .shutdown       = iseries_shutdown_IRQ,
280         .unmask         = iseries_enable_IRQ,
281         .mask           = iseries_disable_IRQ,
282         .eoi            = iseries_end_IRQ
283 };
284
285 /*
286  * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
287  * It calculates the irq value for the slot.
288  * Note that sub_bus is always 0 (at the moment at least).
289  */
290 int __init iSeries_allocate_IRQ(HvBusNumber bus,
291                 HvSubBusNumber sub_bus, u32 bsubbus)
292 {
293         unsigned int realirq;
294         u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
295         u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
296
297         realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
298                 + function;
299
300         return irq_create_mapping(NULL, realirq);
301 }
302
303 #endif /* CONFIG_PCI */
304
305 /*
306  * Get the next pending IRQ.
307  */
308 unsigned int iSeries_get_irq(void)
309 {
310         int irq = NO_IRQ_IGNORE;
311
312 #ifdef CONFIG_SMP
313         if (get_lppaca()->int_dword.fields.ipi_cnt) {
314                 get_lppaca()->int_dword.fields.ipi_cnt = 0;
315                 iSeries_smp_message_recv();
316         }
317 #endif /* CONFIG_SMP */
318         if (hvlpevent_is_pending())
319                 process_hvlpevents();
320
321 #ifdef CONFIG_PCI
322         if (num_pending_irqs) {
323                 spin_lock(&pending_irqs_lock);
324                 for (irq = 0; irq < NR_IRQS; irq++) {
325                         if (pending_irqs[irq]) {
326                                 pending_irqs[irq]--;
327                                 num_pending_irqs--;
328                                 break;
329                         }
330                 }
331                 spin_unlock(&pending_irqs_lock);
332                 if (irq >= NR_IRQS)
333                         irq = NO_IRQ_IGNORE;
334         }
335 #endif
336
337         return irq;
338 }
339
340 static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
341                                 irq_hw_number_t hw)
342 {
343         set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
344
345         return 0;
346 }
347
348 static struct irq_host_ops iseries_irq_host_ops = {
349         .map = iseries_irq_host_map,
350 };
351
352 /*
353  * This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c
354  * It must be called before the bus walk.
355  */
356 void __init iSeries_init_IRQ(void)
357 {
358         /* Register PCI event handler and open an event path */
359         struct irq_host *host;
360         int ret;
361
362         /*
363          * The Hypervisor only allows us up to 256 interrupt
364          * sources (the irq number is passed in a u8).
365          */
366         irq_set_virq_count(256);
367
368         /* Create irq host. No need for a revmap since HV will give us
369          * back our virtual irq number
370          */
371         host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0);
372         BUG_ON(host == NULL);
373         irq_set_default_host(host);
374
375         ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
376                         &pci_event_handler);
377         if (ret == 0) {
378                 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
379                 if (ret != 0)
380                         printk(KERN_ERR "iseries_init_IRQ: open event path "
381                                         "failed with rc 0x%x\n", ret);
382         } else
383                 printk(KERN_ERR "iseries_init_IRQ: register handler "
384                                 "failed with rc 0x%x\n", ret);
385 }
386