|  |  |  | @ -92,21 +92,21 @@ static struct ioapic { | 
		
	
		
			
				|  |  |  |  | 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); | 
		
	
		
			
				|  |  |  |  | } ioapics[MAX_IO_APICS]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #define mpc_ioapic_ver(id)		ioapics[id].mp_config.apicver | 
		
	
		
			
				|  |  |  |  | #define mpc_ioapic_ver(ioapic_idx)	ioapics[ioapic_idx].mp_config.apicver | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int mpc_ioapic_id(int id) | 
		
	
		
			
				|  |  |  |  | int mpc_ioapic_id(int ioapic_idx) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	return ioapics[id].mp_config.apicid; | 
		
	
		
			
				|  |  |  |  | 	return ioapics[ioapic_idx].mp_config.apicid; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | unsigned int mpc_ioapic_addr(int id) | 
		
	
		
			
				|  |  |  |  | unsigned int mpc_ioapic_addr(int ioapic_idx) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	return ioapics[id].mp_config.apicaddr; | 
		
	
		
			
				|  |  |  |  | 	return ioapics[ioapic_idx].mp_config.apicaddr; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int id) | 
		
	
		
			
				|  |  |  |  | struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	return &ioapics[id].gsi_config; | 
		
	
		
			
				|  |  |  |  | 	return &ioapics[ioapic_idx].gsi_config; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int nr_ioapics; | 
		
	
	
		
			
				
					
					|  |  |  | @ -186,11 +186,7 @@ static struct irq_pin_list *alloc_irq_pin_list(int node) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ | 
		
	
		
			
				|  |  |  |  | #ifdef CONFIG_SPARSE_IRQ | 
		
	
		
			
				|  |  |  |  | static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY]; | 
		
	
		
			
				|  |  |  |  | #else | 
		
	
		
			
				|  |  |  |  | static struct irq_cfg irq_cfgx[NR_IRQS]; | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int __init arch_early_irq_init(void) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @ -234,7 +230,6 @@ int __init arch_early_irq_init(void) | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #ifdef CONFIG_SPARSE_IRQ | 
		
	
		
			
				|  |  |  |  | static struct irq_cfg *irq_cfg(unsigned int irq) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	return irq_get_chip_data(irq); | 
		
	
	
		
			
				
					
					|  |  |  | @ -269,22 +264,6 @@ static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) | 
		
	
		
			
				|  |  |  |  | 	kfree(cfg); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #else | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct irq_cfg *irq_cfg(unsigned int irq) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	return irq < nr_irqs ? irq_cfgx + irq : NULL; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	return irq_cfgx + irq; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int res = irq_alloc_desc_at(at, node); | 
		
	
	
		
			
				
					
					|  |  |  | @ -802,13 +781,13 @@ int restore_ioapic_entries(void) | 
		
	
		
			
				|  |  |  |  | /*
 | 
		
	
		
			
				|  |  |  |  |  * Find the IRQ entry number of a certain pin. | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | static int find_irq_entry(int apic, int pin, int type) | 
		
	
		
			
				|  |  |  |  | static int find_irq_entry(int ioapic_idx, int pin, int type) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int i; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (i = 0; i < mp_irq_entries; i++) | 
		
	
		
			
				|  |  |  |  | 		if (mp_irqs[i].irqtype == type && | 
		
	
		
			
				|  |  |  |  | 		    (mp_irqs[i].dstapic == mpc_ioapic_id(apic) || | 
		
	
		
			
				|  |  |  |  | 		    (mp_irqs[i].dstapic == mpc_ioapic_id(ioapic_idx) || | 
		
	
		
			
				|  |  |  |  | 		     mp_irqs[i].dstapic == MP_APIC_ALL) && | 
		
	
		
			
				|  |  |  |  | 		    mp_irqs[i].dstirq == pin) | 
		
	
		
			
				|  |  |  |  | 			return i; | 
		
	
	
		
			
				
					
					|  |  |  | @ -847,12 +826,13 @@ static int __init find_isa_irq_apic(int irq, int type) | 
		
	
		
			
				|  |  |  |  | 		    (mp_irqs[i].srcbusirq == irq)) | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (i < mp_irq_entries) { | 
		
	
		
			
				|  |  |  |  | 		int apic; | 
		
	
		
			
				|  |  |  |  | 		for(apic = 0; apic < nr_ioapics; apic++) { | 
		
	
		
			
				|  |  |  |  | 			if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic) | 
		
	
		
			
				|  |  |  |  | 				return apic; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		int ioapic_idx; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) | 
		
	
		
			
				|  |  |  |  | 			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic) | 
		
	
		
			
				|  |  |  |  | 				return ioapic_idx; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	return -1; | 
		
	
	
		
			
				
					
					|  |  |  | @ -1067,7 +1047,7 @@ static int pin_2_irq(int idx, int apic, int pin) | 
		
	
		
			
				|  |  |  |  | int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, | 
		
	
		
			
				|  |  |  |  | 				struct io_apic_irq_attr *irq_attr) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int apic, i, best_guess = -1; | 
		
	
		
			
				|  |  |  |  | 	int ioapic_idx, i, best_guess = -1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	apic_printk(APIC_DEBUG, | 
		
	
		
			
				|  |  |  |  | 		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", | 
		
	
	
		
			
				
					
					|  |  |  | @ -1080,8 +1060,8 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, | 
		
	
		
			
				|  |  |  |  | 	for (i = 0; i < mp_irq_entries; i++) { | 
		
	
		
			
				|  |  |  |  | 		int lbus = mp_irqs[i].srcbus; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		for (apic = 0; apic < nr_ioapics; apic++) | 
		
	
		
			
				|  |  |  |  | 			if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic || | 
		
	
		
			
				|  |  |  |  | 		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) | 
		
	
		
			
				|  |  |  |  | 			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic || | 
		
	
		
			
				|  |  |  |  | 			    mp_irqs[i].dstapic == MP_APIC_ALL) | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					
					|  |  |  | @ -1089,13 +1069,13 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, | 
		
	
		
			
				|  |  |  |  | 		    !mp_irqs[i].irqtype && | 
		
	
		
			
				|  |  |  |  | 		    (bus == lbus) && | 
		
	
		
			
				|  |  |  |  | 		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) { | 
		
	
		
			
				|  |  |  |  | 			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq); | 
		
	
		
			
				|  |  |  |  | 			int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			if (!(apic || IO_APIC_IRQ(irq))) | 
		
	
		
			
				|  |  |  |  | 			if (!(ioapic_idx || IO_APIC_IRQ(irq))) | 
		
	
		
			
				|  |  |  |  | 				continue; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			if (pin == (mp_irqs[i].srcbusirq & 3)) { | 
		
	
		
			
				|  |  |  |  | 				set_io_apic_irq_attr(irq_attr, apic, | 
		
	
		
			
				|  |  |  |  | 				set_io_apic_irq_attr(irq_attr, ioapic_idx, | 
		
	
		
			
				|  |  |  |  | 						     mp_irqs[i].dstirq, | 
		
	
		
			
				|  |  |  |  | 						     irq_trigger(i), | 
		
	
		
			
				|  |  |  |  | 						     irq_polarity(i)); | 
		
	
	
		
			
				
					
					|  |  |  | @ -1106,7 +1086,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, | 
		
	
		
			
				|  |  |  |  | 			 * best-guess fuzzy result for broken mptables. | 
		
	
		
			
				|  |  |  |  | 			 */ | 
		
	
		
			
				|  |  |  |  | 			if (best_guess < 0) { | 
		
	
		
			
				|  |  |  |  | 				set_io_apic_irq_attr(irq_attr, apic, | 
		
	
		
			
				|  |  |  |  | 				set_io_apic_irq_attr(irq_attr, ioapic_idx, | 
		
	
		
			
				|  |  |  |  | 						     mp_irqs[i].dstirq, | 
		
	
		
			
				|  |  |  |  | 						     irq_trigger(i), | 
		
	
		
			
				|  |  |  |  | 						     irq_polarity(i)); | 
		
	
	
		
			
				
					
					|  |  |  | @ -1344,77 +1324,100 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg, | 
		
	
		
			
				|  |  |  |  | 				      fasteoi ? "fasteoi" : "edge"); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static int setup_ioapic_entry(int apic_id, int irq, | 
		
	
		
			
				|  |  |  |  | 			      struct IO_APIC_route_entry *entry, | 
		
	
		
			
				|  |  |  |  | 			      unsigned int destination, int trigger, | 
		
	
		
			
				|  |  |  |  | 			      int polarity, int vector, int pin) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static int setup_ir_ioapic_entry(int irq, | 
		
	
		
			
				|  |  |  |  | 			      struct IR_IO_APIC_route_entry *entry, | 
		
	
		
			
				|  |  |  |  | 			      unsigned int destination, int vector, | 
		
	
		
			
				|  |  |  |  | 			      struct io_apic_irq_attr *attr) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * add it to the IO-APIC irq-routing table: | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	memset(entry,0,sizeof(*entry)); | 
		
	
		
			
				|  |  |  |  | 	int index; | 
		
	
		
			
				|  |  |  |  | 	struct irte irte; | 
		
	
		
			
				|  |  |  |  | 	int ioapic_id = mpc_ioapic_id(attr->ioapic); | 
		
	
		
			
				|  |  |  |  | 	struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (intr_remapping_enabled) { | 
		
	
		
			
				|  |  |  |  | 		struct intel_iommu *iommu = map_ioapic_to_ir(apic_id); | 
		
	
		
			
				|  |  |  |  | 		struct irte irte; | 
		
	
		
			
				|  |  |  |  | 		struct IR_IO_APIC_route_entry *ir_entry = | 
		
	
		
			
				|  |  |  |  | 			(struct IR_IO_APIC_route_entry *) entry; | 
		
	
		
			
				|  |  |  |  | 		int index; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		if (!iommu) | 
		
	
		
			
				|  |  |  |  | 			panic("No mapping iommu for ioapic %d\n", apic_id); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		index = alloc_irte(iommu, irq, 1); | 
		
	
		
			
				|  |  |  |  | 		if (index < 0) | 
		
	
		
			
				|  |  |  |  | 			panic("Failed to allocate IRTE for ioapic %d\n", apic_id); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		prepare_irte(&irte, vector, destination); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		/* Set source-id of interrupt request */ | 
		
	
		
			
				|  |  |  |  | 		set_ioapic_sid(&irte, apic_id); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		modify_irte(irq, &irte); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		ir_entry->index2 = (index >> 15) & 0x1; | 
		
	
		
			
				|  |  |  |  | 		ir_entry->zero = 0; | 
		
	
		
			
				|  |  |  |  | 		ir_entry->format = 1; | 
		
	
		
			
				|  |  |  |  | 		ir_entry->index = (index & 0x7fff); | 
		
	
		
			
				|  |  |  |  | 		/*
 | 
		
	
		
			
				|  |  |  |  | 		 * IO-APIC RTE will be configured with virtual vector. | 
		
	
		
			
				|  |  |  |  | 		 * irq handler will do the explicit EOI to the io-apic. | 
		
	
		
			
				|  |  |  |  | 		 */ | 
		
	
		
			
				|  |  |  |  | 		ir_entry->vector = pin; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " | 
		
	
		
			
				|  |  |  |  | 			"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " | 
		
	
		
			
				|  |  |  |  | 			"Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " | 
		
	
		
			
				|  |  |  |  | 			"Avail:%X Vector:%02X Dest:%08X " | 
		
	
		
			
				|  |  |  |  | 			"SID:%04X SQ:%X SVT:%X)\n", | 
		
	
		
			
				|  |  |  |  | 			apic_id, irte.present, irte.fpd, irte.dst_mode, | 
		
	
		
			
				|  |  |  |  | 			irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, | 
		
	
		
			
				|  |  |  |  | 			irte.avail, irte.vector, irte.dest_id, | 
		
	
		
			
				|  |  |  |  | 			irte.sid, irte.sq, irte.svt); | 
		
	
		
			
				|  |  |  |  | 	} else { | 
		
	
		
			
				|  |  |  |  | 		entry->delivery_mode = apic->irq_delivery_mode; | 
		
	
		
			
				|  |  |  |  | 		entry->dest_mode = apic->irq_dest_mode; | 
		
	
		
			
				|  |  |  |  | 		entry->dest = destination; | 
		
	
		
			
				|  |  |  |  | 		entry->vector = vector; | 
		
	
		
			
				|  |  |  |  | 	if (!iommu) { | 
		
	
		
			
				|  |  |  |  | 		pr_warn("No mapping iommu for ioapic %d\n", ioapic_id); | 
		
	
		
			
				|  |  |  |  | 		return -ENODEV; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	entry->mask = 0;				/* enable IRQ */ | 
		
	
		
			
				|  |  |  |  | 	entry->trigger = trigger; | 
		
	
		
			
				|  |  |  |  | 	entry->polarity = polarity; | 
		
	
		
			
				|  |  |  |  | 	index = alloc_irte(iommu, irq, 1); | 
		
	
		
			
				|  |  |  |  | 	if (index < 0) { | 
		
	
		
			
				|  |  |  |  | 		pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id); | 
		
	
		
			
				|  |  |  |  | 		return -ENOMEM; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	prepare_irte(&irte, vector, destination); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Set source-id of interrupt request */ | 
		
	
		
			
				|  |  |  |  | 	set_ioapic_sid(&irte, ioapic_id); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	modify_irte(irq, &irte); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " | 
		
	
		
			
				|  |  |  |  | 		"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " | 
		
	
		
			
				|  |  |  |  | 		"Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " | 
		
	
		
			
				|  |  |  |  | 		"Avail:%X Vector:%02X Dest:%08X " | 
		
	
		
			
				|  |  |  |  | 		"SID:%04X SQ:%X SVT:%X)\n", | 
		
	
		
			
				|  |  |  |  | 		attr->ioapic, irte.present, irte.fpd, irte.dst_mode, | 
		
	
		
			
				|  |  |  |  | 		irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, | 
		
	
		
			
				|  |  |  |  | 		irte.avail, irte.vector, irte.dest_id, | 
		
	
		
			
				|  |  |  |  | 		irte.sid, irte.sq, irte.svt); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	memset(entry, 0, sizeof(*entry)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	entry->index2	= (index >> 15) & 0x1; | 
		
	
		
			
				|  |  |  |  | 	entry->zero	= 0; | 
		
	
		
			
				|  |  |  |  | 	entry->format	= 1; | 
		
	
		
			
				|  |  |  |  | 	entry->index	= (index & 0x7fff); | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * IO-APIC RTE will be configured with virtual vector. | 
		
	
		
			
				|  |  |  |  | 	 * irq handler will do the explicit EOI to the io-apic. | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	entry->vector	= attr->ioapic_pin; | 
		
	
		
			
				|  |  |  |  | 	entry->mask	= 0;			/* enable IRQ */ | 
		
	
		
			
				|  |  |  |  | 	entry->trigger	= attr->trigger; | 
		
	
		
			
				|  |  |  |  | 	entry->polarity	= attr->polarity; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Mask level triggered irqs.
 | 
		
	
		
			
				|  |  |  |  | 	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs. | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	if (trigger) | 
		
	
		
			
				|  |  |  |  | 	if (attr->trigger) | 
		
	
		
			
				|  |  |  |  | 		entry->mask = 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq, | 
		
	
		
			
				|  |  |  |  | 			     struct irq_cfg *cfg, int trigger, int polarity) | 
		
	
		
			
				|  |  |  |  | static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry, | 
		
	
		
			
				|  |  |  |  | 			       unsigned int destination, int vector, | 
		
	
		
			
				|  |  |  |  | 			       struct io_apic_irq_attr *attr) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (intr_remapping_enabled) | 
		
	
		
			
				|  |  |  |  | 		return setup_ir_ioapic_entry(irq, | 
		
	
		
			
				|  |  |  |  | 			 (struct IR_IO_APIC_route_entry *)entry, | 
		
	
		
			
				|  |  |  |  | 			 destination, vector, attr); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	memset(entry, 0, sizeof(*entry)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	entry->delivery_mode = apic->irq_delivery_mode; | 
		
	
		
			
				|  |  |  |  | 	entry->dest_mode     = apic->irq_dest_mode; | 
		
	
		
			
				|  |  |  |  | 	entry->dest	     = destination; | 
		
	
		
			
				|  |  |  |  | 	entry->vector	     = vector; | 
		
	
		
			
				|  |  |  |  | 	entry->mask	     = 0;			/* enable IRQ */ | 
		
	
		
			
				|  |  |  |  | 	entry->trigger	     = attr->trigger; | 
		
	
		
			
				|  |  |  |  | 	entry->polarity	     = attr->polarity; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * Mask level triggered irqs. | 
		
	
		
			
				|  |  |  |  | 	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs. | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	if (attr->trigger) | 
		
	
		
			
				|  |  |  |  | 		entry->mask = 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, | 
		
	
		
			
				|  |  |  |  | 				struct io_apic_irq_attr *attr) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	struct IO_APIC_route_entry entry; | 
		
	
		
			
				|  |  |  |  | 	unsigned int dest; | 
		
	
	
		
			
				
					
					|  |  |  | @ -1437,49 +1440,48 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq, | 
		
	
		
			
				|  |  |  |  | 	apic_printk(APIC_VERBOSE,KERN_DEBUG | 
		
	
		
			
				|  |  |  |  | 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " | 
		
	
		
			
				|  |  |  |  | 		    "IRQ %d Mode:%i Active:%i Dest:%d)\n", | 
		
	
		
			
				|  |  |  |  | 		    apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector, | 
		
	
		
			
				|  |  |  |  | 		    irq, trigger, polarity, dest); | 
		
	
		
			
				|  |  |  |  | 		    attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin, | 
		
	
		
			
				|  |  |  |  | 		    cfg->vector, irq, attr->trigger, attr->polarity, dest); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry, | 
		
	
		
			
				|  |  |  |  | 			       dest, trigger, polarity, cfg->vector, pin)) { | 
		
	
		
			
				|  |  |  |  | 		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n", | 
		
	
		
			
				|  |  |  |  | 		       mpc_ioapic_id(apic_id), pin); | 
		
	
		
			
				|  |  |  |  | 	if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) { | 
		
	
		
			
				|  |  |  |  | 		pr_warn("Failed to setup ioapic entry for ioapic  %d, pin %d\n", | 
		
	
		
			
				|  |  |  |  | 			mpc_ioapic_id(attr->ioapic), attr->ioapic_pin); | 
		
	
		
			
				|  |  |  |  | 		__clear_irq_vector(irq, cfg); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	ioapic_register_intr(irq, cfg, trigger); | 
		
	
		
			
				|  |  |  |  | 	ioapic_register_intr(irq, cfg, attr->trigger); | 
		
	
		
			
				|  |  |  |  | 	if (irq < legacy_pic->nr_legacy_irqs) | 
		
	
		
			
				|  |  |  |  | 		legacy_pic->mask(irq); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	ioapic_write_entry(apic_id, pin, entry); | 
		
	
		
			
				|  |  |  |  | 	ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin) | 
		
	
		
			
				|  |  |  |  | static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (idx != -1) | 
		
	
		
			
				|  |  |  |  | 		return false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n", | 
		
	
		
			
				|  |  |  |  | 		    mpc_ioapic_id(apic_id), pin); | 
		
	
		
			
				|  |  |  |  | 		    mpc_ioapic_id(ioapic_idx), pin); | 
		
	
		
			
				|  |  |  |  | 	return true; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void __init __io_apic_setup_irqs(unsigned int apic_id) | 
		
	
		
			
				|  |  |  |  | static void __init __io_apic_setup_irqs(unsigned int ioapic_idx) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int idx, node = cpu_to_node(0); | 
		
	
		
			
				|  |  |  |  | 	struct io_apic_irq_attr attr; | 
		
	
		
			
				|  |  |  |  | 	unsigned int pin, irq; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (pin = 0; pin < ioapics[apic_id].nr_registers; pin++) { | 
		
	
		
			
				|  |  |  |  | 		idx = find_irq_entry(apic_id, pin, mp_INT); | 
		
	
		
			
				|  |  |  |  | 		if (io_apic_pin_not_connected(idx, apic_id, pin)) | 
		
	
		
			
				|  |  |  |  | 	for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) { | 
		
	
		
			
				|  |  |  |  | 		idx = find_irq_entry(ioapic_idx, pin, mp_INT); | 
		
	
		
			
				|  |  |  |  | 		if (io_apic_pin_not_connected(idx, ioapic_idx, pin)) | 
		
	
		
			
				|  |  |  |  | 			continue; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		irq = pin_2_irq(idx, apic_id, pin); | 
		
	
		
			
				|  |  |  |  | 		irq = pin_2_irq(idx, ioapic_idx, pin); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		if ((apic_id > 0) && (irq > 16)) | 
		
	
		
			
				|  |  |  |  | 		if ((ioapic_idx > 0) && (irq > 16)) | 
		
	
		
			
				|  |  |  |  | 			continue; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		/*
 | 
		
	
	
		
			
				
					
					|  |  |  | @ -1487,10 +1489,10 @@ static void __init __io_apic_setup_irqs(unsigned int apic_id) | 
		
	
		
			
				|  |  |  |  | 		 * installed and if it returns 1: | 
		
	
		
			
				|  |  |  |  | 		 */ | 
		
	
		
			
				|  |  |  |  | 		if (apic->multi_timer_check && | 
		
	
		
			
				|  |  |  |  | 		    apic->multi_timer_check(apic_id, irq)) | 
		
	
		
			
				|  |  |  |  | 		    apic->multi_timer_check(ioapic_idx, irq)) | 
		
	
		
			
				|  |  |  |  | 			continue; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), | 
		
	
		
			
				|  |  |  |  | 		set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx), | 
		
	
		
			
				|  |  |  |  | 				     irq_polarity(idx)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		io_apic_setup_irq_pin(irq, node, &attr); | 
		
	
	
		
			
				
					
					|  |  |  | @ -1499,12 +1501,12 @@ static void __init __io_apic_setup_irqs(unsigned int apic_id) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void __init setup_IO_APIC_irqs(void) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	unsigned int apic_id; | 
		
	
		
			
				|  |  |  |  | 	unsigned int ioapic_idx; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) | 
		
	
		
			
				|  |  |  |  | 		__io_apic_setup_irqs(apic_id); | 
		
	
		
			
				|  |  |  |  | 	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) | 
		
	
		
			
				|  |  |  |  | 		__io_apic_setup_irqs(ioapic_idx); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | /*
 | 
		
	
	
		
			
				
					
					|  |  |  | @ -1514,28 +1516,28 @@ static void __init setup_IO_APIC_irqs(void) | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | void setup_IO_APIC_irq_extra(u32 gsi) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int apic_id = 0, pin, idx, irq, node = cpu_to_node(0); | 
		
	
		
			
				|  |  |  |  | 	int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0); | 
		
	
		
			
				|  |  |  |  | 	struct io_apic_irq_attr attr; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * Convert 'gsi' to 'ioapic.pin'. | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	apic_id = mp_find_ioapic(gsi); | 
		
	
		
			
				|  |  |  |  | 	if (apic_id < 0) | 
		
	
		
			
				|  |  |  |  | 	ioapic_idx = mp_find_ioapic(gsi); | 
		
	
		
			
				|  |  |  |  | 	if (ioapic_idx < 0) | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	pin = mp_find_ioapic_pin(apic_id, gsi); | 
		
	
		
			
				|  |  |  |  | 	idx = find_irq_entry(apic_id, pin, mp_INT); | 
		
	
		
			
				|  |  |  |  | 	pin = mp_find_ioapic_pin(ioapic_idx, gsi); | 
		
	
		
			
				|  |  |  |  | 	idx = find_irq_entry(ioapic_idx, pin, mp_INT); | 
		
	
		
			
				|  |  |  |  | 	if (idx == -1) | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	irq = pin_2_irq(idx, apic_id, pin); | 
		
	
		
			
				|  |  |  |  | 	irq = pin_2_irq(idx, ioapic_idx, pin); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Only handle the non legacy irqs on secondary ioapics */ | 
		
	
		
			
				|  |  |  |  | 	if (apic_id == 0 || irq < NR_IRQS_LEGACY) | 
		
	
		
			
				|  |  |  |  | 	if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY) | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), | 
		
	
		
			
				|  |  |  |  | 	set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx), | 
		
	
		
			
				|  |  |  |  | 			     irq_polarity(idx)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	io_apic_setup_irq_pin_once(irq, node, &attr); | 
		
	
	
		
			
				
					
					|  |  |  | @ -1544,8 +1546,8 @@ void setup_IO_APIC_irq_extra(u32 gsi) | 
		
	
		
			
				|  |  |  |  | /*
 | 
		
	
		
			
				|  |  |  |  |  * Set up the timer pin, possibly with the 8259A-master behind. | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, | 
		
	
		
			
				|  |  |  |  | 					int vector) | 
		
	
		
			
				|  |  |  |  | static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, | 
		
	
		
			
				|  |  |  |  | 					 unsigned int pin, int vector) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	struct IO_APIC_route_entry entry; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					
					|  |  |  | @ -1576,45 +1578,29 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * Add it to the IO-APIC irq-routing table: | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	ioapic_write_entry(apic_id, pin, entry); | 
		
	
		
			
				|  |  |  |  | 	ioapic_write_entry(ioapic_idx, pin, entry); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | __apicdebuginit(void) print_IO_APIC(void) | 
		
	
		
			
				|  |  |  |  | __apicdebuginit(void) print_IO_APIC(int ioapic_idx) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int apic, i; | 
		
	
		
			
				|  |  |  |  | 	int i; | 
		
	
		
			
				|  |  |  |  | 	union IO_APIC_reg_00 reg_00; | 
		
	
		
			
				|  |  |  |  | 	union IO_APIC_reg_01 reg_01; | 
		
	
		
			
				|  |  |  |  | 	union IO_APIC_reg_02 reg_02; | 
		
	
		
			
				|  |  |  |  | 	union IO_APIC_reg_03 reg_03; | 
		
	
		
			
				|  |  |  |  | 	unsigned long flags; | 
		
	
		
			
				|  |  |  |  | 	struct irq_cfg *cfg; | 
		
	
		
			
				|  |  |  |  | 	unsigned int irq; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); | 
		
	
		
			
				|  |  |  |  | 	for (i = 0; i < nr_ioapics; i++) | 
		
	
		
			
				|  |  |  |  | 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", | 
		
	
		
			
				|  |  |  |  | 		       mpc_ioapic_id(i), ioapics[i].nr_registers); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * We are a bit conservative about what we expect.  We have to | 
		
	
		
			
				|  |  |  |  | 	 * know about every hardware change ASAP. | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_INFO "testing the IO APIC.......................\n"); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (apic = 0; apic < nr_ioapics; apic++) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	raw_spin_lock_irqsave(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 	reg_00.raw = io_apic_read(apic, 0); | 
		
	
		
			
				|  |  |  |  | 	reg_01.raw = io_apic_read(apic, 1); | 
		
	
		
			
				|  |  |  |  | 	reg_00.raw = io_apic_read(ioapic_idx, 0); | 
		
	
		
			
				|  |  |  |  | 	reg_01.raw = io_apic_read(ioapic_idx, 1); | 
		
	
		
			
				|  |  |  |  | 	if (reg_01.bits.version >= 0x10) | 
		
	
		
			
				|  |  |  |  | 		reg_02.raw = io_apic_read(apic, 2); | 
		
	
		
			
				|  |  |  |  | 		reg_02.raw = io_apic_read(ioapic_idx, 2); | 
		
	
		
			
				|  |  |  |  | 	if (reg_01.bits.version >= 0x20) | 
		
	
		
			
				|  |  |  |  | 		reg_03.raw = io_apic_read(apic, 3); | 
		
	
		
			
				|  |  |  |  | 		reg_03.raw = io_apic_read(ioapic_idx, 3); | 
		
	
		
			
				|  |  |  |  | 	raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	printk("\n"); | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(apic)); | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx)); | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID); | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type); | 
		
	
	
		
			
				
					
					|  |  |  | @ -1664,7 +1650,7 @@ __apicdebuginit(void) print_IO_APIC(void) | 
		
	
		
			
				|  |  |  |  | 			struct IO_APIC_route_entry entry; | 
		
	
		
			
				|  |  |  |  | 			struct IR_IO_APIC_route_entry *ir_entry; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			entry = ioapic_read_entry(apic, i); | 
		
	
		
			
				|  |  |  |  | 			entry = ioapic_read_entry(ioapic_idx, i); | 
		
	
		
			
				|  |  |  |  | 			ir_entry = (struct IR_IO_APIC_route_entry *) &entry; | 
		
	
		
			
				|  |  |  |  | 			printk(KERN_DEBUG " %02x %04X ", | 
		
	
		
			
				|  |  |  |  | 				i, | 
		
	
	
		
			
				
					
					|  |  |  | @ -1685,7 +1671,7 @@ __apicdebuginit(void) print_IO_APIC(void) | 
		
	
		
			
				|  |  |  |  | 		} else { | 
		
	
		
			
				|  |  |  |  | 			struct IO_APIC_route_entry entry; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			entry = ioapic_read_entry(apic, i); | 
		
	
		
			
				|  |  |  |  | 			entry = ioapic_read_entry(ioapic_idx, i); | 
		
	
		
			
				|  |  |  |  | 			printk(KERN_DEBUG " %02x %02X  ", | 
		
	
		
			
				|  |  |  |  | 				i, | 
		
	
		
			
				|  |  |  |  | 				entry.dest | 
		
	
	
		
			
				
					
					|  |  |  | @ -1703,7 +1689,28 @@ __apicdebuginit(void) print_IO_APIC(void) | 
		
	
		
			
				|  |  |  |  | 			); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | __apicdebuginit(void) print_IO_APICs(void) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int ioapic_idx; | 
		
	
		
			
				|  |  |  |  | 	struct irq_cfg *cfg; | 
		
	
		
			
				|  |  |  |  | 	unsigned int irq; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); | 
		
	
		
			
				|  |  |  |  | 	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) | 
		
	
		
			
				|  |  |  |  | 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", | 
		
	
		
			
				|  |  |  |  | 		       mpc_ioapic_id(ioapic_idx), | 
		
	
		
			
				|  |  |  |  | 		       ioapics[ioapic_idx].nr_registers); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * We are a bit conservative about what we expect.  We have to | 
		
	
		
			
				|  |  |  |  | 	 * know about every hardware change ASAP. | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_INFO "testing the IO APIC.......................\n"); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) | 
		
	
		
			
				|  |  |  |  | 		print_IO_APIC(ioapic_idx); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_DEBUG "IRQ to pin mappings:\n"); | 
		
	
		
			
				|  |  |  |  | 	for_each_active_irq(irq) { | 
		
	
	
		
			
				
					
					|  |  |  | @ -1722,8 +1729,6 @@ __apicdebuginit(void) print_IO_APIC(void) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	printk(KERN_INFO ".................................... done.\n"); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	return; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | __apicdebuginit(void) print_APIC_field(int base) | 
		
	
	
		
			
				
					
					|  |  |  | @ -1917,7 +1922,7 @@ __apicdebuginit(int) print_ICs(void) | 
		
	
		
			
				|  |  |  |  | 		return 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	print_local_APICs(show_lapic); | 
		
	
		
			
				|  |  |  |  | 	print_IO_APIC(); | 
		
	
		
			
				|  |  |  |  | 	print_IO_APICs(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @ -2042,7 +2047,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	union IO_APIC_reg_00 reg_00; | 
		
	
		
			
				|  |  |  |  | 	physid_mask_t phys_id_present_map; | 
		
	
		
			
				|  |  |  |  | 	int apic_id; | 
		
	
		
			
				|  |  |  |  | 	int ioapic_idx; | 
		
	
		
			
				|  |  |  |  | 	int i; | 
		
	
		
			
				|  |  |  |  | 	unsigned char old_id; | 
		
	
		
			
				|  |  |  |  | 	unsigned long flags; | 
		
	
	
		
			
				
					
					|  |  |  | @ -2056,21 +2061,20 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) | 
		
	
		
			
				|  |  |  |  | 	/*
 | 
		
	
		
			
				|  |  |  |  | 	 * Set the IOAPIC ID to the value stored in the MPC table. | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { | 
		
	
		
			
				|  |  |  |  | 		/* Read the register 0 value */ | 
		
	
		
			
				|  |  |  |  | 		raw_spin_lock_irqsave(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 		reg_00.raw = io_apic_read(apic_id, 0); | 
		
	
		
			
				|  |  |  |  | 		reg_00.raw = io_apic_read(ioapic_idx, 0); | 
		
	
		
			
				|  |  |  |  | 		raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		old_id = mpc_ioapic_id(apic_id); | 
		
	
		
			
				|  |  |  |  | 		old_id = mpc_ioapic_id(ioapic_idx); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		if (mpc_ioapic_id(apic_id) >= get_physical_broadcast()) { | 
		
	
		
			
				|  |  |  |  | 		if (mpc_ioapic_id(ioapic_idx) >= get_physical_broadcast()) { | 
		
	
		
			
				|  |  |  |  | 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", | 
		
	
		
			
				|  |  |  |  | 				apic_id, mpc_ioapic_id(apic_id)); | 
		
	
		
			
				|  |  |  |  | 				ioapic_idx, mpc_ioapic_id(ioapic_idx)); | 
		
	
		
			
				|  |  |  |  | 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", | 
		
	
		
			
				|  |  |  |  | 				reg_00.bits.ID); | 
		
	
		
			
				|  |  |  |  | 			ioapics[apic_id].mp_config.apicid = reg_00.bits.ID; | 
		
	
		
			
				|  |  |  |  | 			ioapics[ioapic_idx].mp_config.apicid = reg_00.bits.ID; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		/*
 | 
		
	
	
		
			
				
					
					|  |  |  | @ -2079,9 +2083,9 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) | 
		
	
		
			
				|  |  |  |  | 		 * 'stuck on smp_invalidate_needed IPI wait' messages. | 
		
	
		
			
				|  |  |  |  | 		 */ | 
		
	
		
			
				|  |  |  |  | 		if (apic->check_apicid_used(&phys_id_present_map, | 
		
	
		
			
				|  |  |  |  | 					    mpc_ioapic_id(apic_id))) { | 
		
	
		
			
				|  |  |  |  | 					    mpc_ioapic_id(ioapic_idx))) { | 
		
	
		
			
				|  |  |  |  | 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", | 
		
	
		
			
				|  |  |  |  | 				apic_id, mpc_ioapic_id(apic_id)); | 
		
	
		
			
				|  |  |  |  | 				ioapic_idx, mpc_ioapic_id(ioapic_idx)); | 
		
	
		
			
				|  |  |  |  | 			for (i = 0; i < get_physical_broadcast(); i++) | 
		
	
		
			
				|  |  |  |  | 				if (!physid_isset(i, phys_id_present_map)) | 
		
	
		
			
				|  |  |  |  | 					break; | 
		
	
	
		
			
				
					
					|  |  |  | @ -2090,14 +2094,14 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) | 
		
	
		
			
				|  |  |  |  | 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", | 
		
	
		
			
				|  |  |  |  | 				i); | 
		
	
		
			
				|  |  |  |  | 			physid_set(i, phys_id_present_map); | 
		
	
		
			
				|  |  |  |  | 			ioapics[apic_id].mp_config.apicid = i; | 
		
	
		
			
				|  |  |  |  | 			ioapics[ioapic_idx].mp_config.apicid = i; | 
		
	
		
			
				|  |  |  |  | 		} else { | 
		
	
		
			
				|  |  |  |  | 			physid_mask_t tmp; | 
		
	
		
			
				|  |  |  |  | 			apic->apicid_to_cpu_present(mpc_ioapic_id(apic_id), | 
		
	
		
			
				|  |  |  |  | 			apic->apicid_to_cpu_present(mpc_ioapic_id(ioapic_idx), | 
		
	
		
			
				|  |  |  |  | 						    &tmp); | 
		
	
		
			
				|  |  |  |  | 			apic_printk(APIC_VERBOSE, "Setting %d in the " | 
		
	
		
			
				|  |  |  |  | 					"phys_id_present_map\n", | 
		
	
		
			
				|  |  |  |  | 					mpc_ioapic_id(apic_id)); | 
		
	
		
			
				|  |  |  |  | 					mpc_ioapic_id(ioapic_idx)); | 
		
	
		
			
				|  |  |  |  | 			physids_or(phys_id_present_map, phys_id_present_map, tmp); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					
					|  |  |  | @ -2105,35 +2109,35 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) | 
		
	
		
			
				|  |  |  |  | 		 * We need to adjust the IRQ routing table | 
		
	
		
			
				|  |  |  |  | 		 * if the ID changed. | 
		
	
		
			
				|  |  |  |  | 		 */ | 
		
	
		
			
				|  |  |  |  | 		if (old_id != mpc_ioapic_id(apic_id)) | 
		
	
		
			
				|  |  |  |  | 		if (old_id != mpc_ioapic_id(ioapic_idx)) | 
		
	
		
			
				|  |  |  |  | 			for (i = 0; i < mp_irq_entries; i++) | 
		
	
		
			
				|  |  |  |  | 				if (mp_irqs[i].dstapic == old_id) | 
		
	
		
			
				|  |  |  |  | 					mp_irqs[i].dstapic | 
		
	
		
			
				|  |  |  |  | 						= mpc_ioapic_id(apic_id); | 
		
	
		
			
				|  |  |  |  | 						= mpc_ioapic_id(ioapic_idx); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		/*
 | 
		
	
		
			
				|  |  |  |  | 		 * Update the ID register according to the right value | 
		
	
		
			
				|  |  |  |  | 		 * from the MPC table if they are different. | 
		
	
		
			
				|  |  |  |  | 		 */ | 
		
	
		
			
				|  |  |  |  | 		if (mpc_ioapic_id(apic_id) == reg_00.bits.ID) | 
		
	
		
			
				|  |  |  |  | 		if (mpc_ioapic_id(ioapic_idx) == reg_00.bits.ID) | 
		
	
		
			
				|  |  |  |  | 			continue; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		apic_printk(APIC_VERBOSE, KERN_INFO | 
		
	
		
			
				|  |  |  |  | 			"...changing IO-APIC physical APIC ID to %d ...", | 
		
	
		
			
				|  |  |  |  | 			mpc_ioapic_id(apic_id)); | 
		
	
		
			
				|  |  |  |  | 			mpc_ioapic_id(ioapic_idx)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		reg_00.bits.ID = mpc_ioapic_id(apic_id); | 
		
	
		
			
				|  |  |  |  | 		reg_00.bits.ID = mpc_ioapic_id(ioapic_idx); | 
		
	
		
			
				|  |  |  |  | 		raw_spin_lock_irqsave(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 		io_apic_write(apic_id, 0, reg_00.raw); | 
		
	
		
			
				|  |  |  |  | 		io_apic_write(ioapic_idx, 0, reg_00.raw); | 
		
	
		
			
				|  |  |  |  | 		raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		/*
 | 
		
	
		
			
				|  |  |  |  | 		 * Sanity check | 
		
	
		
			
				|  |  |  |  | 		 */ | 
		
	
		
			
				|  |  |  |  | 		raw_spin_lock_irqsave(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 		reg_00.raw = io_apic_read(apic_id, 0); | 
		
	
		
			
				|  |  |  |  | 		reg_00.raw = io_apic_read(ioapic_idx, 0); | 
		
	
		
			
				|  |  |  |  | 		raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 		if (reg_00.bits.ID != mpc_ioapic_id(apic_id)) | 
		
	
		
			
				|  |  |  |  | 		if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) | 
		
	
		
			
				|  |  |  |  | 			printk("could not set ID!\n"); | 
		
	
		
			
				|  |  |  |  | 		else | 
		
	
		
			
				|  |  |  |  | 			apic_printk(APIC_VERBOSE, " ok.\n"); | 
		
	
	
		
			
				
					
					|  |  |  | @ -3001,27 +3005,26 @@ static int __init io_apic_bug_finalize(void) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | late_initcall(io_apic_bug_finalize); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void resume_ioapic_id(int ioapic_id) | 
		
	
		
			
				|  |  |  |  | static void resume_ioapic_id(int ioapic_idx) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	unsigned long flags; | 
		
	
		
			
				|  |  |  |  | 	union IO_APIC_reg_00 reg_00; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	raw_spin_lock_irqsave(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | 	reg_00.raw = io_apic_read(ioapic_id, 0); | 
		
	
		
			
				|  |  |  |  | 	if (reg_00.bits.ID != mpc_ioapic_id(ioapic_id)) { | 
		
	
		
			
				|  |  |  |  | 		reg_00.bits.ID = mpc_ioapic_id(ioapic_id); | 
		
	
		
			
				|  |  |  |  | 		io_apic_write(ioapic_id, 0, reg_00.raw); | 
		
	
		
			
				|  |  |  |  | 	reg_00.raw = io_apic_read(ioapic_idx, 0); | 
		
	
		
			
				|  |  |  |  | 	if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) { | 
		
	
		
			
				|  |  |  |  | 		reg_00.bits.ID = mpc_ioapic_id(ioapic_idx); | 
		
	
		
			
				|  |  |  |  | 		io_apic_write(ioapic_idx, 0, reg_00.raw); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void ioapic_resume(void) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int ioapic_id; | 
		
	
		
			
				|  |  |  |  | 	int ioapic_idx; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--) | 
		
	
		
			
				|  |  |  |  | 		resume_ioapic_id(ioapic_id); | 
		
	
		
			
				|  |  |  |  | 	for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--) | 
		
	
		
			
				|  |  |  |  | 		resume_ioapic_id(ioapic_idx); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	restore_ioapic_entries(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @ -3558,26 +3561,25 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) | 
		
	
		
			
				|  |  |  |  | 		return -EINVAL; | 
		
	
		
			
				|  |  |  |  | 	ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin); | 
		
	
		
			
				|  |  |  |  | 	if (!ret) | 
		
	
		
			
				|  |  |  |  | 		setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg, | 
		
	
		
			
				|  |  |  |  | 				 attr->trigger, attr->polarity); | 
		
	
		
			
				|  |  |  |  | 		setup_ioapic_irq(irq, cfg, attr); | 
		
	
		
			
				|  |  |  |  | 	return ret; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int io_apic_setup_irq_pin_once(unsigned int irq, int node, | 
		
	
		
			
				|  |  |  |  | 			       struct io_apic_irq_attr *attr) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	unsigned int id = attr->ioapic, pin = attr->ioapic_pin; | 
		
	
		
			
				|  |  |  |  | 	unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin; | 
		
	
		
			
				|  |  |  |  | 	int ret; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Avoid redundant programming */ | 
		
	
		
			
				|  |  |  |  | 	if (test_bit(pin, ioapics[id].pin_programmed)) { | 
		
	
		
			
				|  |  |  |  | 	if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) { | 
		
	
		
			
				|  |  |  |  | 		pr_debug("Pin %d-%d already programmed\n", | 
		
	
		
			
				|  |  |  |  | 			 mpc_ioapic_id(id), pin); | 
		
	
		
			
				|  |  |  |  | 			 mpc_ioapic_id(ioapic_idx), pin); | 
		
	
		
			
				|  |  |  |  | 		return 0; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	ret = io_apic_setup_irq_pin(irq, node, attr); | 
		
	
		
			
				|  |  |  |  | 	if (!ret) | 
		
	
		
			
				|  |  |  |  | 		set_bit(pin, ioapics[id].pin_programmed); | 
		
	
		
			
				|  |  |  |  | 		set_bit(pin, ioapics[ioapic_idx].pin_programmed); | 
		
	
		
			
				|  |  |  |  | 	return ret; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					
					|  |  |  | @ -3613,7 +3615,6 @@ int get_nr_irqs_gsi(void) | 
		
	
		
			
				|  |  |  |  | 	return nr_irqs_gsi; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #ifdef CONFIG_SPARSE_IRQ | 
		
	
		
			
				|  |  |  |  | int __init arch_probe_nr_irqs(void) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int nr; | 
		
	
	
		
			
				
					
					|  |  |  | @ -3633,7 +3634,6 @@ int __init arch_probe_nr_irqs(void) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	return NR_IRQS_LEGACY; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int io_apic_set_pci_routing(struct device *dev, int irq, | 
		
	
		
			
				|  |  |  |  | 			    struct io_apic_irq_attr *irq_attr) | 
		
	
	
		
			
				
					
					|  |  |  | 
 |