setup.c

来自「linux2.6.16版本」· C语言 代码 · 共 634 行 · 第 1/2 页

C
634
字号
	 * Setup interrupt mapping options that are needed for finish_device_tree	 * to properly parse the OF interrupt tree & do the virtual irq mapping	 */	__irq_offset_value = NUM_ISA_INTERRUPTS;	ppc64_interrupt_controller = IC_INVALID;	for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {		typep = (char *)get_property(np, "compatible", NULL);		if (strstr(typep, "open-pic")) {			ppc64_interrupt_controller = IC_OPEN_PIC;			break;		} else if (strstr(typep, "ppc-xicp")) {			ppc64_interrupt_controller = IC_PPC_XIC;			break;		}	}	if (ppc64_interrupt_controller == IC_INVALID)		printk("pSeries_discover_pic: failed to recognize"			" interrupt-controller\n");}static void pSeries_mach_cpu_die(void){	local_irq_disable();	idle_task_exit();	/* Some hardware requires clearing the CPPR, while other hardware does not	 * it is safe either way	 */	pSeriesLP_cppr_info(0, 0);	rtas_stop_self();	/* Should never get here... */	BUG();	for(;;);}static int pseries_set_dabr(unsigned long dabr){	return plpar_hcall_norets(H_SET_DABR, dabr);}static int pseries_set_xdabr(unsigned long dabr){	/* We want to catch accesses from kernel and userspace */	return plpar_hcall_norets(H_SET_XDABR, dabr,			H_DABRX_KERNEL | H_DABRX_USER);}/* * Early initialization.  Relocation is on but do not reference unbolted pages */static void __init pSeries_init_early(void){	int iommu_off = 0;	DBG(" -> pSeries_init_early()\n");	fw_feature_init();		if (platform_is_lpar())		hpte_init_lpar();	else {		hpte_init_native();		iommu_off = (of_chosen &&			     get_property(of_chosen, "linux,iommu-off", NULL));	}	if (platform_is_lpar())		find_udbg_vterm();	if (firmware_has_feature(FW_FEATURE_DABR))		ppc_md.set_dabr = pseries_set_dabr;	else if (firmware_has_feature(FW_FEATURE_XDABR))		ppc_md.set_dabr = pseries_set_xdabr;	iommu_init_early_pSeries();	pSeries_discover_pic();	DBG(" <- pSeries_init_early()\n");}static int pSeries_check_legacy_ioport(unsigned int baseport){	struct device_node *np;#define I8042_DATA_REG	0x60#define FDC_BASE	0x3f0	switch(baseport) {	case I8042_DATA_REG:		np = of_find_node_by_type(NULL, "8042");		if (np == NULL)			return -ENODEV;		of_node_put(np);		break;	case FDC_BASE:		np = of_find_node_by_type(NULL, "fdc");		if (np == NULL)			return -ENODEV;		of_node_put(np);		break;	}	return 0;}/* * Called very early, MMU is off, device-tree isn't unflattened */extern struct machdep_calls pSeries_md;static int __init pSeries_probe(int platform){	if (platform != PLATFORM_PSERIES &&	    platform != PLATFORM_PSERIES_LPAR)		return 0;	/* if we have some ppc_md fixups for LPAR to do, do	 * it here ...	 */	return 1;}DECLARE_PER_CPU(unsigned long, smt_snooze_delay);static inline void dedicated_idle_sleep(unsigned int cpu){	struct lppaca *plppaca = &lppaca[cpu ^ 1];	/* Only sleep if the other thread is not idle */	if (!(plppaca->idle)) {		local_irq_disable();		/*		 * We are about to sleep the thread and so wont be polling any		 * more.		 */		clear_thread_flag(TIF_POLLING_NRFLAG);		smp_mb__after_clear_bit();		/*		 * SMT dynamic mode. Cede will result in this thread going		 * dormant, if the partner thread is still doing work.  Thread		 * wakes up if partner goes idle, an interrupt is presented, or		 * a prod occurs.  Returning from the cede enables external		 * interrupts.		 */		if (!need_resched())			cede_processor();		else			local_irq_enable();		set_thread_flag(TIF_POLLING_NRFLAG);	} else {		/*		 * Give the HV an opportunity at the processor, since we are		 * not doing any work.		 */		poll_pending();	}}static void pseries_dedicated_idle(void){ 	unsigned int cpu = smp_processor_id();	unsigned long start_snooze;	unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);	set_thread_flag(TIF_POLLING_NRFLAG);	while (1) {		/*		 * Indicate to the HV that we are idle. Now would be		 * a good time to find other work to dispatch.		 */		get_lppaca()->idle = 1;		if (!need_resched()) {			start_snooze = get_tb() +				*smt_snooze_delay * tb_ticks_per_usec;			while (!need_resched() && !cpu_is_offline(cpu)) {				ppc64_runlatch_off();				/*				 * Go into low thread priority and possibly				 * low power mode.				 */				HMT_low();				HMT_very_low();				if (*smt_snooze_delay != 0 &&				    get_tb() > start_snooze) {					HMT_medium();					dedicated_idle_sleep(cpu);				}			}			HMT_medium();		}		get_lppaca()->idle = 0;		ppc64_runlatch_on();		preempt_enable_no_resched();		schedule();		preempt_disable();		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)			cpu_die();	}}static void pseries_shared_idle(void){	unsigned int cpu = smp_processor_id();	while (1) {		/*		 * Indicate to the HV that we are idle. Now would be		 * a good time to find other work to dispatch.		 */		get_lppaca()->idle = 1;		while (!need_resched() && !cpu_is_offline(cpu)) {			local_irq_disable();			ppc64_runlatch_off();			/*			 * Yield the processor to the hypervisor.  We return if			 * an external interrupt occurs (which are driven prior			 * to returning here) or if a prod occurs from another			 * processor. When returning here, external interrupts			 * are enabled.			 *			 * Check need_resched() again with interrupts disabled			 * to avoid a race.			 */			if (!need_resched())				cede_processor();			else				local_irq_enable();			HMT_medium();		}		get_lppaca()->idle = 0;		ppc64_runlatch_on();		preempt_enable_no_resched();		schedule();		preempt_disable();		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)			cpu_die();	}}static int pSeries_pci_probe_mode(struct pci_bus *bus){	if (platform_is_lpar())		return PCI_PROBE_DEVTREE;	return PCI_PROBE_NORMAL;}#ifdef CONFIG_KEXECstatic void pseries_kexec_cpu_down(int crash_shutdown, int secondary){	/* Don't risk a hypervisor call if we're crashing */	if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {		unsigned long vpa = __pa(get_lppaca());		if (unregister_vpa(hard_smp_processor_id(), vpa)) {			printk("VPA deregistration of cpu %u (hw_cpu_id %d) "					"failed\n", smp_processor_id(),					hard_smp_processor_id());		}	}	if (ppc64_interrupt_controller == IC_OPEN_PIC)		mpic_teardown_this_cpu(secondary);	else		xics_teardown_cpu(secondary);}#endifstruct machdep_calls __initdata pSeries_md = {	.probe			= pSeries_probe,	.setup_arch		= pSeries_setup_arch,	.init_early		= pSeries_init_early,	.show_cpuinfo		= pSeries_show_cpuinfo,	.log_error		= pSeries_log_error,	.pcibios_fixup		= pSeries_final_fixup,	.pci_probe_mode		= pSeries_pci_probe_mode,	.irq_bus_setup		= pSeries_irq_bus_setup,	.restart		= rtas_restart,	.power_off		= rtas_power_off,	.halt			= rtas_halt,	.panic			= rtas_os_term,	.cpu_die		= pSeries_mach_cpu_die,	.get_boot_time		= rtas_get_boot_time,	.get_rtc_time		= rtas_get_rtc_time,	.set_rtc_time		= rtas_set_rtc_time,	.calibrate_decr		= generic_calibrate_decr,	.progress		= rtas_progress,	.check_legacy_ioport	= pSeries_check_legacy_ioport,	.system_reset_exception = pSeries_system_reset_exception,	.machine_check_exception = pSeries_machine_check_exception,#ifdef CONFIG_KEXEC	.kexec_cpu_down		= pseries_kexec_cpu_down,	.machine_kexec		= default_machine_kexec,	.machine_kexec_prepare	= default_machine_kexec_prepare,	.machine_crash_shutdown	= default_machine_crash_shutdown,#endif};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?