Deleted Added
full compact
intr_machdep.c (208165) intr_machdep.c (210528)
1/*-
2 * Copyright (c) 2006-2009 RMI Corporation
3 * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer,
11 * without modification, immediately at the beginning of the file.
12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2006-2009 RMI Corporation
3 * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer,
11 * without modification, immediately at the beginning of the file.
12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/mips/rmi/intr_machdep.c 208165 2010-05-16 19:43:48Z rrs $");
30__FBSDID("$FreeBSD: head/sys/mips/rmi/intr_machdep.c 210528 2010-07-27 09:22:41Z jchandra $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/interrupt.h>
36#include <sys/kernel.h>
37
38#include <machine/cpu.h>
39#include <machine/cpufunc.h>
40#include <machine/cpuinfo.h>
41#include <machine/cpuregs.h>
42#include <machine/frame.h>
43#include <machine/intr_machdep.h>
44#include <machine/md_var.h>
45#include <machine/trap.h>
46#include <machine/hwfunc.h>
47#include <mips/rmi/xlrconfig.h>
48#include <mips/rmi/interrupt.h>
49#include <mips/rmi/clock.h>
50#include <mips/rmi/pic.h>
51
52/*#include <machine/intrcnt.h>*/
53static mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR];
54static struct intr_event *mips_intr_events[XLR_MAX_INTR];
55static int intrcnt_index;
56
57void
58xlr_mask_hard_irq(void *source)
59{
60 uintptr_t irq = (uintptr_t) source;
61
62 write_c0_eimr64(read_c0_eimr64() & ~(1ULL << irq));
63}
64
65void
66xlr_unmask_hard_irq(void *source)
67{
68 uintptr_t irq = (uintptr_t) source;
69
70 write_c0_eimr64(read_c0_eimr64() | (1ULL << irq));
71}
72
73void
74xlr_cpu_establish_hardintr(const char *name, driver_filter_t * filt,
75 void (*handler) (void *), void *arg, int irq, int flags, void **cookiep,
76 void (*pre_ithread)(void *), void (*post_ithread)(void *),
77 void (*post_filter)(void *), int (*assign_cpu)(void *, u_char))
78{
79 struct intr_event *ie; /* descriptor for the IRQ */
80 int errcode;
81
82 if (irq < 0 || irq > XLR_MAX_INTR)
83 panic("%s called for unknown hard intr %d", __func__, irq);
84
85 /*
86 * FIXME locking - not needed now, because we do this only on
87 * startup from CPU0
88 */
89 ie = mips_intr_events[irq];
90 /* mih->cntp = &intrcnt[irq]; */
91 if (ie == NULL) {
92 errcode = intr_event_create(&ie, (void *)(uintptr_t) irq, 0,
93 irq, pre_ithread, post_ithread, post_filter, assign_cpu,
94 "hard intr%d:", irq);
95
96 if (errcode) {
97 printf("Could not create event for intr %d\n", irq);
98 return;
99 }
100 mips_intr_events[irq] = ie;
101 }
102
103 intr_event_add_handler(ie, name, filt, handler, arg,
104 intr_priority(flags), flags, cookiep);
105 xlr_unmask_hard_irq((void *)(uintptr_t) irq);
106}
107
108void
109cpu_establish_hardintr(const char *name, driver_filter_t * filt,
110 void (*handler) (void *), void *arg, int irq, int flags, void **cookiep)
111{
112 xlr_cpu_establish_hardintr(name, filt, handler, arg, irq,
113 flags, cookiep, xlr_mask_hard_irq, xlr_unmask_hard_irq,
114 NULL, NULL);
115}
116
117void
118cpu_establish_softintr(const char *name, driver_filter_t * filt,
119 void (*handler) (void *), void *arg, int irq, int flags,
120 void **cookiep)
121{
122 /* we don't separate them into soft/hard like other mips */
123 xlr_cpu_establish_hardintr(name, filt, handler, arg, irq,
124 flags, cookiep, xlr_mask_hard_irq, xlr_unmask_hard_irq,
125 NULL, NULL);
126}
127
128void
129cpu_intr(struct trapframe *tf)
130{
131 struct intr_event *ie;
132 uint64_t eirr, eimr;
133 int i;
134
135 critical_enter();
136
137 /* find a list of enabled interrupts */
138 eirr = read_c0_eirr64();
139 eimr = read_c0_eimr64();
140 eirr &= eimr;
141
142 if (eirr == 0) {
143 critical_exit();
144 return;
145 }
146 /*
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/interrupt.h>
36#include <sys/kernel.h>
37
38#include <machine/cpu.h>
39#include <machine/cpufunc.h>
40#include <machine/cpuinfo.h>
41#include <machine/cpuregs.h>
42#include <machine/frame.h>
43#include <machine/intr_machdep.h>
44#include <machine/md_var.h>
45#include <machine/trap.h>
46#include <machine/hwfunc.h>
47#include <mips/rmi/xlrconfig.h>
48#include <mips/rmi/interrupt.h>
49#include <mips/rmi/clock.h>
50#include <mips/rmi/pic.h>
51
52/*#include <machine/intrcnt.h>*/
53static mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR];
54static struct intr_event *mips_intr_events[XLR_MAX_INTR];
55static int intrcnt_index;
56
57void
58xlr_mask_hard_irq(void *source)
59{
60 uintptr_t irq = (uintptr_t) source;
61
62 write_c0_eimr64(read_c0_eimr64() & ~(1ULL << irq));
63}
64
65void
66xlr_unmask_hard_irq(void *source)
67{
68 uintptr_t irq = (uintptr_t) source;
69
70 write_c0_eimr64(read_c0_eimr64() | (1ULL << irq));
71}
72
73void
74xlr_cpu_establish_hardintr(const char *name, driver_filter_t * filt,
75 void (*handler) (void *), void *arg, int irq, int flags, void **cookiep,
76 void (*pre_ithread)(void *), void (*post_ithread)(void *),
77 void (*post_filter)(void *), int (*assign_cpu)(void *, u_char))
78{
79 struct intr_event *ie; /* descriptor for the IRQ */
80 int errcode;
81
82 if (irq < 0 || irq > XLR_MAX_INTR)
83 panic("%s called for unknown hard intr %d", __func__, irq);
84
85 /*
86 * FIXME locking - not needed now, because we do this only on
87 * startup from CPU0
88 */
89 ie = mips_intr_events[irq];
90 /* mih->cntp = &intrcnt[irq]; */
91 if (ie == NULL) {
92 errcode = intr_event_create(&ie, (void *)(uintptr_t) irq, 0,
93 irq, pre_ithread, post_ithread, post_filter, assign_cpu,
94 "hard intr%d:", irq);
95
96 if (errcode) {
97 printf("Could not create event for intr %d\n", irq);
98 return;
99 }
100 mips_intr_events[irq] = ie;
101 }
102
103 intr_event_add_handler(ie, name, filt, handler, arg,
104 intr_priority(flags), flags, cookiep);
105 xlr_unmask_hard_irq((void *)(uintptr_t) irq);
106}
107
108void
109cpu_establish_hardintr(const char *name, driver_filter_t * filt,
110 void (*handler) (void *), void *arg, int irq, int flags, void **cookiep)
111{
112 xlr_cpu_establish_hardintr(name, filt, handler, arg, irq,
113 flags, cookiep, xlr_mask_hard_irq, xlr_unmask_hard_irq,
114 NULL, NULL);
115}
116
117void
118cpu_establish_softintr(const char *name, driver_filter_t * filt,
119 void (*handler) (void *), void *arg, int irq, int flags,
120 void **cookiep)
121{
122 /* we don't separate them into soft/hard like other mips */
123 xlr_cpu_establish_hardintr(name, filt, handler, arg, irq,
124 flags, cookiep, xlr_mask_hard_irq, xlr_unmask_hard_irq,
125 NULL, NULL);
126}
127
128void
129cpu_intr(struct trapframe *tf)
130{
131 struct intr_event *ie;
132 uint64_t eirr, eimr;
133 int i;
134
135 critical_enter();
136
137 /* find a list of enabled interrupts */
138 eirr = read_c0_eirr64();
139 eimr = read_c0_eimr64();
140 eirr &= eimr;
141
142 if (eirr == 0) {
143 critical_exit();
144 return;
145 }
146 /*
147 * No need to clear the EIRR here. the handler is gonna write to
148 * compare which clears eirr also
147 * No need to clear the EIRR here as the handler writes to
148 * compare which ACKs the interrupt.
149 */
150 if (eirr & (1 << IRQ_TIMER)) {
149 */
150 if (eirr & (1 << IRQ_TIMER)) {
151 count_compare_clockhandler(tf);
151 intr_event_handle(mips_intr_events[IRQ_TIMER], tf);
152 critical_exit();
153 return;
154 }
155
156 /* FIXME sched pin >? LOCK>? */
157 for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) {
158 if ((eirr & (1ULL << i)) == 0)
159 continue;
160
161 ie = mips_intr_events[i];
162 /* Don't account special IRQs */
163 switch (i) {
164 case IRQ_IPI:
165 case IRQ_MSGRING:
166 break;
167 default:
168 mips_intrcnt_inc(mips_intr_counters[i]);
169 }
170 write_c0_eirr64(1ULL << i);
171 pic_ack(i, 0);
172 if (!ie || TAILQ_EMPTY(&ie->ie_handlers)) {
173 printf("stray interrupt %d\n", i);
174 continue;
175 }
176 if (intr_event_handle(ie, tf) != 0) {
177 printf("stray interrupt %d\n", i);
178 }
179 pic_delayed_ack(i, 0);
180 }
181 critical_exit();
182}
183
184void
185mips_intrcnt_setname(mips_intrcnt_t counter, const char *name)
186{
187 int idx = counter - intrcnt;
188
189 KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter"));
190
191 snprintf(intrnames + (MAXCOMLEN + 1) * idx,
192 MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
193}
194
195mips_intrcnt_t
196mips_intrcnt_create(const char* name)
197{
198 mips_intrcnt_t counter = &intrcnt[intrcnt_index++];
199
200 mips_intrcnt_setname(counter, name);
201 return counter;
202}
203
204void
205cpu_init_interrupts()
206{
207 int i;
208 char name[MAXCOMLEN + 1];
209
210 /*
211 * Initialize all available vectors so spare IRQ
212 * would show up in systat output
213 */
214 for (i = 0; i < XLR_MAX_INTR; i++) {
215 snprintf(name, MAXCOMLEN + 1, "int%d:", i);
216 mips_intr_counters[i] = mips_intrcnt_create(name);
217 }
218}
152 critical_exit();
153 return;
154 }
155
156 /* FIXME sched pin >? LOCK>? */
157 for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) {
158 if ((eirr & (1ULL << i)) == 0)
159 continue;
160
161 ie = mips_intr_events[i];
162 /* Don't account special IRQs */
163 switch (i) {
164 case IRQ_IPI:
165 case IRQ_MSGRING:
166 break;
167 default:
168 mips_intrcnt_inc(mips_intr_counters[i]);
169 }
170 write_c0_eirr64(1ULL << i);
171 pic_ack(i, 0);
172 if (!ie || TAILQ_EMPTY(&ie->ie_handlers)) {
173 printf("stray interrupt %d\n", i);
174 continue;
175 }
176 if (intr_event_handle(ie, tf) != 0) {
177 printf("stray interrupt %d\n", i);
178 }
179 pic_delayed_ack(i, 0);
180 }
181 critical_exit();
182}
183
184void
185mips_intrcnt_setname(mips_intrcnt_t counter, const char *name)
186{
187 int idx = counter - intrcnt;
188
189 KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter"));
190
191 snprintf(intrnames + (MAXCOMLEN + 1) * idx,
192 MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
193}
194
195mips_intrcnt_t
196mips_intrcnt_create(const char* name)
197{
198 mips_intrcnt_t counter = &intrcnt[intrcnt_index++];
199
200 mips_intrcnt_setname(counter, name);
201 return counter;
202}
203
204void
205cpu_init_interrupts()
206{
207 int i;
208 char name[MAXCOMLEN + 1];
209
210 /*
211 * Initialize all available vectors so spare IRQ
212 * would show up in systat output
213 */
214 for (i = 0; i < XLR_MAX_INTR; i++) {
215 snprintf(name, MAXCOMLEN + 1, "int%d:", i);
216 mips_intr_counters[i] = mips_intrcnt_create(name);
217 }
218}