⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io_apic.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Try to find the IRQ that is closest to the imbalance		 * without going over.		 */		if (move_this_load < IRQ_DELTA(max_loaded,j)) {			move_this_load = IRQ_DELTA(max_loaded,j);			selected_irq = j;		}	}	if (selected_irq == -1) {		goto tryanothercpu;	}	imbalance = move_this_load;		/* For physical_balance case, we accumlated both load	 * values in the one of the siblings cpu_irq[],	 * to use the same code for physical and logical processors	 * as much as possible. 	 *	 * NOTE: the cpu_irq[] array holds the sum of the load for	 * sibling A and sibling B in the slot for the lowest numbered	 * sibling (A), _AND_ the load for sibling B in the slot for	 * the higher numbered sibling.	 *	 * We seek the least loaded sibling by making the comparison	 * (A+B)/2 vs B	 */	load = CPU_IRQ(min_loaded) >> 1;	for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) {		if (load > CPU_IRQ(j)) {			/* This won't change cpu_sibling_map[min_loaded] */			load = CPU_IRQ(j);			min_loaded = j;		}	}	cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]);	target_cpu_mask = cpumask_of_cpu(min_loaded);	cpus_and(tmp, target_cpu_mask, allowed_mask);	if (!cpus_empty(tmp)) {		irq_desc_t *desc = irq_desc + selected_irq;		unsigned long flags;		Dprintk("irq = %d moved to cpu = %d\n",				selected_irq, min_loaded);		/* mark for change destination */		spin_lock_irqsave(&desc->lock, flags);		pending_irq_balance_cpumask[selected_irq] =					cpumask_of_cpu(min_loaded);		spin_unlock_irqrestore(&desc->lock, flags);		/* Since we made a change, come back sooner to 		 * check for more variation.		 */		balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,			balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);			return;	}	goto tryanotherirq;not_worth_the_effort:	/*	 * if we did not find an IRQ to move, then adjust the time interval	 * upward	 */	balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);		Dprintk("IRQ worth rotating not found\n");	return;}static int balanced_irq(void *unused){	int i;	unsigned long prev_balance_time = jiffies;	long time_remaining = balanced_irq_interval;	daemonize("kirqd");		/* push everything to CPU 0 to give us a starting point.  */	for (i = 0 ; i < NR_IRQS ; i++) {		pending_irq_balance_cpumask[i] = cpumask_of_cpu(0);	}	for ( ; ; ) {		set_current_state(TASK_INTERRUPTIBLE);		time_remaining = schedule_timeout(time_remaining);		if (time_after(jiffies,				prev_balance_time+balanced_irq_interval)) {			do_irq_balance();			prev_balance_time = jiffies;			time_remaining = balanced_irq_interval;		}	}	return 0;}static int __init balanced_irq_init(void){	int i;	struct cpuinfo_x86 *c;	cpumask_t tmp;	cpus_shift_right(tmp, cpu_online_map, 2);        c = &boot_cpu_data;	/* When not overwritten by the command line ask subarchitecture. */	if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH)		irqbalance_disabled = NO_BALANCE_IRQ;	if (irqbalance_disabled)		return 0;		 /* disable irqbalance completely if there is only one processor online */	if (num_online_cpus() < 2) {		irqbalance_disabled = 1;		return 0;	}	/*	 * Enable physical balance only if more than 1 physical processor	 * is present	 */	if (smp_num_siblings > 1 && !cpus_empty(tmp))		physical_balance = 1;	for (i = 0; i < NR_CPUS; i++) {		if (!cpu_online(i))			continue;		irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);		irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);		if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {			printk(KERN_ERR "balanced_irq_init: out of memory");			goto failed;		}		memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS);		memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS);	}		printk(KERN_INFO "Starting balanced_irq\n");	if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0) 		return 0;	else 		printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");failed:	for (i = 0; i < NR_CPUS; i++) {		if(irq_cpu_data[i].irq_delta)			kfree(irq_cpu_data[i].irq_delta);		if(irq_cpu_data[i].last_irq)			kfree(irq_cpu_data[i].last_irq);	}	return 0;}static int __init irqbalance_disable(char *str){	irqbalance_disabled = 1;	return 0;}__setup("noirqbalance", irqbalance_disable);static inline void move_irq(int irq){	/* note - we hold the desc->lock */	if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) {		set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]);		cpus_clear(pending_irq_balance_cpumask[irq]);	}}__initcall(balanced_irq_init);#else /* !CONFIG_IRQBALANCE */static inline void move_irq(int irq) { }#endif /* CONFIG_IRQBALANCE */#ifndef CONFIG_SMPvoid fastcall send_IPI_self(int vector){	unsigned int cfg;	/*	 * Wait for idle.	 */	apic_wait_icr_idle();	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;	/*	 * Send the IPI. The write to APIC_ICR fires this off.	 */	apic_write_around(APIC_ICR, cfg);}#endif /* !CONFIG_SMP *//* * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to * specific CPU-side IRQs. */#define MAX_PIRQS 8int pirq_entries [MAX_PIRQS];int pirqs_enabled;int skip_ioapic_setup;static int __init ioapic_setup(char *str){	skip_ioapic_setup = 1;	return 1;}__setup("noapic", ioapic_setup);static int __init ioapic_pirq_setup(char *str){	int i, max;	int ints[MAX_PIRQS+1];	get_options(str, ARRAY_SIZE(ints), ints);	for (i = 0; i < MAX_PIRQS; i++)		pirq_entries[i] = -1;	pirqs_enabled = 1;	printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");	max = MAX_PIRQS;	if (ints[0] < MAX_PIRQS)		max = ints[0];	for (i = 0; i < max; i++) {		printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);		/*		 * PIRQs are mapped upside down, usually.		 */		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];	}	return 1;}__setup("pirq=", ioapic_pirq_setup);/* * Find the IRQ entry number of a certain pin. */static int __init find_irq_entry(int apic, int pin, int type){	int i;	for (i = 0; i < mp_irq_entries; i++)		if (mp_irqs[i].mpc_irqtype == type &&		    (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||		     mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&		    mp_irqs[i].mpc_dstirq == pin)			return i;	return -1;}/* * Find the pin to which IRQ[irq] (ISA) is connected */static int __init find_isa_irq_pin(int irq, int type){	int i;	for (i = 0; i < mp_irq_entries; i++) {		int lbus = mp_irqs[i].mpc_srcbus;		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||		     mp_bus_id_to_type[lbus] == MP_BUS_MCA ||		     mp_bus_id_to_type[lbus] == MP_BUS_NEC98		    ) &&		    (mp_irqs[i].mpc_irqtype == type) &&		    (mp_irqs[i].mpc_srcbusirq == irq))			return mp_irqs[i].mpc_dstirq;	}	return -1;}/* * Find a specific PCI IRQ entry. * Not an __init, possibly needed by modules */static int pin_2_irq(int idx, int apic, int pin);int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin){	int apic, i, best_guess = -1;	Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",		bus, slot, pin);	if (mp_bus_id_to_pci_bus[bus] == -1) {		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);		return -1;	}	for (i = 0; i < mp_irq_entries; i++) {		int lbus = mp_irqs[i].mpc_srcbus;		for (apic = 0; apic < nr_ioapics; apic++)			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)				break;		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&		    !mp_irqs[i].mpc_irqtype &&		    (bus == lbus) &&		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);			if (!(apic || IO_APIC_IRQ(irq)))				continue;			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))				return irq;			/*			 * Use the first all-but-pin matching entry as a			 * best-guess fuzzy result for broken mptables.			 */			if (best_guess < 0)				best_guess = irq;		}	}	return best_guess;}/* * This function currently is only a helper for the i386 smp boot process where  * we need to reprogram the ioredtbls to cater for the cpus which have come online * so mask in all cases should simply be TARGET_CPUS */void __init setup_ioapic_dest(void){	int pin, ioapic, irq, irq_entry;	if (skip_ioapic_setup == 1)		return;	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {			irq_entry = find_irq_entry(ioapic, pin, mp_INT);			if (irq_entry == -1)				continue;			irq = pin_2_irq(irq_entry, ioapic, pin);			set_ioapic_affinity_irq(irq, TARGET_CPUS);		}	}}/* * EISA Edge/Level control register, ELCR */static int __init EISA_ELCR(unsigned int irq){	if (irq < 16) {		unsigned int port = 0x4d0 + (irq >> 3);		return (inb(port) >> (irq & 7)) & 1;	}	printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq);	return 0;}/* EISA interrupts are always polarity zero and can be edge or level * trigger depending on the ELCR value.  If an interrupt is listed as * EISA conforming in the MP table, that means its trigger type must * be read in from the ELCR */#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))#define default_EISA_polarity(idx)	(0)/* ISA interrupts are always polarity zero edge triggered, * when listed as conforming in the MP table. */#define default_ISA_trigger(idx)	(0)#define default_ISA_polarity(idx)	(0)/* PCI interrupts are always polarity one level triggered, * when listed as conforming in the MP table. */#define default_PCI_trigger(idx)	(1)#define default_PCI_polarity(idx)	(1)/* MCA interrupts are always polarity zero level triggered, * when listed as conforming in the MP table. */#define default_MCA_trigger(idx)	(1)#define default_MCA_polarity(idx)	(0)/* NEC98 interrupts are always polarity zero edge triggered, * when listed as conforming in the MP table. */#define default_NEC98_trigger(idx)     (0)#define default_NEC98_polarity(idx)    (0)static int __init MPBIOS_polarity(int idx){	int bus = mp_irqs[idx].mpc_srcbus;	int polarity;	/*	 * Determine IRQ line polarity (high active or low active):	 */	switch (mp_irqs[idx].mpc_irqflag & 3)	{		case 0: /* conforms, ie. bus-type dependent polarity */		{			switch (mp_bus_id_to_type[bus])			{				case MP_BUS_ISA: /* ISA pin */				{					polarity = default_ISA_polarity(idx);					break;				}				case MP_BUS_EISA: /* EISA pin */				{					polarity = default_EISA_polarity(idx);					break;				}				case MP_BUS_PCI: /* PCI pin */				{					polarity = default_PCI_polarity(idx);					break;				}				case MP_BUS_MCA: /* MCA pin */				{					polarity = default_MCA_polarity(idx);					break;				}				case MP_BUS_NEC98: /* NEC 98 pin */				{					polarity = default_NEC98_polarity(idx);					break;				}				default:				{					printk(KERN_WARNING "broken BIOS!!\n");					polarity = 1;					break;				}			}			break;		}		case 1: /* high active */		{			polarity = 0;			break;		}		case 2: /* reserved */		{			printk(KERN_WARNING "broken BIOS!!\n");			polarity = 1;			break;		}		case 3: /* low active */		{			polarity = 1;			break;		}		default: /* invalid */		{			printk(KERN_WARNING "broken BIOS!!\n");			polarity = 1;			break;		}	}	return polarity;}static int __init MPBIOS_trigger(int idx){	int bus = mp_irqs[idx].mpc_srcbus;	int trigger;	/*	 * Determine IRQ trigger mode (edge or level sensitive):	 */	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)	{		case 0: /* conforms, ie. bus-type dependent */		{			switch (mp_bus_id_to_type[bus])			{				case MP_BUS_ISA: /* ISA pin */				{					trigger = default_ISA_trigger(idx);					break;				}

⌨️ 快捷键说明

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