aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic/common
diff options
context:
space:
mode:
authorJayachandran C <jchandra@broadcom.com>2013-01-14 10:11:54 -0500
committerJohn Crispin <blogic@openwrt.org>2013-02-16 18:15:19 -0500
commit220d9122e8c5a467fdeefc1857e077f29a623bfd (patch)
treee5efff5e5df4f3b11f77451412665ad1b4031a59 /arch/mips/netlogic/common
parentf0cb40e5c384cf2cc4b2b932b61474544ac1fc9a (diff)
MIPS: Netlogic: Optimize EIMR/EIRR accesses in 32-bit
Provide functions ack_c0_eirr(), set_c0_eimr(), clear_c0_eimr() and read_c0_eirr_and_eimr() that do the EIMR and EIRR operations and update the interrupt handling code to use these functions. Also, use the EIMR register functions to mask interrupts in the irq code. The 64-bit interrupt request and mask registers (EIRR and EIMR) are accessed when the interrupts are off, and the common operations are to set or clear a bit in these registers. Using the 64-bit c0 access functions for these operations is not optimal in 32-bit, because it will disable/restore interrupts and split/join the 64-bit value during each register access. Signed-off-by: Jayachandran C <jchandra@broadcom.com> Patchwork: http://patchwork.linux-mips.org/patch/4790/ Signed-off-by: John Crispin <blogic@openwrt.org>
Diffstat (limited to 'arch/mips/netlogic/common')
-rw-r--r--arch/mips/netlogic/common/irq.c39
-rw-r--r--arch/mips/netlogic/common/smp.c8
2 files changed, 19 insertions, 28 deletions
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index 00dcc7a2bc5a..d42cd1a2a124 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -105,21 +105,23 @@ static void xlp_pic_disable(struct irq_data *d)
105static void xlp_pic_mask_ack(struct irq_data *d) 105static void xlp_pic_mask_ack(struct irq_data *d)
106{ 106{
107 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d); 107 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
108 uint64_t mask = 1ull << pd->picirq;
109 108
110 write_c0_eirr(mask); /* ack by writing EIRR */ 109 clear_c0_eimr(pd->picirq);
110 ack_c0_eirr(pd->picirq);
111} 111}
112 112
113static void xlp_pic_unmask(struct irq_data *d) 113static void xlp_pic_unmask(struct irq_data *d)
114{ 114{
115 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d); 115 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
116 116
117 if (!pd) 117 BUG_ON(!pd);
118 return;
119 118
120 if (pd->extra_ack) 119 if (pd->extra_ack)
121 pd->extra_ack(d); 120 pd->extra_ack(d);
122 121
122 /* re-enable the intr on this cpu */
123 set_c0_eimr(pd->picirq);
124
123 /* Ack is a single write, no need to lock */ 125 /* Ack is a single write, no need to lock */
124 nlm_pic_ack(pd->node->picbase, pd->irt); 126 nlm_pic_ack(pd->node->picbase, pd->irt);
125} 127}
@@ -134,32 +136,17 @@ static struct irq_chip xlp_pic = {
134 136
135static void cpuintr_disable(struct irq_data *d) 137static void cpuintr_disable(struct irq_data *d)
136{ 138{
137 uint64_t eimr; 139 clear_c0_eimr(d->irq);
138 uint64_t mask = 1ull << d->irq;
139
140 eimr = read_c0_eimr();
141 write_c0_eimr(eimr & ~mask);
142} 140}
143 141
144static void cpuintr_enable(struct irq_data *d) 142static void cpuintr_enable(struct irq_data *d)
145{ 143{
146 uint64_t eimr; 144 set_c0_eimr(d->irq);
147 uint64_t mask = 1ull << d->irq;
148
149 eimr = read_c0_eimr();
150 write_c0_eimr(eimr | mask);
151} 145}
152 146
153static void cpuintr_ack(struct irq_data *d) 147static void cpuintr_ack(struct irq_data *d)
154{ 148{
155 uint64_t mask = 1ull << d->irq; 149 ack_c0_eirr(d->irq);
156
157 write_c0_eirr(mask);
158}
159
160static void cpuintr_nop(struct irq_data *d)
161{
162 WARN(d->irq >= PIC_IRQ_BASE, "Bad irq %d", d->irq);
163} 150}
164 151
165/* 152/*
@@ -170,9 +157,9 @@ struct irq_chip nlm_cpu_intr = {
170 .name = "XLP-CPU-INTR", 157 .name = "XLP-CPU-INTR",
171 .irq_enable = cpuintr_enable, 158 .irq_enable = cpuintr_enable,
172 .irq_disable = cpuintr_disable, 159 .irq_disable = cpuintr_disable,
173 .irq_mask = cpuintr_nop, 160 .irq_mask = cpuintr_disable,
174 .irq_ack = cpuintr_nop, 161 .irq_ack = cpuintr_ack,
175 .irq_eoi = cpuintr_ack, 162 .irq_eoi = cpuintr_enable,
176}; 163};
177 164
178static void __init nlm_init_percpu_irqs(void) 165static void __init nlm_init_percpu_irqs(void)
@@ -265,7 +252,7 @@ asmlinkage void plat_irq_dispatch(void)
265 int i, node; 252 int i, node;
266 253
267 node = nlm_nodeid(); 254 node = nlm_nodeid();
268 eirr = read_c0_eirr() & read_c0_eimr(); 255 eirr = read_c0_eirr_and_eimr();
269 256
270 i = __ilog2_u64(eirr); 257 i = __ilog2_u64(eirr);
271 if (i == -1) 258 if (i == -1)
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index a080d9ee3cd7..2bb95dcfe20a 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -84,15 +84,19 @@ void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
84/* IRQ_IPI_SMP_FUNCTION Handler */ 84/* IRQ_IPI_SMP_FUNCTION Handler */
85void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc) 85void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
86{ 86{
87 write_c0_eirr(1ull << irq); 87 clear_c0_eimr(irq);
88 ack_c0_eirr(irq);
88 smp_call_function_interrupt(); 89 smp_call_function_interrupt();
90 set_c0_eimr(irq);
89} 91}
90 92
91/* IRQ_IPI_SMP_RESCHEDULE handler */ 93/* IRQ_IPI_SMP_RESCHEDULE handler */
92void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc) 94void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
93{ 95{
94 write_c0_eirr(1ull << irq); 96 clear_c0_eimr(irq);
97 ack_c0_eirr(irq);
95 scheduler_ipi(); 98 scheduler_ipi();
99 set_c0_eimr(irq);
96} 100}
97 101
98/* 102/*