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/module.h> 23 #include <linux/irq.h> 24 25 #include <asm/machdep.h> 26 #include <asm/udbg.h> 27 #include <asm/lv1call.h> 28 29 #include "platform.h" 30 31 #if defined(DEBUG) 32 #define DBG(fmt...) udbg_printf(fmt) 33 #else 34 #define DBG(fmt...) do{if(0)printk(fmt);}while(0) 35 #endif 36 37 /** 38 * struct ps3_bmp - a per cpu irq status and mask bitmap structure 39 * @status: 256 bit status bitmap indexed by plug 40 * @unused_1: 41 * @mask: 256 bit mask bitmap indexed by plug 42 * @unused_2: 43 * @lock: 44 * @ipi_debug_brk_mask: 45 * 46 * The HV mantains per SMT thread mappings of HV outlet to HV plug on 47 * behalf of the guest. These mappings are implemented as 256 bit guest 48 * supplied bitmaps indexed by plug number. The addresses of the bitmaps 49 * are registered with the HV through lv1_configure_irq_state_bitmap(). 50 * The HV requires that the 512 bits of status + mask not cross a page 51 * boundary. PS3_BMP_MINALIGN is used to define this minimal 64 byte 52 * alignment. 53 * 54 * The HV supports 256 plugs per thread, assigned as {0..255}, for a total 55 * of 512 plugs supported on a processor. To simplify the logic this 56 * implementation equates HV plug value to Linux virq value, constrains each 57 * interrupt to have a system wide unique plug number, and limits the range 58 * of the plug values to map into the first dword of the bitmaps. This 59 * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note 60 * that there is no constraint on how many in this set an individual thread 61 * can acquire. 62 */ 63 64 #define PS3_BMP_MINALIGN 64 65 66 struct ps3_bmp { 67 struct { 68 u64 status; 69 u64 unused_1[3]; 70 u64 mask; 71 u64 unused_2[3]; 72 }; 73 u64 ipi_debug_brk_mask; 74 spinlock_t lock; 75 }; 76 77 /** 78 * struct ps3_private - a per cpu data structure 79 * @bmp: ps3_bmp structure 80 * @node: HV logical_ppe_id 81 * @cpu: HV thread_id 82 */ 83 84 struct ps3_private { 85 struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); 86 u64 node; 87 unsigned int cpu; 88 }; 89 90 static DEFINE_PER_CPU(struct ps3_private, ps3_private); 91 92 int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, 93 unsigned int *virq) 94 { 95 int result; 96 struct ps3_private *pd; 97 98 /* This defines the default interrupt distribution policy. */ 99 100 if (cpu == PS3_BINDING_CPU_ANY) 101 cpu = 0; 102 103 pd = &per_cpu(ps3_private, cpu); 104 105 *virq = irq_create_mapping(NULL, outlet); 106 107 if (*virq == NO_IRQ) { 108 pr_debug("%s:%d: irq_create_mapping failed: outlet %lu\n", 109 __func__, __LINE__, outlet); 110 result = -ENOMEM; 111 goto fail_create; 112 } 113 114 /* Binds outlet to cpu + virq. */ 115 116 result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); 117 118 if (result) { 119 pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", 120 __func__, __LINE__, ps3_result(result)); 121 result = -EPERM; 122 goto fail_connect; 123 } 124 125 pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__, 126 outlet, cpu, *virq); 127 128 result = set_irq_chip_data(*virq, pd); 129 130 if (result) { 131 pr_debug("%s:%d: set_irq_chip_data failed\n", 132 __func__, __LINE__); 133 goto fail_set; 134 } 135 136 return result; 137 138 fail_set: 139 lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq); 140 fail_connect: 141 irq_dispose_mapping(*virq); 142 fail_create: 143 return result; 144 } 145 EXPORT_SYMBOL_GPL(ps3_alloc_irq); 146 147 int ps3_free_irq(unsigned int virq) 148 { 149 int result; 150 const struct ps3_private *pd = get_irq_chip_data(virq); 151 152 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, 153 pd->node, pd->cpu, virq); 154 155 result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); 156 157 if (result) 158 pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", 159 __func__, __LINE__, ps3_result(result)); 160 161 set_irq_chip_data(virq, NULL); 162 irq_dispose_mapping(virq); 163 return result; 164 } 165 EXPORT_SYMBOL_GPL(ps3_free_irq); 166 167 /** 168 * ps3_alloc_io_irq - Assign a virq to a system bus device. 169 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 170 * serviced on. 171 * @interrupt_id: The device interrupt id read from the system repository. 172 * @virq: The assigned Linux virq. 173 * 174 * An io irq represents a non-virtualized device interrupt. interrupt_id 175 * coresponds to the interrupt number of the interrupt controller. 176 */ 177 178 int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id, 179 unsigned int *virq) 180 { 181 int result; 182 unsigned long outlet; 183 184 result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); 185 186 if (result) { 187 pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", 188 __func__, __LINE__, ps3_result(result)); 189 return result; 190 } 191 192 result = ps3_alloc_irq(cpu, outlet, virq); 193 BUG_ON(result); 194 195 return result; 196 } 197 EXPORT_SYMBOL_GPL(ps3_alloc_io_irq); 198 199 int ps3_free_io_irq(unsigned int virq) 200 { 201 int result; 202 203 result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); 204 205 if (result) 206 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", 207 __func__, __LINE__, ps3_result(result)); 208 209 ps3_free_irq(virq); 210 211 return result; 212 } 213 EXPORT_SYMBOL_GPL(ps3_free_io_irq); 214 215 /** 216 * ps3_alloc_event_irq - Allocate a virq for use with a system event. 217 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 218 * serviced on. 219 * @virq: The assigned Linux virq. 220 * 221 * The virq can be used with lv1_connect_interrupt_event_receive_port() to 222 * arrange to receive events, or with ps3_send_event_locally() to signal 223 * events. 224 */ 225 226 int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) 227 { 228 int result; 229 unsigned long outlet; 230 231 result = lv1_construct_event_receive_port(&outlet); 232 233 if (result) { 234 pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n", 235 __func__, __LINE__, ps3_result(result)); 236 *virq = NO_IRQ; 237 return result; 238 } 239 240 result = ps3_alloc_irq(cpu, outlet, virq); 241 BUG_ON(result); 242 243 return result; 244 } 245 246 int ps3_free_event_irq(unsigned int virq) 247 { 248 int result; 249 250 pr_debug(" -> %s:%d\n", __func__, __LINE__); 251 252 result = lv1_destruct_event_receive_port(virq_to_hw(virq)); 253 254 if (result) 255 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", 256 __func__, __LINE__, ps3_result(result)); 257 258 ps3_free_irq(virq); 259 260 pr_debug(" <- %s:%d\n", __func__, __LINE__); 261 return result; 262 } 263 264 int ps3_send_event_locally(unsigned int virq) 265 { 266 return lv1_send_event_locally(virq_to_hw(virq)); 267 } 268 269 /** 270 * ps3_connect_event_irq - Assign a virq to a system bus device. 271 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 272 * serviced on. 273 * @did: The HV device identifier read from the system repository. 274 * @interrupt_id: The device interrupt id read from the system repository. 275 * @virq: The assigned Linux virq. 276 * 277 * An event irq represents a virtual device interrupt. The interrupt_id 278 * coresponds to the software interrupt number. 279 */ 280 281 int ps3_connect_event_irq(enum ps3_cpu_binding cpu, 282 const struct ps3_device_id *did, unsigned int interrupt_id, 283 unsigned int *virq) 284 { 285 int result; 286 287 result = ps3_alloc_event_irq(cpu, virq); 288 289 if (result) 290 return result; 291 292 result = lv1_connect_interrupt_event_receive_port(did->bus_id, 293 did->dev_id, virq_to_hw(*virq), interrupt_id); 294 295 if (result) { 296 pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" 297 " failed: %s\n", __func__, __LINE__, 298 ps3_result(result)); 299 ps3_free_event_irq(*virq); 300 *virq = NO_IRQ; 301 return result; 302 } 303 304 pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, 305 interrupt_id, *virq); 306 307 return 0; 308 } 309 310 int ps3_disconnect_event_irq(const struct ps3_device_id *did, 311 unsigned int interrupt_id, unsigned int virq) 312 { 313 int result; 314 315 pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, 316 interrupt_id, virq); 317 318 result = lv1_disconnect_interrupt_event_receive_port(did->bus_id, 319 did->dev_id, virq_to_hw(virq), interrupt_id); 320 321 if (result) 322 pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" 323 " failed: %s\n", __func__, __LINE__, 324 ps3_result(result)); 325 326 ps3_free_event_irq(virq); 327 328 pr_debug(" <- %s:%d\n", __func__, __LINE__); 329 return result; 330 } 331 332 /** 333 * ps3_alloc_vuart_irq - Configure the system virtual uart virq. 334 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 335 * serviced on. 336 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap. 337 * @virq: The assigned Linux virq. 338 * 339 * The system supports only a single virtual uart, so multiple calls without 340 * freeing the interrupt will return a wrong state error. 341 */ 342 343 int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, 344 unsigned int *virq) 345 { 346 int result; 347 unsigned long outlet; 348 u64 lpar_addr; 349 350 BUG_ON(!is_kernel_addr((u64)virt_addr_bmp)); 351 352 lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp)); 353 354 result = lv1_configure_virtual_uart_irq(lpar_addr, &outlet); 355 356 if (result) { 357 pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", 358 __func__, __LINE__, ps3_result(result)); 359 return result; 360 } 361 362 result = ps3_alloc_irq(cpu, outlet, virq); 363 BUG_ON(result); 364 365 return result; 366 } 367 368 int ps3_free_vuart_irq(unsigned int virq) 369 { 370 int result; 371 372 result = lv1_deconfigure_virtual_uart_irq(); 373 374 if (result) { 375 pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", 376 __func__, __LINE__, ps3_result(result)); 377 return result; 378 } 379 380 ps3_free_irq(virq); 381 382 return result; 383 } 384 385 /** 386 * ps3_alloc_spe_irq - Configure an spe virq. 387 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 388 * serviced on. 389 * @spe_id: The spe_id returned from lv1_construct_logical_spe(). 390 * @class: The spe interrupt class {0,1,2}. 391 * @virq: The assigned Linux virq. 392 * 393 */ 394 395 int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, 396 unsigned int class, unsigned int *virq) 397 { 398 int result; 399 unsigned long outlet; 400 401 BUG_ON(class > 2); 402 403 result = lv1_get_spe_irq_outlet(spe_id, class, &outlet); 404 405 if (result) { 406 pr_debug("%s:%d: lv1_get_spe_irq_outlet failed: %s\n", 407 __func__, __LINE__, ps3_result(result)); 408 return result; 409 } 410 411 result = ps3_alloc_irq(cpu, outlet, virq); 412 BUG_ON(result); 413 414 return result; 415 } 416 417 int ps3_free_spe_irq(unsigned int virq) 418 { 419 ps3_free_irq(virq); 420 return 0; 421 } 422 423 424 #define PS3_INVALID_OUTLET ((irq_hw_number_t)-1) 425 #define PS3_PLUG_MAX 63 426 427 #if defined(DEBUG) 428 static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu, 429 const char* func, int line) 430 { 431 pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n", 432 func, line, header, cpu, 433 *p >> 48, (*p >> 32) & 0xffff, (*p >> 16) & 0xffff, 434 *p & 0xffff); 435 } 436 437 static void __attribute__ ((unused)) _dump_256_bmp(const char *header, 438 const u64 *p, unsigned cpu, const char* func, int line) 439 { 440 pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", 441 func, line, header, cpu, p[0], p[1], p[2], p[3]); 442 } 443 444 #define dump_bmp(_x) _dump_bmp(_x, __func__, __LINE__) 445 static void _dump_bmp(struct ps3_private* pd, const char* func, int line) 446 { 447 unsigned long flags; 448 449 spin_lock_irqsave(&pd->bmp.lock, flags); 450 _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line); 451 _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); 452 spin_unlock_irqrestore(&pd->bmp.lock, flags); 453 } 454 455 #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) 456 static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd, 457 const char* func, int line) 458 { 459 unsigned long flags; 460 461 spin_lock_irqsave(&pd->bmp.lock, flags); 462 _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); 463 spin_unlock_irqrestore(&pd->bmp.lock, flags); 464 } 465 #else 466 static void dump_bmp(struct ps3_private* pd) {}; 467 #endif /* defined(DEBUG) */ 468 469 static void ps3_chip_mask(unsigned int virq) 470 { 471 struct ps3_private *pd = get_irq_chip_data(virq); 472 u64 bit = 0x8000000000000000UL >> virq; 473 u64 *p = &pd->bmp.mask; 474 u64 old; 475 unsigned long flags; 476 477 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); 478 479 local_irq_save(flags); 480 asm volatile( 481 "1: ldarx %0,0,%3\n" 482 "andc %0,%0,%2\n" 483 "stdcx. %0,0,%3\n" 484 "bne- 1b" 485 : "=&r" (old), "+m" (*p) 486 : "r" (bit), "r" (p) 487 : "cc" ); 488 489 lv1_did_update_interrupt_mask(pd->node, pd->cpu); 490 local_irq_restore(flags); 491 } 492 493 static void ps3_chip_unmask(unsigned int virq) 494 { 495 struct ps3_private *pd = get_irq_chip_data(virq); 496 u64 bit = 0x8000000000000000UL >> virq; 497 u64 *p = &pd->bmp.mask; 498 u64 old; 499 unsigned long flags; 500 501 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); 502 503 local_irq_save(flags); 504 asm volatile( 505 "1: ldarx %0,0,%3\n" 506 "or %0,%0,%2\n" 507 "stdcx. %0,0,%3\n" 508 "bne- 1b" 509 : "=&r" (old), "+m" (*p) 510 : "r" (bit), "r" (p) 511 : "cc" ); 512 513 lv1_did_update_interrupt_mask(pd->node, pd->cpu); 514 local_irq_restore(flags); 515 } 516 517 static void ps3_chip_eoi(unsigned int virq) 518 { 519 const struct ps3_private *pd = get_irq_chip_data(virq); 520 lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq); 521 } 522 523 static struct irq_chip irq_chip = { 524 .typename = "ps3", 525 .mask = ps3_chip_mask, 526 .unmask = ps3_chip_unmask, 527 .eoi = ps3_chip_eoi, 528 }; 529 530 static void ps3_host_unmap(struct irq_host *h, unsigned int virq) 531 { 532 set_irq_chip_data(virq, NULL); 533 } 534 535 static int ps3_host_map(struct irq_host *h, unsigned int virq, 536 irq_hw_number_t hwirq) 537 { 538 pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, 539 virq); 540 541 set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); 542 543 return 0; 544 } 545 546 static struct irq_host_ops ps3_host_ops = { 547 .map = ps3_host_map, 548 .unmap = ps3_host_unmap, 549 }; 550 551 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) 552 { 553 struct ps3_private *pd = &per_cpu(ps3_private, cpu); 554 555 pd->bmp.ipi_debug_brk_mask = 0x8000000000000000UL >> virq; 556 557 pr_debug("%s:%d: cpu %u, virq %u, mask %lxh\n", __func__, __LINE__, 558 cpu, virq, pd->bmp.ipi_debug_brk_mask); 559 } 560 561 unsigned int ps3_get_irq(void) 562 { 563 struct ps3_private *pd = &__get_cpu_var(ps3_private); 564 u64 x = (pd->bmp.status & pd->bmp.mask); 565 unsigned int plug; 566 567 /* check for ipi break first to stop this cpu ASAP */ 568 569 if (x & pd->bmp.ipi_debug_brk_mask) 570 x &= pd->bmp.ipi_debug_brk_mask; 571 572 asm volatile("cntlzd %0,%1" : "=r" (plug) : "r" (x)); 573 plug &= 0x3f; 574 575 if (unlikely(plug) == NO_IRQ) { 576 pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__, 577 pd->cpu); 578 dump_bmp(&per_cpu(ps3_private, 0)); 579 dump_bmp(&per_cpu(ps3_private, 1)); 580 return NO_IRQ; 581 } 582 583 #if defined(DEBUG) 584 if (unlikely(plug < NUM_ISA_INTERRUPTS || plug > PS3_PLUG_MAX)) { 585 dump_bmp(&per_cpu(ps3_private, 0)); 586 dump_bmp(&per_cpu(ps3_private, 1)); 587 BUG(); 588 } 589 #endif 590 return plug; 591 } 592 593 void __init ps3_init_IRQ(void) 594 { 595 int result; 596 unsigned cpu; 597 struct irq_host *host; 598 599 host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, 600 PS3_INVALID_OUTLET); 601 irq_set_default_host(host); 602 irq_set_virq_count(PS3_PLUG_MAX + 1); 603 604 for_each_possible_cpu(cpu) { 605 struct ps3_private *pd = &per_cpu(ps3_private, cpu); 606 607 lv1_get_logical_ppe_id(&pd->node); 608 pd->cpu = get_hard_smp_processor_id(cpu); 609 spin_lock_init(&pd->bmp.lock); 610 611 pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__, 612 __LINE__, pd->node, pd->cpu, 613 ps3_mm_phys_to_lpar(__pa(&pd->bmp))); 614 615 result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu, 616 ps3_mm_phys_to_lpar(__pa(&pd->bmp))); 617 618 if (result) 619 pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" 620 " %s\n", __func__, __LINE__, 621 ps3_result(result)); 622 } 623 624 ppc_md.get_irq = ps3_get_irq; 625 } 626