Deleted Added
full compact
intr_machdep.c (171785) intr_machdep.c (171805)
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 43 unchanged lines hidden (view full) ---

52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
58 * form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20
59 *
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 43 unchanged lines hidden (view full) ---

52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
58 * form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20
59 *
60 * $FreeBSD: head/sys/powerpc/powerpc/intr_machdep.c 171785 2007-08-07 23:33:35Z marcel $
60 * $FreeBSD: head/sys/powerpc/powerpc/intr_machdep.c 171805 2007-08-11 19:25:32Z marcel $
61 */
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/kernel.h>
66#include <sys/queue.h>
67#include <sys/bus.h>
68#include <sys/interrupt.h>
69#include <sys/ktr.h>
70#include <sys/lock.h>
71#include <sys/malloc.h>
72#include <sys/mutex.h>
73#include <sys/pcpu.h>
61 */
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/kernel.h>
66#include <sys/queue.h>
67#include <sys/bus.h>
68#include <sys/interrupt.h>
69#include <sys/ktr.h>
70#include <sys/lock.h>
71#include <sys/malloc.h>
72#include <sys/mutex.h>
73#include <sys/pcpu.h>
74#include <sys/syslog.h>
74#include <sys/vmmeter.h>
75#include <sys/proc.h>
76
77#include <machine/frame.h>
78#include <machine/intr_machdep.h>
75#include <sys/vmmeter.h>
76#include <sys/proc.h>
77
78#include <machine/frame.h>
79#include <machine/intr_machdep.h>
80#include <machine/md_var.h>
79#include <machine/trap.h>
80
81#include <machine/trap.h>
82
83#include "pic_if.h"
84
81#define MAX_STRAY_LOG 5
82
83MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
84
85#define MAX_STRAY_LOG 5
86
87MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
88
85struct ppc_intr {
89struct powerpc_intr {
86 struct intr_event *event;
87 long *cntp;
90 struct intr_event *event;
91 long *cntp;
88 int cntidx;
92 u_int irq;
89};
90
93};
94
91static struct mtx ppc_intrs_lock;
92static struct ppc_intr **ppc_intrs;
93static u_int ppc_nintrs;
95static struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
96static u_int nvectors; /* Allocated vectors */
97static u_int stray_count;
94
98
95static int intrcnt_index;
99device_t pic;
96
100
97static void (*irq_enable)(uintptr_t);
98
99static void
100intrcnt_setname(const char *name, int index)
101{
102 snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s",
103 MAXCOMLEN, name);
104}
105
101static void
102intrcnt_setname(const char *name, int index)
103{
104 snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s",
105 MAXCOMLEN, name);
106}
107
106void
107intr_init(void (*handler)(void), int nirq, void (*irq_e)(uintptr_t),
108 void (*irq_d)(uintptr_t))
108#ifdef INTR_FILTER
109static void
110powerpc_intr_eoi(void *arg)
109{
111{
110 uint32_t msr;
112 u_int irq = (uintptr_t)arg;
111
113
112 if (ppc_intrs != NULL)
113 panic("intr_init: interrupts initialized twice\n");
114 PIC_EOI(pic, irq);
115}
114
116
115 ppc_nintrs = nirq;
116 ppc_intrs = malloc(nirq * sizeof(struct ppc_intr *), M_INTR,
117 M_NOWAIT|M_ZERO);
118 if (ppc_intrs == NULL)
119 panic("intr_init: unable to allocate interrupt handler array");
117static void
118powerpc_intr_mask(void *arg)
119{
120 u_int irq = (uintptr_t)arg;
120
121
121 mtx_init(&ppc_intrs_lock, "intr table", NULL, MTX_SPIN);
122 PIC_MASK(pic, irq);
123}
124#endif
122
125
123 irq_enable = irq_e;
126static void
127powerpc_intr_unmask(void *arg)
128{
129 u_int irq = (uintptr_t)arg;
124
130
125 intrcnt_setname("???", 0);
126 intrcnt_index = 1;
131 PIC_UNMASK(pic, irq);
132}
127
133
128 msr = mfmsr();
129 mtmsr(msr & ~PSL_EE);
130 ext_intr_install(handler);
131 mtmsr(msr);
134void
135powerpc_register_pic(device_t dev)
136{
137
138 pic = dev;
132}
133
134int
139}
140
141int
135inthand_add(const char *name, u_int irq, driver_filter_t *filter,
136 void (*handler)(void *), void *arg, int flags, void **cookiep)
142powerpc_enable_intr(void)
137{
143{
138 struct ppc_intr *i, *orphan;
139 u_int idx;
144 struct powerpc_intr *i;
145 int vector;
146
147 for (vector = 0; vector < nvectors; vector++) {
148 i = powerpc_intrs[vector];
149 if (i == NULL)
150 continue;
151
152 PIC_ENABLE(pic, i->irq, vector);
153 }
154
155 return (0);
156}
157
158int
159powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
160 driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
161{
162 struct powerpc_intr *i;
163 u_int vector;
140 int error;
141
164 int error;
165
142 /*
143 * Work around a race where more than one CPU may be registering
144 * handlers on the same IRQ at the same time.
145 */
146 mtx_lock_spin(&ppc_intrs_lock);
147 i = ppc_intrs[irq];
148 mtx_unlock_spin(&ppc_intrs_lock);
166 /* XXX lock */
149
167
168 i = NULL;
169 for (vector = 0; vector < nvectors; vector++) {
170 i = powerpc_intrs[vector];
171 if (i == NULL)
172 continue;
173 if (i->irq == irq)
174 break;
175 i = NULL;
176 }
177
150 if (i == NULL) {
178 if (i == NULL) {
179 if (nvectors >= INTR_VECTORS) {
180 /* XXX unlock */
181 return (ENOENT);
182 }
183
151 i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
184 i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
152 if (i == NULL)
185 if (i == NULL) {
186 /* XXX unlock */
153 return (ENOMEM);
187 return (ENOMEM);
188 }
154 error = intr_event_create(&i->event, (void *)irq, 0,
189 error = intr_event_create(&i->event, (void *)irq, 0,
155 (void (*)(void *))irq_enable, "irq%d:", irq);
190 powerpc_intr_unmask,
191#ifdef INTR_FILTER
192 powerpc_intr_eoi, powerpc_intr_mask,
193#endif
194 "irq%u:", irq);
156 if (error) {
195 if (error) {
196 /* XXX unlock */
157 free(i, M_INTR);
158 return (error);
159 }
160
197 free(i, M_INTR);
198 return (error);
199 }
200
161 mtx_lock_spin(&ppc_intrs_lock);
162 if (ppc_intrs[irq] != NULL) {
163 orphan = i;
164 i = ppc_intrs[irq];
165 mtx_unlock_spin(&ppc_intrs_lock);
201 vector = nvectors++;
202 powerpc_intrs[vector] = i;
166
203
167 intr_event_destroy(orphan->event);
168 free(orphan, M_INTR);
169 } else {
170 ppc_intrs[irq] = i;
171 idx = intrcnt_index++;
172 mtx_unlock_spin(&ppc_intrs_lock);
204 i->irq = irq;
173
205
174 i->cntidx = idx;
175 i->cntp = &intrcnt[idx];
176 intrcnt_setname(i->event->ie_fullname, idx);
177 }
206 /* XXX unlock */
207
208 i->cntp = &intrcnt[vector];
209 intrcnt_setname(i->event->ie_fullname, vector);
210
211 if (!cold)
212 PIC_ENABLE(pic, i->irq, vector);
213 } else {
214 /* XXX unlock */
178 }
179
180 error = intr_event_add_handler(i->event, name, filter, handler, arg,
181 intr_priority(flags), flags, cookiep);
182 if (!error)
215 }
216
217 error = intr_event_add_handler(i->event, name, filter, handler, arg,
218 intr_priority(flags), flags, cookiep);
219 if (!error)
183 intrcnt_setname(i->event->ie_fullname, i->cntidx);
220 intrcnt_setname(i->event->ie_fullname, vector);
184 return (error);
185}
186
187int
221 return (error);
222}
223
224int
188inthand_remove(u_int irq, void *cookie)
225powerpc_teardown_intr(void *cookie)
189{
190
191 return (intr_event_remove_handler(cookie));
192}
193
194void
226{
227
228 return (intr_event_remove_handler(cookie));
229}
230
231void
195intr_handle(u_int irq)
232powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
196{
233{
197 struct ppc_intr *i;
234 struct powerpc_intr *i;
198 struct intr_event *ie;
235 struct intr_event *ie;
236#ifndef INTR_FILTER
199 struct intr_handler *ih;
200 int error, sched, ret;
237 struct intr_handler *ih;
238 int error, sched, ret;
239#endif
201
240
202 i = ppc_intrs[irq];
241 i = powerpc_intrs[vector];
203 if (i == NULL)
204 goto stray;
205
242 if (i == NULL)
243 goto stray;
244
206 atomic_add_long(i->cntp, 1);
245 (*i->cntp)++;
207
208 ie = i->event;
209 KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
210
246
247 ie = i->event;
248 KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
249
250#ifdef INTR_FILTER
251 if (intr_event_handle(ie, tf) != 0) {
252 PIC_MASK(pic, i->irq);
253 log(LOG_ERR, "stray irq%u\n", i->irq);
254 }
255#else
211 if (TAILQ_EMPTY(&ie->ie_handlers))
212 goto stray;
213
214 /*
215 * Execute all fast interrupt handlers directly without Giant. Note
216 * that this means that any fast interrupt handler must be MP safe.
217 */
218 ret = 0;

--- 14 unchanged lines hidden (view full) ---

233 if (!sched) {
234 if (ret == FILTER_SCHEDULE_THREAD)
235 sched = 1;
236 }
237 }
238 critical_exit();
239
240 if (sched) {
256 if (TAILQ_EMPTY(&ie->ie_handlers))
257 goto stray;
258
259 /*
260 * Execute all fast interrupt handlers directly without Giant. Note
261 * that this means that any fast interrupt handler must be MP safe.
262 */
263 ret = 0;

--- 14 unchanged lines hidden (view full) ---

278 if (!sched) {
279 if (ret == FILTER_SCHEDULE_THREAD)
280 sched = 1;
281 }
282 }
283 critical_exit();
284
285 if (sched) {
286 PIC_MASK(pic, i->irq);
241 error = intr_event_schedule_thread(ie);
242 KASSERT(error == 0, ("%s: impossible stray interrupt",
243 __func__));
244 } else
287 error = intr_event_schedule_thread(ie);
288 KASSERT(error == 0, ("%s: impossible stray interrupt",
289 __func__));
290 } else
245 irq_enable(irq);
291 PIC_EOI(pic, i->irq);
292#endif
246 return;
247
248stray:
293 return;
294
295stray:
249 atomic_add_long(&intrcnt[0], 1);
250 if (intrcnt[0] <= MAX_STRAY_LOG) {
251 printf("stray irq %d\n", irq);
252 if (intrcnt[0] >= MAX_STRAY_LOG) {
296 stray_count++;
297 if (stray_count <= MAX_STRAY_LOG) {
298 printf("stray irq %d\n", i->irq);
299 if (stray_count >= MAX_STRAY_LOG) {
253 printf("got %d stray interrupts, not logging anymore\n",
300 printf("got %d stray interrupts, not logging anymore\n",
254 MAX_STRAY_LOG);
301 MAX_STRAY_LOG);
255 }
256 }
302 }
303 }
304 if (i != NULL)
305 PIC_MASK(pic, i->irq);
257}
306}