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