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.c333
1 files changed, 213 insertions, 120 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 9a95f16c19a5..7d31d7cc392d 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -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. */
@@ -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 */
@@ -414,7 +404,7 @@ static 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
@@ -435,7 +425,7 @@ static void mpic_mask_irq(unsigned int irq)
435{ 425{
436 unsigned int loops = 100000; 426 unsigned int loops = 100000;
437 struct mpic *mpic = mpic_from_irq(irq); 427 struct mpic *mpic = mpic_from_irq(irq);
438 unsigned int src = irq - mpic->irq_offset; 428 unsigned int src = mpic_irq_to_hw(irq);
439 429
440 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);
441 431
@@ -472,7 +462,7 @@ static void mpic_end_irq(unsigned int irq)
472static void mpic_unmask_ht_irq(unsigned int irq) 462static void mpic_unmask_ht_irq(unsigned int irq)
473{ 463{
474 struct mpic *mpic = mpic_from_irq(irq); 464 struct mpic *mpic = mpic_from_irq(irq);
475 unsigned int src = irq - mpic->irq_offset; 465 unsigned int src = mpic_irq_to_hw(irq);
476 466
477 mpic_unmask_irq(irq); 467 mpic_unmask_irq(irq);
478 468
@@ -483,7 +473,7 @@ static void mpic_unmask_ht_irq(unsigned int irq)
483static unsigned int mpic_startup_ht_irq(unsigned int irq) 473static unsigned int mpic_startup_ht_irq(unsigned int irq)
484{ 474{
485 struct mpic *mpic = mpic_from_irq(irq); 475 struct mpic *mpic = mpic_from_irq(irq);
486 unsigned int src = irq - mpic->irq_offset; 476 unsigned int src = mpic_irq_to_hw(irq);
487 477
488 mpic_unmask_irq(irq); 478 mpic_unmask_irq(irq);
489 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); 479 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
@@ -494,7 +484,7 @@ static unsigned int mpic_startup_ht_irq(unsigned int irq)
494static void mpic_shutdown_ht_irq(unsigned int irq) 484static void mpic_shutdown_ht_irq(unsigned int irq)
495{ 485{
496 struct mpic *mpic = mpic_from_irq(irq); 486 struct mpic *mpic = mpic_from_irq(irq);
497 unsigned int src = irq - mpic->irq_offset; 487 unsigned int src = mpic_irq_to_hw(irq);
498 488
499 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); 489 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
500 mpic_mask_irq(irq); 490 mpic_mask_irq(irq);
@@ -503,7 +493,7 @@ static void mpic_shutdown_ht_irq(unsigned int irq)
503static void mpic_end_ht_irq(unsigned int irq) 493static void mpic_end_ht_irq(unsigned int irq)
504{ 494{
505 struct mpic *mpic = mpic_from_irq(irq); 495 struct mpic *mpic = mpic_from_irq(irq);
506 unsigned int src = irq - mpic->irq_offset; 496 unsigned int src = mpic_irq_to_hw(irq);
507 497
508#ifdef DEBUG_IRQ 498#ifdef DEBUG_IRQ
509 DBG("%s: end_irq: %d\n", mpic->name, irq); 499 DBG("%s: end_irq: %d\n", mpic->name, irq);
@@ -525,7 +515,7 @@ static void mpic_end_ht_irq(unsigned int irq)
525static void mpic_unmask_ipi(unsigned int irq) 515static void mpic_unmask_ipi(unsigned int irq)
526{ 516{
527 struct mpic *mpic = mpic_from_ipi(irq); 517 struct mpic *mpic = mpic_from_ipi(irq);
528 unsigned int src = irq - mpic->ipi_offset; 518 unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0;
529 519
530 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);
531 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 521 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
@@ -555,15 +545,46 @@ static void mpic_end_ipi(unsigned int irq)
555static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) 545static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
556{ 546{
557 struct mpic *mpic = mpic_from_irq(irq); 547 struct mpic *mpic = mpic_from_irq(irq);
548 unsigned int src = mpic_irq_to_hw(irq);
558 549
559 cpumask_t tmp; 550 cpumask_t tmp;
560 551
561 cpus_and(tmp, cpumask, cpu_online_map); 552 cpus_and(tmp, cpumask, cpu_online_map);
562 553
563 mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION, 554 mpic_irq_write(src, MPIC_IRQ_DESTINATION,
564 mpic_physmask(cpus_addr(tmp)[0])); 555 mpic_physmask(cpus_addr(tmp)[0]));
565} 556}
566 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
567static struct irq_chip mpic_irq_chip = { 588static struct irq_chip mpic_irq_chip = {
568 .mask = mpic_mask_irq, 589 .mask = mpic_mask_irq,
569 .unmask = mpic_unmask_irq, 590 .unmask = mpic_unmask_irq,
@@ -589,19 +610,111 @@ static struct irq_chip mpic_irq_ht_chip = {
589#endif /* CONFIG_MPIC_BROKEN_U3 */ 610#endif /* CONFIG_MPIC_BROKEN_U3 */
590 611
591 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};
708
592/* 709/*
593 * Exported functions 710 * Exported functions
594 */ 711 */
595 712
596 713struct mpic * __init mpic_alloc(struct device_node *node,
597struct mpic * __init mpic_alloc(unsigned long phys_addr, 714 unsigned long phys_addr,
598 unsigned int flags, 715 unsigned int flags,
599 unsigned int isu_size, 716 unsigned int isu_size,
600 unsigned int irq_offset,
601 unsigned int irq_count, 717 unsigned int irq_count,
602 unsigned int ipi_offset,
603 unsigned char *senses,
604 unsigned int senses_count,
605 const char *name) 718 const char *name)
606{ 719{
607 struct mpic *mpic; 720 struct mpic *mpic;
@@ -613,10 +726,19 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
613 if (mpic == NULL) 726 if (mpic == NULL)
614 return NULL; 727 return NULL;
615 728
616
617 memset(mpic, 0, sizeof(struct mpic)); 729 memset(mpic, 0, sizeof(struct mpic));
618 mpic->name = name; 730 mpic->name = name;
731 mpic->of_node = node ? of_node_get(node) : NULL;
619 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;
620 mpic->hc_irq = mpic_irq_chip; 742 mpic->hc_irq = mpic_irq_chip;
621 mpic->hc_irq.typename = name; 743 mpic->hc_irq.typename = name;
622 if (flags & MPIC_PRIMARY) 744 if (flags & MPIC_PRIMARY)
@@ -628,18 +750,14 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
628 mpic->hc_ht_irq.set_affinity = mpic_set_affinity; 750 mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
629#endif /* CONFIG_MPIC_BROKEN_U3 */ 751#endif /* CONFIG_MPIC_BROKEN_U3 */
630#ifdef CONFIG_SMP 752#ifdef CONFIG_SMP
631 mpic->hc_ipi.typename = name;
632 mpic->hc_ipi = mpic_ipi_chip; 753 mpic->hc_ipi = mpic_ipi_chip;
754 mpic->hc_ipi.typename = name;
633#endif /* CONFIG_SMP */ 755#endif /* CONFIG_SMP */
634 756
635 mpic->flags = flags; 757 mpic->flags = flags;
636 mpic->isu_size = isu_size; 758 mpic->isu_size = isu_size;
637 mpic->irq_offset = irq_offset;
638 mpic->irq_count = irq_count; 759 mpic->irq_count = irq_count;
639 mpic->ipi_offset = ipi_offset;
640 mpic->num_sources = 0; /* so far */ 760 mpic->num_sources = 0; /* so far */
641 mpic->senses = senses;
642 mpic->senses_count = senses_count;
643 761
644 /* Map the global registers */ 762 /* Map the global registers */
645 mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); 763 mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
@@ -707,8 +825,10 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
707 mpic->next = mpics; 825 mpic->next = mpics;
708 mpics = mpic; 826 mpics = mpic;
709 827
710 if (flags & MPIC_PRIMARY) 828 if (flags & MPIC_PRIMARY) {
711 mpic_primary = mpic; 829 mpic_primary = mpic;
830 irq_set_default_host(mpic->irqhost);
831 }
712 832
713 return mpic; 833 return mpic;
714} 834}
@@ -725,11 +845,22 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
725 mpic->num_sources = isu_first + mpic->isu_size; 845 mpic->num_sources = isu_first + mpic->isu_size;
726} 846}
727 847
848void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
849{
850 mpic->senses = senses;
851 mpic->senses_count = count;
852}
853
728void __init mpic_init(struct mpic *mpic) 854void __init mpic_init(struct mpic *mpic)
729{ 855{
730 int i; 856 int i;
731 857
732 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;
733 864
734 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);
735 866
@@ -753,14 +884,6 @@ void __init mpic_init(struct mpic *mpic)
753 MPIC_VECPRI_MASK | 884 MPIC_VECPRI_MASK |
754 (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 885 (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
755 (MPIC_VEC_IPI_0 + i)); 886 (MPIC_VEC_IPI_0 + i));
756#ifdef CONFIG_SMP
757 if (!(mpic->flags & MPIC_PRIMARY))
758 continue;
759 set_irq_chip_data(mpic->ipi_offset+i, mpic);
760 set_irq_chip_and_handler(mpic->ipi_offset+i,
761 &mpic->hc_ipi,
762 handle_percpu_irq);
763#endif /* CONFIG_SMP */
764 } 887 }
765 888
766 /* Initialize interrupt sources */ 889 /* Initialize interrupt sources */
@@ -777,25 +900,15 @@ void __init mpic_init(struct mpic *mpic)
777 for (i = 0; i < mpic->num_sources; i++) { 900 for (i = 0; i < mpic->num_sources; i++) {
778 /* start with vector = source number, and masked */ 901 /* start with vector = source number, and masked */
779 u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); 902 u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
780 int level = 0; 903 int level = 1;
781 904
782 /* if it's an IPI, we skip it */
783 if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
784 (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4))
785 continue;
786
787 /* do senses munging */ 905 /* do senses munging */
788 if (mpic->senses && i < mpic->senses_count) { 906 if (mpic->senses && i < mpic->senses_count)
789 if (mpic->senses[i] & IRQ_SENSE_LEVEL) 907 vecpri = mpic_flags_to_vecpri(mpic->senses[i],
790 vecpri |= MPIC_VECPRI_SENSE_LEVEL; 908 &level);
791 if (mpic->senses[i] & IRQ_POLARITY_POSITIVE) 909 else
792 vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
793 } else
794 vecpri |= MPIC_VECPRI_SENSE_LEVEL; 910 vecpri |= MPIC_VECPRI_SENSE_LEVEL;
795 911
796 /* remember if it was a level interrupts */
797 level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
798
799 /* deal with broken U3 */ 912 /* deal with broken U3 */
800 if (mpic->flags & MPIC_BROKEN_U3) { 913 if (mpic->flags & MPIC_BROKEN_U3) {
801#ifdef CONFIG_MPIC_BROKEN_U3 914#ifdef CONFIG_MPIC_BROKEN_U3
@@ -816,21 +929,6 @@ void __init mpic_init(struct mpic *mpic)
816 mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); 929 mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
817 mpic_irq_write(i, MPIC_IRQ_DESTINATION, 930 mpic_irq_write(i, MPIC_IRQ_DESTINATION,
818 1 << hard_smp_processor_id()); 931 1 << hard_smp_processor_id());
819
820 /* init linux descriptors */
821 if (i < mpic->irq_count) {
822 struct irq_chip *chip = &mpic->hc_irq;
823
824 irq_desc[mpic->irq_offset+i].status |=
825 level ? IRQ_LEVEL : 0;
826#ifdef CONFIG_MPIC_BROKEN_U3
827 if (mpic_is_ht_interrupt(mpic, i))
828 chip = &mpic->hc_ht_irq;
829#endif /* CONFIG_MPIC_BROKEN_U3 */
830 set_irq_chip_data(mpic->irq_offset+i, mpic);
831 set_irq_chip_and_handler(mpic->irq_offset+i, chip,
832 handle_fasteoi_irq);
833 }
834 } 932 }
835 933
836 /* Init spurrious vector */ 934 /* Init spurrious vector */
@@ -871,19 +969,20 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
871{ 969{
872 int is_ipi; 970 int is_ipi;
873 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);
874 unsigned long flags; 973 unsigned long flags;
875 u32 reg; 974 u32 reg;
876 975
877 spin_lock_irqsave(&mpic_lock, flags); 976 spin_lock_irqsave(&mpic_lock, flags);
878 if (is_ipi) { 977 if (is_ipi) {
879 reg = mpic_ipi_read(irq - mpic->ipi_offset) & 978 reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) &
880 ~MPIC_VECPRI_PRIORITY_MASK; 979 ~MPIC_VECPRI_PRIORITY_MASK;
881 mpic_ipi_write(irq - mpic->ipi_offset, 980 mpic_ipi_write(src - MPIC_VEC_IPI_0,
882 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 981 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
883 } else { 982 } else {
884 reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI) 983 reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
885 & ~MPIC_VECPRI_PRIORITY_MASK; 984 & ~MPIC_VECPRI_PRIORITY_MASK;
886 mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI, 985 mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
887 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 986 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
888 } 987 }
889 spin_unlock_irqrestore(&mpic_lock, flags); 988 spin_unlock_irqrestore(&mpic_lock, flags);
@@ -893,14 +992,15 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
893{ 992{
894 int is_ipi; 993 int is_ipi;
895 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);
896 unsigned long flags; 996 unsigned long flags;
897 u32 reg; 997 u32 reg;
898 998
899 spin_lock_irqsave(&mpic_lock, flags); 999 spin_lock_irqsave(&mpic_lock, flags);
900 if (is_ipi) 1000 if (is_ipi)
901 reg = mpic_ipi_read(irq - mpic->ipi_offset); 1001 reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
902 else 1002 else
903 reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI); 1003 reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
904 spin_unlock_irqrestore(&mpic_lock, flags); 1004 spin_unlock_irqrestore(&mpic_lock, flags);
905 return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; 1005 return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
906} 1006}
@@ -995,29 +1095,20 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
995 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); 1095 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
996} 1096}
997 1097
998int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) 1098unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
999{ 1099{
1000 u32 irq; 1100 u32 src;
1001 1101
1002 irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; 1102 src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
1003#ifdef DEBUG_LOW 1103#ifdef DEBUG_LOW
1004 DBG("%s: get_one_irq(): %d\n", mpic->name, irq); 1104 DBG("%s: get_one_irq(): %d\n", mpic->name, src);
1005#endif
1006 if (unlikely(irq == MPIC_VEC_SPURRIOUS))
1007 return -1;
1008 if (irq < MPIC_VEC_IPI_0) {
1009#ifdef DEBUG_IRQ
1010 DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
1011#endif 1105#endif
1012 return irq + mpic->irq_offset; 1106 if (unlikely(src == MPIC_VEC_SPURRIOUS))
1013 } 1107 return NO_IRQ;
1014#ifdef DEBUG_IPI 1108 return irq_linear_revmap(mpic->irqhost, src);
1015 DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
1016#endif
1017 return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
1018} 1109}
1019 1110
1020int mpic_get_irq(struct pt_regs *regs) 1111unsigned int mpic_get_irq(struct pt_regs *regs)
1021{ 1112{
1022 struct mpic *mpic = mpic_primary; 1113 struct mpic *mpic = mpic_primary;
1023 1114
@@ -1031,25 +1122,27 @@ int mpic_get_irq(struct pt_regs *regs)
1031void mpic_request_ipis(void) 1122void mpic_request_ipis(void)
1032{ 1123{
1033 struct mpic *mpic = mpic_primary; 1124 struct mpic *mpic = mpic_primary;
1034 1125 int i;
1126 static char *ipi_names[] = {
1127 "IPI0 (call function)",
1128 "IPI1 (reschedule)",
1129 "IPI2 (unused)",
1130 "IPI3 (debugger break)",
1131 };
1035 BUG_ON(mpic == NULL); 1132 BUG_ON(mpic == NULL);
1036
1037 printk("requesting IPIs ... \n");
1038 1133
1039 /* 1134 printk(KERN_INFO "mpic: requesting IPIs ... \n");
1040 * IPIs are marked IRQF_DISABLED as they must run with irqs 1135
1041 * disabled 1136 for (i = 0; i < 4; i++) {
1042 */ 1137 unsigned int vipi = irq_create_mapping(mpic->irqhost,
1043 request_irq(mpic->ipi_offset+0, mpic_ipi_action, IRQF_DISABLED, 1138 MPIC_VEC_IPI_0 + i, 0);
1044 "IPI0 (call function)", mpic); 1139 if (vipi == NO_IRQ) {
1045 request_irq(mpic->ipi_offset+1, mpic_ipi_action, IRQF_DISABLED, 1140 printk(KERN_ERR "Failed to map IPI %d\n", i);
1046 "IPI1 (reschedule)", mpic); 1141 break;
1047 request_irq(mpic->ipi_offset+2, mpic_ipi_action, IRQF_DISABLED, 1142 }
1048 "IPI2 (unused)", mpic); 1143 request_irq(vipi, mpic_ipi_action, IRQF_DISABLED,
1049 request_irq(mpic->ipi_offset+3, mpic_ipi_action, IRQF_DISABLED, 1144 ipi_names[i], mpic);
1050 "IPI3 (debugger break)", mpic); 1145 }
1051
1052 printk("IPIs requested... \n");
1053} 1146}
1054 1147
1055void smp_mpic_message_pass(int target, int msg) 1148void smp_mpic_message_pass(int target, int msg)