1/* $Id: ml_SN_intr.c,v 1.1.1.1 2008/10/15 03:26:03 james26_jang Exp $ 2 * 3 * This file is subject to the terms and conditions of the GNU General Public 4 * License. See the file "COPYING" in the main directory of this archive 5 * for more details. 6 * 7 * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. 8 */ 9 10/* 11 * intr.c- 12 * This file contains all of the routines necessary to set up and 13 * handle interrupts on an IP27 board. 14 */ 15 16#ident "$Revision: 1.1.1.1 $" 17 18#include <linux/types.h> 19#include <linux/config.h> 20#include <linux/slab.h> 21#include <asm/smp.h> 22#include <asm/sn/sgi.h> 23#include <asm/sn/io.h> 24#include <asm/sn/iograph.h> 25#include <asm/sn/invent.h> 26#include <asm/sn/hcl.h> 27#include <asm/sn/labelcl.h> 28#include <asm/sn/sn_private.h> 29#include <asm/sn/klconfig.h> 30#include <asm/sn/sn_cpuid.h> 31#include <asm/sn/pci/pciio.h> 32#include <asm/sn/pci/pcibr.h> 33#include <asm/sn/xtalk/xtalk.h> 34#include <asm/sn/pci/pcibr_private.h> 35#include <asm/sn/intr.h> 36 37 38#if DEBUG_INTR_TSTAMP_DEBUG 39#include <sys/debug.h> 40#include <sys/idbg.h> 41#include <sys/inst.h> 42void do_splx_log(int, int); 43void spldebug_log_event(int); 44#endif 45 46#ifdef CONFIG_SMP 47extern unsigned long cpu_online_map; 48#endif 49#define cpu_allows_intr(cpu) (1) 50// If I understand what's going on with this, 32 should work. 51// physmem_maxradius seems to be the maximum number of router 52// hops to get from one end of the system to the other. With 53// a maximally configured machine, with the dumbest possible 54// topology, we would make 32 router hops. For what we're using 55// it for, the dumbest possible should suffice. 56#define physmem_maxradius() 32 57 58#define SUBNODE_ANY (-1) 59 60extern int nmied; 61extern int hub_intr_wakeup_cnt; 62extern synergy_da_t *Synergy_da_indr[]; 63extern cpuid_t master_procid; 64 65extern cnodeid_t master_node_get(devfs_handle_t vhdl); 66 67extern void snia_error_intr_handler(int irq, void *devid, struct pt_regs *pt_regs); 68 69 70#define INTR_LOCK(vecblk) \ 71 (s = mutex_spinlock(&(vecblk)->vector_lock)) 72#define INTR_UNLOCK(vecblk) \ 73 mutex_spinunlock(&(vecblk)->vector_lock, s) 74 75/* 76 * REACT/Pro 77 */ 78 79 80 81/* 82 * Find first bit set 83 * Used outside this file also 84 */ 85int ms1bit(unsigned long x) 86{ 87 int b; 88 89 if (x >> 32) b = 32, x >>= 32; 90 else b = 0; 91 if (x >> 16) b += 16, x >>= 16; 92 if (x >> 8) b += 8, x >>= 8; 93 if (x >> 4) b += 4, x >>= 4; 94 if (x >> 2) b += 2, x >>= 2; 95 96 return b + (int) (x >> 1); 97} 98 99/* ARGSUSED */ 100void 101intr_stray(void *lvl) 102{ 103 printk(KERN_WARNING "Stray Interrupt - level %ld to cpu %d", (long)lvl, smp_processor_id()); 104} 105 106#if defined(DEBUG) 107 108/* Infrastructure to gather the device - target cpu mapping info */ 109#define MAX_DEVICES 1000 /* Reasonable large number . Need not be 110 * the exact maximum # devices possible. 111 */ 112#define MAX_NAME 100 113typedef struct { 114 dev_t dev; /* device */ 115 cpuid_t cpuid; /* target cpu */ 116 cnodeid_t cnodeid;/* node on which the target cpu is present */ 117 int bit; /* intr bit reserved */ 118 char intr_name[MAX_NAME]; /* name of the interrupt */ 119} intr_dev_targ_map_t; 120 121intr_dev_targ_map_t intr_dev_targ_map[MAX_DEVICES]; 122uint64_t intr_dev_targ_map_size; 123spinlock_t intr_dev_targ_map_lock; 124 125/* Print out the device - target cpu mapping. 126 * This routine is used only in the idbg command 127 * "intrmap" 128 */ 129void 130intr_dev_targ_map_print(cnodeid_t cnodeid) 131{ 132 int i,j,size = 0; 133 int print_flag = 0,verbose = 0; 134 char node_name[10]; 135 136 if (cnodeid != CNODEID_NONE) { 137 nodepda_t *npda; 138 139 npda = NODEPDA(cnodeid); 140 for (j=0; j<NUM_SUBNODES; j++) { 141 qprintf("\n SUBNODE %d\n INT_PEND0: ", j); 142 for(i = 0 ; i < N_INTPEND_BITS ; i++) 143 qprintf("%d",SNPDA(npda,j)->intr_dispatch0.info[i].ii_flags); 144 qprintf("\n INT_PEND1: "); 145 for(i = 0 ; i < N_INTPEND_BITS ; i++) 146 qprintf("%d",SNPDA(npda,j)->intr_dispatch1.info[i].ii_flags); 147 } 148 verbose = 1; 149 } 150 qprintf("\n Device - Target Map [Interrupts: %s Node%s]\n\n", 151 (verbose ? "All" : "Non-hardwired"), 152 (cnodeid == CNODEID_NONE) ? "s: All" : node_name); 153 154 qprintf("Device\tCpu\tCnode\tIntr_bit\tIntr_name\n"); 155 for (i = 0 ; i < intr_dev_targ_map_size ; i++) { 156 157 print_flag = 0; 158 if (verbose) { 159 if (cnodeid != CNODEID_NONE) { 160 if (cnodeid == intr_dev_targ_map[i].cnodeid) 161 print_flag = 1; 162 } else { 163 print_flag = 1; 164 } 165 } else { 166 if (intr_dev_targ_map[i].dev != 0) { 167 if (cnodeid != CNODEID_NONE) { 168 if (cnodeid == 169 intr_dev_targ_map[i].cnodeid) 170 print_flag = 1; 171 } else { 172 print_flag = 1; 173 } 174 } 175 } 176 if (print_flag) { 177 size++; 178 qprintf("%d\t%d\t%d\t%d\t%s\n", 179 intr_dev_targ_map[i].dev, 180 intr_dev_targ_map[i].cpuid, 181 intr_dev_targ_map[i].cnodeid, 182 intr_dev_targ_map[i].bit, 183 intr_dev_targ_map[i].intr_name); 184 } 185 186 } 187 qprintf("\nTotal : %d\n",size); 188} 189#endif /* DEBUG */ 190 191/* 192 * The spinlocks have already been initialized. Now initialize the interrupt 193 * vectors. One processor on each hub does the work. 194 */ 195void 196intr_init_vecblk(nodepda_t *npda, cnodeid_t node, int sn) 197{ 198 int i, ip=0; 199 intr_vecblk_t *vecblk; 200 subnode_pda_t *snpda; 201 202 203 snpda = SNPDA(npda,sn); 204 do { 205 if (ip == 0) { 206 vecblk = &snpda->intr_dispatch0; 207 } else { 208 vecblk = &snpda->intr_dispatch1; 209 } 210 211 /* Initialize this vector. */ 212 for (i = 0; i < N_INTPEND_BITS; i++) { 213 vecblk->vectors[i].iv_func = intr_stray; 214 vecblk->vectors[i].iv_prefunc = NULL; 215 vecblk->vectors[i].iv_arg = (void *)(__psint_t)(ip * N_INTPEND_BITS + i); 216 217 vecblk->info[i].ii_owner_dev = 0; 218 strcpy(vecblk->info[i].ii_name, "Unused"); 219 vecblk->info[i].ii_flags = 0; /* No flags */ 220 vecblk->vectors[i].iv_mustruncpu = -1; /* No CPU yet. */ 221 222 } 223 224 mutex_spinlock_init(&vecblk->vector_lock); 225 226 vecblk->vector_count = 0; 227 for (i = 0; i < CPUS_PER_SUBNODE; i++) 228 vecblk->cpu_count[i] = 0; 229 230 vecblk->vector_state = VECTOR_UNINITED; 231 232 } while (++ip < 2); 233 234} 235 236 237/* 238 * do_intr_reserve_level(cpuid_t cpu, int bit, int resflags, int reserve, 239 * devfs_handle_t owner_dev, char *name) 240 * Internal work routine to reserve or unreserve an interrupt level. 241 * cpu is the CPU to which the interrupt will be sent. 242 * bit is the level bit to reserve. -1 means any level 243 * resflags should include II_ERRORINT if this is an 244 * error interrupt, II_THREADED if the interrupt handler 245 * will be threaded, or 0 otherwise. 246 * reserve should be set to II_RESERVE or II_UNRESERVE 247 * to get or clear a reservation. 248 * owner_dev is the device that "owns" this interrupt, if supplied 249 * name is a human-readable name for this interrupt, if supplied 250 * intr_reserve_level returns the bit reserved or -1 to indicate an error 251 */ 252static int 253do_intr_reserve_level(cpuid_t cpu, int bit, int resflags, int reserve, 254 devfs_handle_t owner_dev, char *name) 255{ 256 intr_vecblk_t *vecblk; 257 hub_intmasks_t *hub_intmasks; 258 unsigned long s; 259 int rv = 0; 260 int ip; 261 synergy_da_t *sda; 262 int which_synergy; 263 cnodeid_t cnode; 264 265 ASSERT(bit < N_INTPEND_BITS * 2); 266 267 cnode = cpuid_to_cnodeid(cpu); 268 which_synergy = cpuid_to_synergy(cpu); 269 sda = Synergy_da_indr[(cnode * 2) + which_synergy]; 270 hub_intmasks = &sda->s_intmasks; 271 // hub_intmasks = &pdaindr[cpu].pda->p_intmasks; 272 273 // if (pdaindr[cpu].pda == NULL) return -1; 274 if ((bit < N_INTPEND_BITS) && !(resflags & II_ERRORINT)) { 275 vecblk = hub_intmasks->dispatch0; 276 ip = 0; 277 } else { 278 ASSERT((bit >= N_INTPEND_BITS) || (bit == -1)); 279 bit -= N_INTPEND_BITS; /* Get position relative to INT_PEND1 reg. */ 280 vecblk = hub_intmasks->dispatch1; 281 ip = 1; 282 } 283 284 INTR_LOCK(vecblk); 285 286 if (bit <= -1) { 287 bit = 0; 288 ASSERT(reserve == II_RESERVE); 289 /* Choose any available level */ 290 for (; bit < N_INTPEND_BITS; bit++) { 291 if (!(vecblk->info[bit].ii_flags & II_RESERVE)) { 292 rv = bit; 293 break; 294 } 295 } 296 297 /* Return -1 if all interrupt levels int this register are taken. */ 298 if (bit == N_INTPEND_BITS) 299 rv = -1; 300 301 } else { 302 /* Reserve a particular level if it's available. */ 303 if ((vecblk->info[bit].ii_flags & II_RESERVE) == reserve) { 304 /* Can't (un)reserve a level that's already (un)reserved. */ 305 rv = -1; 306 } else { 307 rv = bit; 308 } 309 } 310 311 /* Reserve the level and bump the count. */ 312 if (rv != -1) { 313 if (reserve) { 314 int maxlen = sizeof(vecblk->info[bit].ii_name) - 1; 315 int namelen; 316 vecblk->info[bit].ii_flags |= (II_RESERVE | resflags); 317 vecblk->info[bit].ii_owner_dev = owner_dev; 318 /* Copy in the name. */ 319 namelen = name ? strlen(name) : 0; 320 strncpy(vecblk->info[bit].ii_name, name, min(namelen, maxlen)); 321 vecblk->info[bit].ii_name[maxlen] = '\0'; 322 vecblk->vector_count++; 323 } else { 324 vecblk->info[bit].ii_flags = 0; /* Clear all the flags */ 325 vecblk->info[bit].ii_owner_dev = 0; 326 /* Clear the name. */ 327 vecblk->info[bit].ii_name[0] = '\0'; 328 vecblk->vector_count--; 329 } 330 } 331 332 INTR_UNLOCK(vecblk); 333 334#if defined(DEBUG) 335 if (rv >= 0) { 336 int namelen = name ? strlen(name) : 0; 337 /* Gather this device - target cpu mapping information 338 * in a table which can be used later by the idbg "intrmap" 339 * command 340 */ 341 s = mutex_spinlock(&intr_dev_targ_map_lock); 342 if (intr_dev_targ_map_size < MAX_DEVICES) { 343 intr_dev_targ_map_t *p; 344 345 p = &intr_dev_targ_map[intr_dev_targ_map_size]; 346 p->dev = owner_dev; 347 p->cpuid = cpu; 348 p->cnodeid = cpuid_to_cnodeid(cpu); 349 p->bit = ip * N_INTPEND_BITS + rv; 350 strncpy(p->intr_name, 351 name, 352 min(MAX_NAME,namelen)); 353 intr_dev_targ_map_size++; 354 } 355 mutex_spinunlock(&intr_dev_targ_map_lock,s); 356 } 357#endif /* DEBUG */ 358 359 return (((rv == -1) ? rv : (ip * N_INTPEND_BITS) + rv)) ; 360} 361 362 363/* 364 * WARNING: This routine should only be called from within ml/SN. 365 * Reserve an interrupt level. 366 */ 367int 368intr_reserve_level(cpuid_t cpu, int bit, int resflags, devfs_handle_t owner_dev, char *name) 369{ 370 return(do_intr_reserve_level(cpu, bit, resflags, II_RESERVE, owner_dev, name)); 371} 372 373 374/* 375 * WARNING: This routine should only be called from within ml/SN. 376 * Unreserve an interrupt level. 377 */ 378void 379intr_unreserve_level(cpuid_t cpu, int bit) 380{ 381 (void)do_intr_reserve_level(cpu, bit, 0, II_UNRESERVE, 0, NULL); 382} 383 384/* 385 * Get values that vary depending on which CPU and bit we're operating on 386 */ 387static hub_intmasks_t * 388intr_get_ptrs(cpuid_t cpu, int bit, 389 int *new_bit, /* Bit relative to the register */ 390 hubreg_t **intpend_masks, /* Masks for this register */ 391 intr_vecblk_t **vecblk, /* Vecblock for this interrupt */ 392 int *ip) /* Which intpend register */ 393{ 394 hub_intmasks_t *hub_intmasks; 395 synergy_da_t *sda; 396 int which_synergy; 397 cnodeid_t cnode; 398 399 ASSERT(bit < N_INTPEND_BITS * 2); 400 401 cnode = cpuid_to_cnodeid(cpu); 402 which_synergy = cpuid_to_synergy(cpu); 403 sda = Synergy_da_indr[(cnode * 2) + which_synergy]; 404 hub_intmasks = &sda->s_intmasks; 405 406 // hub_intmasks = &pdaindr[cpu].pda->p_intmasks; 407 408 if (bit < N_INTPEND_BITS) { 409 *intpend_masks = hub_intmasks->intpend0_masks; 410 *vecblk = hub_intmasks->dispatch0; 411 *ip = 0; 412 *new_bit = bit; 413 } else { 414 *intpend_masks = hub_intmasks->intpend1_masks; 415 *vecblk = hub_intmasks->dispatch1; 416 *ip = 1; 417 *new_bit = bit - N_INTPEND_BITS; 418 } 419 420 return hub_intmasks; 421} 422 423 424/* 425 * intr_connect_level(cpuid_t cpu, int bit, ilvl_t intr_swlevel, 426 * intr_func_t intr_func, void *intr_arg); 427 * This is the lowest-level interface to the interrupt code. It shouldn't 428 * be called from outside the ml/SN directory. 429 * intr_connect_level hooks up an interrupt to a particular bit in 430 * the INT_PEND0/1 masks. Returns 0 on success. 431 * cpu is the CPU to which the interrupt will be sent. 432 * bit is the level bit to connect to 433 * intr_swlevel tells which software level to use 434 * intr_func is the interrupt handler 435 * intr_arg is an arbitrary argument interpreted by the handler 436 * intr_prefunc is a prologue function, to be called 437 * with interrupts disabled, to disable 438 * the interrupt at source. It is called 439 * with the same argument. Should be NULL for 440 * typical interrupts, which can be masked 441 * by the infrastructure at the level bit. 442 * intr_connect_level returns 0 on success or nonzero on an error 443 */ 444/* ARGSUSED */ 445int 446intr_connect_level(cpuid_t cpu, int bit, ilvl_t intr_swlevel, intr_func_t intr_prefunc) 447{ 448 intr_vecblk_t *vecblk; 449 hubreg_t *intpend_masks; 450 int rv = 0; 451 int ip; 452 unsigned long s; 453 454 ASSERT(bit < N_INTPEND_BITS * 2); 455 456 (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, 457 &vecblk, &ip); 458 459 INTR_LOCK(vecblk); 460 461 if ((vecblk->info[bit].ii_flags & II_INUSE) || 462 (!(vecblk->info[bit].ii_flags & II_RESERVE))) { 463 /* Can't assign to a level that's in use or isn't reserved. */ 464 rv = -1; 465 } else { 466 /* Stuff parameters into vector and info */ 467 vecblk->vectors[bit].iv_prefunc = intr_prefunc; 468 vecblk->info[bit].ii_flags |= II_INUSE; 469 } 470 471 /* Now stuff the masks if everything's okay. */ 472 if (!rv) { 473 int lslice; 474 volatile hubreg_t *mask_reg; 475 // nasid_t nasid = COMPACT_TO_NASID_NODEID(cpuid_to_cnodeid(cpu)); 476 nasid_t nasid = cpuid_to_nasid(cpu); 477 int subnode = cpuid_to_subnode(cpu); 478 479 /* Make sure it's not already pending when we connect it. */ 480 REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit + ip * N_INTPEND_BITS); 481 482 if (bit >= GFX_INTR_A && bit <= CC_PEND_B) { 483 intpend_masks[0] |= (1ULL << (uint64_t)bit); 484 } 485 486 lslice = cpuid_to_localslice(cpu); 487 vecblk->cpu_count[lslice]++; 488#if SN1 489 /* 490 * On SN1, there are 8 interrupt mask registers per node: 491 * PI_0 MASK_0 A 492 * PI_0 MASK_1 A 493 * PI_0 MASK_0 B 494 * PI_0 MASK_1 B 495 * PI_1 MASK_0 A 496 * PI_1 MASK_1 A 497 * PI_1 MASK_0 B 498 * PI_1 MASK_1 B 499 */ 500#endif 501 if (ip == 0) { 502 mask_reg = REMOTE_HUB_PI_ADDR(nasid, subnode, 503 PI_INT_MASK0_A + PI_INT_MASK_OFFSET * lslice); 504 } else { 505 mask_reg = REMOTE_HUB_PI_ADDR(nasid, subnode, 506 PI_INT_MASK1_A + PI_INT_MASK_OFFSET * lslice); 507 } 508 509 HUB_S(mask_reg, intpend_masks[0]); 510 } 511 512 INTR_UNLOCK(vecblk); 513 514 return rv; 515} 516 517 518/* 519 * intr_disconnect_level(cpuid_t cpu, int bit) 520 * 521 * This is the lowest-level interface to the interrupt code. It should 522 * not be called from outside the ml/SN directory. 523 * intr_disconnect_level removes a particular bit from an interrupt in 524 * the INT_PEND0/1 masks. Returns 0 on success or nonzero on failure. 525 */ 526int 527intr_disconnect_level(cpuid_t cpu, int bit) 528{ 529 intr_vecblk_t *vecblk; 530 hubreg_t *intpend_masks; 531 unsigned long s; 532 int rv = 0; 533 int ip; 534 535 (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, 536 &vecblk, &ip); 537 538 INTR_LOCK(vecblk); 539 540 if ((vecblk->info[bit].ii_flags & (II_RESERVE | II_INUSE)) != 541 ((II_RESERVE | II_INUSE))) { 542 /* Can't remove a level that's not in use or isn't reserved. */ 543 rv = -1; 544 } else { 545 /* Stuff parameters into vector and info */ 546 vecblk->vectors[bit].iv_func = (intr_func_t)NULL; 547 vecblk->vectors[bit].iv_prefunc = (intr_func_t)NULL; 548 vecblk->vectors[bit].iv_arg = 0; 549 vecblk->info[bit].ii_flags &= ~II_INUSE; 550#ifdef BASE_ITHRTEAD 551 vecblk->vectors[bit].iv_mustruncpu = -1; /* No mustrun CPU any more. */ 552#endif 553 } 554 555 /* Now clear the masks if everything's okay. */ 556 if (!rv) { 557 int lslice; 558 volatile hubreg_t *mask_reg; 559 560 intpend_masks[0] &= ~(1ULL << (uint64_t)bit); 561 lslice = cpuid_to_localslice(cpu); 562 vecblk->cpu_count[lslice]--; 563 mask_reg = REMOTE_HUB_PI_ADDR(COMPACT_TO_NASID_NODEID(cpuid_to_cnodeid(cpu)), 564 cpuid_to_subnode(cpu), 565 ip == 0 ? PI_INT_MASK0_A : PI_INT_MASK1_A); 566 mask_reg = (volatile hubreg_t *)((__psunsigned_t)mask_reg + 567 (PI_INT_MASK_OFFSET * lslice)); 568 *mask_reg = intpend_masks[0]; 569 } 570 571 INTR_UNLOCK(vecblk); 572 573 return rv; 574} 575 576/* 577 * Actually block or unblock an interrupt 578 */ 579void 580do_intr_block_bit(cpuid_t cpu, int bit, int block) 581{ 582 intr_vecblk_t *vecblk; 583 int ip; 584 unsigned long s; 585 hubreg_t *intpend_masks; 586 volatile hubreg_t mask_value; 587 volatile hubreg_t *mask_reg; 588 589 intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &vecblk, &ip); 590 591 INTR_LOCK(vecblk); 592 593 if (block) 594 /* Block */ 595 intpend_masks[0] &= ~(1ULL << (uint64_t)bit); 596 else 597 /* Unblock */ 598 intpend_masks[0] |= (1ULL << (uint64_t)bit); 599 600 if (ip == 0) { 601 mask_reg = REMOTE_HUB_PI_ADDR(COMPACT_TO_NASID_NODEID(cpuid_to_cnodeid(cpu)), 602 cpuid_to_subnode(cpu), PI_INT_MASK0_A); 603 } else { 604 mask_reg = REMOTE_HUB_PI_ADDR(COMPACT_TO_NASID_NODEID(cpuid_to_cnodeid(cpu)), 605 cpuid_to_subnode(cpu), PI_INT_MASK1_A); 606 } 607 608 HUB_S(mask_reg, intpend_masks[0]); 609 610 /* 611 * Wait for it to take effect. (One read should suffice.) 612 * This is only necessary when blocking an interrupt 613 */ 614 if (block) 615 while ((mask_value = HUB_L(mask_reg)) != intpend_masks[0]) 616 ; 617 618 INTR_UNLOCK(vecblk); 619} 620 621 622/* 623 * Block a particular interrupt (cpu/bit pair). 624 */ 625/* ARGSUSED */ 626void 627intr_block_bit(cpuid_t cpu, int bit) 628{ 629 do_intr_block_bit(cpu, bit, 1); 630} 631 632 633/* 634 * Unblock a particular interrupt (cpu/bit pair). 635 */ 636/* ARGSUSED */ 637void 638intr_unblock_bit(cpuid_t cpu, int bit) 639{ 640 do_intr_block_bit(cpu, bit, 0); 641} 642 643 644/* verifies that the specified CPUID is on the specified SUBNODE (if any) */ 645#define cpu_on_subnode(cpuid, which_subnode) \ 646 (((which_subnode) == SUBNODE_ANY) || (cpuid_to_subnode(cpuid) == (which_subnode))) 647 648 649/* 650 * Choose one of the CPUs on a specified node or subnode to receive 651 * interrupts. Don't pick a cpu which has been specified as a NOINTR cpu. 652 * 653 * Among all acceptable CPUs, the CPU that has the fewest total number 654 * of interrupts targetted towards it is chosen. Note that we never 655 * consider how frequent each of these interrupts might occur, so a rare 656 * hardware error interrupt is weighted equally with a disk interrupt. 657 */ 658static cpuid_t 659do_intr_cpu_choose(cnodeid_t cnode, int which_subnode) 660{ 661 cpuid_t cpu, best_cpu = CPU_NONE; 662 int slice, min_count=1000; 663 664 min_count = 1000; 665 for (slice=0; slice < CPUS_PER_NODE; slice++) { 666 intr_vecblk_t *vecblk0, *vecblk1; 667 int total_intrs_to_slice; 668 subnode_pda_t *snpda; 669 int local_cpu_num; 670 671 cpu = cnode_slice_to_cpuid(cnode, slice); 672 if (cpu == CPU_NONE) 673 continue; 674 675 /* If this cpu isn't enabled for interrupts, skip it */ 676 if (!cpu_enabled(cpu) || !cpu_allows_intr(cpu)) 677 continue; 678 679 /* If this isn't the right subnode, skip it */ 680 if (!cpu_on_subnode(cpu, which_subnode)) 681 continue; 682 683 /* OK, this one's a potential CPU for interrupts */ 684 snpda = SUBNODEPDA(cnode,SUBNODE(slice)); 685 vecblk0 = &snpda->intr_dispatch0; 686 vecblk1 = &snpda->intr_dispatch1; 687 local_cpu_num = LOCALCPU(slice); 688 total_intrs_to_slice = vecblk0->cpu_count[local_cpu_num] + 689 vecblk1->cpu_count[local_cpu_num]; 690 691 if (min_count > total_intrs_to_slice) { 692 min_count = total_intrs_to_slice; 693 best_cpu = cpu; 694 } 695 } 696 return best_cpu; 697} 698 699/* 700 * Choose an appropriate interrupt target CPU on a specified node. 701 * If which_subnode is SUBNODE_ANY, then subnode is not considered. 702 * Otherwise, the chosen CPU must be on the specified subnode. 703 */ 704static cpuid_t 705intr_cpu_choose_from_node(cnodeid_t cnode, int which_subnode) 706{ 707 return(do_intr_cpu_choose(cnode, which_subnode)); 708} 709 710 711/* Make it easy to identify subnode vertices in the hwgraph */ 712void 713mark_subnodevertex_as_subnode(devfs_handle_t vhdl, int which_subnode) 714{ 715 graph_error_t rv; 716 717 ASSERT(0 <= which_subnode); 718 ASSERT(which_subnode < NUM_SUBNODES); 719 720 rv = hwgraph_info_add_LBL(vhdl, INFO_LBL_CPUBUS, (arbitrary_info_t)which_subnode); 721 ASSERT_ALWAYS(rv == GRAPH_SUCCESS); 722 723 rv = hwgraph_info_export_LBL(vhdl, INFO_LBL_CPUBUS, sizeof(arbitrary_info_t)); 724 ASSERT_ALWAYS(rv == GRAPH_SUCCESS); 725} 726 727 728/* 729 * Given a device descriptor, extract interrupt target information and 730 * choose an appropriate CPU. Return CPU_NONE if we can't make sense 731 * out of the target information. 732 * TBD: Should this be considered platform-independent code? 733 */ 734 735 736/* 737 * intr_bit_reserve_test(cpuid,which_subnode,cnode,req_bit,intr_resflags, 738 * owner_dev,intr_name,*resp_bit) 739 * Either cpuid is not CPU_NONE or cnodeid not CNODE_NONE but 740 * not both. 741 * 1. If cpuid is specified, this routine tests if this cpu can be a valid 742 * interrupt target candidate. 743 * 2. If cnodeid is specified, this routine tests if there is a cpu on 744 * this node which can be a valid interrupt target candidate. 745 * 3. If a valid interrupt target cpu candidate is found then an attempt at 746 * reserving an interrupt bit on the corresponding cnode is made. 747 * 748 * If steps 1 & 2 both fail or step 3 fails then we are not able to get a valid 749 * interrupt target cpu then routine returns CPU_NONE (failure) 750 * Otherwise routine returns cpuid of interrupt target (success) 751 */ 752static cpuid_t 753intr_bit_reserve_test(cpuid_t cpuid, 754 int favor_subnode, 755 cnodeid_t cnodeid, 756 int req_bit, 757 int intr_resflags, 758 devfs_handle_t owner_dev, 759 char *intr_name, 760 int *resp_bit) 761{ 762 763 ASSERT((cpuid==CPU_NONE) || (cnodeid==CNODEID_NONE)); 764 765 if (cnodeid != CNODEID_NONE) { 766 /* Try to choose a interrupt cpu candidate */ 767 cpuid = intr_cpu_choose_from_node(cnodeid, favor_subnode); 768 } 769 770 if (cpuid != CPU_NONE) { 771 /* Try to reserve an interrupt bit on the hub 772 * corresponding to the canidate cnode. If we 773 * are successful then we got a cpu which can 774 * act as an interrupt target for the io device. 775 * Otherwise we need to continue the search 776 * further. 777 */ 778 *resp_bit = do_intr_reserve_level(cpuid, 779 req_bit, 780 intr_resflags, 781 II_RESERVE, 782 owner_dev, 783 intr_name); 784 785 if (*resp_bit >= 0) 786 /* The interrupt target specified was fine */ 787 return(cpuid); 788 } 789 return(CPU_NONE); 790} 791/* 792 * intr_heuristic(dev_t dev,device_desc_t dev_desc, 793 * int req_bit,int intr_resflags,dev_t owner_dev, 794 * char *intr_name,int *resp_bit) 795 * 796 * Choose an interrupt destination for an interrupt. 797 * dev is the device for which the interrupt is being set up 798 * dev_desc is a description of hardware and policy that could 799 * help determine where this interrupt should go 800 * req_bit is the interrupt bit requested 801 * (can be INTRCONNECT_ANY_BIT in which the first available 802 * interrupt bit is used) 803 * intr_resflags indicates whether we want to (un)reserve bit 804 * owner_dev is the owner device 805 * intr_name is the readable interrupt name 806 * resp_bit indicates whether we succeeded in getting the required 807 * action { (un)reservation} done 808 * negative value indicates failure 809 * 810 */ 811/* ARGSUSED */ 812cpuid_t 813intr_heuristic(devfs_handle_t dev, 814 device_desc_t dev_desc, 815 int req_bit, 816 int intr_resflags, 817 devfs_handle_t owner_dev, 818 char *intr_name, 819 int *resp_bit) 820{ 821 cpuid_t cpuid; /* possible intr targ*/ 822 cnodeid_t candidate; /* possible canidate */ 823 int which_subnode = SUBNODE_ANY; 824 825/* SN1 + pcibr Addressing Limitation */ 826 { 827 devfs_handle_t pconn_vhdl; 828 pcibr_soft_t pcibr_soft; 829 830 if ((hwgraph_edge_get(dev, EDGE_LBL_PCI, &pconn_vhdl) == GRAPH_SUCCESS) && 831 ((pcibr_soft = pcibr_soft_get(pconn_vhdl)) != NULL)) { 832 /* 833 * We "know" that the error interrupt is the first 834 * interrupt set up by pcibr_attach. Send all interrupts 835 * on this bridge to the same subnode number. 836 */ 837 if (pcibr_soft->bsi_err_intr) { 838 which_subnode = cpuid_to_subnode(((hub_intr_t) pcibr_soft->bsi_err_intr)->i_cpuid); 839 } 840 } 841 } 842 843 /* Check if we can find a valid interrupt target candidate on 844 * the master node for the device. 845 */ 846 cpuid = intr_bit_reserve_test(CPU_NONE, 847 which_subnode, 848 master_node_get(dev), 849 req_bit, 850 intr_resflags, 851 owner_dev, 852 intr_name, 853 resp_bit); 854 855 if (cpuid != CPU_NONE) { 856 if (cpu_on_subnode(cpuid, which_subnode)) 857 return(cpuid); /* got a valid interrupt target */ 858 else 859 intr_unreserve_level(cpuid, *resp_bit); 860 } 861 862 printk(KERN_WARNING "Cannot target interrupts to closest node(%d): (0x%lx)\n", 863 master_node_get(dev),(unsigned long)owner_dev); 864 865 /* Fall through into the default algorithm 866 * (exhaustive-search-for-the-nearest-possible-interrupt-target) 867 * for finding the interrupt target 868 */ 869 870 { 871 /* 872 * Do a stupid round-robin assignment of the node. 873 * (Should do a "nearest neighbor" but not for SN1. 874 */ 875 static cnodeid_t last_node = -1; 876 877 if (last_node >= numnodes) last_node = 0; 878 for (candidate = last_node + 1; candidate != last_node; candidate++) { 879 if (candidate == numnodes) candidate = 0; 880 cpuid = intr_bit_reserve_test(CPU_NONE, 881 which_subnode, 882 candidate, 883 req_bit, 884 intr_resflags, 885 owner_dev, 886 intr_name, 887 resp_bit); 888 889 if (cpuid != CPU_NONE) { 890 if (cpu_on_subnode(cpuid, which_subnode)) { 891 last_node = candidate; 892 return(cpuid); /* got a valid interrupt target */ 893 } 894 else 895 intr_unreserve_level(cpuid, *resp_bit); 896 } 897 } 898 last_node = candidate; 899 } 900 901 printk(KERN_WARNING "Cannot target interrupts to any close node: %ld (0x%lx)\n", 902 (long)owner_dev, (unsigned long)owner_dev); 903 904 /* In the worst case try to allocate interrupt bits on the 905 * master processor's node. We may get here during error interrupt 906 * allocation phase when the topology matrix is not yet setup 907 * and hence cannot do an exhaustive search. 908 */ 909 ASSERT(cpu_allows_intr(master_procid)); 910 cpuid = intr_bit_reserve_test(master_procid, 911 which_subnode, 912 CNODEID_NONE, 913 req_bit, 914 intr_resflags, 915 owner_dev, 916 intr_name, 917 resp_bit); 918 919 if (cpuid != CPU_NONE) { 920 if (cpu_on_subnode(cpuid, which_subnode)) 921 return(cpuid); 922 else 923 intr_unreserve_level(cpuid, *resp_bit); 924 } 925 926 printk(KERN_WARNING "Cannot target interrupts: (0x%lx)\n", 927 (unsigned long)owner_dev); 928 929 return(CPU_NONE); /* Should never get here */ 930} 931 932struct hardwired_intr_s { 933 signed char level; 934 int flags; 935 char *name; 936} const hardwired_intr[] = { 937 { INT_PEND0_BASELVL + RESERVED_INTR, 0, "Reserved" }, 938 { INT_PEND0_BASELVL + GFX_INTR_A, 0, "Gfx A" }, 939 { INT_PEND0_BASELVL + GFX_INTR_B, 0, "Gfx B" }, 940 { INT_PEND0_BASELVL + PG_MIG_INTR, II_THREADED, "Migration" }, 941 { INT_PEND0_BASELVL + UART_INTR, II_THREADED, "Bedrock/L1" }, 942 { INT_PEND0_BASELVL + CC_PEND_A, 0, "Crosscall A" }, 943 { INT_PEND0_BASELVL + CC_PEND_B, 0, "Crosscall B" }, 944 { INT_PEND1_BASELVL + CLK_ERR_INTR, II_ERRORINT, "Clock Error" }, 945 { INT_PEND1_BASELVL + COR_ERR_INTR_A, II_ERRORINT, "Correctable Error A" }, 946 { INT_PEND1_BASELVL + COR_ERR_INTR_B, II_ERRORINT, "Correctable Error B" }, 947 { INT_PEND1_BASELVL + MD_COR_ERR_INTR, II_ERRORINT, "MD Correct. Error" }, 948 { INT_PEND1_BASELVL + NI_ERROR_INTR, II_ERRORINT, "NI Error" }, 949 { INT_PEND1_BASELVL + NI_BRDCAST_ERR_A, II_ERRORINT, "Remote NI Error"}, 950 { INT_PEND1_BASELVL + NI_BRDCAST_ERR_B, II_ERRORINT, "Remote NI Error"}, 951 { INT_PEND1_BASELVL + MSC_PANIC_INTR, II_ERRORINT, "MSC Panic" }, 952 { INT_PEND1_BASELVL + LLP_PFAIL_INTR_A, II_ERRORINT, "LLP Pfail WAR" }, 953 { INT_PEND1_BASELVL + LLP_PFAIL_INTR_B, II_ERRORINT, "LLP Pfail WAR" }, 954 { INT_PEND1_BASELVL + NACK_INT_A, 0, "CPU A Nack count == NACK_CMP" }, 955 { INT_PEND1_BASELVL + NACK_INT_B, 0, "CPU B Nack count == NACK_CMP" }, 956 { INT_PEND1_BASELVL + LB_ERROR, 0, "Local Block Error" }, 957 { INT_PEND1_BASELVL + XB_ERROR, 0, "Local XBar Error" }, 958 { -1, 0, (char *)NULL}, 959}; 960 961/* 962 * Reserve all of the hardwired interrupt levels so they're not used as 963 * general purpose bits later. 964 */ 965void 966intr_reserve_hardwired(cnodeid_t cnode) 967{ 968 cpuid_t cpu; 969 int level; 970 int i; 971 char subnode_done[NUM_SUBNODES]; 972 973 // cpu = cnodetocpu(cnode); 974 for (cpu = 0; cpu < smp_num_cpus; cpu++) { 975 if (cpuid_to_cnodeid(cpu) == cnode) { 976 break; 977 } 978 } 979 if (cpu == smp_num_cpus) cpu = CPU_NONE; 980 if (cpu == CPU_NONE) { 981 printk("Node %d has no CPUs", cnode); 982 return; 983 } 984 985 for (i=0; i<NUM_SUBNODES; i++) 986 subnode_done[i] = 0; 987 988 for (; cpu<smp_num_cpus && cpu_enabled(cpu) && cpuid_to_cnodeid(cpu) == cnode; cpu++) { 989 int which_subnode = cpuid_to_subnode(cpu); 990 if (subnode_done[which_subnode]) 991 continue; 992 subnode_done[which_subnode] = 1; 993 994 for (i = 0; hardwired_intr[i].level != -1; i++) { 995 level = hardwired_intr[i].level; 996 997 if (level != intr_reserve_level(cpu, level, 998 hardwired_intr[i].flags, 999 (devfs_handle_t) NULL, 1000 hardwired_intr[i].name)) 1001 panic("intr_reserve_hardwired: Can't reserve level %d, cpu %ld.", level, cpu); 1002 } 1003 } 1004} 1005 1006 1007/* 1008 * Check and clear interrupts. 1009 */ 1010/*ARGSUSED*/ 1011static void 1012intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level, 1013 char *name) 1014{ 1015 volatile hubreg_t bits; 1016 int i; 1017 1018 /* Check pending interrupts */ 1019 if ((bits = HUB_L(pend)) != 0) { 1020 for (i = 0; i < N_INTPEND_BITS; i++) { 1021 if (bits & (1 << i)) { 1022#ifdef INTRDEBUG 1023 printk(KERN_WARNING "Nasid %d interrupt bit %d set in %s", 1024 nasid, i, name); 1025#endif 1026 LOCAL_HUB_CLR_INTR(base_level + i); 1027 } 1028 } 1029 } 1030} 1031 1032/* 1033 * Clear out our interrupt registers. 1034 */ 1035void 1036intr_clear_all(nasid_t nasid) 1037{ 1038 int sn; 1039 1040 for(sn=0; sn<NUM_SUBNODES; sn++) { 1041 REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK0_A, 0); 1042 REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK0_B, 0); 1043 REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK1_A, 0); 1044 REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK1_B, 0); 1045 1046 intr_clear_bits(nasid, REMOTE_HUB_PI_ADDR(nasid, sn, PI_INT_PEND0), 1047 INT_PEND0_BASELVL, "INT_PEND0"); 1048 intr_clear_bits(nasid, REMOTE_HUB_PI_ADDR(nasid, sn, PI_INT_PEND1), 1049 INT_PEND1_BASELVL, "INT_PEND1"); 1050 } 1051} 1052 1053/* 1054 * Dump information about a particular interrupt vector. 1055 */ 1056static void 1057dump_vector(intr_info_t *info, intr_vector_t *vector, int bit, hubreg_t ip, 1058 hubreg_t ima, hubreg_t imb, void (*pf)(char *, ...)) 1059{ 1060 hubreg_t value = 1LL << bit; 1061 1062 pf(" Bit %02d: %s: func 0x%x arg 0x%x prefunc 0x%x\n", 1063 bit, info->ii_name, 1064 vector->iv_func, vector->iv_arg, vector->iv_prefunc); 1065 pf(" vertex 0x%x %s%s", 1066 info->ii_owner_dev, 1067 ((info->ii_flags) & II_RESERVE) ? "R" : "U", 1068 ((info->ii_flags) & II_INUSE) ? "C" : "-"); 1069 pf("%s%s%s%s", 1070 ip & value ? "P" : "-", 1071 ima & value ? "A" : "-", 1072 imb & value ? "B" : "-", 1073 ((info->ii_flags) & II_ERRORINT) ? "E" : "-"); 1074 pf("\n"); 1075} 1076 1077 1078/* 1079 * Dump information about interrupt vector assignment. 1080 */ 1081void 1082intr_dumpvec(cnodeid_t cnode, void (*pf)(char *, ...)) 1083{ 1084 nodepda_t *npda; 1085 int ip, sn, bit; 1086 intr_vecblk_t *dispatch; 1087 hubreg_t ipr, ima, imb; 1088 nasid_t nasid; 1089 1090 if ((cnode < 0) || (cnode >= numnodes)) { 1091 pf("intr_dumpvec: cnodeid out of range: %d\n", cnode); 1092 return ; 1093 } 1094 1095 nasid = COMPACT_TO_NASID_NODEID(cnode); 1096 1097 if (nasid == INVALID_NASID) { 1098 pf("intr_dumpvec: Bad cnodeid: %d\n", cnode); 1099 return ; 1100 } 1101 1102 1103 npda = NODEPDA(cnode); 1104 1105 for (sn = 0; sn < NUM_SUBNODES; sn++) { 1106 for (ip = 0; ip < 2; ip++) { 1107 dispatch = ip ? &(SNPDA(npda,sn)->intr_dispatch1) : &(SNPDA(npda,sn)->intr_dispatch0); 1108 ipr = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_PEND1 : PI_INT_PEND0); 1109 ima = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_MASK1_A : PI_INT_MASK0_A); 1110 imb = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_MASK1_B : PI_INT_MASK0_B); 1111 1112 pf("Node %d INT_PEND%d:\n", cnode, ip); 1113 1114 if (dispatch->ithreads_enabled) 1115 pf(" Ithreads enabled\n"); 1116 else 1117 pf(" Ithreads disabled\n"); 1118 pf(" vector_count = %d, vector_state = %d\n", 1119 dispatch->vector_count, 1120 dispatch->vector_state); 1121 pf(" CPU A count %d, CPU B count %d\n", 1122 dispatch->cpu_count[0], 1123 dispatch->cpu_count[1]); 1124 pf(" &vector_lock = 0x%x\n", 1125 &(dispatch->vector_lock)); 1126 for (bit = 0; bit < N_INTPEND_BITS; bit++) { 1127 if ((dispatch->info[bit].ii_flags & II_RESERVE) || 1128 (ipr & (1L << bit))) { 1129 dump_vector(&(dispatch->info[bit]), 1130 &(dispatch->vectors[bit]), 1131 bit, ipr, ima, imb, pf); 1132 } 1133 } 1134 pf("\n"); 1135 } 1136 } 1137} 1138 1139