static unsigned long *
lookup_fit(int nasid)
{
	unsigned long *fitp;
	unsigned long fit_paddr;
	unsigned long *fit_vaddr;

#ifdef CONFIG_IA64_SGI_SN_SIM
	if (IS_RUNNING_ON_SIMULATOR())
		return fakefit;
#endif

	fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32);
	DPRINTK("pointer to fit at %p\n", (void *)fitp);
	fit_paddr = readq(fitp);
	DPRINTK("fit pointer contains %lx\n", fit_paddr);
	/* snag just the node-relative offset */
	fit_paddr &= ~0ul >> (63-35);
	/* the pointer to the FIT is relative to IA-64 compatibility
	 * space.  However, the PROM is mapped at a different offset
	 * in MMR space (both local and global)
	 */
	fit_paddr += 0x700000000;
	fit_vaddr = (void *)GLOBAL_MMR_ADDR(nasid, fit_paddr);
	DPRINTK("fit at %p\n", (void *)fit_vaddr);
	return fit_vaddr;
}
Пример #2
0
/*
 * Change protections to allow IPI operations (and AMO operations on
 * Shub 1.1 systems).
 */
void
xpc_allow_IPI_ops(void)
{
	int node;
	int nasid;


	// >>> Change SH_IPI_ACCESS code to use SAL call once it is available.

	if (is_shub2()) {
		xpc_sh2_IPI_access0 =
			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
		xpc_sh2_IPI_access1 =
			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
		xpc_sh2_IPI_access2 =
			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
		xpc_sh2_IPI_access3 =
			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));

		for_each_online_node(node) {
			nasid = cnodeid_to_nasid(node);
			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
								-1UL);
			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
								-1UL);
			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
								-1UL);
			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
								-1UL);
		}

	} else {
Пример #3
0
static void sn_ack_irq(unsigned int irq)
{
	uint64_t event_occurred, mask = 0;
	int nasid;

	irq = irq & 0xff;
	nasid = get_nasid();
	event_occurred =
	    HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED));
	mask = event_occurred & SH_ALL_INT_MASK;
	HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS),
		 mask);
	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);

	move_irq(irq);
}
Пример #4
0
static inline void
shub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val)
{
	int		   nasid = cnodeid_to_nasid(cnode);
	volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));

	*addr = val;
	__ia64_mf_a();
}
Пример #5
0
static inline uint32_t
shub_mmr_read32(cnodeid_t cnode, shubreg_t reg)
{
	int		  nasid = cnodeid_to_nasid(cnode);
	volatile uint32_t val;

	val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
	__ia64_mf_a();

	return val;
}
Пример #6
0
static void
sn_ack_irq(unsigned int irq)
{
	unsigned long event_occurred, mask = 0;
	int nasid;

	irq = irq & 0xff;
	nasid = smp_physical_node_id();
	event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
	if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
	}
	if (event_occurred & SH_EVENT_OCCURRED_IPI_INT_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_IPI_INT_SHFT);
	}
	if (event_occurred & SH_EVENT_OCCURRED_II_INT0_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_II_INT0_SHFT);
	}
	if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
	}
	HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask );
	__set_bit(irq, (volatile void *)pda.sn_in_service_ivecs);
}
Пример #7
0
static void
sn_end_irq(unsigned int irq)
{
	int nasid;
	int ivec;
	unsigned long event_occurred;

	ivec = irq & 0xff;
	if (ivec == SGI_UART_VECTOR) {
		nasid = smp_physical_node_id();
		event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
		// If the UART bit is set here, we may have received an interrupt from the
		// UART that the driver missed.  To make sure, we IPI ourselves to force us
		// to look again.
		if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
				platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0);
		}
	}
	clear_bit(ivec, (volatile void *)pda.sn_in_service_ivecs);
	if (sn_force_interrupt_flag)
		force_interrupt(irq);
}
Пример #8
0
static void
sn_end_irq(unsigned int irq)
{
#ifdef CONFIG_IA64_SGI_SN1
	unsigned long long intpend_val, mask = 0x70L;
	int subnode;
#endif
	int nasid;
#ifdef CONFIG_IA64_SGI_SN2
	unsigned long event_occurred;
#endif

	irq = irq & 0xff;
#ifdef CONFIG_IA64_SGI_SN1
	if (irq == SGI_UART_IRQ) {
		nasid = smp_physical_node_id();
		subnode = cpuid_to_subnode(smp_processor_id());
		intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
		if (intpend_val & mask) {
			platform_send_ipi(smp_processor_id(), SGI_UART_IRQ, IA64_IPI_DM_INT, 0);
		}
	}
#endif
#ifdef CONFIG_IA64_SGI_SN2
	if (irq == SGI_UART_VECTOR) {
		nasid = smp_physical_node_id();
		event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
		// If the UART bit is set here, we may have received an interrupt from the
		// UART that the driver missed.  To make sure, we IPI ourselves to force us
		// to look again.
		if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
				platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0);
		}
	}
#endif

}
Пример #9
0
static void
sn_ack_irq(unsigned int irq)
{
#ifdef CONFIG_IA64_SGI_SN1
	int bit = -1;
	unsigned long long intpend_val;
	int subnode;
#endif
#ifdef CONFIG_IA64_SGI_SN2
	unsigned long event_occurred, mask = 0;
#endif
	int nasid;

	irq = irq & 0xff;
	nasid = smp_physical_node_id();
#ifdef CONFIG_IA64_SGI_SN1
	subnode = cpuid_to_subnode(smp_processor_id());
	if (irq == SGI_UART_IRQ) {
		intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
		if (intpend_val & (1L<<GFX_INTR_A) ) {
			bit = GFX_INTR_A;
			REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
		}
		if ( intpend_val & (1L<<GFX_INTR_B) ) {
			bit = GFX_INTR_B;
			REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
		}
		if (intpend_val & (1L<<PG_MIG_INTR) ) {
			bit = PG_MIG_INTR;
			REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
		}
		if (intpend_val & (1L<<CC_PEND_A)) {
			bit = CC_PEND_A;
			REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
		}
		if (intpend_val & (1L<<CC_PEND_B)) {
			bit = CC_PEND_B;
			REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
		}
		return;
	}
	bit = irq_to_bit_pos(irq);
	REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
#endif

#ifdef CONFIG_IA64_SGI_SN2
	event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
	if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
	}
	if (event_occurred & SH_EVENT_OCCURRED_IPI_INT_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_IPI_INT_SHFT);
	}
	if (event_occurred & SH_EVENT_OCCURRED_II_INT0_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_II_INT0_SHFT);
	}
	if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) {
		mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
	}
	HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask );
#endif
}
Пример #10
0
/**
 * sn_cpu_init - initialize per-cpu data areas
 * @cpuid: cpuid of the caller
 *
 * Called during cpu initialization on each cpu as it starts.
 * Currently, initializes the per-cpu data area for SNIA.
 * Also sets up a few fields in the nodepda.  Also known as
 * platform_cpu_init() by the ia64 machvec code.
 */
void __cpuinit sn_cpu_init(void)
{
	int cpuid;
	int cpuphyid;
	int nasid;
	int subnode;
	int slice;
	int cnode;
	int i;
	static int wars_have_been_checked;

	cpuid = smp_processor_id();
	if (cpuid == 0 && IS_MEDUSA()) {
		if (ia64_sn_is_fake_prom())
			sn_prom_type = 2;
		else
			sn_prom_type = 1;
		printk(KERN_INFO "Running on medusa with %s PROM\n",
		       (sn_prom_type == 1) ? "real" : "fake");
	}

	memset(pda, 0, sizeof(pda));
	if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2,
				&sn_hub_info->nasid_bitmask,
				&sn_hub_info->nasid_shift,
				&sn_system_size, &sn_sharing_domain_size,
				&sn_partition_id, &sn_coherency_id,
				&sn_region_size))
		BUG();
	sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;

	/*
	 * Don't check status. The SAL call is not supported on all PROMs
	 * but a failure is harmless.
	 */
	(void) ia64_sn_set_cpu_number(cpuid);

	/*
	 * The boot cpu makes this call again after platform initialization is
	 * complete.
	 */
	if (nodepdaindr[0] == NULL)
		return;

	for (i = 0; i < MAX_PROM_FEATURE_SETS; i++)
		if (ia64_sn_get_prom_feature_set(i, &sn_prom_features[i]) != 0)
			break;

	cpuphyid = get_sapicid();

	if (ia64_sn_get_sapic_info(cpuphyid, &nasid, &subnode, &slice))
		BUG();

	for (i=0; i < MAX_NUMNODES; i++) {
		if (nodepdaindr[i]) {
			nodepdaindr[i]->phys_cpuid[cpuid].nasid = nasid;
			nodepdaindr[i]->phys_cpuid[cpuid].slice = slice;
			nodepdaindr[i]->phys_cpuid[cpuid].subnode = subnode;
		}
	}

	cnode = nasid_to_cnodeid(nasid);

	sn_nodepda = nodepdaindr[cnode];

	pda->led_address =
	    (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));
	pda->led_state = LED_ALWAYS_SET;
	pda->hb_count = HZ / 2;
	pda->hb_state = 0;
	pda->idle_flag = 0;

	if (cpuid != 0) {
		/* copy cpu 0's sn_cnodeid_to_nasid table to this cpu's */
		memcpy(sn_cnodeid_to_nasid,
		       (&per_cpu(__sn_cnodeid_to_nasid, 0)),
		       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
	}

	/*
	 * Check for WARs.
	 * Only needs to be done once, on BSP.
	 * Has to be done after loop above, because it uses this cpu's
	 * sn_cnodeid_to_nasid table which was just initialized if this
	 * isn't cpu 0.
	 * Has to be done before assignment below.
	 */
	if (!wars_have_been_checked) {
		sn_check_for_wars();
		wars_have_been_checked = 1;
	}
	sn_hub_info->shub_1_1_found = shub_1_1_found;

	/*
	 * Set up addresses of PIO/MEM write status registers.
	 */
	{
		u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0};
		u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_2,
			SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
		u64 *pio;
		pio = is_shub1() ? pio1 : pio2;
		pda->pio_write_status_addr =
		   (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]);
		pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
	}

	/*
	 * WAR addresses for SHUB 1.x.
	 */
	if (local_node_data->active_cpu_count++ == 0 && is_shub1()) {
		int buddy_nasid;
		buddy_nasid =
		    cnodeid_to_nasid(numa_node_id() ==
				     num_online_nodes() - 1 ? 0 : numa_node_id() + 1);
		pda->pio_shub_war_cam_addr =
		    (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid,
							      SH1_PI_CAM_CONTROL);
	}
}
Пример #11
0
/**
 * sn_cpu_init - initialize per-cpu data areas
 * @cpuid: cpuid of the caller
 *
 * Called during cpu initialization on each cpu as it starts.
 * Currently, initializes the per-cpu data area for SNIA.
 * Also sets up a few fields in the nodepda.  Also known as
 * platform_cpu_init() by the ia64 machvec code.
 */
void __init sn_cpu_init(void)
{
	int cpuid;
	int cpuphyid;
	int nasid;
	int subnode;
	int slice;
	int cnode;
	int i;
	static int wars_have_been_checked;

	memset(pda, 0, sizeof(pda));
	if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift,
				&sn_system_size, &sn_sharing_domain_size, &sn_partition_id,
				&sn_coherency_id, &sn_region_size))
		BUG();
	sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;

	/*
	 * The boot cpu makes this call again after platform initialization is
	 * complete.
	 */
	if (nodepdaindr[0] == NULL)
		return;

	cpuid = smp_processor_id();
	cpuphyid = get_sapicid();

	if (ia64_sn_get_sapic_info(cpuphyid, &nasid, &subnode, &slice))
		BUG();

	for (i=0; i < MAX_NUMNODES; i++) {
		if (nodepdaindr[i]) {
			nodepdaindr[i]->phys_cpuid[cpuid].nasid = nasid;
			nodepdaindr[i]->phys_cpuid[cpuid].slice = slice;
			nodepdaindr[i]->phys_cpuid[cpuid].subnode = subnode;
		}
	}

	cnode = nasid_to_cnodeid(nasid);

	pda->p_nodepda = nodepdaindr[cnode];
	pda->led_address =
	    (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));
	pda->led_state = LED_ALWAYS_SET;
	pda->hb_count = HZ / 2;
	pda->hb_state = 0;
	pda->idle_flag = 0;

	if (cpuid != 0) {
		memcpy(pda->cnodeid_to_nasid_table,
		       pdacpu(0)->cnodeid_to_nasid_table,
		       sizeof(pda->cnodeid_to_nasid_table));
	}

	/*
	 * Check for WARs.
	 * Only needs to be done once, on BSP.
	 * Has to be done after loop above, because it uses pda.cnodeid_to_nasid_table[i].
	 * Has to be done before assignment below.
	 */
	if (!wars_have_been_checked) {
		sn_check_for_wars();
		wars_have_been_checked = 1;
	}
	sn_hub_info->shub_1_1_found = shub_1_1_found;

	/*
	 * Set up addresses of PIO/MEM write status registers.
	 */
	{
		u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0};
		u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_1, 
			SH2_PIO_WRITE_STATUS_2, SH2_PIO_WRITE_STATUS_3};
		u64 *pio;
		pio = is_shub1() ? pio1 : pio2;
		pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]);
		pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
	}

	/*
	 * WAR addresses for SHUB 1.x.
	 */
	if (local_node_data->active_cpu_count++ == 0 && is_shub1()) {
		int buddy_nasid;
		buddy_nasid =
		    cnodeid_to_nasid(numa_node_id() ==
				     num_online_nodes() - 1 ? 0 : numa_node_id() + 1);
		pda->pio_shub_war_cam_addr =
		    (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid,
							      SH1_PI_CAM_CONTROL);
	}
}
Пример #12
0
void
intr_init_vecblk( nodepda_t *npda,
                  cnodeid_t node,
                  int sn)
{
    int 			nasid = cnodeid_to_nasid(node);
    sh_ii_int0_config_u_t	ii_int_config;
    cpuid_t			cpu;
    cpuid_t			cpu0, cpu1;
    nodepda_t		*lnodepda;
    sh_ii_int0_enable_u_t	ii_int_enable;
    sh_int_node_id_config_u_t	node_id_config;
    sh_local_int5_config_u_t	local5_config;
    sh_local_int5_enable_u_t	local5_enable;
    extern void sn_init_cpei_timer(void);
    static int timer_added = 0;


    if (is_headless_node(node) ) {
        int cnode;
        struct ia64_sal_retval ret_stuff;

        // retarget all interrupts on this node to the master node.
        node_id_config.sh_int_node_id_config_regval = 0;
        node_id_config.sh_int_node_id_config_s.node_id = master_nasid;
        node_id_config.sh_int_node_id_config_s.id_sel = 1;
        HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_INT_NODE_ID_CONFIG),
               node_id_config.sh_int_node_id_config_regval);
        cnode = nasid_to_cnodeid(master_nasid);
        lnodepda = NODEPDA(cnode);
        cpu = lnodepda->node_first_cpu;
        cpu = cpu_physical_id(cpu);
        SAL_CALL(ret_stuff, SN_SAL_REGISTER_CE, nasid, cpu, master_nasid,0,0,0,0);
        if (ret_stuff.status < 0) {
            printk("%s: SN_SAL_REGISTER_CE SAL_CALL failed\n",__FUNCTION__);
        }
    } else {
        lnodepda = NODEPDA(node);
        cpu = lnodepda->node_first_cpu;
        cpu = cpu_physical_id(cpu);
    }

    // Get the physical id's of the cpu's on this node.
    cpu0 = nasid_slice_to_cpu_physical_id(nasid, 0);
    cpu1 = nasid_slice_to_cpu_physical_id(nasid, 2);

    HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_PI_ERROR_MASK), 0);
    HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_PI_CRBP_ERROR_MASK), 0);

    // Config and enable UART interrupt, all nodes.

    local5_config.sh_local_int5_config_regval = 0;
    local5_config.sh_local_int5_config_s.idx = SGI_UART_VECTOR;
    local5_config.sh_local_int5_config_s.pid = cpu;
    HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG),
           local5_config.sh_local_int5_config_regval);

    local5_enable.sh_local_int5_enable_regval = 0;
    local5_enable.sh_local_int5_enable_s.uart_int = 1;
    HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_ENABLE),
           local5_enable.sh_local_int5_enable_regval);


    // The II_INT_CONFIG register for cpu 0.
    ii_int_config.sh_ii_int0_config_regval = 0;
    ii_int_config.sh_ii_int0_config_s.type = 0;
    ii_int_config.sh_ii_int0_config_s.agt = 0;
    ii_int_config.sh_ii_int0_config_s.pid = cpu0;
    ii_int_config.sh_ii_int0_config_s.base = 0;

    HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_II_INT0_CONFIG),
          ii_int_config.sh_ii_int0_config_regval);


    // The II_INT_CONFIG register for cpu 1.
    ii_int_config.sh_ii_int0_config_regval = 0;
    ii_int_config.sh_ii_int0_config_s.type = 0;
    ii_int_config.sh_ii_int0_config_s.agt = 0;
    ii_int_config.sh_ii_int0_config_s.pid = cpu1;
    ii_int_config.sh_ii_int0_config_s.base = 0;

    HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_II_INT1_CONFIG),
          ii_int_config.sh_ii_int0_config_regval);


    // Enable interrupts for II_INT0 and 1.
    ii_int_enable.sh_ii_int0_enable_regval = 0;
    ii_int_enable.sh_ii_int0_enable_s.ii_enable = 1;

    HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_II_INT0_ENABLE),
          ii_int_enable.sh_ii_int0_enable_regval);
    HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_II_INT1_ENABLE),
          ii_int_enable.sh_ii_int0_enable_regval);


    if (!timer_added) { // can only init the timer once.
        timer_added = 1;
        sn_init_cpei_timer();
    }
}