aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/iseries/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/iseries/irq.c')
-rw-r--r--arch/powerpc/platforms/iseries/irq.c110
1 files changed, 66 insertions, 44 deletions
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 62bbbcf5ded3..2275e64f3152 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -23,7 +23,6 @@
23 * Created, December 13, 2000 by Wayne Holm 23 * Created, December 13, 2000 by Wayne Holm
24 * End Change Activity 24 * End Change Activity
25 */ 25 */
26#include <linux/config.h>
27#include <linux/pci.h> 26#include <linux/pci.h>
28#include <linux/init.h> 27#include <linux/init.h>
29#include <linux/threads.h> 28#include <linux/threads.h>
@@ -163,27 +162,6 @@ static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs)
163 printk(KERN_ERR "pci_event_handler: NULL event received\n"); 162 printk(KERN_ERR "pci_event_handler: NULL event received\n");
164} 163}
165 164
166/*
167 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
168 * It must be called before the bus walk.
169 */
170void __init iSeries_init_IRQ(void)
171{
172 /* Register PCI event handler and open an event path */
173 int ret;
174
175 ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
176 &pci_event_handler);
177 if (ret == 0) {
178 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
179 if (ret != 0)
180 printk(KERN_ERR "iseries_init_IRQ: open event path "
181 "failed with rc 0x%x\n", ret);
182 } else
183 printk(KERN_ERR "iseries_init_IRQ: register handler "
184 "failed with rc 0x%x\n", ret);
185}
186
187#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff) 165#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
188#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) 166#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
189#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) 167#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
@@ -197,7 +175,7 @@ static void iseries_enable_IRQ(unsigned int irq)
197{ 175{
198 u32 bus, dev_id, function, mask; 176 u32 bus, dev_id, function, mask;
199 const u32 sub_bus = 0; 177 const u32 sub_bus = 0;
200 unsigned int rirq = virt_irq_to_real_map[irq]; 178 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
201 179
202 /* The IRQ has already been locked by the caller */ 180 /* The IRQ has already been locked by the caller */
203 bus = REAL_IRQ_TO_BUS(rirq); 181 bus = REAL_IRQ_TO_BUS(rirq);
@@ -214,7 +192,7 @@ static unsigned int iseries_startup_IRQ(unsigned int irq)
214{ 192{
215 u32 bus, dev_id, function, mask; 193 u32 bus, dev_id, function, mask;
216 const u32 sub_bus = 0; 194 const u32 sub_bus = 0;
217 unsigned int rirq = virt_irq_to_real_map[irq]; 195 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
218 196
219 bus = REAL_IRQ_TO_BUS(rirq); 197 bus = REAL_IRQ_TO_BUS(rirq);
220 function = REAL_IRQ_TO_FUNC(rirq); 198 function = REAL_IRQ_TO_FUNC(rirq);
@@ -242,9 +220,9 @@ void __init iSeries_activate_IRQs()
242 for_each_irq (irq) { 220 for_each_irq (irq) {
243 irq_desc_t *desc = get_irq_desc(irq); 221 irq_desc_t *desc = get_irq_desc(irq);
244 222
245 if (desc && desc->handler && desc->handler->startup) { 223 if (desc && desc->chip && desc->chip->startup) {
246 spin_lock_irqsave(&desc->lock, flags); 224 spin_lock_irqsave(&desc->lock, flags);
247 desc->handler->startup(irq); 225 desc->chip->startup(irq);
248 spin_unlock_irqrestore(&desc->lock, flags); 226 spin_unlock_irqrestore(&desc->lock, flags);
249 } 227 }
250 } 228 }
@@ -255,7 +233,7 @@ static void iseries_shutdown_IRQ(unsigned int irq)
255{ 233{
256 u32 bus, dev_id, function, mask; 234 u32 bus, dev_id, function, mask;
257 const u32 sub_bus = 0; 235 const u32 sub_bus = 0;
258 unsigned int rirq = virt_irq_to_real_map[irq]; 236 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
259 237
260 /* irq should be locked by the caller */ 238 /* irq should be locked by the caller */
261 bus = REAL_IRQ_TO_BUS(rirq); 239 bus = REAL_IRQ_TO_BUS(rirq);
@@ -278,7 +256,7 @@ static void iseries_disable_IRQ(unsigned int irq)
278{ 256{
279 u32 bus, dev_id, function, mask; 257 u32 bus, dev_id, function, mask;
280 const u32 sub_bus = 0; 258 const u32 sub_bus = 0;
281 unsigned int rirq = virt_irq_to_real_map[irq]; 259 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
282 260
283 /* The IRQ has already been locked by the caller */ 261 /* The IRQ has already been locked by the caller */
284 bus = REAL_IRQ_TO_BUS(rirq); 262 bus = REAL_IRQ_TO_BUS(rirq);
@@ -292,19 +270,19 @@ static void iseries_disable_IRQ(unsigned int irq)
292 270
293static void iseries_end_IRQ(unsigned int irq) 271static void iseries_end_IRQ(unsigned int irq)
294{ 272{
295 unsigned int rirq = virt_irq_to_real_map[irq]; 273 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
296 274
297 HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq), 275 HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
298 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); 276 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
299} 277}
300 278
301static hw_irq_controller iSeries_IRQ_handler = { 279static struct irq_chip iseries_pic = {
302 .typename = "iSeries irq controller", 280 .typename = "iSeries irq controller",
303 .startup = iseries_startup_IRQ, 281 .startup = iseries_startup_IRQ,
304 .shutdown = iseries_shutdown_IRQ, 282 .shutdown = iseries_shutdown_IRQ,
305 .enable = iseries_enable_IRQ, 283 .unmask = iseries_enable_IRQ,
306 .disable = iseries_disable_IRQ, 284 .mask = iseries_disable_IRQ,
307 .end = iseries_end_IRQ 285 .eoi = iseries_end_IRQ
308}; 286};
309 287
310/* 288/*
@@ -315,17 +293,14 @@ static hw_irq_controller iSeries_IRQ_handler = {
315int __init iSeries_allocate_IRQ(HvBusNumber bus, 293int __init iSeries_allocate_IRQ(HvBusNumber bus,
316 HvSubBusNumber sub_bus, u32 bsubbus) 294 HvSubBusNumber sub_bus, u32 bsubbus)
317{ 295{
318 int virtirq;
319 unsigned int realirq; 296 unsigned int realirq;
320 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); 297 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
321 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); 298 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
322 299
323 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) 300 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
324 + function; 301 + function;
325 virtirq = virt_irq_create_mapping(realirq);
326 302
327 irq_desc[virtirq].handler = &iSeries_IRQ_handler; 303 return irq_create_mapping(NULL, realirq, IRQ_TYPE_NONE);
328 return virtirq;
329} 304}
330 305
331#endif /* CONFIG_PCI */ 306#endif /* CONFIG_PCI */
@@ -333,10 +308,9 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
333/* 308/*
334 * Get the next pending IRQ. 309 * Get the next pending IRQ.
335 */ 310 */
336int iSeries_get_irq(struct pt_regs *regs) 311unsigned int iSeries_get_irq(struct pt_regs *regs)
337{ 312{
338 /* -2 means ignore this interrupt */ 313 int irq = NO_IRQ_IGNORE;
339 int irq = -2;
340 314
341#ifdef CONFIG_SMP 315#ifdef CONFIG_SMP
342 if (get_lppaca()->int_dword.fields.ipi_cnt) { 316 if (get_lppaca()->int_dword.fields.ipi_cnt) {
@@ -359,9 +333,57 @@ int iSeries_get_irq(struct pt_regs *regs)
359 } 333 }
360 spin_unlock(&pending_irqs_lock); 334 spin_unlock(&pending_irqs_lock);
361 if (irq >= NR_IRQS) 335 if (irq >= NR_IRQS)
362 irq = -2; 336 irq = NO_IRQ_IGNORE;
363 } 337 }
364#endif 338#endif
365 339
366 return irq; 340 return irq;
367} 341}
342
343static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
344 irq_hw_number_t hw, unsigned int flags)
345{
346 set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
347
348 return 0;
349}
350
351static struct irq_host_ops iseries_irq_host_ops = {
352 .map = iseries_irq_host_map,
353};
354
355/*
356 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
357 * It must be called before the bus walk.
358 */
359void __init iSeries_init_IRQ(void)
360{
361 /* Register PCI event handler and open an event path */
362 struct irq_host *host;
363 int ret;
364
365 /*
366 * The Hypervisor only allows us up to 256 interrupt
367 * sources (the irq number is passed in a u8).
368 */
369 irq_set_virq_count(256);
370
371 /* Create irq host. No need for a revmap since HV will give us
372 * back our virtual irq number
373 */
374 host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0);
375 BUG_ON(host == NULL);
376 irq_set_default_host(host);
377
378 ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
379 &pci_event_handler);
380 if (ret == 0) {
381 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
382 if (ret != 0)
383 printk(KERN_ERR "iseries_init_IRQ: open event path "
384 "failed with rc 0x%x\n", ret);
385 } else
386 printk(KERN_ERR "iseries_init_IRQ: register handler "
387 "failed with rc 0x%x\n", ret);
388}
389