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