/* $Id: huberror.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern void hubni_eint_init(cnodeid_t cnode); extern void hubii_eint_init(cnodeid_t cnode); extern void hubii_eint_handler (int irq, void *arg, struct pt_regs *ep); extern void snia_error_intr_handler(int irq, void *devid, struct pt_regs *pt_regs); extern int maxcpus; #define HUB_ERROR_PERIOD (120 * HZ) /* 2 minutes */ void hub_error_clear(nasid_t nasid) { int i; hubreg_t idsr; int sn; for(sn=0; snh_cnodeid == cnode); ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ILCSR); if ((ilcsr.ii_ilcsr_fld_s.i_llp_stat & 0x2) == 0) { /* * HUB II link is not up. * Just disable LLP, and don't connect any interrupts. */ ilcsr.ii_ilcsr_fld_s.i_llp_en = 0; REMOTE_HUB_S(hinfo->h_nasid, IIO_ILCSR, ilcsr.ii_ilcsr_regval); return; } /* Select a possible interrupt target where there is a free interrupt * bit and also reserve the interrupt bit for this IO error interrupt */ intr_cpu = intr_heuristic(hub_v,0,INTRCONNECT_ANYBIT,II_ERRORINT,hub_v, "HUB IO error interrupt",&bit); if (intr_cpu == CPU_NONE) { printk("hubii_eint_init: intr_reserve_level failed, cnode %d", cnode); return; } rv = intr_connect_level(intr_cpu, bit, 0, NULL); synergy_intr_connect(bit, intr_cpu); request_irq(bit_pos_to_irq(bit) + (intr_cpu << 8), hubii_eint_handler, 0, "SN hub error", (void *)hub_v); ASSERT_ALWAYS(rv >= 0); hubio_eint.ii_iidsr_regval = 0; hubio_eint.ii_iidsr_fld_s.i_enable = 1; hubio_eint.ii_iidsr_fld_s.i_level = bit;/* Take the least significant bits*/ hubio_eint.ii_iidsr_fld_s.i_node = COMPACT_TO_NASID_NODEID(cnode); hubio_eint.ii_iidsr_fld_s.i_pi_id = cpuid_to_subnode(intr_cpu); REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, hubio_eint.ii_iidsr_regval); } void hubni_eint_init(cnodeid_t cnode) { int intr_bit; cpuid_t targ; if ((targ = cnodeid_to_cpuid(cnode)) == CPU_NONE) return; /* The prom chooses which cpu gets these interrupts, but we * don't know which one it chose. We will register all of the * cpus to be sure. This only costs us an irqaction per cpu. */ for (; targ < CPUS_PER_NODE; targ++) { if (!cpu_enabled(targ) ) continue; /* connect the INTEND1 bits. */ for (intr_bit = XB_ERROR; intr_bit <= MSC_PANIC_INTR; intr_bit++) { intr_connect_level(targ, intr_bit, II_ERRORINT, NULL); } request_irq(SGI_HUB_ERROR_IRQ + (targ << 8), snia_error_intr_handler, 0, "SN hub error", NULL); /* synergy masks are initialized in the prom to enable all interrupts. */ /* We'll just leave them that way, here, for these interrupts. */ } } /*ARGSUSED*/ void hubii_eint_handler (int irq, void *arg, struct pt_regs *ep) { panic("Hubii interrupt\n"); }