forked from mirrors/linux
		
	ACPI: fix two IRQ8 issues in IOAPIC mode
Use mp_irqs[] to get PNP device's interrupt polarity and trigger. There are two reasons to do this: 1. BIOS bug for PNP interrupt 2. BIOS explictly does override mp_irqs[] should cover all the cases. http://bugzilla.kernel.org/show_bug.cgi?id=5243 http://bugzilla.kernel.org/show_bug.cgi?id=7679 http://bugzilla.kernel.org/show_bug.cgi?id=9153 [lenb: fixed !IOAPIC and 64-bit !SMP builds] Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
		
							parent
							
								
									f0714d2023
								
							
						
					
					
						commit
						61fd47e0c8
					
				
					 4 changed files with 65 additions and 3 deletions
				
			
		|  | @ -962,7 +962,7 @@ static int EISA_ELCR(unsigned int irq) | ||||||
| #define default_MCA_trigger(idx)	(1) | #define default_MCA_trigger(idx)	(1) | ||||||
| #define default_MCA_polarity(idx)	(0) | #define default_MCA_polarity(idx)	(0) | ||||||
| 
 | 
 | ||||||
| static int __init MPBIOS_polarity(int idx) | static int MPBIOS_polarity(int idx) | ||||||
| { | { | ||||||
| 	int bus = mp_irqs[idx].mpc_srcbus; | 	int bus = mp_irqs[idx].mpc_srcbus; | ||||||
| 	int polarity; | 	int polarity; | ||||||
|  | @ -2830,6 +2830,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	if (skip_ioapic_setup) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < mp_irq_entries; i++) | ||||||
|  | 		if (mp_irqs[i].mpc_irqtype == mp_INT && | ||||||
|  | 		    mp_irqs[i].mpc_srcbusirq == bus_irq) | ||||||
|  | 			break; | ||||||
|  | 	if (i >= mp_irq_entries) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	*trigger = irq_trigger(i); | ||||||
|  | 	*polarity = irq_polarity(i); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif /* CONFIG_ACPI */ | #endif /* CONFIG_ACPI */ | ||||||
| 
 | 
 | ||||||
| static int __init parse_disable_timer_pin_1(char *arg) | static int __init parse_disable_timer_pin_1(char *arg) | ||||||
|  |  | ||||||
|  | @ -546,7 +546,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) | ||||||
| #define default_PCI_trigger(idx)	(1) | #define default_PCI_trigger(idx)	(1) | ||||||
| #define default_PCI_polarity(idx)	(1) | #define default_PCI_polarity(idx)	(1) | ||||||
| 
 | 
 | ||||||
| static int __init MPBIOS_polarity(int idx) | static int MPBIOS_polarity(int idx) | ||||||
| { | { | ||||||
| 	int bus = mp_irqs[idx].mpc_srcbus; | 	int bus = mp_irqs[idx].mpc_srcbus; | ||||||
| 	int polarity; | 	int polarity; | ||||||
|  | @ -2222,8 +2222,27 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif /* CONFIG_ACPI */ |  | ||||||
| 
 | 
 | ||||||
|  | int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	if (skip_ioapic_setup) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < mp_irq_entries; i++) | ||||||
|  | 		if (mp_irqs[i].mpc_irqtype == mp_INT && | ||||||
|  | 		    mp_irqs[i].mpc_srcbusirq == bus_irq) | ||||||
|  | 			break; | ||||||
|  | 	if (i >= mp_irq_entries) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	*trigger = irq_trigger(i); | ||||||
|  | 	*polarity = irq_polarity(i); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* CONFIG_ACPI */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * This function currently is only a helper for the i386 smp boot process where |  * This function currently is only a helper for the i386 smp boot process where | ||||||
|  | @ -2260,3 +2279,4 @@ void __init setup_ioapic_dest(void) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -75,6 +75,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, | ||||||
| { | { | ||||||
| 	int i = 0; | 	int i = 0; | ||||||
| 	int irq; | 	int irq; | ||||||
|  | 	int p, t; | ||||||
| 
 | 
 | ||||||
| 	if (!valid_IRQ(gsi)) | 	if (!valid_IRQ(gsi)) | ||||||
| 		return; | 		return; | ||||||
|  | @ -85,6 +86,23 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, | ||||||
| 	if (i >= PNP_MAX_IRQ) | 	if (i >= PNP_MAX_IRQ) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * in IO-APIC mode, use overrided attribute. Two reasons: | ||||||
|  | 	 * 1. BIOS bug in DSDT | ||||||
|  | 	 * 2. BIOS uses IO-APIC mode Interrupt Source Override | ||||||
|  | 	 */ | ||||||
|  | 	if (!acpi_get_override_irq(gsi, &t, &p)) { | ||||||
|  | 		t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | ||||||
|  | 		p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | ||||||
|  | 
 | ||||||
|  | 		if (triggering != t || polarity != p) { | ||||||
|  | 			pnp_warn("IRQ %d override to %s, %s", | ||||||
|  | 				gsi, t ? "edge":"level", p ? "low":"high"); | ||||||
|  | 			triggering = t; | ||||||
|  | 			polarity = p; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	res->irq_resource[i].flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
 | 	res->irq_resource[i].flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
 | ||||||
| 	res->irq_resource[i].flags |= irq_flags(triggering, polarity); | 	res->irq_resource[i].flags |= irq_flags(triggering, polarity); | ||||||
| 	irq = acpi_register_gsi(gsi, triggering, polarity); | 	irq = acpi_register_gsi(gsi, triggering, polarity); | ||||||
|  |  | ||||||
|  | @ -132,6 +132,11 @@ extern unsigned long acpi_realmode_flags; | ||||||
| int acpi_register_gsi (u32 gsi, int triggering, int polarity); | int acpi_register_gsi (u32 gsi, int triggering, int polarity); | ||||||
| int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); | int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_X86_IO_APIC | ||||||
|  | extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity); | ||||||
|  | #else | ||||||
|  | #define acpi_get_override_irq(bus, trigger, polarity) (-1) | ||||||
|  | #endif | ||||||
| /*
 | /*
 | ||||||
|  * This function undoes the effect of one call to acpi_register_gsi(). |  * This function undoes the effect of one call to acpi_register_gsi(). | ||||||
|  * If this matches the last registration, any IRQ resources for gsi |  * If this matches the last registration, any IRQ resources for gsi | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Shaohua Li
						Shaohua Li