aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c482
1 files changed, 292 insertions, 190 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e469358895f..7d31d7cc392d 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -100,8 +100,8 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
100 100
101 if (mpic->flags & MPIC_PRIMARY) 101 if (mpic->flags & MPIC_PRIMARY)
102 cpu = hard_smp_processor_id(); 102 cpu = hard_smp_processor_id();
103 103 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,
104 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg); 104 mpic->cpuregs[cpu], reg);
105} 105}
106 106
107static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) 107static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
@@ -340,27 +340,19 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
340#endif /* CONFIG_MPIC_BROKEN_U3 */ 340#endif /* CONFIG_MPIC_BROKEN_U3 */
341 341
342 342
343#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
344
343/* Find an mpic associated with a given linux interrupt */ 345/* Find an mpic associated with a given linux interrupt */
344static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) 346static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
345{ 347{
346 struct mpic *mpic = mpics; 348 unsigned int src = mpic_irq_to_hw(irq);
347 349
348 while(mpic) { 350 if (irq < NUM_ISA_INTERRUPTS)
349 /* search IPIs first since they may override the main interrupts */ 351 return NULL;
350 if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) { 352 if (is_ipi)
351 if (is_ipi) 353 *is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3);
352 *is_ipi = 1; 354
353 return mpic; 355 return irq_desc[irq].chip_data;
354 }
355 if (irq >= mpic->irq_offset &&
356 irq < (mpic->irq_offset + mpic->irq_count)) {
357 if (is_ipi)
358 *is_ipi = 0;
359 return mpic;
360 }
361 mpic = mpic -> next;
362 }
363 return NULL;
364} 356}
365 357
366/* Convert a cpu mask from logical to physical cpu numbers. */ 358/* Convert a cpu mask from logical to physical cpu numbers. */
@@ -378,14 +370,14 @@ static inline u32 mpic_physmask(u32 cpumask)
378/* Get the mpic structure from the IPI number */ 370/* Get the mpic structure from the IPI number */
379static inline struct mpic * mpic_from_ipi(unsigned int ipi) 371static inline struct mpic * mpic_from_ipi(unsigned int ipi)
380{ 372{
381 return container_of(irq_desc[ipi].chip, struct mpic, hc_ipi); 373 return irq_desc[ipi].chip_data;
382} 374}
383#endif 375#endif
384 376
385/* Get the mpic structure from the irq number */ 377/* Get the mpic structure from the irq number */
386static inline struct mpic * mpic_from_irq(unsigned int irq) 378static inline struct mpic * mpic_from_irq(unsigned int irq)
387{ 379{
388 return container_of(irq_desc[irq].chip, struct mpic, hc_irq); 380 return irq_desc[irq].chip_data;
389} 381}
390 382
391/* Send an EOI */ 383/* Send an EOI */
@@ -398,9 +390,7 @@ static inline void mpic_eoi(struct mpic *mpic)
398#ifdef CONFIG_SMP 390#ifdef CONFIG_SMP
399static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) 391static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
400{ 392{
401 struct mpic *mpic = dev_id; 393 smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0, regs);
402
403 smp_message_recv(irq - mpic->ipi_offset, regs);
404 return IRQ_HANDLED; 394 return IRQ_HANDLED;
405} 395}
406#endif /* CONFIG_SMP */ 396#endif /* CONFIG_SMP */
@@ -410,11 +400,11 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
410 */ 400 */
411 401
412 402
413static void mpic_enable_irq(unsigned int irq) 403static void mpic_unmask_irq(unsigned int irq)
414{ 404{
415 unsigned int loops = 100000; 405 unsigned int loops = 100000;
416 struct mpic *mpic = mpic_from_irq(irq); 406 struct mpic *mpic = mpic_from_irq(irq);
417 unsigned int src = irq - mpic->irq_offset; 407 unsigned int src = mpic_irq_to_hw(irq);
418 408
419 DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); 409 DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
420 410
@@ -429,39 +419,13 @@ static void mpic_enable_irq(unsigned int irq)
429 break; 419 break;
430 } 420 }
431 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); 421 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
432
433#ifdef CONFIG_MPIC_BROKEN_U3
434 if (mpic->flags & MPIC_BROKEN_U3) {
435 unsigned int src = irq - mpic->irq_offset;
436 if (mpic_is_ht_interrupt(mpic, src) &&
437 (irq_desc[irq].status & IRQ_LEVEL))
438 mpic_ht_end_irq(mpic, src);
439 }
440#endif /* CONFIG_MPIC_BROKEN_U3 */
441}
442
443static unsigned int mpic_startup_irq(unsigned int irq)
444{
445#ifdef CONFIG_MPIC_BROKEN_U3
446 struct mpic *mpic = mpic_from_irq(irq);
447 unsigned int src = irq - mpic->irq_offset;
448#endif /* CONFIG_MPIC_BROKEN_U3 */
449
450 mpic_enable_irq(irq);
451
452#ifdef CONFIG_MPIC_BROKEN_U3
453 if (mpic_is_ht_interrupt(mpic, src))
454 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
455#endif /* CONFIG_MPIC_BROKEN_U3 */
456
457 return 0;
458} 422}
459 423
460static void mpic_disable_irq(unsigned int irq) 424static void mpic_mask_irq(unsigned int irq)
461{ 425{
462 unsigned int loops = 100000; 426 unsigned int loops = 100000;
463 struct mpic *mpic = mpic_from_irq(irq); 427 struct mpic *mpic = mpic_from_irq(irq);
464 unsigned int src = irq - mpic->irq_offset; 428 unsigned int src = mpic_irq_to_hw(irq);
465 429
466 DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); 430 DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
467 431
@@ -478,23 +442,58 @@ static void mpic_disable_irq(unsigned int irq)
478 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); 442 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
479} 443}
480 444
481static void mpic_shutdown_irq(unsigned int irq) 445static void mpic_end_irq(unsigned int irq)
482{ 446{
447 struct mpic *mpic = mpic_from_irq(irq);
448
449#ifdef DEBUG_IRQ
450 DBG("%s: end_irq: %d\n", mpic->name, irq);
451#endif
452 /* We always EOI on end_irq() even for edge interrupts since that
453 * should only lower the priority, the MPIC should have properly
454 * latched another edge interrupt coming in anyway
455 */
456
457 mpic_eoi(mpic);
458}
459
483#ifdef CONFIG_MPIC_BROKEN_U3 460#ifdef CONFIG_MPIC_BROKEN_U3
461
462static void mpic_unmask_ht_irq(unsigned int irq)
463{
484 struct mpic *mpic = mpic_from_irq(irq); 464 struct mpic *mpic = mpic_from_irq(irq);
485 unsigned int src = irq - mpic->irq_offset; 465 unsigned int src = mpic_irq_to_hw(irq);
486 466
487 if (mpic_is_ht_interrupt(mpic, src)) 467 mpic_unmask_irq(irq);
488 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
489 468
490#endif /* CONFIG_MPIC_BROKEN_U3 */ 469 if (irq_desc[irq].status & IRQ_LEVEL)
470 mpic_ht_end_irq(mpic, src);
471}
472
473static unsigned int mpic_startup_ht_irq(unsigned int irq)
474{
475 struct mpic *mpic = mpic_from_irq(irq);
476 unsigned int src = mpic_irq_to_hw(irq);
477
478 mpic_unmask_irq(irq);
479 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
491 480
492 mpic_disable_irq(irq); 481 return 0;
493} 482}
494 483
495static void mpic_end_irq(unsigned int irq) 484static void mpic_shutdown_ht_irq(unsigned int irq)
496{ 485{
497 struct mpic *mpic = mpic_from_irq(irq); 486 struct mpic *mpic = mpic_from_irq(irq);
487 unsigned int src = mpic_irq_to_hw(irq);
488
489 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
490 mpic_mask_irq(irq);
491}
492
493static void mpic_end_ht_irq(unsigned int irq)
494{
495 struct mpic *mpic = mpic_from_irq(irq);
496 unsigned int src = mpic_irq_to_hw(irq);
498 497
499#ifdef DEBUG_IRQ 498#ifdef DEBUG_IRQ
500 DBG("%s: end_irq: %d\n", mpic->name, irq); 499 DBG("%s: end_irq: %d\n", mpic->name, irq);
@@ -504,30 +503,25 @@ static void mpic_end_irq(unsigned int irq)
504 * latched another edge interrupt coming in anyway 503 * latched another edge interrupt coming in anyway
505 */ 504 */
506 505
507#ifdef CONFIG_MPIC_BROKEN_U3 506 if (irq_desc[irq].status & IRQ_LEVEL)
508 if (mpic->flags & MPIC_BROKEN_U3) { 507 mpic_ht_end_irq(mpic, src);
509 unsigned int src = irq - mpic->irq_offset;
510 if (mpic_is_ht_interrupt(mpic, src) &&
511 (irq_desc[irq].status & IRQ_LEVEL))
512 mpic_ht_end_irq(mpic, src);
513 }
514#endif /* CONFIG_MPIC_BROKEN_U3 */
515
516 mpic_eoi(mpic); 508 mpic_eoi(mpic);
517} 509}
518 510
511#endif /* CONFIG_MPIC_BROKEN_U3 */
512
519#ifdef CONFIG_SMP 513#ifdef CONFIG_SMP
520 514
521static void mpic_enable_ipi(unsigned int irq) 515static void mpic_unmask_ipi(unsigned int irq)
522{ 516{
523 struct mpic *mpic = mpic_from_ipi(irq); 517 struct mpic *mpic = mpic_from_ipi(irq);
524 unsigned int src = irq - mpic->ipi_offset; 518 unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0;
525 519
526 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); 520 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
527 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 521 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
528} 522}
529 523
530static void mpic_disable_ipi(unsigned int irq) 524static void mpic_mask_ipi(unsigned int irq)
531{ 525{
532 /* NEVER disable an IPI... that's just plain wrong! */ 526 /* NEVER disable an IPI... that's just plain wrong! */
533} 527}
@@ -551,29 +545,176 @@ static void mpic_end_ipi(unsigned int irq)
551static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) 545static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
552{ 546{
553 struct mpic *mpic = mpic_from_irq(irq); 547 struct mpic *mpic = mpic_from_irq(irq);
548 unsigned int src = mpic_irq_to_hw(irq);
554 549
555 cpumask_t tmp; 550 cpumask_t tmp;
556 551
557 cpus_and(tmp, cpumask, cpu_online_map); 552 cpus_and(tmp, cpumask, cpu_online_map);
558 553
559 mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION, 554 mpic_irq_write(src, MPIC_IRQ_DESTINATION,
560 mpic_physmask(cpus_addr(tmp)[0])); 555 mpic_physmask(cpus_addr(tmp)[0]));
561} 556}
562 557
558static unsigned int mpic_flags_to_vecpri(unsigned int flags, int *level)
559{
560 unsigned int vecpri;
561
562 /* Now convert sense value */
563 switch(flags & IRQ_TYPE_SENSE_MASK) {
564 case IRQ_TYPE_EDGE_RISING:
565 vecpri = MPIC_VECPRI_SENSE_EDGE |
566 MPIC_VECPRI_POLARITY_POSITIVE;
567 *level = 0;
568 break;
569 case IRQ_TYPE_EDGE_FALLING:
570 vecpri = MPIC_VECPRI_SENSE_EDGE |
571 MPIC_VECPRI_POLARITY_NEGATIVE;
572 *level = 0;
573 break;
574 case IRQ_TYPE_LEVEL_HIGH:
575 vecpri = MPIC_VECPRI_SENSE_LEVEL |
576 MPIC_VECPRI_POLARITY_POSITIVE;
577 *level = 1;
578 break;
579 case IRQ_TYPE_LEVEL_LOW:
580 default:
581 vecpri = MPIC_VECPRI_SENSE_LEVEL |
582 MPIC_VECPRI_POLARITY_NEGATIVE;
583 *level = 1;
584 }
585 return vecpri;
586}
587
588static struct irq_chip mpic_irq_chip = {
589 .mask = mpic_mask_irq,
590 .unmask = mpic_unmask_irq,
591 .eoi = mpic_end_irq,
592};
593
594#ifdef CONFIG_SMP
595static struct irq_chip mpic_ipi_chip = {
596 .mask = mpic_mask_ipi,
597 .unmask = mpic_unmask_ipi,
598 .eoi = mpic_end_ipi,
599};
600#endif /* CONFIG_SMP */
601
602#ifdef CONFIG_MPIC_BROKEN_U3
603static struct irq_chip mpic_irq_ht_chip = {
604 .startup = mpic_startup_ht_irq,
605 .shutdown = mpic_shutdown_ht_irq,
606 .mask = mpic_mask_irq,
607 .unmask = mpic_unmask_ht_irq,
608 .eoi = mpic_end_ht_irq,
609};
610#endif /* CONFIG_MPIC_BROKEN_U3 */
611
612
613static int mpic_host_match(struct irq_host *h, struct device_node *node)
614{
615 struct mpic *mpic = h->host_data;
616
617 /* Exact match, unless mpic node is NULL */
618 return mpic->of_node == NULL || mpic->of_node == node;
619}
620
621static int mpic_host_map(struct irq_host *h, unsigned int virq,
622 irq_hw_number_t hw, unsigned int flags)
623{
624 struct irq_desc *desc = get_irq_desc(virq);
625 struct irq_chip *chip;
626 struct mpic *mpic = h->host_data;
627 unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL |
628 MPIC_VECPRI_POLARITY_NEGATIVE;
629 int level;
630
631 pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n",
632 virq, hw, flags);
633
634 if (hw == MPIC_VEC_SPURRIOUS)
635 return -EINVAL;
636#ifdef CONFIG_SMP
637 else if (hw >= MPIC_VEC_IPI_0) {
638 WARN_ON(!(mpic->flags & MPIC_PRIMARY));
639
640 pr_debug("mpic: mapping as IPI\n");
641 set_irq_chip_data(virq, mpic);
642 set_irq_chip_and_handler(virq, &mpic->hc_ipi,
643 handle_percpu_irq);
644 return 0;
645 }
646#endif /* CONFIG_SMP */
647
648 if (hw >= mpic->irq_count)
649 return -EINVAL;
650
651 /* If no sense provided, check default sense array */
652 if (((flags & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE) &&
653 mpic->senses && hw < mpic->senses_count)
654 flags |= mpic->senses[hw];
655
656 vecpri = mpic_flags_to_vecpri(flags, &level);
657 if (level)
658 desc->status |= IRQ_LEVEL;
659 chip = &mpic->hc_irq;
660
661#ifdef CONFIG_MPIC_BROKEN_U3
662 /* Check for HT interrupts, override vecpri */
663 if (mpic_is_ht_interrupt(mpic, hw)) {
664 vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
665 MPIC_VECPRI_POLARITY_MASK);
666 vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
667 chip = &mpic->hc_ht_irq;
668 }
669#endif
670
671 /* Reconfigure irq */
672 vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
673 mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
674
675 pr_debug("mpic: mapping as IRQ\n");
676
677 set_irq_chip_data(virq, mpic);
678 set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
679 return 0;
680}
681
682static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
683 u32 *intspec, unsigned int intsize,
684 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
685
686{
687 static unsigned char map_mpic_senses[4] = {
688 IRQ_TYPE_EDGE_RISING,
689 IRQ_TYPE_LEVEL_LOW,
690 IRQ_TYPE_LEVEL_HIGH,
691 IRQ_TYPE_EDGE_FALLING,
692 };
693
694 *out_hwirq = intspec[0];
695 if (intsize > 1 && intspec[1] < 4)
696 *out_flags = map_mpic_senses[intspec[1]];
697 else
698 *out_flags = IRQ_TYPE_NONE;
699
700 return 0;
701}
702
703static struct irq_host_ops mpic_host_ops = {
704 .match = mpic_host_match,
705 .map = mpic_host_map,
706 .xlate = mpic_host_xlate,
707};
563 708
564/* 709/*
565 * Exported functions 710 * Exported functions
566 */ 711 */
567 712
568 713struct mpic * __init mpic_alloc(struct device_node *node,
569struct mpic * __init mpic_alloc(unsigned long phys_addr, 714 unsigned long phys_addr,
570 unsigned int flags, 715 unsigned int flags,
571 unsigned int isu_size, 716 unsigned int isu_size,
572 unsigned int irq_offset,
573 unsigned int irq_count, 717 unsigned int irq_count,
574 unsigned int ipi_offset,
575 unsigned char *senses,
576 unsigned int senses_count,
577 const char *name) 718 const char *name)
578{ 719{
579 struct mpic *mpic; 720 struct mpic *mpic;
@@ -585,33 +726,38 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
585 if (mpic == NULL) 726 if (mpic == NULL)
586 return NULL; 727 return NULL;
587 728
588
589 memset(mpic, 0, sizeof(struct mpic)); 729 memset(mpic, 0, sizeof(struct mpic));
590 mpic->name = name; 730 mpic->name = name;
731 mpic->of_node = node ? of_node_get(node) : NULL;
591 732
733 mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256,
734 &mpic_host_ops,
735 MPIC_VEC_SPURRIOUS);
736 if (mpic->irqhost == NULL) {
737 of_node_put(node);
738 return NULL;
739 }
740
741 mpic->irqhost->host_data = mpic;
742 mpic->hc_irq = mpic_irq_chip;
592 mpic->hc_irq.typename = name; 743 mpic->hc_irq.typename = name;
593 mpic->hc_irq.startup = mpic_startup_irq;
594 mpic->hc_irq.shutdown = mpic_shutdown_irq;
595 mpic->hc_irq.enable = mpic_enable_irq;
596 mpic->hc_irq.disable = mpic_disable_irq;
597 mpic->hc_irq.end = mpic_end_irq;
598 if (flags & MPIC_PRIMARY) 744 if (flags & MPIC_PRIMARY)
599 mpic->hc_irq.set_affinity = mpic_set_affinity; 745 mpic->hc_irq.set_affinity = mpic_set_affinity;
746#ifdef CONFIG_MPIC_BROKEN_U3
747 mpic->hc_ht_irq = mpic_irq_ht_chip;
748 mpic->hc_ht_irq.typename = name;
749 if (flags & MPIC_PRIMARY)
750 mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
751#endif /* CONFIG_MPIC_BROKEN_U3 */
600#ifdef CONFIG_SMP 752#ifdef CONFIG_SMP
753 mpic->hc_ipi = mpic_ipi_chip;
601 mpic->hc_ipi.typename = name; 754 mpic->hc_ipi.typename = name;
602 mpic->hc_ipi.enable = mpic_enable_ipi;
603 mpic->hc_ipi.disable = mpic_disable_ipi;
604 mpic->hc_ipi.end = mpic_end_ipi;
605#endif /* CONFIG_SMP */ 755#endif /* CONFIG_SMP */
606 756
607 mpic->flags = flags; 757 mpic->flags = flags;
608 mpic->isu_size = isu_size; 758 mpic->isu_size = isu_size;
609 mpic->irq_offset = irq_offset;
610 mpic->irq_count = irq_count; 759 mpic->irq_count = irq_count;
611 mpic->ipi_offset = ipi_offset;
612 mpic->num_sources = 0; /* so far */ 760 mpic->num_sources = 0; /* so far */
613 mpic->senses = senses;
614 mpic->senses_count = senses_count;
615 761
616 /* Map the global registers */ 762 /* Map the global registers */
617 mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); 763 mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
@@ -679,8 +825,10 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
679 mpic->next = mpics; 825 mpic->next = mpics;
680 mpics = mpic; 826 mpics = mpic;
681 827
682 if (flags & MPIC_PRIMARY) 828 if (flags & MPIC_PRIMARY) {
683 mpic_primary = mpic; 829 mpic_primary = mpic;
830 irq_set_default_host(mpic->irqhost);
831 }
684 832
685 return mpic; 833 return mpic;
686} 834}
@@ -697,26 +845,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
697 mpic->num_sources = isu_first + mpic->isu_size; 845 mpic->num_sources = isu_first + mpic->isu_size;
698} 846}
699 847
700void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler, 848void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
701 void *data)
702{ 849{
703 struct mpic *mpic = mpic_find(irq, NULL); 850 mpic->senses = senses;
704 unsigned long flags; 851 mpic->senses_count = count;
705
706 /* Synchronization here is a bit dodgy, so don't try to replace cascade
707 * interrupts on the fly too often ... but normally it's set up at boot.
708 */
709 spin_lock_irqsave(&mpic_lock, flags);
710 if (mpic->cascade)
711 mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
712 mpic->cascade = NULL;
713 wmb();
714 mpic->cascade_vec = irq - mpic->irq_offset;
715 mpic->cascade_data = data;
716 wmb();
717 mpic->cascade = handler;
718 mpic_enable_irq(irq);
719 spin_unlock_irqrestore(&mpic_lock, flags);
720} 852}
721 853
722void __init mpic_init(struct mpic *mpic) 854void __init mpic_init(struct mpic *mpic)
@@ -724,6 +856,11 @@ void __init mpic_init(struct mpic *mpic)
724 int i; 856 int i;
725 857
726 BUG_ON(mpic->num_sources == 0); 858 BUG_ON(mpic->num_sources == 0);
859 WARN_ON(mpic->num_sources > MPIC_VEC_IPI_0);
860
861 /* Sanitize source count */
862 if (mpic->num_sources > MPIC_VEC_IPI_0)
863 mpic->num_sources = MPIC_VEC_IPI_0;
727 864
728 printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); 865 printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
729 866
@@ -747,12 +884,6 @@ void __init mpic_init(struct mpic *mpic)
747 MPIC_VECPRI_MASK | 884 MPIC_VECPRI_MASK |
748 (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 885 (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
749 (MPIC_VEC_IPI_0 + i)); 886 (MPIC_VEC_IPI_0 + i));
750#ifdef CONFIG_SMP
751 if (!(mpic->flags & MPIC_PRIMARY))
752 continue;
753 irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
754 irq_desc[mpic->ipi_offset+i].chip = &mpic->hc_ipi;
755#endif /* CONFIG_SMP */
756 } 887 }
757 888
758 /* Initialize interrupt sources */ 889 /* Initialize interrupt sources */
@@ -763,31 +894,21 @@ void __init mpic_init(struct mpic *mpic)
763 /* Do the HT PIC fixups on U3 broken mpic */ 894 /* Do the HT PIC fixups on U3 broken mpic */
764 DBG("MPIC flags: %x\n", mpic->flags); 895 DBG("MPIC flags: %x\n", mpic->flags);
765 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) 896 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
766 mpic_scan_ht_pics(mpic); 897 mpic_scan_ht_pics(mpic);
767#endif /* CONFIG_MPIC_BROKEN_U3 */ 898#endif /* CONFIG_MPIC_BROKEN_U3 */
768 899
769 for (i = 0; i < mpic->num_sources; i++) { 900 for (i = 0; i < mpic->num_sources; i++) {
770 /* start with vector = source number, and masked */ 901 /* start with vector = source number, and masked */
771 u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); 902 u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
772 int level = 0; 903 int level = 1;
773 904
774 /* if it's an IPI, we skip it */
775 if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
776 (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4))
777 continue;
778
779 /* do senses munging */ 905 /* do senses munging */
780 if (mpic->senses && i < mpic->senses_count) { 906 if (mpic->senses && i < mpic->senses_count)
781 if (mpic->senses[i] & IRQ_SENSE_LEVEL) 907 vecpri = mpic_flags_to_vecpri(mpic->senses[i],
782 vecpri |= MPIC_VECPRI_SENSE_LEVEL; 908 &level);
783 if (mpic->senses[i] & IRQ_POLARITY_POSITIVE) 909 else
784 vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
785 } else
786 vecpri |= MPIC_VECPRI_SENSE_LEVEL; 910 vecpri |= MPIC_VECPRI_SENSE_LEVEL;
787 911
788 /* remember if it was a level interrupts */
789 level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
790
791 /* deal with broken U3 */ 912 /* deal with broken U3 */
792 if (mpic->flags & MPIC_BROKEN_U3) { 913 if (mpic->flags & MPIC_BROKEN_U3) {
793#ifdef CONFIG_MPIC_BROKEN_U3 914#ifdef CONFIG_MPIC_BROKEN_U3
@@ -808,12 +929,6 @@ void __init mpic_init(struct mpic *mpic)
808 mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); 929 mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
809 mpic_irq_write(i, MPIC_IRQ_DESTINATION, 930 mpic_irq_write(i, MPIC_IRQ_DESTINATION,
810 1 << hard_smp_processor_id()); 931 1 << hard_smp_processor_id());
811
812 /* init linux descriptors */
813 if (i < mpic->irq_count) {
814 irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0;
815 irq_desc[mpic->irq_offset+i].chip = &mpic->hc_irq;
816 }
817 } 932 }
818 933
819 /* Init spurrious vector */ 934 /* Init spurrious vector */
@@ -854,19 +969,20 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
854{ 969{
855 int is_ipi; 970 int is_ipi;
856 struct mpic *mpic = mpic_find(irq, &is_ipi); 971 struct mpic *mpic = mpic_find(irq, &is_ipi);
972 unsigned int src = mpic_irq_to_hw(irq);
857 unsigned long flags; 973 unsigned long flags;
858 u32 reg; 974 u32 reg;
859 975
860 spin_lock_irqsave(&mpic_lock, flags); 976 spin_lock_irqsave(&mpic_lock, flags);
861 if (is_ipi) { 977 if (is_ipi) {
862 reg = mpic_ipi_read(irq - mpic->ipi_offset) & 978 reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) &
863 ~MPIC_VECPRI_PRIORITY_MASK; 979 ~MPIC_VECPRI_PRIORITY_MASK;
864 mpic_ipi_write(irq - mpic->ipi_offset, 980 mpic_ipi_write(src - MPIC_VEC_IPI_0,
865 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 981 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
866 } else { 982 } else {
867 reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI) 983 reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
868 & ~MPIC_VECPRI_PRIORITY_MASK; 984 & ~MPIC_VECPRI_PRIORITY_MASK;
869 mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI, 985 mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
870 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 986 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
871 } 987 }
872 spin_unlock_irqrestore(&mpic_lock, flags); 988 spin_unlock_irqrestore(&mpic_lock, flags);
@@ -876,14 +992,15 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
876{ 992{
877 int is_ipi; 993 int is_ipi;
878 struct mpic *mpic = mpic_find(irq, &is_ipi); 994 struct mpic *mpic = mpic_find(irq, &is_ipi);
995 unsigned int src = mpic_irq_to_hw(irq);
879 unsigned long flags; 996 unsigned long flags;
880 u32 reg; 997 u32 reg;
881 998
882 spin_lock_irqsave(&mpic_lock, flags); 999 spin_lock_irqsave(&mpic_lock, flags);
883 if (is_ipi) 1000 if (is_ipi)
884 reg = mpic_ipi_read(irq - mpic->ipi_offset); 1001 reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
885 else 1002 else
886 reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI); 1003 reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
887 spin_unlock_irqrestore(&mpic_lock, flags); 1004 spin_unlock_irqrestore(&mpic_lock, flags);
888 return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; 1005 return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
889} 1006}
@@ -978,37 +1095,20 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
978 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); 1095 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
979} 1096}
980 1097
981int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) 1098unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
982{ 1099{
983 u32 irq; 1100 u32 src;
984 1101
985 irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; 1102 src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
986#ifdef DEBUG_LOW 1103#ifdef DEBUG_LOW
987 DBG("%s: get_one_irq(): %d\n", mpic->name, irq); 1104 DBG("%s: get_one_irq(): %d\n", mpic->name, src);
988#endif 1105#endif
989 if (mpic->cascade && irq == mpic->cascade_vec) { 1106 if (unlikely(src == MPIC_VEC_SPURRIOUS))
990#ifdef DEBUG_LOW 1107 return NO_IRQ;
991 DBG("%s: cascading ...\n", mpic->name); 1108 return irq_linear_revmap(mpic->irqhost, src);
992#endif
993 irq = mpic->cascade(regs, mpic->cascade_data);
994 mpic_eoi(mpic);
995 return irq;
996 }
997 if (unlikely(irq == MPIC_VEC_SPURRIOUS))
998 return -1;
999 if (irq < MPIC_VEC_IPI_0) {
1000#ifdef DEBUG_IRQ
1001 DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
1002#endif
1003 return irq + mpic->irq_offset;
1004 }
1005#ifdef DEBUG_IPI
1006 DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
1007#endif
1008 return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
1009} 1109}
1010 1110
1011int mpic_get_irq(struct pt_regs *regs) 1111unsigned int mpic_get_irq(struct pt_regs *regs)
1012{ 1112{
1013 struct mpic *mpic = mpic_primary; 1113 struct mpic *mpic = mpic_primary;
1014 1114
@@ -1022,25 +1122,27 @@ int mpic_get_irq(struct pt_regs *regs)
1022void mpic_request_ipis(void) 1122void mpic_request_ipis(void)
1023{ 1123{
1024 struct mpic *mpic = mpic_primary; 1124 struct mpic *mpic = mpic_primary;
1025 1125 int i;
1126 static char *ipi_names[] = {
1127 "IPI0 (call function)",
1128 "IPI1 (reschedule)",
1129 "IPI2 (unused)",
1130 "IPI3 (debugger break)",
1131 };
1026 BUG_ON(mpic == NULL); 1132 BUG_ON(mpic == NULL);
1027
1028 printk("requesting IPIs ... \n");
1029 1133
1030 /* 1134 printk(KERN_INFO "mpic: requesting IPIs ... \n");
1031 * IPIs are marked IRQF_DISABLED as they must run with irqs 1135
1032 * disabled 1136 for (i = 0; i < 4; i++) {
1033 */ 1137 unsigned int vipi = irq_create_mapping(mpic->irqhost,
1034 request_irq(mpic->ipi_offset+0, mpic_ipi_action, IRQF_DISABLED, 1138 MPIC_VEC_IPI_0 + i, 0);
1035 "IPI0 (call function)", mpic); 1139 if (vipi == NO_IRQ) {
1036 request_irq(mpic->ipi_offset+1, mpic_ipi_action, IRQF_DISABLED, 1140 printk(KERN_ERR "Failed to map IPI %d\n", i);
1037 "IPI1 (reschedule)", mpic); 1141 break;
1038 request_irq(mpic->ipi_offset+2, mpic_ipi_action, IRQF_DISABLED, 1142 }
1039 "IPI2 (unused)", mpic); 1143 request_irq(vipi, mpic_ipi_action, IRQF_DISABLED,
1040 request_irq(mpic->ipi_offset+3, mpic_ipi_action, IRQF_DISABLED, 1144 ipi_names[i], mpic);
1041 "IPI3 (debugger break)", mpic); 1145 }
1042
1043 printk("IPIs requested... \n");
1044} 1146}
1045 1147
1046void smp_mpic_message_pass(int target, int msg) 1148void smp_mpic_message_pass(int target, int msg)