int hub_intr_connect(hub_intr_t intr_hdl, xtalk_intr_setfunc_t setfunc, void *setfunc_arg) { int rv; cpuid_t cpu = intr_hdl->i_cpuid; int vector = intr_hdl->i_bit; ASSERT(intr_hdl->i_flags & HUB_INTR_IS_ALLOCED); rv = intr_connect_level(cpu, vector, intr_hdl->i_swlevel, NULL); if (rv < 0) { return rv; } intr_hdl->i_xtalk_info.xi_setfunc = setfunc; intr_hdl->i_xtalk_info.xi_sfarg = setfunc_arg; if (setfunc) { (*setfunc)((xtalk_intr_t)intr_hdl); } intr_hdl->i_flags |= HUB_INTR_IS_CONNECTED; return 0; }
int request_bridge_irq(struct bridge_controller *bc) { int irq = allocate_irqno(); int swlevel, cpu; nasid_t nasid; if (irq < 0) return irq; /* * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ cpu = bc->irq_cpu; swlevel = alloc_level(cpu, irq); if (unlikely(swlevel < 0)) { free_irqno(irq); return -EAGAIN; } /* Make sure it's not already pending when we connect it. */ nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); REMOTE_HUB_CLR_INTR(nasid, swlevel); intr_connect_level(cpu, swlevel); register_bridge_irq(irq); return irq; }
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*/ int hub_intr_connect( hub_intr_t intr_hdl, /* xtalk intr resource handle */ intr_func_t intr_func, /* xtalk intr handler */ void *intr_arg, /* arg to intr handler */ xtalk_intr_setfunc_t setfunc, /* func to set intr hw */ void *setfunc_arg, /* arg to setfunc */ void *thread) /* intr thread to use */ { int rv; cpuid_t cpu = intr_hdl->i_cpuid; int bit = intr_hdl->i_bit; #ifdef CONFIG_IA64_SGI_SN1 extern int synergy_intr_connect(int, int); #endif ASSERT(intr_hdl->i_flags & HUB_INTR_IS_ALLOCED); #if defined(NEW_INTERRUPTS) rv = intr_connect_level(cpu, bit, intr_hdl->i_swlevel, intr_func, intr_arg, NULL); if (rv < 0) return(rv); #endif intr_hdl->i_xtalk_info.xi_setfunc = setfunc; intr_hdl->i_xtalk_info.xi_sfarg = setfunc_arg; if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl); intr_hdl->i_flags |= HUB_INTR_IS_CONNECTED; #ifdef CONFIG_IA64_SGI_SN1 return(synergy_intr_connect((int)bit, (int)cpu)); #endif }
static inline void enable_bridge_irq(struct irq_data *d) { cpuid_t cpu; int swlevel; swlevel = find_level(&cpu, d->irq); /* Criminal offence */ intr_connect_level(cpu, swlevel); }
void hubii_eint_init(cnodeid_t cnode) { int bit, rv; ii_iidsr_u_t hubio_eint; hubinfo_t hinfo; cpuid_t intr_cpu; devfs_handle_t hub_v; ii_ilcsr_u_t ilcsr; int bit_pos_to_irq(int bit); int synergy_intr_connect(int bit, int cpuid); hub_v = (devfs_handle_t)cnodeid_to_vertex(cnode); ASSERT_ALWAYS(hub_v); hubinfo_get(hub_v, &hinfo); ASSERT(hinfo); ASSERT(hinfo->h_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 hubii_eint_init(cnodeid_t cnode) { int bit, rv; ii_iidsr_u_t hubio_eint; hubinfo_t hinfo; cpuid_t intr_cpu; vertex_hdl_t hub_v; int bit_pos_to_irq(int bit); ii_ilcsr_u_t ilcsr; hub_v = (vertex_hdl_t)cnodeid_to_vertex(cnode); ASSERT_ALWAYS(hub_v); hubinfo_get(hub_v, &hinfo); ASSERT(hinfo); ASSERT(hinfo->h_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. Disable LLP. Clear old errors. * Enable interrupts to handle BTE errors. */ ilcsr.ii_ilcsr_fld_s.i_llp_en = 0; REMOTE_HUB_S(hinfo->h_nasid, IIO_ILCSR, ilcsr.ii_ilcsr_regval); } /* 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,SGI_II_ERROR,0,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, SGI_II_ERROR, 0, NULL); request_irq(SGI_II_ERROR, hubii_eint_handler, SA_SHIRQ, "SN_hub_error", (void *)hub_v); irq_desc(bit)->status |= SN2_IRQ_PER_HUB; 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); }
/* Startup one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int startup_bridge_irq(struct irq_data *d) { struct bridge_controller *bc; bridgereg_t device; bridge_t *bridge; int pin, swlevel; cpuid_t cpu; pin = SLOT_FROM_PCI_IRQ(d->irq); bc = IRQ_TO_BRIDGE(d->irq); bridge = bc->base; pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); /* * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ swlevel = find_level(&cpu, d->irq); bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); bridge->b_int_enable |= (1 << pin); bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ /* * Enable sending of an interrupt clear packt to the hub on a high to * low transition of the interrupt pin. * * IRIX sets additional bits in the address which are documented as * reserved in the bridge docs. */ bridge->b_int_mode |= (1UL << pin); /* * We assume the bridge to have a 1:1 mapping between devices * (slots) and intr pins. */ device = bridge->b_int_device; device &= ~(7 << (pin*3)); device |= (pin << (pin*3)); bridge->b_int_device = device; bridge->b_wid_tflush; intr_connect_level(cpu, swlevel); return 0; /* Never anything pending. */ }
/*ARGSUSED*/ int hub_intr_connect( hub_intr_t intr_hdl, /* xtalk intr resource handle */ xtalk_intr_setfunc_t setfunc, /* func to set intr hw */ void *setfunc_arg) /* arg to setfunc */ { int rv; cpuid_t cpu = intr_hdl->i_cpuid; int bit = intr_hdl->i_bit; extern int synergy_intr_connect(int, int); ASSERT(intr_hdl->i_flags & HUB_INTR_IS_ALLOCED); rv = intr_connect_level(cpu, bit, intr_hdl->i_swlevel, NULL); if (rv < 0) return(rv); intr_hdl->i_xtalk_info.xi_setfunc = setfunc; intr_hdl->i_xtalk_info.xi_sfarg = setfunc_arg; if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl); intr_hdl->i_flags |= HUB_INTR_IS_CONNECTED; return(synergy_intr_connect((int)bit, (int)cpu)); }