diff options
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
| -rw-r--r-- | arch/x86/kernel/acpi/boot.c | 236 | 
1 files changed, 54 insertions, 182 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 723989d7f80..6b8ca3a0285 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -33,6 +33,7 @@  #include <linux/irq.h>  #include <linux/bootmem.h>  #include <linux/ioport.h> +#include <linux/pci.h>  #include <asm/pgtable.h>  #include <asm/io_apic.h> @@ -43,11 +44,7 @@  static int __initdata acpi_force = 0;  u32 acpi_rsdt_forced; -#ifdef	CONFIG_ACPI -int acpi_disabled = 0; -#else -int acpi_disabled = 1; -#endif +int acpi_disabled;  EXPORT_SYMBOL(acpi_disabled);  #ifdef	CONFIG_X86_64 @@ -121,72 +118,6 @@ void __init __acpi_unmap_table(char *map, unsigned long size)  	early_iounmap(map, size);  } -#ifdef CONFIG_PCI_MMCONFIG - -static int acpi_mcfg_64bit_base_addr __initdata = FALSE; - -/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */ -struct acpi_mcfg_allocation *pci_mmcfg_config; -int pci_mmcfg_config_num; - -static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg) -{ -	if (!strcmp(mcfg->header.oem_id, "SGI")) -		acpi_mcfg_64bit_base_addr = TRUE; - -	return 0; -} - -int __init acpi_parse_mcfg(struct acpi_table_header *header) -{ -	struct acpi_table_mcfg *mcfg; -	unsigned long i; -	int config_size; - -	if (!header) -		return -EINVAL; - -	mcfg = (struct acpi_table_mcfg *)header; - -	/* how many config structures do we have */ -	pci_mmcfg_config_num = 0; -	i = header->length - sizeof(struct acpi_table_mcfg); -	while (i >= sizeof(struct acpi_mcfg_allocation)) { -		++pci_mmcfg_config_num; -		i -= sizeof(struct acpi_mcfg_allocation); -	}; -	if (pci_mmcfg_config_num == 0) { -		printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); -		return -ENODEV; -	} - -	config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); -	pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); -	if (!pci_mmcfg_config) { -		printk(KERN_WARNING PREFIX -		       "No memory for MCFG config tables\n"); -		return -ENOMEM; -	} - -	memcpy(pci_mmcfg_config, &mcfg[1], config_size); - -	acpi_mcfg_oem_check(mcfg); - -	for (i = 0; i < pci_mmcfg_config_num; ++i) { -		if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) && -		    !acpi_mcfg_64bit_base_addr) { -			printk(KERN_ERR PREFIX -			       "MMCONFIG not in low 4GB of memory\n"); -			kfree(pci_mmcfg_config); -			pci_mmcfg_config_num = 0; -			return -ENODEV; -		} -	} - -	return 0; -} -#endif				/* CONFIG_PCI_MMCONFIG */ -  #ifdef CONFIG_X86_LOCAL_APIC  static int __init acpi_parse_madt(struct acpi_table_header *table)  { @@ -522,7 +453,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)   * success: return IRQ number (>=0)   * failure: return < 0   */ -int acpi_register_gsi(u32 gsi, int triggering, int polarity) +int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)  {  	unsigned int irq;  	unsigned int plat_gsi = gsi; @@ -532,14 +463,14 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)  	 * Make sure all (legacy) PCI IRQs are set as level-triggered.  	 */  	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { -		if (triggering == ACPI_LEVEL_SENSITIVE) +		if (trigger == ACPI_LEVEL_SENSITIVE)  			eisa_set_level_irq(gsi);  	}  #endif  #ifdef CONFIG_X86_IO_APIC  	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { -		plat_gsi = mp_register_gsi(gsi, triggering, polarity); +		plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);  	}  #endif  	acpi_gsi_to_irq(plat_gsi, &irq); @@ -903,10 +834,8 @@ extern int es7000_plat;  #endif  static struct { -	int apic_id;  	int gsi_base;  	int gsi_end; -	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);  } mp_ioapic_routing[MAX_IO_APICS];  int mp_find_ioapic(int gsi) @@ -986,16 +915,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)  	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);  	mp_ioapics[idx].apicid = uniq_ioapic_id(id); -#ifdef CONFIG_X86_32  	mp_ioapics[idx].apicver = io_apic_get_version(idx); -#else -	mp_ioapics[idx].apicver = 0; -#endif +  	/*  	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups  	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).  	 */ -	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;  	mp_ioapic_routing[idx].gsi_base = gsi_base;  	mp_ioapic_routing[idx].gsi_end = gsi_base +  	    io_apic_get_redir_entries(idx); @@ -1158,26 +1083,52 @@ void __init mp_config_acpi_legacy_irqs(void)  	}  } -int mp_register_gsi(u32 gsi, int triggering, int polarity) +static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger, +			int polarity)  { +#ifdef CONFIG_X86_MPPARSE +	struct mpc_intsrc mp_irq; +	struct pci_dev *pdev; +	unsigned char number; +	unsigned int devfn;  	int ioapic; -	int ioapic_pin; -#ifdef CONFIG_X86_32 -#define MAX_GSI_NUM	4096 -#define IRQ_COMPRESSION_START	64 +	u8 pin; -	static int pci_irq = IRQ_COMPRESSION_START; -	/* -	 * Mapping between Global System Interrupts, which -	 * represent all possible interrupts, and IRQs -	 * assigned to actual devices. -	 */ -	static int gsi_to_irq[MAX_GSI_NUM]; -#else +	if (!acpi_ioapic) +		return 0; +	if (!dev) +		return 0; +	if (dev->bus != &pci_bus_type) +		return 0; + +	pdev = to_pci_dev(dev); +	number = pdev->bus->number; +	devfn = pdev->devfn; +	pin = pdev->pin; +	/* print the entry should happen on mptable identically */ +	mp_irq.type = MP_INTSRC; +	mp_irq.irqtype = mp_INT; +	mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | +				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3); +	mp_irq.srcbus = number; +	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); +	ioapic = mp_find_ioapic(gsi); +	mp_irq.dstapic = mp_ioapics[ioapic].apicid; +	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); + +	save_mp_irq(&mp_irq); +#endif +	return 0; +} + +int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) +{ +	int ioapic; +	int ioapic_pin; +	struct io_apic_irq_attr irq_attr;  	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)  		return gsi; -#endif  	/* Don't set up the ACPI SCI because it's already set up */  	if (acpi_gbl_FADT.sci_interrupt == gsi) @@ -1196,93 +1147,22 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)  		gsi = ioapic_renumber_irq(ioapic, gsi);  #endif -	/* -	 * Avoid pin reprogramming.  PRTs typically include entries -	 * with redundant pin->gsi mappings (but unique PCI devices); -	 * we only program the IOAPIC on the first. -	 */  	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {  		printk(KERN_ERR "Invalid reference to IOAPIC pin " -		       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, +		       "%d-%d\n", mp_ioapics[ioapic].apicid,  		       ioapic_pin);  		return gsi;  	} -	if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { -		pr_debug("Pin %d-%d already programmed\n", -			 mp_ioapic_routing[ioapic].apic_id, ioapic_pin); -#ifdef CONFIG_X86_32 -		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); -#else -		return gsi; -#endif -	} - -	set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); -#ifdef CONFIG_X86_32 -	/* -	 * For GSI >= 64, use IRQ compression -	 */ -	if ((gsi >= IRQ_COMPRESSION_START) -	    && (triggering == ACPI_LEVEL_SENSITIVE)) { -		/* -		 * For PCI devices assign IRQs in order, avoiding gaps -		 * due to unused I/O APIC pins. -		 */ -		int irq = gsi; -		if (gsi < MAX_GSI_NUM) { -			/* -			 * Retain the VIA chipset work-around (gsi > 15), but -			 * avoid a problem where the 8254 timer (IRQ0) is setup -			 * via an override (so it's not on pin 0 of the ioapic), -			 * and at the same time, the pin 0 interrupt is a PCI -			 * type.  The gsi > 15 test could cause these two pins -			 * to be shared as IRQ0, and they are not shareable. -			 * So test for this condition, and if necessary, avoid -			 * the pin collision. -			 */ -			gsi = pci_irq++; -			/* -			 * Don't assign IRQ used by ACPI SCI -			 */ -			if (gsi == acpi_gbl_FADT.sci_interrupt) -				gsi = pci_irq++; -			gsi_to_irq[irq] = gsi; -		} else { -			printk(KERN_ERR "GSI %u is too high\n", gsi); -			return gsi; -		} -	} -#endif -	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, -				triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, -				polarity == ACPI_ACTIVE_HIGH ? 0 : 1); -	return gsi; -} - -int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, -			u32 gsi, int triggering, int polarity) -{ -#ifdef CONFIG_X86_MPPARSE -	struct mpc_intsrc mp_irq; -	int ioapic; -	if (!acpi_ioapic) -		return 0; +	if (enable_update_mptable) +		mp_config_acpi_gsi(dev, gsi, trigger, polarity); -	/* print the entry should happen on mptable identically */ -	mp_irq.type = MP_INTSRC; -	mp_irq.irqtype = mp_INT; -	mp_irq.irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | -				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3); -	mp_irq.srcbus = number; -	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); -	ioapic = mp_find_ioapic(gsi); -	mp_irq.dstapic = mp_ioapic_routing[ioapic].apic_id; -	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); +	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); -	save_mp_irq(&mp_irq); -#endif -	return 0; +	return gsi;  }  /* @@ -1569,14 +1449,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {  	 },  	{  	 .callback = force_acpi_ht, -	 .ident = "ASUS P4B266", -	 .matches = { -		     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), -		     DMI_MATCH(DMI_BOARD_NAME, "P4B266"), -		     }, -	 }, -	{ -	 .callback = force_acpi_ht,  	 .ident = "ASUS P2B-DS",  	 .matches = {  		     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),  |