예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
0
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. */
    }
}
예제 #4
0
파일: io.c 프로젝트: dot-Sean/linux_kernels
/*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
}
예제 #5
0
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);
}
예제 #6
0
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);

}
예제 #7
0
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);

}
예제 #8
0
/* 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.  */
}
예제 #9
0
/*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));
}