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.c105
1 files changed, 64 insertions, 41 deletions
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index f70e820e7304..2275e64f3152 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -162,27 +162,6 @@ static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs)
162 printk(KERN_ERR "pci_event_handler: NULL event received\n"); 162 printk(KERN_ERR "pci_event_handler: NULL event received\n");
163} 163}
164 164
165/*
166 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
167 * It must be called before the bus walk.
168 */
169void __init iSeries_init_IRQ(void)
170{
171 /* Register PCI event handler and open an event path */
172 int ret;
173
174 ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
175 &pci_event_handler);
176 if (ret == 0) {
177 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
178 if (ret != 0)
179 printk(KERN_ERR "iseries_init_IRQ: open event path "
180 "failed with rc 0x%x\n", ret);
181 } else
182 printk(KERN_ERR "iseries_init_IRQ: register handler "
183 "failed with rc 0x%x\n", ret);
184}
185
186#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff) 165#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
187#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) 166#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
188#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) 167#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
@@ -196,7 +175,7 @@ static void iseries_enable_IRQ(unsigned int irq)
196{ 175{
197 u32 bus, dev_id, function, mask; 176 u32 bus, dev_id, function, mask;
198 const u32 sub_bus = 0; 177 const u32 sub_bus = 0;
199 unsigned int rirq = virt_irq_to_real_map[irq]; 178 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
200 179
201 /* The IRQ has already been locked by the caller */ 180 /* The IRQ has already been locked by the caller */
202 bus = REAL_IRQ_TO_BUS(rirq); 181 bus = REAL_IRQ_TO_BUS(rirq);
@@ -213,7 +192,7 @@ static unsigned int iseries_startup_IRQ(unsigned int irq)
213{ 192{
214 u32 bus, dev_id, function, mask; 193 u32 bus, dev_id, function, mask;
215 const u32 sub_bus = 0; 194 const u32 sub_bus = 0;
216 unsigned int rirq = virt_irq_to_real_map[irq]; 195 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
217 196
218 bus = REAL_IRQ_TO_BUS(rirq); 197 bus = REAL_IRQ_TO_BUS(rirq);
219 function = REAL_IRQ_TO_FUNC(rirq); 198 function = REAL_IRQ_TO_FUNC(rirq);
@@ -254,7 +233,7 @@ static void iseries_shutdown_IRQ(unsigned int irq)
254{ 233{
255 u32 bus, dev_id, function, mask; 234 u32 bus, dev_id, function, mask;
256 const u32 sub_bus = 0; 235 const u32 sub_bus = 0;
257 unsigned int rirq = virt_irq_to_real_map[irq]; 236 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
258 237
259 /* irq should be locked by the caller */ 238 /* irq should be locked by the caller */
260 bus = REAL_IRQ_TO_BUS(rirq); 239 bus = REAL_IRQ_TO_BUS(rirq);
@@ -277,7 +256,7 @@ static void iseries_disable_IRQ(unsigned int irq)
277{ 256{
278 u32 bus, dev_id, function, mask; 257 u32 bus, dev_id, function, mask;
279 const u32 sub_bus = 0; 258 const u32 sub_bus = 0;
280 unsigned int rirq = virt_irq_to_real_map[irq]; 259 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
281 260
282 /* The IRQ has already been locked by the caller */ 261 /* The IRQ has already been locked by the caller */
283 bus = REAL_IRQ_TO_BUS(rirq); 262 bus = REAL_IRQ_TO_BUS(rirq);
@@ -291,19 +270,19 @@ static void iseries_disable_IRQ(unsigned int irq)
291 270
292static void iseries_end_IRQ(unsigned int irq) 271static void iseries_end_IRQ(unsigned int irq)
293{ 272{
294 unsigned int rirq = virt_irq_to_real_map[irq]; 273 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
295 274
296 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),
297 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); 276 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
298} 277}
299 278
300static hw_irq_controller iSeries_IRQ_handler = { 279static struct irq_chip iseries_pic = {
301 .typename = "iSeries irq controller", 280 .typename = "iSeries irq controller",
302 .startup = iseries_startup_IRQ, 281 .startup = iseries_startup_IRQ,
303 .shutdown = iseries_shutdown_IRQ, 282 .shutdown = iseries_shutdown_IRQ,
304 .enable = iseries_enable_IRQ, 283 .unmask = iseries_enable_IRQ,
305 .disable = iseries_disable_IRQ, 284 .mask = iseries_disable_IRQ,
306 .end = iseries_end_IRQ 285 .eoi = iseries_end_IRQ
307}; 286};
308 287
309/* 288/*
@@ -314,17 +293,14 @@ static hw_irq_controller iSeries_IRQ_handler = {
314int __init iSeries_allocate_IRQ(HvBusNumber bus, 293int __init iSeries_allocate_IRQ(HvBusNumber bus,
315 HvSubBusNumber sub_bus, u32 bsubbus) 294 HvSubBusNumber sub_bus, u32 bsubbus)
316{ 295{
317 int virtirq;
318 unsigned int realirq; 296 unsigned int realirq;
319 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); 297 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
320 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); 298 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
321 299
322 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) 300 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
323 + function; 301 + function;
324 virtirq = virt_irq_create_mapping(realirq);
325 302
326 irq_desc[virtirq].chip = &iSeries_IRQ_handler; 303 return irq_create_mapping(NULL, realirq, IRQ_TYPE_NONE);
327 return virtirq;
328} 304}
329 305
330#endif /* CONFIG_PCI */ 306#endif /* CONFIG_PCI */
@@ -332,10 +308,9 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
332/* 308/*
333 * Get the next pending IRQ. 309 * Get the next pending IRQ.
334 */ 310 */
335int iSeries_get_irq(struct pt_regs *regs) 311unsigned int iSeries_get_irq(struct pt_regs *regs)
336{ 312{
337 /* -2 means ignore this interrupt */ 313 int irq = NO_IRQ_IGNORE;
338 int irq = -2;
339 314
340#ifdef CONFIG_SMP 315#ifdef CONFIG_SMP
341 if (get_lppaca()->int_dword.fields.ipi_cnt) { 316 if (get_lppaca()->int_dword.fields.ipi_cnt) {
@@ -358,9 +333,57 @@ int iSeries_get_irq(struct pt_regs *regs)
358 } 333 }
359 spin_unlock(&pending_irqs_lock); 334 spin_unlock(&pending_irqs_lock);
360 if (irq >= NR_IRQS) 335 if (irq >= NR_IRQS)
361 irq = -2; 336 irq = NO_IRQ_IGNORE;
362 } 337 }
363#endif 338#endif
364 339
365 return irq; 340 return irq;
366} 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