interrupt.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /*
  2. * PS3 interrupt routines.
  3. *
  4. * Copyright (C) 2006 Sony Computer Entertainment Inc.
  5. * Copyright 2006 Sony Corp.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; version 2 of the License.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/export.h>
  22. #include <linux/irq.h>
  23. #include <asm/machdep.h>
  24. #include <asm/udbg.h>
  25. #include <asm/lv1call.h>
  26. #include <asm/smp.h>
  27. #include "platform.h"
  28. #if defined(DEBUG)
  29. #define DBG udbg_printf
  30. #else
  31. #define DBG pr_debug
  32. #endif
  33. /**
  34. * struct ps3_bmp - a per cpu irq status and mask bitmap structure
  35. * @status: 256 bit status bitmap indexed by plug
  36. * @unused_1:
  37. * @mask: 256 bit mask bitmap indexed by plug
  38. * @unused_2:
  39. * @lock:
  40. * @ipi_debug_brk_mask:
  41. *
  42. * The HV maintains per SMT thread mappings of HV outlet to HV plug on
  43. * behalf of the guest. These mappings are implemented as 256 bit guest
  44. * supplied bitmaps indexed by plug number. The addresses of the bitmaps
  45. * are registered with the HV through lv1_configure_irq_state_bitmap().
  46. * The HV requires that the 512 bits of status + mask not cross a page
  47. * boundary. PS3_BMP_MINALIGN is used to define this minimal 64 byte
  48. * alignment.
  49. *
  50. * The HV supports 256 plugs per thread, assigned as {0..255}, for a total
  51. * of 512 plugs supported on a processor. To simplify the logic this
  52. * implementation equates HV plug value to Linux virq value, constrains each
  53. * interrupt to have a system wide unique plug number, and limits the range
  54. * of the plug values to map into the first dword of the bitmaps. This
  55. * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note
  56. * that there is no constraint on how many in this set an individual thread
  57. * can acquire.
  58. *
  59. * The mask is declared as unsigned long so we can use set/clear_bit on it.
  60. */
  61. #define PS3_BMP_MINALIGN 64
  62. struct ps3_bmp {
  63. struct {
  64. u64 status;
  65. u64 unused_1[3];
  66. unsigned long mask;
  67. u64 unused_2[3];
  68. };
  69. u64 ipi_debug_brk_mask;
  70. spinlock_t lock;
  71. };
  72. /**
  73. * struct ps3_private - a per cpu data structure
  74. * @bmp: ps3_bmp structure
  75. * @ppe_id: HV logical_ppe_id
  76. * @thread_id: HV thread_id
  77. */
  78. struct ps3_private {
  79. struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
  80. u64 ppe_id;
  81. u64 thread_id;
  82. unsigned long ipi_mask;
  83. };
  84. static DEFINE_PER_CPU(struct ps3_private, ps3_private);
  85. /**
  86. * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
  87. * @virq: The assigned Linux virq.
  88. *
  89. * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
  90. */
  91. static void ps3_chip_mask(struct irq_data *d)
  92. {
  93. struct ps3_private *pd = irq_data_get_irq_chip_data(d);
  94. unsigned long flags;
  95. pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
  96. pd->thread_id, d->irq);
  97. local_irq_save(flags);
  98. clear_bit(63 - d->irq, &pd->bmp.mask);
  99. lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
  100. local_irq_restore(flags);
  101. }
  102. /**
  103. * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
  104. * @virq: The assigned Linux virq.
  105. *
  106. * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
  107. */
  108. static void ps3_chip_unmask(struct irq_data *d)
  109. {
  110. struct ps3_private *pd = irq_data_get_irq_chip_data(d);
  111. unsigned long flags;
  112. pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
  113. pd->thread_id, d->irq);
  114. local_irq_save(flags);
  115. set_bit(63 - d->irq, &pd->bmp.mask);
  116. lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
  117. local_irq_restore(flags);
  118. }
  119. /**
  120. * ps3_chip_eoi - HV end-of-interrupt.
  121. * @virq: The assigned Linux virq.
  122. *
  123. * Calls lv1_end_of_interrupt_ext().
  124. */
  125. static void ps3_chip_eoi(struct irq_data *d)
  126. {
  127. const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
  128. /* non-IPIs are EOIed here. */
  129. if (!test_bit(63 - d->irq, &pd->ipi_mask))
  130. lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
  131. }
  132. /**
  133. * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
  134. */
  135. static struct irq_chip ps3_irq_chip = {
  136. .name = "ps3",
  137. .irq_mask = ps3_chip_mask,
  138. .irq_unmask = ps3_chip_unmask,
  139. .irq_eoi = ps3_chip_eoi,
  140. };
  141. /**
  142. * ps3_virq_setup - virq related setup.
  143. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  144. * serviced on.
  145. * @outlet: The HV outlet from the various create outlet routines.
  146. * @virq: The assigned Linux virq.
  147. *
  148. * Calls irq_create_mapping() to get a virq and sets the chip data to
  149. * ps3_private data.
  150. */
  151. static int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
  152. unsigned int *virq)
  153. {
  154. int result;
  155. struct ps3_private *pd;
  156. /* This defines the default interrupt distribution policy. */
  157. if (cpu == PS3_BINDING_CPU_ANY)
  158. cpu = 0;
  159. pd = &per_cpu(ps3_private, cpu);
  160. *virq = irq_create_mapping(NULL, outlet);
  161. if (*virq == NO_IRQ) {
  162. pr_debug("%s:%d: irq_create_mapping failed: outlet %lu\n",
  163. __func__, __LINE__, outlet);
  164. result = -ENOMEM;
  165. goto fail_create;
  166. }
  167. pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
  168. outlet, cpu, *virq);
  169. result = irq_set_chip_data(*virq, pd);
  170. if (result) {
  171. pr_debug("%s:%d: irq_set_chip_data failed\n",
  172. __func__, __LINE__);
  173. goto fail_set;
  174. }
  175. ps3_chip_mask(irq_get_irq_data(*virq));
  176. return result;
  177. fail_set:
  178. irq_dispose_mapping(*virq);
  179. fail_create:
  180. return result;
  181. }
  182. /**
  183. * ps3_virq_destroy - virq related teardown.
  184. * @virq: The assigned Linux virq.
  185. *
  186. * Clears chip data and calls irq_dispose_mapping() for the virq.
  187. */
  188. static int ps3_virq_destroy(unsigned int virq)
  189. {
  190. const struct ps3_private *pd = irq_get_chip_data(virq);
  191. pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
  192. __LINE__, pd->ppe_id, pd->thread_id, virq);
  193. irq_set_chip_data(virq, NULL);
  194. irq_dispose_mapping(virq);
  195. pr_debug("%s:%d <-\n", __func__, __LINE__);
  196. return 0;
  197. }
  198. /**
  199. * ps3_irq_plug_setup - Generic outlet and virq related setup.
  200. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  201. * serviced on.
  202. * @outlet: The HV outlet from the various create outlet routines.
  203. * @virq: The assigned Linux virq.
  204. *
  205. * Sets up virq and connects the irq plug.
  206. */
  207. int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
  208. unsigned int *virq)
  209. {
  210. int result;
  211. struct ps3_private *pd;
  212. result = ps3_virq_setup(cpu, outlet, virq);
  213. if (result) {
  214. pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__);
  215. goto fail_setup;
  216. }
  217. pd = irq_get_chip_data(*virq);
  218. /* Binds outlet to cpu + virq. */
  219. result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq,
  220. outlet, 0);
  221. if (result) {
  222. pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
  223. __func__, __LINE__, ps3_result(result));
  224. result = -EPERM;
  225. goto fail_connect;
  226. }
  227. return result;
  228. fail_connect:
  229. ps3_virq_destroy(*virq);
  230. fail_setup:
  231. return result;
  232. }
  233. EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
  234. /**
  235. * ps3_irq_plug_destroy - Generic outlet and virq related teardown.
  236. * @virq: The assigned Linux virq.
  237. *
  238. * Disconnects the irq plug and tears down virq.
  239. * Do not call for system bus event interrupts setup with
  240. * ps3_sb_event_receive_port_setup().
  241. */
  242. int ps3_irq_plug_destroy(unsigned int virq)
  243. {
  244. int result;
  245. const struct ps3_private *pd = irq_get_chip_data(virq);
  246. pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
  247. __LINE__, pd->ppe_id, pd->thread_id, virq);
  248. ps3_chip_mask(irq_get_irq_data(virq));
  249. result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
  250. if (result)
  251. pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
  252. __func__, __LINE__, ps3_result(result));
  253. ps3_virq_destroy(virq);
  254. return result;
  255. }
  256. EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
  257. /**
  258. * ps3_event_receive_port_setup - Setup an event receive port.
  259. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  260. * serviced on.
  261. * @virq: The assigned Linux virq.
  262. *
  263. * The virq can be used with lv1_connect_interrupt_event_receive_port() to
  264. * arrange to receive interrupts from system-bus devices, or with
  265. * ps3_send_event_locally() to signal events.
  266. */
  267. int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
  268. {
  269. int result;
  270. u64 outlet;
  271. result = lv1_construct_event_receive_port(&outlet);
  272. if (result) {
  273. pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n",
  274. __func__, __LINE__, ps3_result(result));
  275. *virq = NO_IRQ;
  276. return result;
  277. }
  278. result = ps3_irq_plug_setup(cpu, outlet, virq);
  279. BUG_ON(result);
  280. return result;
  281. }
  282. EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup);
  283. /**
  284. * ps3_event_receive_port_destroy - Destroy an event receive port.
  285. * @virq: The assigned Linux virq.
  286. *
  287. * Since ps3_event_receive_port_destroy destroys the receive port outlet,
  288. * SB devices need to call disconnect_interrupt_event_receive_port() before
  289. * this.
  290. */
  291. int ps3_event_receive_port_destroy(unsigned int virq)
  292. {
  293. int result;
  294. pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
  295. ps3_chip_mask(irq_get_irq_data(virq));
  296. result = lv1_destruct_event_receive_port(virq_to_hw(virq));
  297. if (result)
  298. pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
  299. __func__, __LINE__, ps3_result(result));
  300. /*
  301. * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
  302. * calls from interrupt context (smp_call_function) when kexecing.
  303. */
  304. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  305. return result;
  306. }
  307. int ps3_send_event_locally(unsigned int virq)
  308. {
  309. return lv1_send_event_locally(virq_to_hw(virq));
  310. }
  311. /**
  312. * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
  313. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  314. * serviced on.
  315. * @dev: The system bus device instance.
  316. * @virq: The assigned Linux virq.
  317. *
  318. * An event irq represents a virtual device interrupt. The interrupt_id
  319. * coresponds to the software interrupt number.
  320. */
  321. int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
  322. enum ps3_cpu_binding cpu, unsigned int *virq)
  323. {
  324. /* this should go in system-bus.c */
  325. int result;
  326. result = ps3_event_receive_port_setup(cpu, virq);
  327. if (result)
  328. return result;
  329. result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
  330. dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
  331. if (result) {
  332. pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
  333. " failed: %s\n", __func__, __LINE__,
  334. ps3_result(result));
  335. ps3_event_receive_port_destroy(*virq);
  336. *virq = NO_IRQ;
  337. return result;
  338. }
  339. pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
  340. dev->interrupt_id, *virq);
  341. return 0;
  342. }
  343. EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
  344. int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
  345. unsigned int virq)
  346. {
  347. /* this should go in system-bus.c */
  348. int result;
  349. pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
  350. dev->interrupt_id, virq);
  351. result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
  352. dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
  353. if (result)
  354. pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
  355. " failed: %s\n", __func__, __LINE__,
  356. ps3_result(result));
  357. result = ps3_event_receive_port_destroy(virq);
  358. BUG_ON(result);
  359. /*
  360. * ps3_event_receive_port_destroy() destroys the IRQ plug,
  361. * so don't call ps3_irq_plug_destroy() here.
  362. */
  363. result = ps3_virq_destroy(virq);
  364. BUG_ON(result);
  365. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  366. return result;
  367. }
  368. EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy);
  369. /**
  370. * ps3_io_irq_setup - Setup a system bus io irq.
  371. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  372. * serviced on.
  373. * @interrupt_id: The device interrupt id read from the system repository.
  374. * @virq: The assigned Linux virq.
  375. *
  376. * An io irq represents a non-virtualized device interrupt. interrupt_id
  377. * coresponds to the interrupt number of the interrupt controller.
  378. */
  379. int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
  380. unsigned int *virq)
  381. {
  382. int result;
  383. u64 outlet;
  384. result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
  385. if (result) {
  386. pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
  387. __func__, __LINE__, ps3_result(result));
  388. return result;
  389. }
  390. result = ps3_irq_plug_setup(cpu, outlet, virq);
  391. BUG_ON(result);
  392. return result;
  393. }
  394. EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
  395. int ps3_io_irq_destroy(unsigned int virq)
  396. {
  397. int result;
  398. unsigned long outlet = virq_to_hw(virq);
  399. ps3_chip_mask(irq_get_irq_data(virq));
  400. /*
  401. * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
  402. * so call ps3_irq_plug_destroy() first.
  403. */
  404. result = ps3_irq_plug_destroy(virq);
  405. BUG_ON(result);
  406. result = lv1_destruct_io_irq_outlet(outlet);
  407. if (result)
  408. pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
  409. __func__, __LINE__, ps3_result(result));
  410. return result;
  411. }
  412. EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
  413. /**
  414. * ps3_vuart_irq_setup - Setup the system virtual uart virq.
  415. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  416. * serviced on.
  417. * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
  418. * @virq: The assigned Linux virq.
  419. *
  420. * The system supports only a single virtual uart, so multiple calls without
  421. * freeing the interrupt will return a wrong state error.
  422. */
  423. int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
  424. unsigned int *virq)
  425. {
  426. int result;
  427. u64 outlet;
  428. u64 lpar_addr;
  429. BUG_ON(!is_kernel_addr((u64)virt_addr_bmp));
  430. lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp));
  431. result = lv1_configure_virtual_uart_irq(lpar_addr, &outlet);
  432. if (result) {
  433. pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
  434. __func__, __LINE__, ps3_result(result));
  435. return result;
  436. }
  437. result = ps3_irq_plug_setup(cpu, outlet, virq);
  438. BUG_ON(result);
  439. return result;
  440. }
  441. EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
  442. int ps3_vuart_irq_destroy(unsigned int virq)
  443. {
  444. int result;
  445. ps3_chip_mask(irq_get_irq_data(virq));
  446. result = lv1_deconfigure_virtual_uart_irq();
  447. if (result) {
  448. pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
  449. __func__, __LINE__, ps3_result(result));
  450. return result;
  451. }
  452. result = ps3_irq_plug_destroy(virq);
  453. BUG_ON(result);
  454. return result;
  455. }
  456. EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
  457. /**
  458. * ps3_spe_irq_setup - Setup an spe virq.
  459. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  460. * serviced on.
  461. * @spe_id: The spe_id returned from lv1_construct_logical_spe().
  462. * @class: The spe interrupt class {0,1,2}.
  463. * @virq: The assigned Linux virq.
  464. *
  465. */
  466. int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
  467. unsigned int class, unsigned int *virq)
  468. {
  469. int result;
  470. u64 outlet;
  471. BUG_ON(class > 2);
  472. result = lv1_get_spe_irq_outlet(spe_id, class, &outlet);
  473. if (result) {
  474. pr_debug("%s:%d: lv1_get_spe_irq_outlet failed: %s\n",
  475. __func__, __LINE__, ps3_result(result));
  476. return result;
  477. }
  478. result = ps3_irq_plug_setup(cpu, outlet, virq);
  479. BUG_ON(result);
  480. return result;
  481. }
  482. int ps3_spe_irq_destroy(unsigned int virq)
  483. {
  484. int result;
  485. ps3_chip_mask(irq_get_irq_data(virq));
  486. result = ps3_irq_plug_destroy(virq);
  487. BUG_ON(result);
  488. return result;
  489. }
  490. #define PS3_INVALID_OUTLET ((irq_hw_number_t)-1)
  491. #define PS3_PLUG_MAX 63
  492. #if defined(DEBUG)
  493. static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu,
  494. const char* func, int line)
  495. {
  496. pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n",
  497. func, line, header, cpu,
  498. *p >> 48, (*p >> 32) & 0xffff, (*p >> 16) & 0xffff,
  499. *p & 0xffff);
  500. }
  501. static void __maybe_unused _dump_256_bmp(const char *header,
  502. const u64 *p, unsigned cpu, const char* func, int line)
  503. {
  504. pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
  505. func, line, header, cpu, p[0], p[1], p[2], p[3]);
  506. }
  507. #define dump_bmp(_x) _dump_bmp(_x, __func__, __LINE__)
  508. static void _dump_bmp(struct ps3_private* pd, const char* func, int line)
  509. {
  510. unsigned long flags;
  511. spin_lock_irqsave(&pd->bmp.lock, flags);
  512. _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line);
  513. _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
  514. spin_unlock_irqrestore(&pd->bmp.lock, flags);
  515. }
  516. #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
  517. static void __maybe_unused _dump_mask(struct ps3_private *pd,
  518. const char* func, int line)
  519. {
  520. unsigned long flags;
  521. spin_lock_irqsave(&pd->bmp.lock, flags);
  522. _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
  523. spin_unlock_irqrestore(&pd->bmp.lock, flags);
  524. }
  525. #else
  526. static void dump_bmp(struct ps3_private* pd) {};
  527. #endif /* defined(DEBUG) */
  528. static int ps3_host_map(struct irq_host *h, unsigned int virq,
  529. irq_hw_number_t hwirq)
  530. {
  531. pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
  532. virq);
  533. irq_set_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
  534. return 0;
  535. }
  536. static int ps3_host_match(struct irq_host *h, struct device_node *np)
  537. {
  538. /* Match all */
  539. return 1;
  540. }
  541. static struct irq_host_ops ps3_host_ops = {
  542. .map = ps3_host_map,
  543. .match = ps3_host_match,
  544. };
  545. void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
  546. {
  547. struct ps3_private *pd = &per_cpu(ps3_private, cpu);
  548. pd->bmp.ipi_debug_brk_mask = 0x8000000000000000UL >> virq;
  549. pr_debug("%s:%d: cpu %u, virq %u, mask %llxh\n", __func__, __LINE__,
  550. cpu, virq, pd->bmp.ipi_debug_brk_mask);
  551. }
  552. void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq)
  553. {
  554. struct ps3_private *pd = &per_cpu(ps3_private, cpu);
  555. set_bit(63 - virq, &pd->ipi_mask);
  556. DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__,
  557. cpu, virq, pd->ipi_mask);
  558. }
  559. static unsigned int ps3_get_irq(void)
  560. {
  561. struct ps3_private *pd = &__get_cpu_var(ps3_private);
  562. u64 x = (pd->bmp.status & pd->bmp.mask);
  563. unsigned int plug;
  564. /* check for ipi break first to stop this cpu ASAP */
  565. if (x & pd->bmp.ipi_debug_brk_mask)
  566. x &= pd->bmp.ipi_debug_brk_mask;
  567. asm volatile("cntlzd %0,%1" : "=r" (plug) : "r" (x));
  568. plug &= 0x3f;
  569. if (unlikely(plug == NO_IRQ)) {
  570. pr_debug("%s:%d: no plug found: thread_id %llu\n", __func__,
  571. __LINE__, pd->thread_id);
  572. dump_bmp(&per_cpu(ps3_private, 0));
  573. dump_bmp(&per_cpu(ps3_private, 1));
  574. return NO_IRQ;
  575. }
  576. #if defined(DEBUG)
  577. if (unlikely(plug < NUM_ISA_INTERRUPTS || plug > PS3_PLUG_MAX)) {
  578. dump_bmp(&per_cpu(ps3_private, 0));
  579. dump_bmp(&per_cpu(ps3_private, 1));
  580. BUG();
  581. }
  582. #endif
  583. /* IPIs are EOIed here. */
  584. if (test_bit(63 - plug, &pd->ipi_mask))
  585. lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug);
  586. return plug;
  587. }
  588. void __init ps3_init_IRQ(void)
  589. {
  590. int result;
  591. unsigned cpu;
  592. struct irq_host *host;
  593. host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
  594. PS3_INVALID_OUTLET);
  595. irq_set_default_host(host);
  596. irq_set_virq_count(PS3_PLUG_MAX + 1);
  597. for_each_possible_cpu(cpu) {
  598. struct ps3_private *pd = &per_cpu(ps3_private, cpu);
  599. lv1_get_logical_ppe_id(&pd->ppe_id);
  600. pd->thread_id = get_hard_smp_processor_id(cpu);
  601. spin_lock_init(&pd->bmp.lock);
  602. pr_debug("%s:%d: ppe_id %llu, thread_id %llu, bmp %lxh\n",
  603. __func__, __LINE__, pd->ppe_id, pd->thread_id,
  604. ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
  605. result = lv1_configure_irq_state_bitmap(pd->ppe_id,
  606. pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
  607. if (result)
  608. pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
  609. " %s\n", __func__, __LINE__,
  610. ps3_result(result));
  611. }
  612. ppc_md.get_irq = ps3_get_irq;
  613. }
  614. void ps3_shutdown_IRQ(int cpu)
  615. {
  616. int result;
  617. u64 ppe_id;
  618. u64 thread_id = get_hard_smp_processor_id(cpu);
  619. lv1_get_logical_ppe_id(&ppe_id);
  620. result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
  621. DBG("%s:%d: lv1_configure_irq_state_bitmap (%llu:%llu/%d) %s\n", __func__,
  622. __LINE__, ppe_id, thread_id, cpu, ps3_result(result));
  623. }