diff options
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
| -rw-r--r-- | arch/x86/kernel/acpi/boot.c | 133 | 
1 files changed, 85 insertions, 48 deletions
| diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index cd40aba6aa95..9a5ed58f09dc 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -94,6 +94,53 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;  /* + * ISA irqs by default are the first 16 gsis but can be + * any gsi as specified by an interrupt source override. + */ +static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = { +	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +static unsigned int gsi_to_irq(unsigned int gsi) +{ +	unsigned int irq = gsi + NR_IRQS_LEGACY; +	unsigned int i; + +	for (i = 0; i < NR_IRQS_LEGACY; i++) { +		if (isa_irq_to_gsi[i] == gsi) { +			return i; +		} +	} + +	/* Provide an identity mapping of gsi == irq +	 * except on truly weird platforms that have +	 * non isa irqs in the first 16 gsis. +	 */ +	if (gsi >= NR_IRQS_LEGACY) +		irq = gsi; +	else +		irq = gsi_end + 1 + gsi; + +	return irq; +} + +static u32 irq_to_gsi(int irq) +{ +	unsigned int gsi; + +	if (irq < NR_IRQS_LEGACY) +		gsi = isa_irq_to_gsi[irq]; +	else if (irq <= gsi_end) +		gsi = irq; +	else if (irq <= (gsi_end + NR_IRQS_LEGACY)) +		gsi = irq - gsi_end; +	else +		gsi = 0xffffffff; + +	return gsi; +} + +/*   * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,   * to map the target physical address. The problem is that set_fixmap()   * provides a single page, and it is possible that the page is not @@ -313,7 +360,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)  /*   * Parse Interrupt Source Override for the ACPI SCI   */ -static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) +static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi)  {  	if (trigger == 0)	/* compatible SCI trigger is level */  		trigger = 3; @@ -333,7 +380,7 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)  	 * If GSI is < 16, this will update its flags,  	 * else it will create a new mp_irqs[] entry.  	 */ -	mp_override_legacy_irq(gsi, polarity, trigger, gsi); +	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);  	/*  	 * stash over-ride to indicate we've been here @@ -357,9 +404,10 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,  	acpi_table_print_madt_entry(header);  	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { -		acpi_sci_ioapic_setup(intsrc->global_irq, +		acpi_sci_ioapic_setup(intsrc->source_irq,  				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, -				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2); +				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2, +				      intsrc->global_irq);  		return 0;  	} @@ -448,7 +496,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)  int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)  { -	*irq = gsi; +	*irq = gsi_to_irq(gsi);  #ifdef CONFIG_X86_IO_APIC  	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) @@ -458,6 +506,14 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)  	return 0;  } +int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) +{ +	if (isa_irq >= 16) +		return -1; +	*gsi = irq_to_gsi(isa_irq); +	return 0; +} +  /*   * success: return IRQ number (>=0)   * failure: return < 0 @@ -482,7 +538,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)  		plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);  	}  #endif -	irq = plat_gsi; +	irq = gsi_to_irq(plat_gsi);  	return irq;  } @@ -867,29 +923,6 @@ static int __init acpi_parse_madt_lapic_entries(void)  extern int es7000_plat;  #endif -int __init acpi_probe_gsi(void) -{ -	int idx; -	int gsi; -	int max_gsi = 0; - -	if (acpi_disabled) -		return 0; - -	if (!acpi_ioapic) -		return 0; - -	max_gsi = 0; -	for (idx = 0; idx < nr_ioapics; idx++) { -		gsi = mp_gsi_routing[idx].gsi_end; - -		if (gsi > max_gsi) -			max_gsi = gsi; -	} - -	return max_gsi + 1; -} -  static void assign_to_mp_irq(struct mpc_intsrc *m,  				    struct mpc_intsrc *mp_irq)  { @@ -947,13 +980,13 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)  	mp_irq.dstirq = pin;	/* INTIN# */  	save_mp_irq(&mp_irq); + +	isa_irq_to_gsi[bus_irq] = gsi;  }  void __init mp_config_acpi_legacy_irqs(void)  {  	int i; -	int ioapic; -	unsigned int dstapic;  	struct mpc_intsrc mp_irq;  #if defined (CONFIG_MCA) || defined (CONFIG_EISA) @@ -974,19 +1007,27 @@ void __init mp_config_acpi_legacy_irqs(void)  #endif  	/* -	 * Locate the IOAPIC that manages the ISA IRQs (0-15). -	 */ -	ioapic = mp_find_ioapic(0); -	if (ioapic < 0) -		return; -	dstapic = mp_ioapics[ioapic].apicid; - -	/*  	 * Use the default configuration for the IRQs 0-15.  Unless  	 * overridden by (MADT) interrupt source override entries.  	 */  	for (i = 0; i < 16; i++) { +		int ioapic, pin; +		unsigned int dstapic;  		int idx; +		u32 gsi; + +		/* Locate the gsi that irq i maps to. */ +		if (acpi_isa_irq_to_gsi(i, &gsi)) +			continue; + +		/* +		 * Locate the IOAPIC that manages the ISA IRQ. +		 */ +		ioapic = mp_find_ioapic(gsi); +		if (ioapic < 0) +			continue; +		pin = mp_find_ioapic_pin(ioapic, gsi); +		dstapic = mp_ioapics[ioapic].apicid;  		for (idx = 0; idx < mp_irq_entries; idx++) {  			struct mpc_intsrc *irq = mp_irqs + idx; @@ -996,7 +1037,7 @@ void __init mp_config_acpi_legacy_irqs(void)  				break;  			/* Do we already have a mapping for this IOAPIC pin */ -			if (irq->dstapic == dstapic && irq->dstirq == i) +			if (irq->dstapic == dstapic && irq->dstirq == pin)  				break;  		} @@ -1011,7 +1052,7 @@ void __init mp_config_acpi_legacy_irqs(void)  		mp_irq.dstapic = dstapic;  		mp_irq.irqtype = mp_INT;  		mp_irq.srcbusirq = i; /* Identity mapped */ -		mp_irq.dstirq = i; +		mp_irq.dstirq = pin;  		save_mp_irq(&mp_irq);  	} @@ -1076,11 +1117,6 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)  	ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); -#ifdef CONFIG_X86_32 -	if (ioapic_renumber_irq) -		gsi = ioapic_renumber_irq(ioapic, gsi); -#endif -  	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {  		printk(KERN_ERR "Invalid reference to IOAPIC pin "  		       "%d-%d\n", mp_ioapics[ioapic].apicid, @@ -1094,7 +1130,7 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)  	set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,  			     trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,  			     polarity == ACPI_ACTIVE_HIGH ? 0 : 1); -	io_apic_set_pci_routing(dev, gsi, &irq_attr); +	io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);  	return gsi;  } @@ -1154,7 +1190,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)  	 * pretend we got one so we can set the SCI flags.  	 */  	if (!acpi_sci_override_gsi) -		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0); +		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0, +				      acpi_gbl_FADT.sci_interrupt);  	/* Fill in identity legacy mappings where no override */  	mp_config_acpi_legacy_irqs(); |