📄 setup.c
字号:
/* * Now copy the array of nodepda pointers to each nodepda. */ for (cnode=0; cnode < numnodes; cnode++) memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, sizeof(nodepdaindr)); /* * Set up IO related platform-dependent nodepda fields. * The following routine actually sets up the hubinfo struct * in nodepda. */ for (cnode = 0; cnode < numnodes; cnode++) { init_platform_nodepda(nodepdaindr[cnode], cnode); bte_init_node (nodepdaindr[cnode], cnode); }}/** * 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 __initsn_cpu_init(void){ int cpuid; int cpuphyid; int nasid; int slice; int cnode; /* * The boot cpu makes this call again after platform initialization is * complete. */ if (nodepdaindr[0] == NULL) return; cpuid = smp_processor_id(); cpuphyid = ((ia64_get_lid() >> 16) & 0xffff); nasid = cpu_physical_id_to_nasid(cpuphyid); cnode = nasid_to_cnodeid(nasid); slice = cpu_physical_id_to_slice(cpuphyid); printk("CPU %d: nasid %d, slice %d, cnode %d\n", smp_processor_id(), nasid, slice, cnode); memset(&pda, 0, sizeof(pda)); pda.p_nodepda = nodepdaindr[cnode]; pda.led_address = (typeof(pda.led_address)) (LED0 + (slice<<LED_CPU_SHIFT));#ifdef LED_WAR pda.led_address = (typeof(pda.led_address)) (LED0 + (slice<<(LED_CPU_SHIFT-1))); /* temp til L1 firmware fixed */#endif pda.led_state = LED_ALWAYS_SET; pda.hb_count = HZ/2; pda.hb_state = 0; pda.idle_flag = 0; if (local_node_data->active_cpu_count == 1) nodepda->node_first_cpu = cpuid;#ifdef CONFIG_IA64_SGI_SN1 { int synergy; synergy = cpu_physical_id_to_synergy(cpuphyid); pda.p_subnodepda = &nodepdaindr[cnode]->snpda[synergy]; }#endif#ifdef CONFIG_IA64_SGI_SN2 /* * We must use different memory allocators for first cpu (bootmem * allocator) than for the other cpus (regular allocator). */ if (cpuid == 0) irqpdaindr[cpuid] = alloc_bootmem_node(NODE_DATA(cpuid_to_cnodeid(cpuid)),sizeof(irqpda_t)); else irqpdaindr[cpuid] = page_address(alloc_pages_node(local_cnodeid(), GFP_KERNEL, get_order(sizeof(irqpda_t)))); memset(irqpdaindr[cpuid], 0, sizeof(irqpda_t)); pda.p_irqpda = irqpdaindr[cpuid]; pda.pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR((slice < 2 ? SH_PIO_WRITE_STATUS_0 : SH_PIO_WRITE_STATUS_1 ) ); pda.mem_write_status_addr = (volatile u64 *) LOCAL_MMR_ADDR((slice < 2 ? SH_MEMORY_WRITE_STATUS_0 : SH_MEMORY_WRITE_STATUS_1 ) ); if (nodepda->node_first_cpu == cpuid) { int buddy_nasid; buddy_nasid = cnodeid_to_nasid(local_cnodeid() == numnodes-1 ? 0 : local_cnodeid()+ 1); pda.pio_shub_war_cam_addr = (volatile unsigned long*)GLOBAL_MMR_ADDR(nasid, SH_PI_CAM_CONTROL); }#ifdef BRINGUP2 /* * Zero out the counters used for counting MCAs * ZZZZZ temp */ { long *p; p = (long*)LOCAL_MMR_ADDR(SH_XN_IILB_LB_CMP_ENABLE0); *p = 0; p = (long*)LOCAL_MMR_ADDR(SH_XN_IILB_LB_CMP_ENABLE1); *p = 0; }#endif#endif#ifdef CONFIG_IA64_SGI_SN1 pda.bedrock_rev_id = (volatile unsigned long *) LOCAL_HUB(LB_REV_ID); if (cpuid_to_synergy(cpuid)) /* CPU B */ pda.pio_write_status_addr = (volatile unsigned long *) GBL_PERF_B_ADDR; else /* CPU A */ pda.pio_write_status_addr = (volatile unsigned long *) GBL_PERF_A_ADDR;#endif bte_init_cpu();}/** * cnodeid_to_cpuid - convert a cnode to a cpuid of a cpu on the node. * @cnode: node to get a cpuid from * * Returns -1 if no cpus exist on the node. * NOTE:BRINGUP ZZZ This is NOT a good way to find cpus on the node. * Need a better way!! */intcnodeid_to_cpuid(int cnode) { int cpu; for (cpu = 0; cpu < smp_num_cpus; cpu++) if (cpuid_to_cnodeid(cpu) == cnode) break; if (cpu == smp_num_cpus) cpu = -1; return cpu;}/** * get_cycles - return a non-decreasing timestamp * * On SN, we use an RTC read for this function */cycles_tget_cycles (void){ return GET_RTC_COUNTER();}/** * gettimeoffset - number of usecs elapsed since &xtime was last updated * * This function is used by do_gettimeofday() to determine the number * of usecs that have elapsed since the last update to &xtime. On SN * this is accomplished using the RTC built in to each Hub chip; each * is guaranteed to be synchronized by the PROM, so a local read will * suffice (get_cycles() does this for us). A snapshot of the RTC value * is taken on every timer interrupt and this function more or less * subtracts that snapshot value from the current value. * * Note that if a lot of processing was done during the last timer * interrupt then &xtime may be some number of jiffies out of date. * This function must account for that. */unsigned longgettimeoffset(void){ unsigned long current_rtc_val, local_last_rtc_val; unsigned long usec; local_last_rtc_val = last_rtc_val; current_rtc_val = get_cycles(); usec = last_itc_lost_usec; /* If the RTC has wrapped around, compensate */ if (unlikely(current_rtc_val < local_last_rtc_val)) { printk(KERN_NOTICE "RTC wrapped cpu:%d current:0x%lx last:0x%lx\n", smp_processor_id(), current_rtc_val, local_last_rtc_val); current_rtc_val += RTC_MASK; } usec += ((current_rtc_val - local_last_rtc_val)*sn_rtc_usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT; /* * usec is the number of microseconds into the current clock interval. Every * clock tick, xtime is advanced by "tick" microseconds. If "usec" * is allowed to get larger than "tick", the time value returned by gettimeofday * will go backward. */ if (usec >= tick) usec = tick-1; return usec;}#ifdef II_PRTE_TLB_WARlong iiprt_lock[16*64] __cacheline_aligned; /* allow for NASIDs up to 64 */#endif#ifdef BUS_INT_WAR#include <asm/hw_irq.h>#include <asm/sn/pda.h>void ia64_handle_irq (ia64_vector vector, struct pt_regs *regs);static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;#define IRQCPU(irq) ((irq)>>8)voidsn_add_polled_interrupt(int irq, int interval){ unsigned long flags, irq_cnt; sn_poll_entry_t *irq_list; irq_list = pdacpu(IRQCPU(irq)).pda_poll_entries;; spin_lock_irqsave(&irq_lock, flags); irq_cnt = pdacpu(IRQCPU(irq)).pda_poll_entry_count; irq_list[irq_cnt].irq = irq; irq_list[irq_cnt].interval = interval; irq_list[irq_cnt].tick = interval; pdacpu(IRQCPU(irq)).pda_poll_entry_count++; spin_unlock_irqrestore(&irq_lock, flags);}voidsn_delete_polled_interrupt(int irq){ unsigned long flags, i, irq_cnt; sn_poll_entry_t *irq_list; irq_list = pdacpu(IRQCPU(irq)).pda_poll_entries; spin_lock_irqsave(&irq_lock, flags); irq_cnt = pdacpu(IRQCPU(irq)).pda_poll_entry_count; for (i=0; i<irq_cnt; i++) { if (irq_list[i].irq == irq) { irq_list[i] = irq_list[irq_cnt-1]; pdacpu(IRQCPU(irq)).pda_poll_entry_count--; break; } } spin_unlock_irqrestore(&irq_lock, flags);}long sn_int_poll_ticks=50;voidsn_irq_poll(int cpu, int reason) { unsigned long flags, i; sn_poll_entry_t *irq_list;#ifdef CONFIG_SHUB_1_0_SPECIFIC ia64_handle_irq(IA64_IPI_VECTOR, 0);#else if (sn_int_poll_ticks == 0) return;#endif irq_list = pda.pda_poll_entries; for (i=0; i<pda.pda_poll_entry_count; i++, irq_list++) { if (--irq_list->tick <= 0) {#ifdef CONFIG_SHUB_1_0_SPECIFIC irq_list->tick = irq_list->interval;#else irq_list->tick = sn_int_poll_ticks;#endif local_irq_save(flags); ia64_handle_irq(irq_to_vector(irq_list->irq), 0); local_irq_restore(flags); } }} #define PROCFILENAME "sn_int_poll_ticks"static struct proc_dir_entry *proc_op;static intread_proc(char *buffer, char **start, off_t off, int count, int *eof, void *data){ int len = 0; len += sprintf(buffer + len, "Poll hack: interval %ld ticks\n", sn_int_poll_ticks); if (len <= off+count) *eof = 1; *start = buffer + off; len -= off; if (len>count) len = count; if (len<0) len = 0; return len;}static intwrite_proc (struct file *file, const char *userbuf, unsigned long count, void *data){ extern long atoi(char *); char buf[80]; if (copy_from_user(buf, userbuf, count < sizeof(buf) ? count : sizeof(buf))) return -EFAULT; sn_int_poll_ticks = atoi(buf); return count;}int __initsn_poll_init(void){ if ((proc_op = create_proc_entry(PROCFILENAME, 0644, NULL)) == NULL) { printk("%s: unable to create proc entry", PROCFILENAME); return -1; } proc_op->read_proc = read_proc; proc_op->write_proc = write_proc; return 0;}module_init(sn_poll_init);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -