aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c299
-rw-r--r--arch/powerpc/platforms/ps3/smp.c2
-rw-r--r--arch/powerpc/platforms/ps3/spu.c12
-rw-r--r--drivers/ps3/vuart.c4
-rw-r--r--include/asm-powerpc/ps3.h23
5 files changed, 200 insertions, 140 deletions
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index d3c97fbff7ef..27afd1f0358a 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -36,15 +36,140 @@
36#endif 36#endif
37 37
38/** 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 *
52 * The HV supports 256 plugs per thread, assigned as {0..255}, for a total
53 * of 512 plugs supported on a processor. To simplify the logic this
54 * implementation equates HV plug value to Linux virq value, constrains each
55 * interrupt to have a system wide unique plug number, and limits the range
56 * of the plug values to map into the first dword of the bitmaps. This
57 * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note
58 * that there is no constraint on how many in this set an individual thread
59 * can acquire.
60 */
61
62struct ps3_bmp {
63 struct {
64 u64 status;
65 u64 unused_1[3];
66 u64 mask;
67 u64 unused_2[3];
68 };
69 u64 ipi_debug_brk_mask;
70 spinlock_t lock;
71};
72
73/**
74 * struct ps3_private - a per cpu data structure
75 * @bmp: ps3_bmp structure
76 * @node: HV logical_ppe_id
77 * @cpu: HV thread_id
78 */
79
80struct ps3_private {
81 struct ps3_bmp bmp __attribute__ ((aligned (64)));
82 u64 node;
83 unsigned int cpu;
84};
85
86static DEFINE_PER_CPU(struct ps3_private, ps3_private);
87
88static int ps3_connect_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
89 unsigned int *virq)
90{
91 int result;
92 struct ps3_private *pd;
93
94 /* This defines the default interrupt distribution policy. */
95
96 if (cpu == PS3_BINDING_CPU_ANY)
97 cpu = 0;
98
99 pd = &per_cpu(ps3_private, cpu);
100
101 *virq = irq_create_mapping(NULL, outlet);
102
103 if (*virq == NO_IRQ) {
104 pr_debug("%s:%d: irq_create_mapping failed: outlet %lu\n",
105 __func__, __LINE__, outlet);
106 result = -ENOMEM;
107 goto fail_create;
108 }
109
110 /* Binds outlet to cpu + virq. */
111
112 result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
113
114 if (result) {
115 pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
116 __func__, __LINE__, ps3_result(result));
117 result = -EPERM;
118 goto fail_connect;
119 }
120
121 pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
122 outlet, cpu, *virq);
123
124 result = set_irq_chip_data(*virq, pd);
125
126 if (result) {
127 pr_debug("%s:%d: set_irq_chip_data failed\n",
128 __func__, __LINE__);
129 goto fail_set;
130 }
131
132 return result;
133
134fail_set:
135 lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq);
136fail_connect:
137 irq_dispose_mapping(*virq);
138fail_create:
139 return result;
140}
141
142static void ps3_disconnect_irq(unsigned int virq)
143{
144 int result;
145 const struct ps3_private *pd = get_irq_chip_data(virq);
146
147 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
148 pd->node, pd->cpu, virq);
149
150 result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
151
152 if (result)
153 pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
154 __func__, __LINE__, ps3_result(result));
155
156 set_irq_chip_data(virq, NULL);
157 irq_dispose_mapping(virq);
158}
159
160/**
39 * ps3_alloc_io_irq - Assign a virq to a system bus device. 161 * ps3_alloc_io_irq - Assign a virq to a system bus device.
40 * interrupt_id: The device interrupt id read from the system repository. 162 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
163 * serviced on.
164 * @interrupt_id: The device interrupt id read from the system repository.
41 * @virq: The assigned Linux virq. 165 * @virq: The assigned Linux virq.
42 * 166 *
43 * An io irq represents a non-virtualized device interrupt. interrupt_id 167 * An io irq represents a non-virtualized device interrupt. interrupt_id
44 * coresponds to the interrupt number of the interrupt controller. 168 * coresponds to the interrupt number of the interrupt controller.
45 */ 169 */
46 170
47int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq) 171int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
172 unsigned int *virq)
48{ 173{
49 int result; 174 int result;
50 unsigned long outlet; 175 unsigned long outlet;
@@ -57,12 +182,10 @@ int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq)
57 return result; 182 return result;
58 } 183 }
59 184
60 *virq = irq_create_mapping(NULL, outlet); 185 result = ps3_connect_irq(cpu, outlet, virq);
61 186 BUG_ON(result);
62 pr_debug("%s:%d: interrupt_id %u => outlet %lu, virq %u\n",
63 __func__, __LINE__, interrupt_id, outlet, *virq);
64 187
65 return 0; 188 return result;
66} 189}
67 190
68int ps3_free_io_irq(unsigned int virq) 191int ps3_free_io_irq(unsigned int virq)
@@ -75,13 +198,15 @@ int ps3_free_io_irq(unsigned int virq)
75 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", 198 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
76 __func__, __LINE__, ps3_result(result)); 199 __func__, __LINE__, ps3_result(result));
77 200
78 irq_dispose_mapping(virq); 201 ps3_disconnect_irq(virq);
79 202
80 return result; 203 return result;
81} 204}
82 205
83/** 206/**
84 * ps3_alloc_event_irq - Allocate a virq for use with a system event. 207 * ps3_alloc_event_irq - Allocate a virq for use with a system event.
208 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
209 * serviced on.
85 * @virq: The assigned Linux virq. 210 * @virq: The assigned Linux virq.
86 * 211 *
87 * The virq can be used with lv1_connect_interrupt_event_receive_port() to 212 * The virq can be used with lv1_connect_interrupt_event_receive_port() to
@@ -89,7 +214,7 @@ int ps3_free_io_irq(unsigned int virq)
89 * events. 214 * events.
90 */ 215 */
91 216
92int ps3_alloc_event_irq(unsigned int *virq) 217int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq)
93{ 218{
94 int result; 219 int result;
95 unsigned long outlet; 220 unsigned long outlet;
@@ -103,12 +228,10 @@ int ps3_alloc_event_irq(unsigned int *virq)
103 return result; 228 return result;
104 } 229 }
105 230
106 *virq = irq_create_mapping(NULL, outlet); 231 result = ps3_connect_irq(cpu, outlet, virq);
107 232 BUG_ON(result);
108 pr_debug("%s:%d: outlet %lu, virq %u\n", __func__, __LINE__, outlet,
109 *virq);
110 233
111 return 0; 234 return result;
112} 235}
113 236
114int ps3_free_event_irq(unsigned int virq) 237int ps3_free_event_irq(unsigned int virq)
@@ -123,7 +246,7 @@ int ps3_free_event_irq(unsigned int virq)
123 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", 246 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
124 __func__, __LINE__, ps3_result(result)); 247 __func__, __LINE__, ps3_result(result));
125 248
126 irq_dispose_mapping(virq); 249 ps3_disconnect_irq(virq);
127 250
128 pr_debug(" <- %s:%d\n", __func__, __LINE__); 251 pr_debug(" <- %s:%d\n", __func__, __LINE__);
129 return result; 252 return result;
@@ -136,6 +259,8 @@ int ps3_send_event_locally(unsigned int virq)
136 259
137/** 260/**
138 * ps3_connect_event_irq - Assign a virq to a system bus device. 261 * ps3_connect_event_irq - Assign a virq to a system bus device.
262 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
263 * serviced on.
139 * @did: The HV device identifier read from the system repository. 264 * @did: The HV device identifier read from the system repository.
140 * @interrupt_id: The device interrupt id read from the system repository. 265 * @interrupt_id: The device interrupt id read from the system repository.
141 * @virq: The assigned Linux virq. 266 * @virq: The assigned Linux virq.
@@ -144,12 +269,13 @@ int ps3_send_event_locally(unsigned int virq)
144 * coresponds to the software interrupt number. 269 * coresponds to the software interrupt number.
145 */ 270 */
146 271
147int ps3_connect_event_irq(const struct ps3_device_id *did, 272int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
148 unsigned int interrupt_id, unsigned int *virq) 273 const struct ps3_device_id *did, unsigned int interrupt_id,
274 unsigned int *virq)
149{ 275{
150 int result; 276 int result;
151 277
152 result = ps3_alloc_event_irq(virq); 278 result = ps3_alloc_event_irq(cpu, virq);
153 279
154 if (result) 280 if (result)
155 return result; 281 return result;
@@ -196,6 +322,8 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
196 322
197/** 323/**
198 * ps3_alloc_vuart_irq - Configure the system virtual uart virq. 324 * ps3_alloc_vuart_irq - Configure the system virtual uart virq.
325 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
326 * serviced on.
199 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap. 327 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
200 * @virq: The assigned Linux virq. 328 * @virq: The assigned Linux virq.
201 * 329 *
@@ -203,13 +331,14 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
203 * freeing the interrupt will return a wrong state error. 331 * freeing the interrupt will return a wrong state error.
204 */ 332 */
205 333
206int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq) 334int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
335 unsigned int *virq)
207{ 336{
208 int result; 337 int result;
209 unsigned long outlet; 338 unsigned long outlet;
210 unsigned long lpar_addr; 339 u64 lpar_addr;
211 340
212 BUG_ON(!is_kernel_addr((unsigned long)virt_addr_bmp)); 341 BUG_ON(!is_kernel_addr((u64)virt_addr_bmp));
213 342
214 lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp)); 343 lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp));
215 344
@@ -221,12 +350,10 @@ int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq)
221 return result; 350 return result;
222 } 351 }
223 352
224 *virq = irq_create_mapping(NULL, outlet); 353 result = ps3_connect_irq(cpu, outlet, virq);
225 354 BUG_ON(result);
226 pr_debug("%s:%d: outlet %lu, virq %u\n", __func__, __LINE__,
227 outlet, *virq);
228 355
229 return 0; 356 return result;
230} 357}
231 358
232int ps3_free_vuart_irq(unsigned int virq) 359int ps3_free_vuart_irq(unsigned int virq)
@@ -241,21 +368,23 @@ int ps3_free_vuart_irq(unsigned int virq)
241 return result; 368 return result;
242 } 369 }
243 370
244 irq_dispose_mapping(virq); 371 ps3_disconnect_irq(virq);
245 372
246 return result; 373 return result;
247} 374}
248 375
249/** 376/**
250 * ps3_alloc_spe_irq - Configure an spe virq. 377 * ps3_alloc_spe_irq - Configure an spe virq.
378 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
379 * serviced on.
251 * @spe_id: The spe_id returned from lv1_construct_logical_spe(). 380 * @spe_id: The spe_id returned from lv1_construct_logical_spe().
252 * @class: The spe interrupt class {0,1,2}. 381 * @class: The spe interrupt class {0,1,2}.
253 * @virq: The assigned Linux virq. 382 * @virq: The assigned Linux virq.
254 * 383 *
255 */ 384 */
256 385
257int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class, 386int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
258 unsigned int *virq) 387 unsigned int class, unsigned int *virq)
259{ 388{
260 int result; 389 int result;
261 unsigned long outlet; 390 unsigned long outlet;
@@ -270,74 +399,23 @@ int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class,
270 return result; 399 return result;
271 } 400 }
272 401
273 *virq = irq_create_mapping(NULL, outlet); 402 result = ps3_connect_irq(cpu, outlet, virq);
274 403 BUG_ON(result);
275 pr_debug("%s:%d: spe_id %lu, class %u, outlet %lu, virq %u\n",
276 __func__, __LINE__, spe_id, class, outlet, *virq);
277 404
278 return 0; 405 return result;
279} 406}
280 407
281int ps3_free_spe_irq(unsigned int virq) 408int ps3_free_spe_irq(unsigned int virq)
282{ 409{
283 irq_dispose_mapping(virq); 410 ps3_disconnect_irq(virq);
284 return 0; 411 return 0;
285} 412}
286 413
287#define PS3_INVALID_OUTLET ((irq_hw_number_t)-1) 414#define PS3_INVALID_OUTLET ((irq_hw_number_t)-1)
288#define PS3_PLUG_MAX 63 415#define PS3_PLUG_MAX 63
289 416
290/**
291 * struct ps3_bmp - a per cpu irq status and mask bitmap structure
292 * @status: 256 bit status bitmap indexed by plug
293 * @unused_1:
294 * @mask: 256 bit mask bitmap indexed by plug
295 * @unused_2:
296 * @lock:
297 * @ipi_debug_brk_mask:
298 *
299 * The HV mantains per SMT thread mappings of HV outlet to HV plug on
300 * behalf of the guest. These mappings are implemented as 256 bit guest
301 * supplied bitmaps indexed by plug number. The address of the bitmaps are
302 * registered with the HV through lv1_configure_irq_state_bitmap().
303 *
304 * The HV supports 256 plugs per thread, assigned as {0..255}, for a total
305 * of 512 plugs supported on a processor. To simplify the logic this
306 * implementation equates HV plug value to linux virq value, constrains each
307 * interrupt to have a system wide unique plug number, and limits the range
308 * of the plug values to map into the first dword of the bitmaps. This
309 * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note
310 * that there is no constraint on how many in this set an individual thread
311 * can aquire.
312 */
313
314struct ps3_bmp {
315 struct {
316 unsigned long status;
317 unsigned long unused_1[3];
318 unsigned long mask;
319 unsigned long unused_2[3];
320 } __attribute__ ((aligned (64)));
321
322 spinlock_t lock;
323 unsigned long ipi_debug_brk_mask;
324};
325
326/**
327 * struct ps3_private - a per cpu data structure
328 * @bmp: ps3_bmp structure
329 * @node: HV logical_ppe_id
330 * @cpu: HV thread_id
331 */
332
333struct ps3_private {
334 struct ps3_bmp bmp;
335 unsigned long node;
336 unsigned int cpu;
337};
338
339#if defined(DEBUG) 417#if defined(DEBUG)
340static void _dump_64_bmp(const char *header, const unsigned long *p, unsigned cpu, 418static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu,
341 const char* func, int line) 419 const char* func, int line)
342{ 420{
343 pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n", 421 pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n",
@@ -347,7 +425,7 @@ static void _dump_64_bmp(const char *header, const unsigned long *p, unsigned cp
347} 425}
348 426
349static void __attribute__ ((unused)) _dump_256_bmp(const char *header, 427static void __attribute__ ((unused)) _dump_256_bmp(const char *header,
350 const unsigned long *p, unsigned cpu, const char* func, int line) 428 const u64 *p, unsigned cpu, const char* func, int line)
351{ 429{
352 pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", 430 pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
353 func, line, header, cpu, p[0], p[1], p[2], p[3]); 431 func, line, header, cpu, p[0], p[1], p[2], p[3]);
@@ -381,9 +459,9 @@ static void dump_bmp(struct ps3_private* pd) {};
381static void ps3_chip_mask(unsigned int virq) 459static void ps3_chip_mask(unsigned int virq)
382{ 460{
383 struct ps3_private *pd = get_irq_chip_data(virq); 461 struct ps3_private *pd = get_irq_chip_data(virq);
384 unsigned long bit = 0x8000000000000000UL >> virq; 462 u64 bit = 0x8000000000000000UL >> virq;
385 unsigned long *p = &pd->bmp.mask; 463 u64 *p = &pd->bmp.mask;
386 unsigned long old; 464 u64 old;
387 unsigned long flags; 465 unsigned long flags;
388 466
389 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); 467 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
@@ -405,9 +483,9 @@ static void ps3_chip_mask(unsigned int virq)
405static void ps3_chip_unmask(unsigned int virq) 483static void ps3_chip_unmask(unsigned int virq)
406{ 484{
407 struct ps3_private *pd = get_irq_chip_data(virq); 485 struct ps3_private *pd = get_irq_chip_data(virq);
408 unsigned long bit = 0x8000000000000000UL >> virq; 486 u64 bit = 0x8000000000000000UL >> virq;
409 unsigned long *p = &pd->bmp.mask; 487 u64 *p = &pd->bmp.mask;
410 unsigned long old; 488 u64 old;
411 unsigned long flags; 489 unsigned long flags;
412 490
413 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); 491 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
@@ -441,45 +519,18 @@ static struct irq_chip irq_chip = {
441 519
442static void ps3_host_unmap(struct irq_host *h, unsigned int virq) 520static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
443{ 521{
444 int result; 522 set_irq_chip_data(virq, NULL);
445 const struct ps3_private *pd = get_irq_chip_data(virq);
446
447 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
448 pd->node, pd->cpu, virq);
449
450 lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
451
452 result = set_irq_chip_data(virq, NULL);
453 BUG_ON(result);
454} 523}
455 524
456static DEFINE_PER_CPU(struct ps3_private, ps3_private);
457
458static int ps3_host_map(struct irq_host *h, unsigned int virq, 525static int ps3_host_map(struct irq_host *h, unsigned int virq,
459 irq_hw_number_t hwirq) 526 irq_hw_number_t hwirq)
460{ 527{
461 int result; 528 pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
462 struct ps3_private *pd = &__get_cpu_var(ps3_private); 529 virq);
463
464 pr_debug("%s:%d: node %lu, cpu %d, hwirq %lu => virq %u\n", __func__,
465 __LINE__, pd->node, pd->cpu, hwirq, virq);
466
467 /* Binds this virq to pd->cpu (current cpu) */
468
469 result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, virq, hwirq, 0);
470
471 if (result) {
472 pr_info("%s:%d: lv1_connect_irq_plug_ext failed:"
473 " %s\n", __func__, __LINE__, ps3_result(result));
474 return -EPERM;
475 }
476
477 result = set_irq_chip_data(virq, pd);
478 BUG_ON(result);
479 530
480 set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); 531 set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
481 532
482 return result; 533 return 0;
483} 534}
484 535
485static struct irq_host_ops ps3_host_ops = { 536static struct irq_host_ops ps3_host_ops = {
@@ -500,7 +551,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
500unsigned int ps3_get_irq(void) 551unsigned int ps3_get_irq(void)
501{ 552{
502 struct ps3_private *pd = &__get_cpu_var(ps3_private); 553 struct ps3_private *pd = &__get_cpu_var(ps3_private);
503 unsigned long x = (pd->bmp.status & pd->bmp.mask); 554 u64 x = (pd->bmp.status & pd->bmp.mask);
504 unsigned int plug; 555 unsigned int plug;
505 556
506 /* check for ipi break first to stop this cpu ASAP */ 557 /* check for ipi break first to stop this cpu ASAP */
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c
index 11d2080607ed..bde71b0572bd 100644
--- a/arch/powerpc/platforms/ps3/smp.c
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -111,7 +111,7 @@ static void __init ps3_smp_setup_cpu(int cpu)
111 BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); 111 BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
112 112
113 for (i = 0; i < MSG_COUNT; i++) { 113 for (i = 0; i < MSG_COUNT; i++) {
114 result = ps3_alloc_event_irq(&virqs[i]); 114 result = ps3_alloc_event_irq(cpu, &virqs[i]);
115 115
116 if (result) 116 if (result)
117 continue; 117 continue;
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index ed88dc6a7f2f..9f6edc58568d 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -267,20 +267,20 @@ static int __init setup_interrupts(struct spu *spu)
267{ 267{
268 int result; 268 int result;
269 269
270 result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 0, 270 result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
271 &spu->irqs[0]); 271 0, &spu->irqs[0]);
272 272
273 if (result) 273 if (result)
274 goto fail_alloc_0; 274 goto fail_alloc_0;
275 275
276 result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 1, 276 result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
277 &spu->irqs[1]); 277 1, &spu->irqs[1]);
278 278
279 if (result) 279 if (result)
280 goto fail_alloc_1; 280 goto fail_alloc_1;
281 281
282 result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 2, 282 result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
283 &spu->irqs[2]); 283 2, &spu->irqs[2]);
284 284
285 if (result) 285 if (result)
286 goto fail_alloc_2; 286 goto fail_alloc_2;
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index 6974f65bcda5..a72da8f651f8 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -783,8 +783,8 @@ static int ps3_vuart_probe(struct device *_dev)
783 783
784 vuart_private.in_use++; 784 vuart_private.in_use++;
785 if (vuart_private.in_use == 1) { 785 if (vuart_private.in_use == 1) {
786 result = ps3_alloc_vuart_irq((void*)&vuart_private.bmp.status, 786 result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY,
787 &vuart_private.virq); 787 (void*)&vuart_private.bmp.status, &vuart_private.virq);
788 788
789 if (result) { 789 if (result) {
790 dev_dbg(&dev->core, 790 dev_dbg(&dev->core,
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 8fed3a041dee..021f802161a6 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -140,19 +140,28 @@ unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr);
140 140
141/* inrerrupt routines */ 141/* inrerrupt routines */
142 142
143int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq); 143enum ps3_cpu_binding {
144 PS3_BINDING_CPU_ANY = -1,
145 PS3_BINDING_CPU_0 = 0,
146 PS3_BINDING_CPU_1 = 1,
147};
148
149int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
150 unsigned int *virq);
144int ps3_free_io_irq(unsigned int virq); 151int ps3_free_io_irq(unsigned int virq);
145int ps3_alloc_event_irq(unsigned int *virq); 152int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq);
146int ps3_free_event_irq(unsigned int virq); 153int ps3_free_event_irq(unsigned int virq);
147int ps3_send_event_locally(unsigned int virq); 154int ps3_send_event_locally(unsigned int virq);
148int ps3_connect_event_irq(const struct ps3_device_id *did, 155int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
149 unsigned int interrupt_id, unsigned int *virq); 156 const struct ps3_device_id *did, unsigned int interrupt_id,
157 unsigned int *virq);
150int ps3_disconnect_event_irq(const struct ps3_device_id *did, 158int ps3_disconnect_event_irq(const struct ps3_device_id *did,
151 unsigned int interrupt_id, unsigned int virq); 159 unsigned int interrupt_id, unsigned int virq);
152int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq); 160int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
153int ps3_free_vuart_irq(unsigned int virq);
154int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class,
155 unsigned int *virq); 161 unsigned int *virq);
162int ps3_free_vuart_irq(unsigned int virq);
163int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
164 unsigned int class, unsigned int *virq);
156int ps3_free_spe_irq(unsigned int virq); 165int ps3_free_spe_irq(unsigned int virq);
157 166
158/* lv1 result codes */ 167/* lv1 result codes */