diff options
Diffstat (limited to 'drivers/sh/intc.c')
-rw-r--r-- | drivers/sh/intc.c | 71 |
1 files changed, 34 insertions, 37 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 3dd231a643b5..559b5fe9dc0f 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
@@ -77,7 +77,7 @@ static unsigned long ack_handle[NR_IRQS]; | |||
77 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) | 77 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) |
78 | { | 78 | { |
79 | struct irq_chip *chip = get_irq_chip(irq); | 79 | struct irq_chip *chip = get_irq_chip(irq); |
80 | return (void *)((char *)chip - offsetof(struct intc_desc_int, chip)); | 80 | return container_of(chip, struct intc_desc_int, chip); |
81 | } | 81 | } |
82 | 82 | ||
83 | static inline unsigned int set_field(unsigned int value, | 83 | static inline unsigned int set_field(unsigned int value, |
@@ -95,16 +95,19 @@ static inline unsigned int set_field(unsigned int value, | |||
95 | static void write_8(unsigned long addr, unsigned long h, unsigned long data) | 95 | static void write_8(unsigned long addr, unsigned long h, unsigned long data) |
96 | { | 96 | { |
97 | __raw_writeb(set_field(0, data, h), addr); | 97 | __raw_writeb(set_field(0, data, h), addr); |
98 | (void)__raw_readb(addr); /* Defeat write posting */ | ||
98 | } | 99 | } |
99 | 100 | ||
100 | static void write_16(unsigned long addr, unsigned long h, unsigned long data) | 101 | static void write_16(unsigned long addr, unsigned long h, unsigned long data) |
101 | { | 102 | { |
102 | __raw_writew(set_field(0, data, h), addr); | 103 | __raw_writew(set_field(0, data, h), addr); |
104 | (void)__raw_readw(addr); /* Defeat write posting */ | ||
103 | } | 105 | } |
104 | 106 | ||
105 | static void write_32(unsigned long addr, unsigned long h, unsigned long data) | 107 | static void write_32(unsigned long addr, unsigned long h, unsigned long data) |
106 | { | 108 | { |
107 | __raw_writel(set_field(0, data, h), addr); | 109 | __raw_writel(set_field(0, data, h), addr); |
110 | (void)__raw_readl(addr); /* Defeat write posting */ | ||
108 | } | 111 | } |
109 | 112 | ||
110 | static void modify_8(unsigned long addr, unsigned long h, unsigned long data) | 113 | static void modify_8(unsigned long addr, unsigned long h, unsigned long data) |
@@ -112,6 +115,7 @@ static void modify_8(unsigned long addr, unsigned long h, unsigned long data) | |||
112 | unsigned long flags; | 115 | unsigned long flags; |
113 | local_irq_save(flags); | 116 | local_irq_save(flags); |
114 | __raw_writeb(set_field(__raw_readb(addr), data, h), addr); | 117 | __raw_writeb(set_field(__raw_readb(addr), data, h), addr); |
118 | (void)__raw_readb(addr); /* Defeat write posting */ | ||
115 | local_irq_restore(flags); | 119 | local_irq_restore(flags); |
116 | } | 120 | } |
117 | 121 | ||
@@ -120,6 +124,7 @@ static void modify_16(unsigned long addr, unsigned long h, unsigned long data) | |||
120 | unsigned long flags; | 124 | unsigned long flags; |
121 | local_irq_save(flags); | 125 | local_irq_save(flags); |
122 | __raw_writew(set_field(__raw_readw(addr), data, h), addr); | 126 | __raw_writew(set_field(__raw_readw(addr), data, h), addr); |
127 | (void)__raw_readw(addr); /* Defeat write posting */ | ||
123 | local_irq_restore(flags); | 128 | local_irq_restore(flags); |
124 | } | 129 | } |
125 | 130 | ||
@@ -128,6 +133,7 @@ static void modify_32(unsigned long addr, unsigned long h, unsigned long data) | |||
128 | unsigned long flags; | 133 | unsigned long flags; |
129 | local_irq_save(flags); | 134 | local_irq_save(flags); |
130 | __raw_writel(set_field(__raw_readl(addr), data, h), addr); | 135 | __raw_writel(set_field(__raw_readl(addr), data, h), addr); |
136 | (void)__raw_readl(addr); /* Defeat write posting */ | ||
131 | local_irq_restore(flags); | 137 | local_irq_restore(flags); |
132 | } | 138 | } |
133 | 139 | ||
@@ -657,16 +663,9 @@ static unsigned int __init save_reg(struct intc_desc_int *d, | |||
657 | return 0; | 663 | return 0; |
658 | } | 664 | } |
659 | 665 | ||
660 | static unsigned char *intc_evt2irq_table; | 666 | static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc) |
661 | |||
662 | unsigned int intc_evt2irq(unsigned int vector) | ||
663 | { | 667 | { |
664 | unsigned int irq = evt2irq(vector); | 668 | generic_handle_irq((unsigned int)get_irq_data(irq)); |
665 | |||
666 | if (intc_evt2irq_table && intc_evt2irq_table[irq]) | ||
667 | irq = intc_evt2irq_table[irq]; | ||
668 | |||
669 | return irq; | ||
670 | } | 669 | } |
671 | 670 | ||
672 | void __init register_intc_controller(struct intc_desc *desc) | 671 | void __init register_intc_controller(struct intc_desc *desc) |
@@ -739,50 +738,48 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
739 | 738 | ||
740 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ | 739 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ |
741 | 740 | ||
742 | /* keep the first vector only if same enum is used multiple times */ | 741 | /* register the vectors one by one */ |
743 | for (i = 0; i < desc->nr_vectors; i++) { | 742 | for (i = 0; i < desc->nr_vectors; i++) { |
744 | struct intc_vect *vect = desc->vectors + i; | 743 | struct intc_vect *vect = desc->vectors + i; |
745 | int first_irq = evt2irq(vect->vect); | 744 | unsigned int irq = evt2irq(vect->vect); |
745 | struct irq_desc *irq_desc; | ||
746 | 746 | ||
747 | if (!vect->enum_id) | 747 | if (!vect->enum_id) |
748 | continue; | 748 | continue; |
749 | 749 | ||
750 | irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); | ||
751 | if (unlikely(!irq_desc)) { | ||
752 | pr_info("can't get irq_desc for %d\n", irq); | ||
753 | continue; | ||
754 | } | ||
755 | |||
756 | intc_register_irq(desc, d, vect->enum_id, irq); | ||
757 | |||
750 | for (k = i + 1; k < desc->nr_vectors; k++) { | 758 | for (k = i + 1; k < desc->nr_vectors; k++) { |
751 | struct intc_vect *vect2 = desc->vectors + k; | 759 | struct intc_vect *vect2 = desc->vectors + k; |
760 | unsigned int irq2 = evt2irq(vect2->vect); | ||
752 | 761 | ||
753 | if (vect->enum_id != vect2->enum_id) | 762 | if (vect->enum_id != vect2->enum_id) |
754 | continue; | 763 | continue; |
755 | 764 | ||
756 | vect2->enum_id = 0; | 765 | /* |
757 | 766 | * In the case of multi-evt handling and sparse | |
758 | if (!intc_evt2irq_table) | 767 | * IRQ support, each vector still needs to have |
759 | intc_evt2irq_table = kzalloc(NR_IRQS, GFP_NOWAIT); | 768 | * its own backing irq_desc. |
760 | 769 | */ | |
761 | if (!intc_evt2irq_table) { | 770 | irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id()); |
762 | pr_warning("intc: cannot allocate evt2irq!\n"); | 771 | if (unlikely(!irq_desc)) { |
772 | pr_info("can't get irq_desc for %d\n", irq2); | ||
763 | continue; | 773 | continue; |
764 | } | 774 | } |
765 | 775 | ||
766 | intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq; | 776 | vect2->enum_id = 0; |
767 | } | ||
768 | } | ||
769 | |||
770 | /* register the vectors one by one */ | ||
771 | for (i = 0; i < desc->nr_vectors; i++) { | ||
772 | struct intc_vect *vect = desc->vectors + i; | ||
773 | unsigned int irq = evt2irq(vect->vect); | ||
774 | struct irq_desc *irq_desc; | ||
775 | |||
776 | if (!vect->enum_id) | ||
777 | continue; | ||
778 | 777 | ||
779 | irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); | 778 | /* redirect this interrupts to the first one */ |
780 | if (unlikely(!irq_desc)) { | 779 | set_irq_chip_and_handler_name(irq2, &d->chip, |
781 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | 780 | intc_redirect_irq, "redirect"); |
782 | continue; | 781 | set_irq_data(irq2, (void *)irq); |
783 | } | 782 | } |
784 | |||
785 | intc_register_irq(desc, d, vect->enum_id, irq); | ||
786 | } | 783 | } |
787 | } | 784 | } |
788 | 785 | ||