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