root/arch/powerpc/platforms/ps3/interrupt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ps3_chip_mask
  2. ps3_chip_unmask
  3. ps3_chip_eoi
  4. ps3_virq_setup
  5. ps3_virq_destroy
  6. ps3_irq_plug_setup
  7. ps3_irq_plug_destroy
  8. ps3_event_receive_port_setup
  9. ps3_event_receive_port_destroy
  10. ps3_send_event_locally
  11. ps3_sb_event_receive_port_setup
  12. ps3_sb_event_receive_port_destroy
  13. ps3_io_irq_setup
  14. ps3_io_irq_destroy
  15. ps3_vuart_irq_setup
  16. ps3_vuart_irq_destroy
  17. ps3_spe_irq_setup
  18. ps3_spe_irq_destroy
  19. _dump_64_bmp
  20. _dump_256_bmp
  21. _dump_bmp
  22. _dump_mask
  23. dump_bmp
  24. ps3_host_map
  25. ps3_host_match
  26. ps3_register_ipi_debug_brk
  27. ps3_register_ipi_irq
  28. ps3_get_irq
  29. ps3_init_IRQ
  30. ps3_shutdown_IRQ

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

/* [<][>][^][v][top][bottom][index][help] */