/arch/powerpc/platforms/ps3/interrupt.c

http://github.com/mirrors/linux · C · 782 lines · 440 code · 169 blank · 173 comment · 24 complexity · dda5d016049cdb4dd83575e4535ac1c3 MD5 · raw file

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