aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeoff Levand <geoffrey.levand@am.sony.com>2007-01-26 22:08:08 -0500
committerPaul Mackerras <paulus@samba.org>2007-02-06 22:03:18 -0500
commit861be32ce7f1cf272a3f809e77213b83117a0bd2 (patch)
tree5765d9227e3dd87582b586d16755e843695f0dd8
parent9cf9e19667f6ce01bd509a154157270069f836f9 (diff)
[POWERPC] ps3: bind interrupt to cpu
Change the PS3 irq allocation routines to take an argument indicating which cpu (processor thread) the interrupt should be serviced on. The current system configuration favors device interrupts that are serviced on cpu0, so that is used as the default. Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-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 */