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