intr_machdep.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /*-
  2. * SPDX-License-Identifier: BSD-3-Clause
  3. *
  4. * Copyright (c) 1991 The Regents of the University of California.
  5. * All rights reserved.
  6. *
  7. * This code is derived from software contributed to Berkeley by
  8. * William Jolitz.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * 3. Neither the name of the University nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. */
  34. /*-
  35. * Copyright (c) 2002 Benno Rice.
  36. * All rights reserved.
  37. *
  38. * Redistribution and use in source and binary forms, with or without
  39. * modification, are permitted provided that the following conditions
  40. * are met:
  41. * 1. Redistributions of source code must retain the above copyright
  42. * notice, this list of conditions and the following disclaimer.
  43. * 2. Redistributions in binary form must reproduce the above copyright
  44. * notice, this list of conditions and the following disclaimer in the
  45. * documentation and/or other materials provided with the distribution.
  46. *
  47. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  48. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  51. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  52. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  53. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  54. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  55. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  56. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  57. * SUCH DAMAGE.
  58. *
  59. * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
  60. * form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20
  61. *
  62. * $FreeBSD$
  63. */
  64. #include "opt_isa.h"
  65. #include <sys/param.h>
  66. #include <sys/systm.h>
  67. #include <sys/kernel.h>
  68. #include <sys/queue.h>
  69. #include <sys/bus.h>
  70. #include <sys/cpuset.h>
  71. #include <sys/interrupt.h>
  72. #include <sys/ktr.h>
  73. #include <sys/lock.h>
  74. #include <sys/malloc.h>
  75. #include <sys/mutex.h>
  76. #include <sys/pcpu.h>
  77. #include <sys/smp.h>
  78. #include <sys/syslog.h>
  79. #include <sys/vmmeter.h>
  80. #include <sys/proc.h>
  81. #include <machine/frame.h>
  82. #include <machine/intr_machdep.h>
  83. #include <machine/md_var.h>
  84. #include <machine/smp.h>
  85. #include <machine/trap.h>
  86. #include "pic_if.h"
  87. #define MAX_STRAY_LOG 5
  88. static MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
  89. struct powerpc_intr {
  90. struct intr_event *event;
  91. long *cntp;
  92. void *priv; /* PIC-private data */
  93. device_t pic;
  94. u_int irq;
  95. u_int intline;
  96. u_int vector;
  97. u_int cntindex;
  98. int fwcode;
  99. int ipi;
  100. int pi_domain;
  101. enum intr_trigger trig;
  102. enum intr_polarity pol;
  103. cpuset_t pi_cpuset;
  104. };
  105. struct pic {
  106. device_t dev;
  107. uint32_t node;
  108. u_int irqs;
  109. u_int ipis;
  110. int base;
  111. };
  112. static u_int intrcnt_index = 0;
  113. static struct mtx intr_table_lock;
  114. static struct powerpc_intr **powerpc_intrs;
  115. static struct pic piclist[MAX_PICS];
  116. static u_int nvectors; /* Allocated vectors */
  117. static u_int npics; /* PICs registered */
  118. #ifdef DEV_ISA
  119. static u_int nirqs = 16; /* Allocated IRQS (ISA pre-allocated). */
  120. #else
  121. static u_int nirqs = 0; /* Allocated IRQs. */
  122. #endif
  123. static u_int stray_count;
  124. u_long *intrcnt;
  125. char *intrnames;
  126. size_t sintrcnt = sizeof(intrcnt);
  127. size_t sintrnames = sizeof(intrnames);
  128. int nintrcnt;
  129. /*
  130. * Just to start
  131. */
  132. #ifdef __powerpc64__
  133. u_int num_io_irqs = 768;
  134. #else
  135. u_int num_io_irqs = 256;
  136. #endif
  137. device_t root_pic;
  138. #ifdef SMP
  139. static void *ipi_cookie;
  140. #endif
  141. static void
  142. intrcnt_setname(const char *name, int index)
  143. {
  144. snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s",
  145. MAXCOMLEN, name);
  146. }
  147. static void
  148. intr_init(void *dummy __unused)
  149. {
  150. mtx_init(&intr_table_lock, "intr sources lock", NULL, MTX_DEF);
  151. }
  152. SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
  153. static void
  154. intr_init_sources(void *arg __unused)
  155. {
  156. powerpc_intrs = mallocarray(num_io_irqs, sizeof(*powerpc_intrs),
  157. M_INTR, M_WAITOK | M_ZERO);
  158. nintrcnt = 1 + num_io_irqs * 2 + mp_ncpus * 2;
  159. #ifdef COUNT_IPIS
  160. if (mp_ncpus > 1)
  161. nintrcnt += 8 * mp_ncpus;
  162. #endif
  163. intrcnt = mallocarray(nintrcnt, sizeof(u_long), M_INTR, M_WAITOK |
  164. M_ZERO);
  165. intrnames = mallocarray(nintrcnt, MAXCOMLEN + 1, M_INTR, M_WAITOK |
  166. M_ZERO);
  167. sintrcnt = nintrcnt * sizeof(u_long);
  168. sintrnames = nintrcnt * (MAXCOMLEN + 1);
  169. intrcnt_setname("???", 0);
  170. intrcnt_index = 1;
  171. }
  172. /*
  173. * This needs to happen before SI_SUB_CPU
  174. */
  175. SYSINIT(intr_init_sources, SI_SUB_KLD, SI_ORDER_ANY, intr_init_sources, NULL);
  176. #ifdef SMP
  177. static void
  178. smp_intr_init(void *dummy __unused)
  179. {
  180. struct powerpc_intr *i;
  181. int vector;
  182. for (vector = 0; vector < nvectors; vector++) {
  183. i = powerpc_intrs[vector];
  184. if (i != NULL && i->event != NULL && i->pic == root_pic)
  185. PIC_BIND(i->pic, i->intline, i->pi_cpuset, &i->priv);
  186. }
  187. }
  188. SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
  189. #endif
  190. void
  191. intrcnt_add(const char *name, u_long **countp)
  192. {
  193. int idx;
  194. idx = atomic_fetchadd_int(&intrcnt_index, 1);
  195. KASSERT(idx < nintrcnt, ("intrcnt_add: Interrupt counter index %d/%d"
  196. "reached nintrcnt : %d", intrcnt_index, idx, nintrcnt));
  197. *countp = &intrcnt[idx];
  198. intrcnt_setname(name, idx);
  199. }
  200. extern void kdb_backtrace(void);
  201. static struct powerpc_intr *
  202. intr_lookup(u_int irq)
  203. {
  204. char intrname[16];
  205. struct powerpc_intr *i, *iscan;
  206. int vector;
  207. mtx_lock(&intr_table_lock);
  208. for (vector = 0; vector < nvectors; vector++) {
  209. i = powerpc_intrs[vector];
  210. if (i != NULL && i->irq == irq) {
  211. mtx_unlock(&intr_table_lock);
  212. return (i);
  213. }
  214. }
  215. i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
  216. if (i == NULL) {
  217. mtx_unlock(&intr_table_lock);
  218. return (NULL);
  219. }
  220. i->event = NULL;
  221. i->cntp = NULL;
  222. i->priv = NULL;
  223. i->trig = INTR_TRIGGER_CONFORM;
  224. i->pol = INTR_POLARITY_CONFORM;
  225. i->irq = irq;
  226. i->pic = NULL;
  227. i->vector = -1;
  228. i->fwcode = 0;
  229. i->ipi = 0;
  230. #ifdef SMP
  231. i->pi_cpuset = all_cpus;
  232. #else
  233. CPU_SETOF(0, &i->pi_cpuset);
  234. #endif
  235. for (vector = 0; vector < num_io_irqs && vector <= nvectors;
  236. vector++) {
  237. iscan = powerpc_intrs[vector];
  238. if (iscan != NULL && iscan->irq == irq)
  239. break;
  240. if (iscan == NULL && i->vector == -1)
  241. i->vector = vector;
  242. iscan = NULL;
  243. }
  244. if (iscan == NULL && i->vector != -1) {
  245. powerpc_intrs[i->vector] = i;
  246. i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1);
  247. i->cntp = &intrcnt[i->cntindex];
  248. sprintf(intrname, "irq%u:", i->irq);
  249. intrcnt_setname(intrname, i->cntindex);
  250. nvectors++;
  251. }
  252. mtx_unlock(&intr_table_lock);
  253. if (iscan != NULL || i->vector == -1) {
  254. free(i, M_INTR);
  255. i = iscan;
  256. }
  257. return (i);
  258. }
  259. static int
  260. powerpc_map_irq(struct powerpc_intr *i)
  261. {
  262. struct pic *p;
  263. u_int cnt;
  264. int idx;
  265. for (idx = 0; idx < npics; idx++) {
  266. p = &piclist[idx];
  267. cnt = p->irqs + p->ipis;
  268. if (i->irq >= p->base && i->irq < p->base + cnt)
  269. break;
  270. }
  271. if (idx == npics)
  272. return (EINVAL);
  273. i->intline = i->irq - p->base;
  274. i->pic = p->dev;
  275. /* Try a best guess if that failed */
  276. if (i->pic == NULL)
  277. i->pic = root_pic;
  278. return (0);
  279. }
  280. static void
  281. powerpc_intr_eoi(void *arg)
  282. {
  283. struct powerpc_intr *i = arg;
  284. PIC_EOI(i->pic, i->intline, i->priv);
  285. }
  286. static void
  287. powerpc_intr_pre_ithread(void *arg)
  288. {
  289. struct powerpc_intr *i = arg;
  290. PIC_MASK(i->pic, i->intline, i->priv);
  291. PIC_EOI(i->pic, i->intline, i->priv);
  292. }
  293. static void
  294. powerpc_intr_post_ithread(void *arg)
  295. {
  296. struct powerpc_intr *i = arg;
  297. PIC_UNMASK(i->pic, i->intline, i->priv);
  298. }
  299. static int
  300. powerpc_assign_intr_cpu(void *arg, int cpu)
  301. {
  302. #ifdef SMP
  303. struct powerpc_intr *i = arg;
  304. if (cpu == NOCPU)
  305. i->pi_cpuset = all_cpus;
  306. else
  307. CPU_SETOF(cpu, &i->pi_cpuset);
  308. if (!cold && i->pic != NULL && i->pic == root_pic)
  309. PIC_BIND(i->pic, i->intline, i->pi_cpuset, &i->priv);
  310. return (0);
  311. #else
  312. return (EOPNOTSUPP);
  313. #endif
  314. }
  315. u_int
  316. powerpc_register_pic(device_t dev, uint32_t node, u_int irqs, u_int ipis,
  317. u_int atpic)
  318. {
  319. struct pic *p;
  320. u_int irq;
  321. int idx;
  322. mtx_lock(&intr_table_lock);
  323. /* XXX see powerpc_get_irq(). */
  324. for (idx = 0; idx < npics; idx++) {
  325. p = &piclist[idx];
  326. if (p->node != node)
  327. continue;
  328. if (node != 0 || p->dev == dev)
  329. break;
  330. }
  331. p = &piclist[idx];
  332. p->dev = dev;
  333. p->node = node;
  334. p->irqs = irqs;
  335. p->ipis = ipis;
  336. if (idx == npics) {
  337. #ifdef DEV_ISA
  338. p->base = (atpic) ? 0 : nirqs;
  339. #else
  340. p->base = nirqs;
  341. #endif
  342. irq = p->base + irqs + ipis;
  343. nirqs = MAX(nirqs, irq);
  344. npics++;
  345. }
  346. KASSERT(npics < MAX_PICS,
  347. ("Number of PICs exceeds maximum (%d)", MAX_PICS));
  348. mtx_unlock(&intr_table_lock);
  349. return (p->base);
  350. }
  351. u_int
  352. powerpc_get_irq(uint32_t node, u_int pin)
  353. {
  354. int idx;
  355. if (node == 0)
  356. return (pin);
  357. mtx_lock(&intr_table_lock);
  358. for (idx = 0; idx < npics; idx++) {
  359. if (piclist[idx].node == node) {
  360. mtx_unlock(&intr_table_lock);
  361. return (piclist[idx].base + pin);
  362. }
  363. }
  364. /*
  365. * XXX we should never encounter an unregistered PIC, but that
  366. * can only be done when we properly support bus enumeration
  367. * using multiple passes. Until then, fake an entry and give it
  368. * some adhoc maximum number of IRQs and IPIs.
  369. */
  370. piclist[idx].dev = NULL;
  371. piclist[idx].node = node;
  372. piclist[idx].irqs = 124;
  373. piclist[idx].ipis = 4;
  374. piclist[idx].base = nirqs;
  375. nirqs += (1 << 25);
  376. npics++;
  377. KASSERT(npics < MAX_PICS,
  378. ("Number of PICs exceeds maximum (%d)", MAX_PICS));
  379. mtx_unlock(&intr_table_lock);
  380. return (piclist[idx].base + pin);
  381. }
  382. int
  383. powerpc_enable_intr(void)
  384. {
  385. struct powerpc_intr *i;
  386. int error, vector;
  387. #ifdef SMP
  388. int n;
  389. #endif
  390. if (npics == 0)
  391. panic("no PIC detected\n");
  392. if (root_pic == NULL)
  393. root_pic = piclist[0].dev;
  394. KASSERT(root_pic != NULL, ("no root PIC!"));
  395. #ifdef SMP
  396. /* Install an IPI handler. */
  397. if (mp_ncpus > 1) {
  398. for (n = 0; n < npics; n++) {
  399. if (piclist[n].dev != root_pic)
  400. continue;
  401. KASSERT(piclist[n].ipis != 0,
  402. ("%s: SMP root PIC does not supply any IPIs",
  403. __func__));
  404. error = powerpc_setup_intr("IPI",
  405. MAP_IRQ(piclist[n].node, piclist[n].irqs),
  406. powerpc_ipi_handler, NULL, NULL,
  407. INTR_TYPE_MISC | INTR_EXCL, &ipi_cookie,
  408. 0 /* domain XXX */);
  409. if (error) {
  410. printf("unable to setup IPI handler\n");
  411. return (error);
  412. }
  413. /*
  414. * Some subterfuge: disable late EOI and mark this
  415. * as an IPI to the dispatch layer.
  416. */
  417. i = intr_lookup(MAP_IRQ(piclist[n].node,
  418. piclist[n].irqs));
  419. i->event->ie_post_filter = NULL;
  420. i->ipi = 1;
  421. }
  422. }
  423. #endif
  424. for (vector = 0; vector < nvectors; vector++) {
  425. i = powerpc_intrs[vector];
  426. if (i == NULL)
  427. continue;
  428. error = powerpc_map_irq(i);
  429. if (error)
  430. continue;
  431. if (i->trig == INTR_TRIGGER_INVALID)
  432. PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode,
  433. &i->trig, &i->pol);
  434. if (i->trig != INTR_TRIGGER_CONFORM ||
  435. i->pol != INTR_POLARITY_CONFORM)
  436. PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
  437. if (i->event != NULL)
  438. PIC_ENABLE(i->pic, i->intline, vector, &i->priv);
  439. }
  440. return (0);
  441. }
  442. int
  443. powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
  444. driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep,
  445. int domain)
  446. {
  447. struct powerpc_intr *i;
  448. int error, enable = 0;
  449. i = intr_lookup(irq);
  450. if (i == NULL)
  451. return (ENOMEM);
  452. if (i->event == NULL) {
  453. error = intr_event_create(&i->event, (void *)i, 0, irq,
  454. powerpc_intr_pre_ithread, powerpc_intr_post_ithread,
  455. powerpc_intr_eoi, powerpc_assign_intr_cpu, "irq%u:", irq);
  456. if (error)
  457. return (error);
  458. enable = 1;
  459. }
  460. error = intr_event_add_handler(i->event, name, filter, handler, arg,
  461. intr_priority(flags), flags, cookiep);
  462. if (error)
  463. return (error);
  464. i->pi_domain = domain;
  465. if (strcmp(name, "IPI") != 0) {
  466. CPU_ZERO(&i->pi_cpuset);
  467. CPU_COPY(&cpuset_domain[domain], &i->pi_cpuset);
  468. }
  469. mtx_lock(&intr_table_lock);
  470. intrcnt_setname(i->event->ie_fullname, i->cntindex);
  471. mtx_unlock(&intr_table_lock);
  472. if (!cold) {
  473. error = powerpc_map_irq(i);
  474. if (!error) {
  475. if (i->trig == INTR_TRIGGER_INVALID)
  476. PIC_TRANSLATE_CODE(i->pic, i->intline,
  477. i->fwcode, &i->trig, &i->pol);
  478. if (i->trig != INTR_TRIGGER_CONFORM ||
  479. i->pol != INTR_POLARITY_CONFORM)
  480. PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
  481. if (i->pic == root_pic)
  482. PIC_BIND(i->pic, i->intline, i->pi_cpuset, &i->priv);
  483. if (enable)
  484. PIC_ENABLE(i->pic, i->intline, i->vector,
  485. &i->priv);
  486. }
  487. }
  488. return (error);
  489. }
  490. int
  491. powerpc_teardown_intr(void *cookie)
  492. {
  493. return (intr_event_remove_handler(cookie));
  494. }
  495. #ifdef SMP
  496. int
  497. powerpc_bind_intr(u_int irq, u_char cpu)
  498. {
  499. struct powerpc_intr *i;
  500. i = intr_lookup(irq);
  501. if (i == NULL)
  502. return (ENOMEM);
  503. return (intr_event_bind(i->event, cpu));
  504. }
  505. #endif
  506. int
  507. powerpc_fw_config_intr(int irq, int sense_code)
  508. {
  509. struct powerpc_intr *i;
  510. i = intr_lookup(irq);
  511. if (i == NULL)
  512. return (ENOMEM);
  513. i->trig = INTR_TRIGGER_INVALID;
  514. i->pol = INTR_POLARITY_CONFORM;
  515. i->fwcode = sense_code;
  516. if (!cold && i->pic != NULL) {
  517. PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode, &i->trig,
  518. &i->pol);
  519. PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
  520. }
  521. return (0);
  522. }
  523. int
  524. powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
  525. {
  526. struct powerpc_intr *i;
  527. i = intr_lookup(irq);
  528. if (i == NULL)
  529. return (ENOMEM);
  530. i->trig = trig;
  531. i->pol = pol;
  532. if (!cold && i->pic != NULL)
  533. PIC_CONFIG(i->pic, i->intline, trig, pol);
  534. return (0);
  535. }
  536. void
  537. powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
  538. {
  539. struct powerpc_intr *i;
  540. struct intr_event *ie;
  541. i = powerpc_intrs[vector];
  542. if (i == NULL)
  543. goto stray;
  544. (*i->cntp)++;
  545. ie = i->event;
  546. KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
  547. /*
  548. * IPIs are magical and need to be EOI'ed before filtering.
  549. * This prevents races in IPI handling.
  550. */
  551. if (i->ipi)
  552. PIC_EOI(i->pic, i->intline, i->priv);
  553. if (intr_event_handle(ie, tf) != 0) {
  554. goto stray;
  555. }
  556. return;
  557. stray:
  558. stray_count++;
  559. if (stray_count <= MAX_STRAY_LOG) {
  560. printf("stray irq %d\n", i ? i->irq : -1);
  561. if (stray_count >= MAX_STRAY_LOG) {
  562. printf("got %d stray interrupts, not logging anymore\n",
  563. MAX_STRAY_LOG);
  564. }
  565. }
  566. if (i != NULL)
  567. PIC_MASK(i->pic, i->intline, i->priv);
  568. }
  569. void
  570. powerpc_intr_mask(u_int irq)
  571. {
  572. struct powerpc_intr *i;
  573. i = intr_lookup(irq);
  574. if (i == NULL || i->pic == NULL)
  575. return;
  576. PIC_MASK(i->pic, i->intline, i->priv);
  577. }
  578. void
  579. powerpc_intr_unmask(u_int irq)
  580. {
  581. struct powerpc_intr *i;
  582. i = intr_lookup(irq);
  583. if (i == NULL || i->pic == NULL)
  584. return;
  585. PIC_UNMASK(i->pic, i->intline, i->priv);
  586. }