linux/arch/powerpc/platforms/ps3/interrupt.c
<<
>>
Prefs
   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
  57struct 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
  76struct 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
  85static 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
  94static 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
 115static 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
 136static 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
 150static 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
 168static 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
 205fail_set:
 206        irq_dispose_mapping(*virq);
 207fail_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
 218static 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
 242int 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
 271fail_connect:
 272        ps3_virq_destroy(*virq);
 273fail_setup:
 274        return result;
 275}
 276EXPORT_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
 287int 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}
 307EXPORT_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
 320int 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}
 339EXPORT_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
 350int 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
 373int 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
 389int 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}
 418EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
 419
 420int 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}
 452EXPORT_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
 465int 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}
 484EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
 485
 486int 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}
 509EXPORT_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
 522int 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}
 546EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
 547
 548int 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}
 566EXPORT_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
 578int 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
 600int 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)
 617static 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
 626static 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__)
 634static 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__)
 645static 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
 655static void dump_bmp(struct ps3_private* pd) {};
 656#endif /* defined(DEBUG) */
 657
 658static 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
 669static 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
 676static const struct irq_domain_ops ps3_host_ops = {
 677        .map = ps3_host_map,
 678        .match = ps3_host_match,
 679};
 680
 681void __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
 691void __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
 701static 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
 739void __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
 771void 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}
 783