示例#1
0
/*
 * Free the hub CRB "crbnum" which encountered an error.
 * Assumption is, error handling was successfully done,
 * and we now want to return the CRB back to Hub for normal usage.
 *
 * In order to free the CRB, all that's needed is to de-allocate it
 *
 * Assumption:
 *      No other processor is mucking around with the hub control register.
 *      So, upper layer has to single thread this.
 */
void
hubiio_crb_free(hubinfo_t hinfo, int crbnum)
{
	ii_icrb0_b_u_t         icrbb;

	/*
	* The hardware does NOT clear the mark bit, so it must get cleared
	* here to be sure the error is not processed twice.
	*/
	icrbb.ii_icrb0_b_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ICRB_B(crbnum));
	icrbb.b_mark   = 0;
	REMOTE_HUB_S(hinfo->h_nasid, IIO_ICRB_B(crbnum), icrbb.ii_icrb0_b_regval);

	/*
	* Deallocate the register.
	*/

	REMOTE_HUB_S(hinfo->h_nasid, IIO_ICDR, (IIO_ICDR_PND | crbnum));

	/*
	* Wait till hub indicates it's done.
	*/
	while (REMOTE_HUB_L(hinfo->h_nasid, IIO_ICDR) & IIO_ICDR_PND)
		us_delay(1);

}
示例#2
0
/**
 * hub_set_piomode  -  set pio mode for a given hub
 *
 * @nasid:	physical node ID for the hub in question
 *
 * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" mode.
 * To do this, we have to make absolutely sure that no PIOs are in progress
 * so we turn off access to all widgets for the duration of the function.
 *
 * XXX - This code should really check what kind of widget we're talking
 * to.  Bridges can only handle three requests, but XG will do more.
 * How many can crossbow handle to widget 0?  We're assuming 1.
 *
 * XXX - There is a bug in the crossbow that link reset PIOs do not
 * return write responses.  The easiest solution to this problem is to
 * leave widget 0 (xbow) in fire-and-forget mode at all times.  This
 * only affects pio's to xbow registers, which should be rare.
 **/
static void hub_set_piomode(nasid_t nasid)
{
	hubreg_t ii_iowa;
	hubii_wcr_t ii_wcr;
	unsigned i;

	ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
	REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);

	ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);

	if (ii_wcr.iwcr_dir_con) {
		/*
		 * Assume a bridge here.
		 */
		hub_setup_prb(nasid, 0, 3);
	} else {
		/*
		 * Assume a crossbow here.
		 */
		hub_setup_prb(nasid, 0, 1);
	}

	/*
	 * XXX - Here's where we should take the widget type into
	 * when account assigning credits.
	 */
	for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++)
		hub_setup_prb(nasid, i, 3);

	REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
}
示例#3
0
void
hub_error_clear(nasid_t nasid)
{
	int i;

    /*
     * Make sure spurious write response errors are cleared
     * (values are from hub_set_prb())
     */
    for (i = 0; i <= HUB_WIDGET_ID_MAX - HUB_WIDGET_ID_MIN + 1; i++) {
        iprb_t prb;

	prb.iprb_regval = REMOTE_HUB_L(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)));

        /* Clear out some fields */
        prb.iprb_ovflow = 1;
        prb.iprb_bnakctr = 0;
        prb.iprb_anakctr = 0;

        prb.iprb_xtalkctr = 3;  /* approx. PIO credits for the widget */

        REMOTE_HUB_S(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)), prb.iprb_regval);
    }

    REMOTE_HUB_S(nasid, IIO_IECLR, -1);

}
示例#4
0
/*
 * hub_set_piomode()
 *
 * 	Put the hub into either "PIO conveyor belt" mode or "fire-and-forget"
 * 	mode.  To do this, we have to make absolutely sure that no PIOs
 *	are in progress so we turn off access to all widgets for the duration
 *	of the function.
 *
 * XXX - This code should really check what kind of widget we're talking
 * to.  Bridges can only handle three requests, but XG will do more.
 * How many can crossbow handle to widget 0?  We're assuming 1.
 *
 * XXX - There is a bug in the crossbow that link reset PIOs do not
 * return write responses.  The easiest solution to this problem is to
 * leave widget 0 (xbow) in fire-and-forget mode at all times.  This
 * only affects pio's to xbow registers, which should be rare.
 */
void
hub_set_piomode(nasid_t nasid, int conveyor)
{
    hubreg_t ii_iowa;
    int direct_connect;
    hubii_wcr_t ii_wcr;
    int prbnum;
    int s, cons_lock = 0;

    ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID);
    if (nasid == get_console_nasid()) {
        PUTBUF_LOCK(s);
        cons_lock = 1;
    }

    ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
    REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);

    ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
    direct_connect = ii_wcr.iwcr_dir_con;

    if (direct_connect) {
        /*
         * Assume a bridge here.
         */
        hub_setup_prb(nasid, 0, 3, conveyor);
    } else {
        /*
         * Assume a crossbow here.
         */
        hub_setup_prb(nasid, 0, 1, conveyor);
    }

    for (prbnum = HUB_WIDGET_ID_MIN; prbnum <= HUB_WIDGET_ID_MAX; prbnum++) {
        /*
         * XXX - Here's where we should take the widget type into
         * when account assigning credits.
         */
        /* Always set the PRBs in fire-and-forget mode */
        hub_setup_prb(nasid, prbnum, 3, conveyor);
    }

#ifdef IRIX
    /*
     * In direct connect mode, disable access to all widgets but 0.
     * Later, the prom will do this for us.
     */
    if (direct_connect)
        ii_iowa = 1;
#endif

    REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);

    if (cons_lock)
        PUTBUF_UNLOCK(s);
}
示例#5
0
/*
 * per_hub_init
 *
 * 	This code is executed once for each Hub chip.
 */
static void
per_hub_init(cnodeid_t cnode)
{
	nasid_t nasid;
	nodepda_t *npdap;
	ii_icmr_u_t ii_icmr;
	ii_ibcr_u_t ii_ibcr;
	ii_ilcsr_u_t ii_ilcsr;

	nasid = cnodeid_to_nasid(cnode);

	ASSERT(nasid != INVALID_NASID);
	ASSERT(nasid_to_cnodeid(nasid) == cnode);

	npdap = NODEPDA(cnode);

	/* Disable the request and reply errors. */
	REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000);

	/*
	 * Set the total number of CRBs that can be used.
	 */
	ii_icmr.ii_icmr_regval = 0x0;
	ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
	if (enable_shub_wars_1_1()) {
		// Set bit one of ICMR to prevent II from sending interrupt for II bug.
		ii_icmr.ii_icmr_regval |= 0x1;
	}
	REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);

	/*
	 * Set the number of CRBs that both of the BTEs combined
	 * can use minus 1.
	 */
	ii_ibcr.ii_ibcr_regval = 0x0;
	ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
	if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) {
		ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
	} else {
		/*
		 * if the LLP is down, there is no attached I/O, so
		 * give BTE all the CRBs.
		 */
		ii_ibcr.ii_ibcr_fld_s.i_count = 0x14;
	}
	REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);

	/*
	 * Set CRB timeout to be 10ms.
	 */
	REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff);
	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);

	/* Initialize error interrupts for this hub. */
	hub_error_init(cnode);
}
示例#6
0
static void tio_corelet_reset(nasid_t nasid, int corelet)
{
	if (!(nasid & 1))
		return;

	REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 1 << corelet);
	udelay(2000);
	REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 0);
	udelay(2000);
}
static void __cpuinit per_hub_init(cnodeid_t cnode)
{
	struct hub_data *hub = hub_data(cnode);
	nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
	int i;

	cpu_set(smp_processor_id(), hub->h_cpus);

	if (test_and_set_bit(cnode, hub_init_mask))
		return;
	/*
                                                  
  */
	REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);

	hub_rtc_init(cnode);
	xtalk_probe_node(cnode);

#ifdef CONFIG_REPLICATE_EXHANDLERS
	/*
                                                  
                                              
  */
	if (get_compact_nodeid() == cnode) {
		extern char except_vec2_generic, except_vec3_generic;
		extern void build_tlb_refill_handler(void);

		memcpy((void *)(CKSEG0 + 0x100), &except_vec2_generic, 0x80);
		memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x80);
		build_tlb_refill_handler();
		memcpy((void *)(CKSEG0 + 0x100), (void *) CKSEG0, 0x80);
		memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x100);
		__flush_cache_all();
	}
#endif

	/*
                                                                       
                                                                        
          
  */
	for (i = 0; i <= BASE_PCI_IRQ; i++) {
		__set_bit(i, hub->irq_alloc_mask);
		LOCAL_HUB_CLR_INTR(INT_PEND0_BASELVL + i);
	}

	__set_bit(IP_PEND0_6_63, hub->irq_alloc_mask);
	LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63);

	for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) {
		__set_bit(i, hub->irq_alloc_mask);
		LOCAL_HUB_CLR_INTR(INT_PEND1_BASELVL + i);
	}
}
示例#8
0
static void __cpuinit per_hub_init(cnodeid_t cnode)
{
	struct hub_data *hub = hub_data(cnode);
	nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
	int i;

	cpu_set(smp_processor_id(), hub->h_cpus);

	if (test_and_set_bit(cnode, hub_init_mask))
		return;
	/*
	 * Set CRB timeout at 5ms, (< PI timeout of 10ms)
	 */
	REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);

	hub_rtc_init(cnode);
	xtalk_probe_node(cnode);

#ifdef CONFIG_REPLICATE_EXHANDLERS
	/*
	 * If this is not a headless node initialization,
	 * copy over the caliased exception handlers.
	 */
	if (get_compact_nodeid() == cnode) {
		extern char except_vec2_generic, except_vec3_generic;
		extern void build_tlb_refill_handler(void);

		memcpy((void *)(CKSEG0 + 0x100), &except_vec2_generic, 0x80);
		memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x80);
		build_tlb_refill_handler();
		memcpy((void *)(CKSEG0 + 0x100), (void *) CKSEG0, 0x80);
		memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x100);
		__flush_cache_all();
	}
#endif

	/*
	 * Some interrupts are reserved by hardware or by software convention.
	 * Mark these as reserved right away so they won't be used accidently
	 * later.
	 */
	for (i = 0; i <= BASE_PCI_IRQ; i++) {
		__set_bit(i, hub->irq_alloc_mask);
		LOCAL_HUB_CLR_INTR(INT_PEND0_BASELVL + i);
	}

	__set_bit(IP_PEND0_6_63, hub->irq_alloc_mask);
	LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63);

	for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) {
		__set_bit(i, hub->irq_alloc_mask);
		LOCAL_HUB_CLR_INTR(INT_PEND1_BASELVL + i);
	}
}
示例#9
0
static void intr_clear_all(nasid_t nasid)
{
	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
	                INT_PEND0_BASELVL);
	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
	                INT_PEND1_BASELVL);
}
示例#10
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);

}
示例#11
0
static __init void intr_clear_all(nasid_t nasid)
{
	int i;

	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);

	for (i = 0; i < 128; i++)
		REMOTE_HUB_CLR_INTR(nasid, i);
}
示例#12
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);

}
示例#13
0
static inline void
shub_mmr_write_iospace(cnodeid_t cnode, shubreg_t reg, uint64_t val)
{
	int		   nasid = cnodeid_to_nasid(cnode);

	REMOTE_HUB_S(nasid, reg, val);
}
示例#14
0
/*
 * hub_setup_prb(nasid, prbnum, credits, conveyor)
 *
 * 	Put a PRB into fire-and-forget mode if conveyor isn't set.  Otherwise,
 * 	put it into conveyor belt mode with the specified number of credits.
 */
static void hub_setup_prb(nasid_t nasid, int prbnum, int credits)
{
	iprb_t prb;
	int prb_offset;

	/*
	 * Get the current register value.
	 */
	prb_offset = IIO_IOPRB(prbnum);
	prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);

	/*
	 * Clear out some fields.
	 */
	prb.iprb_ovflow = 1;
	prb.iprb_bnakctr = 0;
	prb.iprb_anakctr = 0;

	/*
	 * Enable or disable fire-and-forget mode.
	 */
	prb.iprb_ff = force_fire_and_forget ? 1 : 0;

	/*
	 * Set the appropriate number of PIO cresits for the widget.
	 */
	prb.iprb_xtalkctr = credits;

	/*
	 * Store the new value to the register.
	 */
	REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
}
示例#15
0
static int intr_connect_level(int cpu, int bit)
{
	nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
	struct slice_data *si = cpu_data[cpu].data;

	set_bit(bit, si->irq_enable_mask);

	if (!cputoslice(cpu)) {
		REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]);
		REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]);
	} else {
		REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]);
		REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]);
	}

	return 0;
}
示例#16
0
static int mmtimer_disable_int(long nasid, int comparator)
{
	switch (comparator) {
	case 0:
		nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE),
			0UL) : REMOTE_HUB_S(nasid, SH_RTC1_INT_ENABLE, 0UL);
		break;
	case 1:
		nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE),
			0UL) : REMOTE_HUB_S(nasid, SH_RTC2_INT_ENABLE, 0UL);
		break;
	case 2:
		nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE),
			0UL) : REMOTE_HUB_S(nasid, SH_RTC3_INT_ENABLE, 0UL);
		break;
	default:
		return -EFAULT;
	}
	return 0;
}
示例#17
0
/*
 * io_sh_swapper: Turn on Shub byte swapping.
 *	All data destined to and from Shub to XIO are byte-swapped.
 */
void
io_sh_swapper(nasid_t nasid, int onoff)
{
    ii_iwc_u_t      ii_iwc;

    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);

    ii_iwc.ii_iwc_fld_s.i_dma_byte_swap = onoff;
    REMOTE_HUB_S(nasid, IIO_IWC, ii_iwc.ii_iwc_regval);
    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);

}
示例#18
0
static void ip27_machine_halt(void)
{
	int i;

#ifdef CONFIG_SMP
	smp_send_stop();
#endif
	for (i = 0; i < numnodes; i++)
		REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG,
							PROMOP_RESTART);
	LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
	noreturn;
}
示例#19
0
static void __init per_hub_init(cnodeid_t cnode)
{
	struct hub_data *hub = hub_data(cnode);
	nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);

	cpu_set(smp_processor_id(), hub->h_cpus);

	if (test_and_set_bit(cnode, hub_init_mask))
		return;

	/*
	 * Set CRB timeout at 5ms, (< PI timeout of 10ms)
	 */
	REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);

	hub_rtc_init(cnode);
	xtalk_probe_node(cnode);

#ifdef CONFIG_REPLICATE_EXHANDLERS
	/*
	 * If this is not a headless node initialization,
	 * copy over the caliased exception handlers.
	 */
	if (get_compact_nodeid() == cnode) {
		extern char except_vec2_generic, except_vec3_generic;
		extern void build_tlb_refill_handler(void);

		memcpy((void *)(CKSEG0 + 0x100), &except_vec2_generic, 0x80);
		memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x80);
		build_tlb_refill_handler();
		memcpy((void *)(CKSEG0 + 0x100), (void *) CKSEG0, 0x80);
		memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x100);
		__flush_cache_all();
	}
#endif
}
示例#20
0
/* XXX How to pass the reboot command to the firmware??? */
static void ip27_machine_restart(char *command)
{
#if 0
	int i;
#endif

	printk("Reboot started from CPU %d\n", smp_processor_id());
#ifdef CONFIG_SMP
	smp_send_stop();
#endif
#if 0
	for (i = 0; i < numnodes; i++)
		REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG,
							PROMOP_REBOOT);
#else
	LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
#endif
	noreturn;
}
示例#21
0
/*
 * hub_setup_prb(nasid, prbnum, credits, conveyor)
 *
 * 	Put a PRB into fire-and-forget mode if conveyor isn't set.  Otehrwise,
 * 	put it into conveyor belt mode with the specified number of credits.
 */
void
hub_setup_prb(nasid_t nasid, int prbnum, int credits, int conveyor)
{
    iprb_t prb;
    int prb_offset;
#ifdef IRIX
    extern int force_fire_and_forget;
    extern volatile int ignore_conveyor_override;

    if (force_fire_and_forget && !ignore_conveyor_override)
        if (conveyor == HUB_PIO_CONVEYOR)
            conveyor = HUB_PIO_FIRE_N_FORGET;
#endif

    /*
     * Get the current register value.
     */
    prb_offset = IIO_IOPRB(prbnum);
    prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);

    /*
     * Clear out some fields.
     */
    prb.iprb_ovflow = 1;
    prb.iprb_bnakctr = 0;
    prb.iprb_anakctr = 0;

    /*
     * Enable or disable fire-and-forget mode.
     */
    prb.iprb_ff = ((conveyor == HUB_PIO_CONVEYOR) ? 0 : 1);

    /*
     * Set the appropriate number of PIO cresits for the widget.
     */
    prb.iprb_xtalkctr = credits;

    /*
     * Store the new value to the register.
     */
    REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
}
示例#22
0
static void tio_conveyor_set(nasid_t nasid, int enable_flag)
{
	u64 ice_frz;
	u64 disable_cb = (1ull << 61);

	if (!(nasid & 1))
		return;

	ice_frz = REMOTE_HUB_L(nasid, TIO_ICE_FRZ_CFG);
	if (enable_flag) {
		if (!(ice_frz & disable_cb))	/* already enabled */
			return;
		ice_frz &= ~disable_cb;
	} else {
		if (ice_frz & disable_cb)	/* already disabled */
			return;
		ice_frz |= disable_cb;
	}
	DBG(KERN_ALERT "TIO_ICE_FRZ_CFG= 0x%lx\n", ice_frz);
	REMOTE_HUB_S(nasid, TIO_ICE_FRZ_CFG, ice_frz);
}
示例#23
0
/* BRINGUP:  This ought to be useful for IP27 too but, for now,
 * make it SN1 only because `ii_ixtt_u_t' is not in IP27/hubio.h
 * (or anywhere else :-).
 */
int
hubii_ixtt_set(devfs_handle_t widget_vhdl, ii_ixtt_u_t *ixtt)
{
    xwidget_info_t		widget_info = xwidget_info_get(widget_vhdl);
    devfs_handle_t		hub_vhdl    = xwidget_info_master_get(widget_info);
    hubinfo_t		hub_info = 0;
    nasid_t			nasid;
    int			s;

    /* Use the nasid from the hub info hanging off the hub vertex
     * and widget number from the widget vertex
     */
    hubinfo_get(hub_vhdl, &hub_info);
    /* Being over cautious by grabbing a lock */
    s 	= mutex_spinlock(&hub_info->h_bwlock);
    nasid 	= hub_info->h_nasid;

    REMOTE_HUB_S(nasid, IIO_IXTT, ixtt->ii_ixtt_regval);

    mutex_spinunlock(&hub_info->h_bwlock, s);
    return 0;
}
示例#24
0
void
hub_error_clear(nasid_t nasid)
{
	int i;
	hubreg_t idsr;
	int sn;

	for(sn=0; sn<NUM_SUBNODES; sn++) {
		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_PEND, -1);
		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS0_A_CLR, -1);
		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS0_B_CLR, -1);
		REMOTE_HUB_PI_S(nasid, sn, PI_SPURIOUS_HDR_0, 0);
		REMOTE_HUB_PI_S(nasid, sn, PI_SPURIOUS_HDR_1, 0);
	}

	REMOTE_HUB_L(nasid, MD_DIR_ERROR_CLR);
	REMOTE_HUB_L(nasid, MD_MEM_ERROR_CLR);
	REMOTE_HUB_L(nasid, MD_MISC1_ERROR_CLR);
	REMOTE_HUB_L(nasid, MD_PROTOCOL_ERR_CLR);

    /*
     * Make sure spurious write response errors are cleared
     * (values are from hub_set_prb())
     */
    for (i = 0; i <= HUB_WIDGET_ID_MAX - HUB_WIDGET_ID_MIN + 1; i++) {
        iprb_t prb;

	prb.iprb_regval = REMOTE_HUB_L(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)));

        /* Clear out some fields */
        prb.iprb_ovflow = 1;
        prb.iprb_bnakctr = 0;
        prb.iprb_anakctr = 0;

	/*
	 * PIO reads in fire-and-forget mode on bedrock 1.0 don't
	 * frob the credit count properly, making the responses appear
	 * spurious.  So don't use fire-and-forget mode.  Bug 761802.
	 */
        prb.iprb_ff = 0;        /* disable fire-and-forget mode by default */

        prb.iprb_xtalkctr = 3;  /* approx. PIO credits for the widget */

        REMOTE_HUB_S(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)), prb.iprb_regval);
    }

    REMOTE_HUB_S(nasid, IIO_IO_ERR_CLR, -1);
    idsr = REMOTE_HUB_L(nasid, IIO_IIDSR);
    REMOTE_HUB_S(nasid, IIO_IIDSR, (idsr & ~(IIO_IIDSR_SENT_MASK)));

    REMOTE_HUB_L(nasid, NI_PORT_ERROR_CLEAR);
    /* No need to clear NI_PORT_HEADER regs; they are continually overwritten*/

    REMOTE_HUB_S(nasid, LB_ERROR_MASK_CLR, -1);
    REMOTE_HUB_S(nasid, LB_ERROR_HDR1, 0);

    /* Clear XB error regs, in order */
    for (i = 0;
         i <= XB_FIRST_ERROR_CLEAR - XB_POQ0_ERROR_CLEAR;
         i += sizeof(hubreg_t)) {
        REMOTE_HUB_S(nasid, XB_POQ0_ERROR_CLEAR + i, 0);
    }
}
示例#25
0
/*
 * Wait until all BTE related CRBs are completed
 * and then reset the interfaces.
 */
int shub1_bte_error_handler(unsigned long _nodepda)
{
	struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
	struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
	nasid_t nasid;
	int i;
	int valid_crbs;
	ii_imem_u_t imem;	/* II IMEM Register */
	ii_icrb0_d_u_t icrbd;	/* II CRB Register D */
	ii_ibcr_u_t ibcr;
	ii_icmr_u_t icmr;
	ii_ieclr_u_t ieclr;

	BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda,
		    smp_processor_id()));

	if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
	    (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
		BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
			    smp_processor_id()));
		return 1;
	}

	/* Determine information about our hub */
	nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);

	/*
	 * A BTE transfer can use multiple CRBs.  We need to make sure
	 * that all the BTE CRBs are complete (or timed out) before
	 * attempting to clean up the error.  Resetting the BTE while
	 * there are still BTE CRBs active will hang the BTE.
	 * We should look at all the CRBs to see if they are allocated
	 * to the BTE and see if they are still active.  When none
	 * are active, we can continue with the cleanup.
	 *
	 * We also want to make sure that the local NI port is up.
	 * When a router resets the NI port can go down, while it
	 * goes through the LLP handshake, but then comes back up.
	 */
	icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
	if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
		/*
		 * There are errors which still need to be cleaned up by
		 * hubiio_crb_error_handler
		 */
		mod_timer(recovery_timer, jiffies + (HZ * 5));
		BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
			    smp_processor_id()));
		return 1;
	}
	if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {

		valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;

		for (i = 0; i < IIO_NUM_CRBS; i++) {
			if (!((1 << i) & valid_crbs)) {
				/* This crb was not marked as valid, ignore */
				continue;
			}
			icrbd.ii_icrb0_d_regval =
			    REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
			if (icrbd.d_bteop) {
				mod_timer(recovery_timer, jiffies + (HZ * 5));
				BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
					    err_nodepda, smp_processor_id(),
					    i));
				return 1;
			}
		}
	}

	BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda, smp_processor_id()));
	/* Re-enable both bte interfaces */
	imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
	imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
	REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);

	/* Clear BTE0/1 error bits */
	ieclr.ii_ieclr_regval = 0;
	if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
		ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
	if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
		ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
	REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);

	/* Reinitialize both BTE state machines. */
	ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
	ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
	REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);

	del_timer(recovery_timer);
	return 0;
}
示例#26
0
/*ARGSUSED*/
void
hubii_eint_handler (int irq, void *arg, struct pt_regs *ep)
{
    devfs_handle_t	hub_v;
    hubinfo_t		hinfo; 
    ii_wstat_u_t	wstat;
    hubreg_t		idsr;

	panic("Hubii interrupt\n");
#ifdef ajm
    /*
     * If the NI has a problem, everyone has a problem.  We shouldn't
     * even attempt to handle other errors when an NI error is present.
     */
    if (check_ni_errors()) {
	hubni_error_handler("II interrupt", 1);
	/* NOTREACHED */
    }

    /* two levels of casting avoids compiler warning.!! */
    hub_v = (devfs_handle_t)(long)(arg); 
    ASSERT(hub_v);

    hubinfo_get(hub_v, &hinfo);
    
    /* 
     * Identify the reason for error. 
     */
    wstat.ii_wstat_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_WSTAT);

    if (wstat.ii_wstat_fld_s.w_crazy) {
	char	*reason;
	/*
	 * We can do a couple of things here. 
	 * Look at the fields TX_MX_RTY/XT_TAIL_TO/XT_CRD_TO to check
	 * which of these caused the CRAZY bit to be set. 
	 * You may be able to check if the Link is up really.
	 */
	if (wstat.ii_wstat_fld_s.w_tx_mx_rty)
		reason = "Micro Packet Retry Timeout";
	else if (wstat.ii_wstat_fld_s.w_xt_tail_to)
		reason = "Crosstalk Tail Timeout";
	else if (wstat.ii_wstat_fld_s.w_xt_crd_to)
		reason = "Crosstalk Credit Timeout";
	else {
		hubreg_t	hubii_imem;
		/*
		 * Check if widget 0 has been marked as shutdown, or
		 * if BTE 0/1 has been marked.
		 */
		hubii_imem = REMOTE_HUB_L(hinfo->h_nasid, IIO_IMEM);
		if (hubii_imem & IIO_IMEM_W0ESD)
			reason = "Hub Widget 0 has been Shutdown";
		else if (hubii_imem & IIO_IMEM_B0ESD)
			reason = "BTE 0 has been shutdown";
		else if (hubii_imem & IIO_IMEM_B1ESD)
			reason = "BTE 1 has been shutdown";
		else	reason = "Unknown";
	
	}
	/*
	 * Note: we may never be able to print this, if the II talking
	 * to Xbow which hosts the console is dead. 
	 */
	printk("Hub %d to Xtalk Link failed (II_ECRAZY) Reason: %s", 
		hinfo->h_cnodeid, reason);
    }

    /* 
     * It's a toss as to which one among PRB/CRB to check first. 
     * Current decision is based on the severity of the errors. 
     * IO CRB errors tend to be more severe than PRB errors.
     *
     * It is possible for BTE errors to have been handled already, so we
     * may not see any errors handled here. 
     */
    (void)hubiio_crb_error_handler(hub_v, hinfo);
    (void)hubiio_prb_error_handler(hub_v, hinfo);
    /*
     * If we reach here, it indicates crb/prb handlers successfully
     * handled the error. So, re-enable II to send more interrupt
     * and return.
     */
    REMOTE_HUB_S(hinfo->h_nasid, IIO_IECLR, 0xffffff);
    idsr = REMOTE_HUB_L(hinfo->h_nasid, IIO_IIDSR) & ~IIO_IIDSR_SENT_MASK;
    REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, idsr);
#endif /* ajm */
}
示例#27
0
/*
 * Second part error handler.  Wait until all BTE related CRBs are completed
 * and then reset the interfaces.
 */
void
bte_error_handler(unsigned long _nodepda)
{
	struct nodepda_s *err_nodepda = (struct nodepda_s *) _nodepda;
	spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
	struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
	nasid_t nasid;
	int i;
	int valid_crbs;
	unsigned long irq_flags;
	volatile u64 *notify;
	bte_result_t bh_error;
	ii_imem_u_t imem;	/* II IMEM Register */
	ii_icrb0_d_u_t icrbd;	/* II CRB Register D */
	ii_ibcr_u_t ibcr;
	ii_icmr_u_t icmr;
	ii_ieclr_u_t ieclr;


	BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
		    smp_processor_id()));

	spin_lock_irqsave(recovery_lock, irq_flags);

	if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
	    (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
		BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
			    smp_processor_id()));
		spin_unlock_irqrestore(recovery_lock, irq_flags);
		return;
	}
	/*
	 * Lock all interfaces on this node to prevent new transfers
	 * from being queued.
	 */
	for (i = 0; i < BTES_PER_NODE; i++) {
		if (err_nodepda->bte_if[i].cleanup_active) {
			continue;
		}
		spin_lock(&err_nodepda->bte_if[i].spinlock);
		BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
			    smp_processor_id(), i));
		err_nodepda->bte_if[i].cleanup_active = 1;
	}

	/* Determine information about our hub */
	nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);


	/*
	 * A BTE transfer can use multiple CRBs.  We need to make sure
	 * that all the BTE CRBs are complete (or timed out) before
	 * attempting to clean up the error.  Resetting the BTE while
	 * there are still BTE CRBs active will hang the BTE.
	 * We should look at all the CRBs to see if they are allocated
	 * to the BTE and see if they are still active.  When none
	 * are active, we can continue with the cleanup.
	 *
	 * We also want to make sure that the local NI port is up.
	 * When a router resets the NI port can go down, while it
	 * goes through the LLP handshake, but then comes back up.
	 */
	icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
	if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
		/*
		 * There are errors which still need to be cleaned up by
		 * hubiio_crb_error_handler
		 */
		mod_timer(recovery_timer, HZ * 5);
		BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
			    smp_processor_id()));
		spin_unlock_irqrestore(recovery_lock, irq_flags);
		return;
	}
	if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {

		valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;

		for (i = 0; i < IIO_NUM_CRBS; i++) {
			if (!((1 << i) & valid_crbs)) {
				/* This crb was not marked as valid, ignore */
				continue;
			}
			icrbd.ii_icrb0_d_regval =
			    REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
			if (icrbd.d_bteop) {
				mod_timer(recovery_timer, HZ * 5);
				BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
					 err_nodepda, smp_processor_id(), i));
				spin_unlock_irqrestore(recovery_lock,
						       irq_flags);
				return;
			}
		}
	}


	BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda,
		    smp_processor_id()));
	/* Reenable both bte interfaces */
	imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
	imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
	REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);

	/* Clear IBLS0/1 error bits */
	ieclr.ii_ieclr_regval = 0;
	if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
		ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
	if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
                ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
	REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);

	/* Reinitialize both BTE state machines. */
	ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
	ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
	REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);


	for (i = 0; i < BTES_PER_NODE; i++) {
		bh_error = err_nodepda->bte_if[i].bh_error;
		if (bh_error != BTE_SUCCESS) {
			/* There is an error which needs to be notified */
			notify = err_nodepda->bte_if[i].most_rcnt_na;
			BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
				    err_nodepda->bte_if[i].bte_cnode,
				    err_nodepda->bte_if[i].bte_num,
				    IBLS_ERROR | (u64) bh_error));
			*notify = IBLS_ERROR | bh_error;
			err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
		}

		err_nodepda->bte_if[i].cleanup_active = 0;
		BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
			    smp_processor_id(), i));
		spin_unlock(&err_nodepda->bte_if[i].spinlock);
	}

	del_timer(recovery_timer);

	spin_unlock_irqrestore(recovery_lock, irq_flags);
}
示例#28
0
/*ARGSUSED*/
irqreturn_t
hubii_eint_handler (int irq, void *arg, struct pt_regs *ep)
{
    vertex_hdl_t	hub_v;
    hubinfo_t		hinfo; 
    ii_wstat_u_t	wstat;
    hubreg_t		idsr;
    ii_ilcsr_u_t	ilcsr;


    /* two levels of casting avoids compiler warning.!! */
    hub_v = (vertex_hdl_t)(long)(arg); 
    ASSERT(hub_v);

    hubinfo_get(hub_v, &hinfo);
    
    idsr = REMOTE_HUB_L(hinfo->h_nasid, IIO_ICMR);
#if 0
    if (idsr & 0x1) {
	/* ICMR bit is set .. we are getting into "Spurious Interrupts condition. */
	printk("Cnode %d II has seen the ICMR condition\n", hinfo->h_cnodeid);
	printk("***** Please file PV with the above messages *****\n");
	/* panic("We have to panic to prevent further unknown states ..\n"); */
    }
#endif
	
    /* 
     * Identify the reason for error. 
     */
    wstat.ii_wstat_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_WSTAT);

    if (wstat.ii_wstat_fld_s.w_crazy) {
	char	*reason;
	/*
	 * We can do a couple of things here. 
	 * Look at the fields TX_MX_RTY/XT_TAIL_TO/XT_CRD_TO to check
	 * which of these caused the CRAZY bit to be set. 
	 * You may be able to check if the Link is up really.
	 */
	if (wstat.ii_wstat_fld_s.w_tx_mx_rty)
		reason = "Micro Packet Retry Timeout";
	else if (wstat.ii_wstat_fld_s.w_xt_tail_to)
		reason = "Crosstalk Tail Timeout";
	else if (wstat.ii_wstat_fld_s.w_xt_crd_to)
		reason = "Crosstalk Credit Timeout";
	else {
		hubreg_t	hubii_imem;
		/*
		 * Check if widget 0 has been marked as shutdown, or
		 * if BTE 0/1 has been marked.
		 */
		hubii_imem = REMOTE_HUB_L(hinfo->h_nasid, IIO_IMEM);
		if (hubii_imem & IIO_IMEM_W0ESD)
			reason = "Hub Widget 0 has been Shutdown";
		else if (hubii_imem & IIO_IMEM_B0ESD)
			reason = "BTE 0 has been shutdown";
		else if (hubii_imem & IIO_IMEM_B1ESD)
			reason = "BTE 1 has been shutdown";
		else	reason = "Unknown";
	
	}
	/*
	 * Note: we may never be able to print this, if the II talking
	 * to Xbow which hosts the console is dead. 
	 */
	ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ILCSR);
	if (ilcsr.ii_ilcsr_fld_s.i_llp_en == 1) {	/* Link is enabled */
	    printk("Hub %d, cnode %d to Xtalk Link failed (II_ECRAZY) Reason: %s", 
		hinfo->h_nasid, hinfo->h_cnodeid, reason);
	}
    }


    /*
     * Before processing any interrupt related information, clear all
     * error indication and reenable interrupts.  This will prevent
     * lost interrupts due to the interrupt handler scanning past a PRB/CRB
     * which has not errorred yet and then the PRB/CRB goes into error.
     * Note, PRB errors are cleared individually.
     */
    REMOTE_HUB_S(hinfo->h_nasid, IIO_IECLR, 0xff0000);
    idsr = REMOTE_HUB_L(hinfo->h_nasid, IIO_IIDSR) & ~IIO_IIDSR_SENT_MASK;
    REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, idsr);


    /* 
     * It's a toss as to which one among PRB/CRB to check first. 
     * Current decision is based on the severity of the errors. 
     * IO CRB errors tend to be more severe than PRB errors.
     *
     * It is possible for BTE errors to have been handled already, so we
     * may not see any errors handled here. 
     */
    (void)hubiio_crb_error_handler(hub_v, hinfo);
    (void)hubiio_prb_error_handler(hub_v, hinfo);

    return IRQ_HANDLED;
}
示例#29
0
/* 
 * >>> bte_crb_error_handler needs to be broken into two parts.  The
 * first should cleanup the CRB.  The second should wait until all bte
 * related CRB's are complete and then do the error reset.
 */
void
bte_crb_error_handler(devfs_handle_t hub_v, int btenum, 
		      int crbnum, ioerror_t *ioe, int bteop)
/*
 * Function: 	bte_crb_error_handler
 * Purpose:	Process a CRB for a specific HUB/BTE
 * Parameters:	hub_v	- vertex of hub in HW graph
 *		btenum	- bte number on hub (0 == a, 1 == b)
 *		crbnum	- crb number being processed
 * Notes: 
 *	This routine assumes serialization at a higher level. A CRB 
 *	should not be processed more than once. The error recovery 
 *	follows the following sequence - if you change this, be real
 *	sure about what you are doing. 
 *
 */
{
        hubinfo_t	hinfo;
	icrba_t		crba; 
	icrbb_t		crbb; 
	nasid_t		n;
	hubreg_t	iidsr, imem, ieclr;

	hubinfo_get(hub_v, &hinfo);


	n = hinfo->h_nasid;
	

	/*
	 * The following 10 lines (or so) are adapted from IRIXs
	 * bte_crb_error function.  No clear documentation tells
	 * why the crb needs to complete normally in order for
	 * the BTE to resume normal operations.  This first step
	 * appears vital!
	 */

	/*
	 * Zero error and error code to prevent error_dump complaining
	 * about these CRBs. Copy the CRB to the notification line.
	 * The crb address is in shub format (physical address shifted
	 * right by cacheline size).
	 */
	crbb.ii_icrb0_b_regval = REMOTE_HUB_L(n, IIO_ICRB_B(crbnum));
	crbb.b_error=0;
	crbb.b_ecode=0;
	REMOTE_HUB_S(n, IIO_ICRB_B(crbnum), crbb.ii_icrb0_b_regval);

	crba.ii_icrb0_a_regval = REMOTE_HUB_L(n, IIO_ICRB_A(crbnum));
	crba.a_addr = TO_PHYS((u64)&nodepda->bte_if[btenum].notify) >> 3;
	crba.a_valid = 1;
	REMOTE_HUB_S(n, IIO_ICRB_A(crbnum), crba.ii_icrb0_a_regval);

	REMOTE_HUB_S(n, IIO_ICCR, 
		     IIO_ICCR_PENDING | IIO_ICCR_CMD_FLUSH | crbnum);

	while (REMOTE_HUB_L(n, IIO_ICCR) & IIO_ICCR_PENDING)
	    ;


	/* Terminate the BTE. */
	/* >>> The other bte transfer will need to be restarted. */
	HUB_L((shubreg_t *)((nodepda->bte_if[btenum].bte_base_addr +
		       IIO_IBCT0 - IIO_IBLS0)));

	imem = REMOTE_HUB_L(n, IIO_IMEM);
	ieclr = REMOTE_HUB_L(n, IIO_IECLR);
	if (btenum == 0) {
		imem |= IIO_IMEM_W0ESD | IIO_IMEM_B0ESD;
		ieclr|= IECLR_BTE0;
	} else {
		imem |= IIO_IMEM_W0ESD | IIO_IMEM_B1ESD;
		ieclr|= IECLR_BTE1;
	}
	REMOTE_HUB_S(n, IIO_IMEM, imem);
	REMOTE_HUB_S(n, IIO_IECLR, ieclr);
		
	iidsr  = REMOTE_HUB_L(n, IIO_IIDSR);
	iidsr &= ~IIO_IIDSR_SENT_MASK;
	iidsr |= IIO_IIDSR_ENB_MASK;
	REMOTE_HUB_S(n, IIO_IIDSR, iidsr);


 	bte_reset_nasid(n);

	*nodepda->bte_if[btenum].most_rcnt_na = IBLS_ERROR;
}