diff options
Diffstat (limited to 'arch/x86/pci/fixup.c')
| -rw-r--r-- | arch/x86/pci/fixup.c | 119 | 
1 files changed, 76 insertions, 43 deletions
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 6dd89555fbf..b5e60268d93 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -5,10 +5,11 @@  #include <linux/delay.h>  #include <linux/dmi.h>  #include <linux/pci.h> -#include <linux/init.h> +#include <linux/vgaarb.h> +#include <asm/hpet.h>  #include <asm/pci_x86.h> -static void __devinit pci_fixup_i450nx(struct pci_dev *d) +static void pci_fixup_i450nx(struct pci_dev *d)  {  	/*  	 * i450NX -- Find and scan all secondary buses on all PXB's. @@ -25,15 +26,15 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)  		dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno,  			suba, subb);  		if (busno) -			pci_scan_bus_with_sysdata(busno);	/* Bus A */ +			pcibios_scan_root(busno);	/* Bus A */  		if (suba < subb) -			pci_scan_bus_with_sysdata(suba+1);	/* Bus B */ +			pcibios_scan_root(suba+1);	/* Bus B */  	}  	pcibios_last_bus = -1;  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); -static void __devinit pci_fixup_i450gx(struct pci_dev *d) +static void pci_fixup_i450gx(struct pci_dev *d)  {  	/*  	 * i450GX and i450KX -- Find and scan all secondary buses. @@ -42,12 +43,12 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)  	u8 busno;  	pci_read_config_byte(d, 0x4a, &busno);  	dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno); -	pci_scan_bus_with_sysdata(busno); +	pcibios_scan_root(busno);  	pcibios_last_bus = -1;  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx); -static void __devinit  pci_fixup_umc_ide(struct pci_dev *d) +static void pci_fixup_umc_ide(struct pci_dev *d)  {  	/*  	 * UM8886BF IDE controller sets region type bits incorrectly, @@ -61,7 +62,7 @@ static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide); -static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d) +static void pci_fixup_ncr53c810(struct pci_dev *d)  {  	/*  	 * NCR 53C810 returns class code 0 (at least on some systems). @@ -74,7 +75,7 @@ static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810); -static void __devinit  pci_fixup_latency(struct pci_dev *d) +static void pci_fixup_latency(struct pci_dev *d)  {  	/*  	 *  SiS 5597 and 5598 chipsets require latency timer set to @@ -86,7 +87,7 @@ static void __devinit  pci_fixup_latency(struct pci_dev *d)  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency); -static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d) +static void pci_fixup_piix4_acpi(struct pci_dev *d)  {  	/*  	 * PIIX4 ACPI device: hardwired IRQ9 @@ -162,13 +163,13 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_   * system to PCI bus no matter what are their window settings, so they are   * "transparent" (or subtractive decoding) from programmers point of view.   */ -static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev) +static void pci_fixup_transparent_bridge(struct pci_dev *dev)  { -	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && -	    (dev->device & 0xff00) == 0x2400) +	if ((dev->device & 0xff00) == 0x2400)  		dev->transparent = 1;  } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge); +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, +			 PCI_CLASS_BRIDGE_PCI, 8, pci_fixup_transparent_bridge);  /*   * Fixup for C1 Halt Disconnect problem on nForce2 systems. @@ -230,7 +231,7 @@ static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int wh  	offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];  	if ((offset) && (where == offset)) -		value = value & 0xfffffffc; +		value = value & ~PCI_EXP_LNKCTL_ASPMC;  	return raw_pci_write(pci_domain_nr(bus), bus->number,  						devfn, where, size, value); @@ -251,7 +252,7 @@ static struct pci_ops quirk_pcie_aspm_ops = {   */  static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)  { -	int cap_base, i; +	int i;  	struct pci_bus  *pbus;  	struct pci_dev *dev; @@ -277,7 +278,7 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)  		for (i = GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)  			quirk_aspm_offset[i] = 0; -		pbus->ops = pbus->parent->ops; +		pci_bus_set_ops(pbus, pbus->parent->ops);  	} else {  		/*  		 * If devices are attached to the root port at power-up or @@ -285,13 +286,15 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)  		 * each root port to save the register offsets and replace the  		 * bus ops.  		 */ -		list_for_each_entry(dev, &pbus->devices, bus_list) { +		list_for_each_entry(dev, &pbus->devices, bus_list)  			/* There are 0 to 8 devices attached to this bus */ -			cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP); -			quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] = cap_base + 0x10; -		} -		pbus->ops = &quirk_pcie_aspm_ops; +			quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] = +				dev->pcie_cap + PCI_EXP_LNKCTL; + +		pci_bus_set_ops(pbus, &quirk_pcie_aspm_ops); +		dev_info(&pbus->dev, "writes to ASPM control bits will be ignored\n");  	} +  }  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PA,	pcie_rootport_aspm_quirk);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PA1,	pcie_rootport_aspm_quirk); @@ -311,20 +314,18 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PC1,	pcie_r   * IORESOURCE_ROM_SHADOW is used to associate the boot video   * card with this copy. On laptops this copy has to be used since   * the main ROM may be compressed or combined with another image. - * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW - * is marked here since the boot video device will be the only enabled - * video device at this point. + * See pci_map_rom() for use of this flag. Before marking the device + * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set + * by either arch cde or vga-arbitration, if so only apply the fixup to this + * already determined primary video card.   */ -static void __devinit pci_fixup_video(struct pci_dev *pdev) +static void pci_fixup_video(struct pci_dev *pdev)  {  	struct pci_dev *bridge;  	struct pci_bus *bus;  	u16 config; -	if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) -		return; -  	/* Is VGA routed to us? */  	bus = pdev->bus;  	while (bus) { @@ -337,9 +338,7 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)  		 * type BRIDGE, or CARDBUS. Host to PCI controllers use  		 * PCI header type NORMAL.  		 */ -		if (bridge -		    && ((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE) -		       || (bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) { +		if (bridge && (pci_is_bridge(bridge))) {  			pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,  						&config);  			if (!(config & PCI_BRIDGE_CTL_VGA)) @@ -347,16 +346,20 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)  		}  		bus = bus->parent;  	} -	pci_read_config_word(pdev, PCI_COMMAND, &config); -	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { -		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; -		dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n"); +	if (!vga_default_device() || pdev == vga_default_device()) { +		pci_read_config_word(pdev, PCI_COMMAND, &config); +		if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { +			pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; +			dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n"); +			vga_set_default_device(pdev); +		}  	}  } -DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); +DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, +				PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); -static const struct dmi_system_id __devinitconst msi_k8t_dmi_table[] = { +static const struct dmi_system_id msi_k8t_dmi_table[] = {  	{  		.ident = "MSI-K8T-Neo2Fir",  		.matches = { @@ -377,7 +380,7 @@ static const struct dmi_system_id __devinitconst msi_k8t_dmi_table[] = {   * The soundcard is only enabled, if the mainborad is identified   * via DMI-tables and the soundcard is detected to be off.   */ -static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev) +static void pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)  {  	unsigned char val;  	if (!dmi_check_system(msi_k8t_dmi_table)) @@ -413,7 +416,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,   */  static u16 toshiba_line_size; -static const struct dmi_system_id __devinitconst toshiba_ohci1394_dmi_table[] = { +static const struct dmi_system_id toshiba_ohci1394_dmi_table[] = {  	{  		.ident = "Toshiba PS5 based laptop",  		.matches = { @@ -438,7 +441,7 @@ static const struct dmi_system_id __devinitconst toshiba_ohci1394_dmi_table[] =  	{ }  }; -static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev) +static void pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)  {  	if (!dmi_check_system(toshiba_ohci1394_dmi_table))  		return; /* only applies to certain Toshibas (so far) */ @@ -449,7 +452,7 @@ static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,  			 pci_pre_fixup_toshiba_ohci1394); -static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) +static void pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)  {  	if (!dmi_check_system(toshiba_ohci1394_dmi_table))  		return; /* only applies to certain Toshibas (so far) */ @@ -487,7 +490,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,   * Siemens Nixdorf AG FSC Multiprocessor Interrupt Controller:   * prevent update of the BAR0, which doesn't look like a normal BAR.   */ -static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev) +static void pci_siemens_interrupt_controller(struct pci_dev *dev)  {  	dev->resource[0].flags |= IORESOURCE_PCI_FIXED;  } @@ -521,3 +524,33 @@ static void sb600_disable_hpet_bar(struct pci_dev *dev)  	}  }  DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar); + +#ifdef CONFIG_HPET_TIMER +static void sb600_hpet_quirk(struct pci_dev *dev) +{ +	struct resource *r = &dev->resource[1]; + +	if (r->flags & IORESOURCE_MEM && r->start == hpet_address) { +		r->flags |= IORESOURCE_PCI_FIXED; +		dev_info(&dev->dev, "reg 0x14 contains HPET; making it immovable\n"); +	} +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4385, sb600_hpet_quirk); +#endif + +/* + * Twinhead H12Y needs us to block out a region otherwise we map devices + * there and any access kills the box. + * + *   See: https://bugzilla.kernel.org/show_bug.cgi?id=10231 + * + * Match off the LPC and svid/sdid (older kernels lose the bridge subvendor) + */ +static void twinhead_reserve_killing_zone(struct pci_dev *dev) +{ +        if (dev->subsystem_vendor == 0x14FF && dev->subsystem_device == 0xA003) { +                pr_info("Reserving memory on Twinhead H12Y\n"); +                request_mem_region(0xFFB00000, 0x100000, "twinhead"); +        } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);  | 
