linux/arch/powerpc/platforms/ps3/interrupt.c
<<
>>
Prefs
   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
  69struct 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: Synchronize 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
  88struct 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
  97static 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
 106static 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
 127static 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
 148static 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
 162static 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
 180static 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) {
 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
 217fail_set:
 218        irq_dispose_mapping(*virq);
 219fail_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
 230static 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
 254int 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
 283fail_connect:
 284        ps3_virq_destroy(*virq);
 285fail_setup:
 286        return result;
 287}
 288EXPORT_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
 299int 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}
 319EXPORT_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
 332int 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 = 0;
 343                return result;
 344        }
 345
 346        result = ps3_irq_plug_setup(cpu, outlet, virq);
 347        BUG_ON(result);
 348
 349        return result;
 350}
 351EXPORT_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
 362int 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
 385int 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
 401int 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 = 0;
 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}
 430EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
 431
 432int 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}
 464EXPORT_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
 477int 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}
 496EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
 497
 498int 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}
 521EXPORT_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
 534int 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}
 558EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
 559
 560int 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}
 578EXPORT_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
 590int 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
 612int 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)
 629static 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
 638static 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__)
 646static 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__)
 657static 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
 667static void dump_bmp(struct ps3_private* pd) {};
 668#endif /* defined(DEBUG) */
 669
 670static 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
 681static 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
 688static const struct irq_domain_ops ps3_host_ops = {
 689        .map = ps3_host_map,
 690        .match = ps3_host_match,
 691};
 692
 693void __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
 703void __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
 713static 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)) {
 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 0;
 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
 751void __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
 783void 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