Jelajahi Sumber

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/pci-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/pci-2.6: (64 commits)
  PCI: make pci_bus a struct device
  PCI: fix codingstyle issues in include/linux/pci.h
  PCI: fix codingstyle issues in drivers/pci/pci.h
  PCI: PCIE ASPM support
  PCI: Fix fakephp deadlock
  PCI: modify SB700 SATA MSI quirk
  PCI: Run ACPI _OSC method on root bridges only
  PCI ACPI: AER driver should only register PCIe devices with _OSC
  PCI ACPI: Added a function to register _OSC with only PCIe devices.
  PCI: constify function pointer tables
  PCI: Convert drivers/pci/proc.c to use unlocked_ioctl
  pciehp: block new requests from the device before power off
  pciehp: workaround against Bad DLLP during power off
  pciehp: wait for 1000ms before LED operation after power off
  PCI: Remove pci_enable_device_bars() from documentation
  PCI: Remove pci_enable_device_bars()
  PCI: Remove users of pci_enable_device_bars()
  PCI: Add pci_enable_device_{io,mem} intefaces
  PCI: avoid save the same type of cap multiple times
  PCI: correctly initialize a structure for pcie_save_pcix_state()
  ...
Linus Torvalds 17 tahun lalu
induk
melakukan
215e871aaa
63 mengubah file dengan 2079 tambahan dan 890 penghapusan
  1. 1 36
      Documentation/pci.txt
  2. 0 5
      arch/alpha/Kconfig
  3. 0 5
      arch/arm/Kconfig
  4. 0 5
      arch/frv/Kconfig
  5. 0 5
      arch/m32r/Kconfig
  6. 0 5
      arch/m68k/Kconfig
  7. 0 5
      arch/mips/Kconfig
  8. 0 5
      arch/sh/drivers/pci/Kconfig
  9. 0 5
      arch/sparc64/Kconfig
  10. 0 5
      arch/x86/Kconfig
  11. 23 20
      arch/x86/kernel/quirks.c
  12. 11 11
      arch/x86/pci/fixup.c
  13. 0 5
      arch/xtensa/Kconfig
  14. 1 1
      drivers/ata/pata_cs5520.c
  15. 1 1
      drivers/i2c/busses/scx200_acb.c
  16. 8 2
      drivers/ide/pci/cs5520.c
  17. 4 2
      drivers/ide/setup-pci.c
  18. 13 5
      drivers/pci/bus.c
  19. 17 3
      drivers/pci/dmar.c
  20. 2 2
      drivers/pci/hotplug/Kconfig
  21. 3 1
      drivers/pci/hotplug/Makefile
  22. 0 1
      drivers/pci/hotplug/acpiphp.h
  23. 2 3
      drivers/pci/hotplug/acpiphp_glue.c
  24. 35 4
      drivers/pci/hotplug/fakephp.c
  25. 7 4
      drivers/pci/hotplug/ibmphp_core.c
  26. 2 2
      drivers/pci/hotplug/pci_hotplug_core.c
  27. 3 6
      drivers/pci/hotplug/pciehp.h
  28. 26 7
      drivers/pci/hotplug/pciehp_core.c
  29. 2 25
      drivers/pci/hotplug/pciehp_ctrl.c
  30. 202 112
      drivers/pci/hotplug/pciehp_hpc.c
  31. 23 20
      drivers/pci/hotplug/pciehp_pci.c
  32. 0 1
      drivers/pci/hotplug/rpaphp.h
  33. 0 14
      drivers/pci/hotplug/rpaphp_pci.c
  34. 24 23
      drivers/pci/hotplug/rpaphp_slot.c
  35. 1 1
      drivers/pci/hotplug/shpchp_hpc.c
  36. 1 1
      drivers/pci/intel-iommu.c
  37. 46 48
      drivers/pci/msi.c
  38. 3 4
      drivers/pci/pci-acpi.c
  39. 1 3
      drivers/pci/pci-driver.c
  40. 8 3
      drivers/pci/pci-sysfs.c
  41. 75 18
      drivers/pci/pci.c
  42. 6 10
      drivers/pci/pci.h
  43. 20 0
      drivers/pci/pcie/Kconfig
  44. 3 0
      drivers/pci/pcie/Makefile
  45. 7 17
      drivers/pci/pcie/aer/aerdrv_acpi.c
  46. 802 0
      drivers/pci/pcie/aspm.c
  47. 2 3
      drivers/pci/pcie/portdrv_core.c
  48. 34 46
      drivers/pci/probe.c
  49. 9 8
      drivers/pci/proc.c
  50. 259 195
      drivers/pci/quirks.c
  51. 6 4
      drivers/pci/remove.c
  52. 4 2
      drivers/pci/rom.c
  53. 40 24
      drivers/pci/setup-bus.c
  54. 4 3
      drivers/pci/setup-res.c
  55. 0 5
      drivers/pci/syscall.c
  56. 1 2
      drivers/scsi/lpfc/lpfc_init.c
  57. 1 0
      drivers/scsi/qla2xxx/qla_def.h
  58. 17 4
      drivers/scsi/qla2xxx/qla_os.c
  59. 8 14
      drivers/usb/host/pci-quirks.c
  60. 44 0
      include/linux/aspm.h
  61. 10 1
      include/linux/pci-acpi.h
  62. 249 118
      include/linux/pci.h
  63. 8 0
      include/linux/pci_regs.h

+ 1 - 36
Documentation/pci.txt

@@ -274,8 +274,6 @@ the PCI device by calling pci_enable_device(). This will:
 	o allocate an IRQ (if BIOS did not).
 	o allocate an IRQ (if BIOS did not).
 
 
 NOTE: pci_enable_device() can fail! Check the return value.
 NOTE: pci_enable_device() can fail! Check the return value.
-NOTE2: Also see pci_enable_device_bars() below. Drivers can
-    attempt to enable only a subset of BARs they need.
 
 
 [ OS BUG: we don't check resource allocations before enabling those
 [ OS BUG: we don't check resource allocations before enabling those
   resources. The sequence would make more sense if we called
   resources. The sequence would make more sense if we called
@@ -605,40 +603,7 @@ device lists. This is still possible but discouraged.
 
 
 
 
 
 
-10. pci_enable_device_bars() and Legacy I/O Port space
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Large servers may not be able to provide I/O port resources to all PCI
-devices. I/O Port space is only 64KB on Intel Architecture[1] and is
-likely also fragmented since the I/O base register of PCI-to-PCI
-bridge will usually be aligned to a 4KB boundary[2]. On such systems,
-pci_enable_device() and pci_request_region() will fail when
-attempting to enable I/O Port regions that don't have I/O Port
-resources assigned.
-
-Fortunately, many PCI devices which request I/O Port resources also
-provide access to the same registers via MMIO BARs. These devices can
-be handled without using I/O port space and the drivers typically
-offer a CONFIG_ option to only use MMIO regions
-(e.g. CONFIG_TULIP_MMIO). PCI devices typically provide I/O port
-interface for legacy OSes and will work when I/O port resources are not
-assigned. The "PCI Local Bus Specification Revision 3.0" discusses
-this on p.44, "IMPLEMENTATION NOTE".
-
-If your PCI device driver doesn't need I/O port resources assigned to
-I/O Port BARs, you should use pci_enable_device_bars() instead of
-pci_enable_device() in order not to enable I/O port regions for the
-corresponding devices. In addition, you should use
-pci_request_selected_regions() and pci_release_selected_regions()
-instead of pci_request_regions()/pci_release_regions() in order not to
-request/release I/O port regions for the corresponding devices.
-
-[1] Some systems support 64KB I/O port space per PCI segment.
-[2] Some PCI-to-PCI bridges support optional 1KB aligned I/O base.
-
-
-
-11. MMIO Space and "Write Posting"
+10. MMIO Space and "Write Posting"
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
 Converting a driver from using I/O Port space to using MMIO space
 Converting a driver from using I/O Port space to using MMIO space

+ 0 - 5
arch/alpha/Kconfig

@@ -318,11 +318,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 	  VESA. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_DOMAINS
 config PCI_DOMAINS
 	bool
 	bool
 	default y
 	default y

+ 0 - 5
arch/arm/Kconfig

@@ -577,11 +577,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 	  VESA. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_SYSCALL
 config PCI_SYSCALL
 	def_bool PCI
 	def_bool PCI
 
 

+ 0 - 5
arch/frv/Kconfig

@@ -322,11 +322,6 @@ config PCI
 	  onboard. If you have one of these boards and you wish to use the PCI
 	  onboard. If you have one of these boards and you wish to use the PCI
 	  facilities, say Y here.
 	  facilities, say Y here.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config RESERVE_DMA_COHERENT
 config RESERVE_DMA_COHERENT
 	bool "Reserve DMA coherent memory"
 	bool "Reserve DMA coherent memory"
 	depends on PCI && !MMU
 	depends on PCI && !MMU

+ 0 - 5
arch/m32r/Kconfig

@@ -359,11 +359,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 	  VESA. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.linuxdoc.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 choice
 choice
 	prompt "PCI access mode"
 	prompt "PCI access mode"
 	depends on PCI
 	depends on PCI

+ 0 - 5
arch/m68k/Kconfig

@@ -145,11 +145,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 	  VESA. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config MAC
 config MAC
 	bool "Macintosh support"
 	bool "Macintosh support"
 	depends on !MMU_SUN3
 	depends on !MMU_SUN3

+ 0 - 5
arch/mips/Kconfig

@@ -1961,11 +1961,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
 	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
 	  say Y, otherwise N.
 	  say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_DOMAINS
 config PCI_DOMAINS
 	bool
 	bool
 
 

+ 0 - 5
arch/sh/drivers/pci/Kconfig

@@ -6,11 +6,6 @@ config PCI
 	  bus system, i.e. the way the CPU talks to the other stuff inside
 	  bus system, i.e. the way the CPU talks to the other stuff inside
 	  your box. If you have PCI, say Y, otherwise N.
 	  your box. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config SH_PCIDMA_NONCOHERENT
 config SH_PCIDMA_NONCOHERENT
 	bool "Cache and PCI noncoherent"
 	bool "Cache and PCI noncoherent"
 	depends on PCI
 	depends on PCI

+ 0 - 5
arch/sparc64/Kconfig

@@ -351,11 +351,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 	  VESA. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_DOMAINS
 config PCI_DOMAINS
 	def_bool PCI
 	def_bool PCI
 
 

+ 0 - 5
arch/x86/Kconfig

@@ -1369,11 +1369,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 	  VESA. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 choice
 choice
 	prompt "PCI access mode"
 	prompt "PCI access mode"
 	depends on X86_32 && PCI && !X86_VISWS
 	depends on X86_32 && PCI && !X86_VISWS

+ 23 - 20
arch/x86/kernel/quirks.c

@@ -30,8 +30,8 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
 	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 
 
 	if (!(word & (1 << 13))) {
 	if (!(word & (1 << 13))) {
-		printk(KERN_INFO "Intel E7520/7320/7525 detected. "
-			"Disabling irq balancing and affinity\n");
+		dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
+			"disabling irq balancing and affinity\n");
 #ifdef CONFIG_IRQBALANCE
 #ifdef CONFIG_IRQBALANCE
 		irqbalance_disable("");
 		irqbalance_disable("");
 #endif
 #endif
@@ -104,14 +104,16 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
 	pci_read_config_dword(dev, 0xF0, &rcba);
 	pci_read_config_dword(dev, 0xF0, &rcba);
 	rcba &= 0xFFFFC000;
 	rcba &= 0xFFFFC000;
 	if (rcba == 0) {
 	if (rcba == 0) {
-		printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n");
+		dev_printk(KERN_DEBUG, &dev->dev, "RCBA disabled; "
+			"cannot force enable HPET\n");
 		return;
 		return;
 	}
 	}
 
 
 	/* use bits 31:14, 16 kB aligned */
 	/* use bits 31:14, 16 kB aligned */
 	rcba_base = ioremap_nocache(rcba, 0x4000);
 	rcba_base = ioremap_nocache(rcba, 0x4000);
 	if (rcba_base == NULL) {
 	if (rcba_base == NULL) {
-		printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n");
+		dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; "
+			"cannot force enable HPET\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -122,8 +124,8 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
 		/* HPET is enabled in HPTC. Just not reported by BIOS */
 		/* HPET is enabled in HPTC. Just not reported by BIOS */
 		val = val & 0x3;
 		val = val & 0x3;
 		force_hpet_address = 0xFED00000 | (val << 12);
 		force_hpet_address = 0xFED00000 | (val << 12);
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 		iounmap(rcba_base);
 		iounmap(rcba_base);
 		return;
 		return;
 	}
 	}
@@ -142,11 +144,12 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
 	if (err) {
 	if (err) {
 		force_hpet_address = 0;
 		force_hpet_address = 0;
 		iounmap(rcba_base);
 		iounmap(rcba_base);
-		printk(KERN_DEBUG "Failed to force enable HPET\n");
+		dev_printk(KERN_DEBUG, &dev->dev,
+			"Failed to force enable HPET\n");
 	} else {
 	} else {
 		force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
 		force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 	}
 	}
 }
 }
 
 
@@ -208,8 +211,8 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev)
 	if (val & 0x4) {
 	if (val & 0x4) {
 		val &= 0x3;
 		val &= 0x3;
 		force_hpet_address = 0xFED00000 | (val << 12);
 		force_hpet_address = 0xFED00000 | (val << 12);
-		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+			force_hpet_address);
 		return;
 		return;
 	}
 	}
 
 
@@ -229,14 +232,14 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev)
 		/* HPET is enabled in HPTC. Just not reported by BIOS */
 		/* HPET is enabled in HPTC. Just not reported by BIOS */
 		val &= 0x3;
 		val &= 0x3;
 		force_hpet_address = 0xFED00000 | (val << 12);
 		force_hpet_address = 0xFED00000 | (val << 12);
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 		cached_dev = dev;
 		cached_dev = dev;
 		force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
 		force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
 		return;
 		return;
 	}
 	}
 
 
-	printk(KERN_DEBUG "Failed to force enable HPET\n");
+	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
 }
 }
 
 
 /*
 /*
@@ -294,8 +297,8 @@ static void vt8237_force_enable_hpet(struct pci_dev *dev)
 	 */
 	 */
 	if (val & 0x80) {
 	if (val & 0x80) {
 		force_hpet_address = (val & ~0x3ff);
 		force_hpet_address = (val & ~0x3ff);
-		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+			force_hpet_address);
 		return;
 		return;
 	}
 	}
 
 
@@ -309,14 +312,14 @@ static void vt8237_force_enable_hpet(struct pci_dev *dev)
 	pci_read_config_dword(dev, 0x68, &val);
 	pci_read_config_dword(dev, 0x68, &val);
 	if (val & 0x80) {
 	if (val & 0x80) {
 		force_hpet_address = (val & ~0x3ff);
 		force_hpet_address = (val & ~0x3ff);
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 		cached_dev = dev;
 		cached_dev = dev;
 		force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
 		force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
 		return;
 		return;
 	}
 	}
 
 
-	printk(KERN_DEBUG "Failed to force enable HPET\n");
+	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
 }
 }
 
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
@@ -344,7 +347,7 @@ static void nvidia_force_enable_hpet(struct pci_dev *dev)
 	pci_read_config_dword(dev, 0x44, &val);
 	pci_read_config_dword(dev, 0x44, &val);
 	force_hpet_address = val & 0xfffffffe;
 	force_hpet_address = val & 0xfffffffe;
 	force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
 	force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
-	printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
 		force_hpet_address);
 		force_hpet_address);
 	cached_dev = dev;
 	cached_dev = dev;
 	return;
 	return;

+ 11 - 11
arch/x86/pci/fixup.c

@@ -17,7 +17,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
 	int pxb, reg;
 	int pxb, reg;
 	u8 busno, suba, subb;
 	u8 busno, suba, subb;
 
 
-	printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
+	dev_warn(&d->dev, "Searching for i450NX host bridges\n");
 	reg = 0xd0;
 	reg = 0xd0;
 	for(pxb = 0; pxb < 2; pxb++) {
 	for(pxb = 0; pxb < 2; pxb++) {
 		pci_read_config_byte(d, reg++, &busno);
 		pci_read_config_byte(d, reg++, &busno);
@@ -41,7 +41,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)
 	 */
 	 */
 	u8 busno;
 	u8 busno;
 	pci_read_config_byte(d, 0x4a, &busno);
 	pci_read_config_byte(d, 0x4a, &busno);
-	printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
+	dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno);
 	pci_scan_bus_with_sysdata(busno);
 	pci_scan_bus_with_sysdata(busno);
 	pcibios_last_bus = -1;
 	pcibios_last_bus = -1;
 }
 }
@@ -55,7 +55,7 @@ static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
 	 */
 	 */
 	int i;
 	int i;
 
 
-	printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d));
+	dev_warn(&d->dev, "Fixing base address flags\n");
 	for(i = 0; i < 4; i++)
 	for(i = 0; i < 4; i++)
 		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 }
 }
@@ -68,7 +68,7 @@ static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
 	 * Fix class to be PCI_CLASS_STORAGE_SCSI
 	 * Fix class to be PCI_CLASS_STORAGE_SCSI
 	 */
 	 */
 	if (!d->class) {
 	if (!d->class) {
-		printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d));
+		dev_warn(&d->dev, "Fixing NCR 53C810 class code\n");
 		d->class = PCI_CLASS_STORAGE_SCSI << 8;
 		d->class = PCI_CLASS_STORAGE_SCSI << 8;
 	}
 	}
 }
 }
@@ -80,7 +80,7 @@ static void __devinit  pci_fixup_latency(struct pci_dev *d)
 	 *  SiS 5597 and 5598 chipsets require latency timer set to
 	 *  SiS 5597 and 5598 chipsets require latency timer set to
 	 *  at most 32 to avoid lockups.
 	 *  at most 32 to avoid lockups.
 	 */
 	 */
-	DBG("PCI: Setting max latency to 32\n");
+	dev_dbg(&d->dev, "Setting max latency to 32\n");
 	pcibios_max_latency = 32;
 	pcibios_max_latency = 32;
 }
 }
 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_5597, pci_fixup_latency);
@@ -138,7 +138,7 @@ static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
 
 
 	pci_read_config_byte(d, where, &v);
 	pci_read_config_byte(d, where, &v);
 	if (v & ~mask) {
 	if (v & ~mask) {
-		printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
+		dev_warn(&d->dev, "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
 			d->device, d->revision, where, v, mask, v & mask);
 			d->device, d->revision, where, v, mask, v & mask);
 		v &= mask;
 		v &= mask;
 		pci_write_config_byte(d, where, v);
 		pci_write_config_byte(d, where, v);
@@ -200,7 +200,7 @@ static void pci_fixup_nforce2(struct pci_dev *dev)
 	 * Apply fixup if needed, but don't touch disconnect state
 	 * Apply fixup if needed, but don't touch disconnect state
 	 */
 	 */
 	if ((val & 0x00FF0000) != 0x00010000) {
 	if ((val & 0x00FF0000) != 0x00010000) {
-		printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
+		dev_warn(&dev->dev, "nForce2 C1 Halt Disconnect fixup\n");
 		pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
 		pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
 	}
 	}
 }
 }
@@ -348,7 +348,7 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
 	pci_read_config_word(pdev, PCI_COMMAND, &config);
 	pci_read_config_word(pdev, PCI_COMMAND, &config);
 	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
 	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
 		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
 		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-		printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
+		dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
 	}
 	}
 }
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
@@ -388,11 +388,11 @@ static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)
 		/* verify the change for status output */
 		/* verify the change for status output */
 		pci_read_config_byte(dev, 0x50, &val);
 		pci_read_config_byte(dev, 0x50, &val);
 		if (val & 0x40)
 		if (val & 0x40)
-			printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
+			dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
 					"can't enable onboard soundcard!\n");
 					"can't enable onboard soundcard!\n");
 		else
 		else
-			printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
-					"enabled onboard soundcard.\n");
+			dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
+					"enabled onboard soundcard\n");
 	}
 	}
 }
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,

+ 0 - 5
arch/xtensa/Kconfig

@@ -174,11 +174,6 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 	  VESA. If you have PCI, say Y, otherwise N.
 
 
-	  The PCI-HOWTO, available from
-	  <http://www.linuxdoc.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't
-
 source "drivers/pci/Kconfig"
 source "drivers/pci/Kconfig"
 
 
 config HOTPLUG
 config HOTPLUG

+ 1 - 1
drivers/ata/pata_cs5520.c

@@ -229,7 +229,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	/* Perform set up for DMA */
 	/* Perform set up for DMA */
-	if (pci_enable_device_bars(pdev, 1<<2)) {
+	if (pci_enable_device_io(pdev)) {
 		printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
 		printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}

+ 1 - 1
drivers/i2c/busses/scx200_acb.c

@@ -492,7 +492,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
 	iface->pdev = pdev;
 	iface->pdev = pdev;
 	iface->bar = bar;
 	iface->bar = bar;
 
 
-	rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+	rc = pci_enable_device_io(iface->pdev);
 	if (rc)
 	if (rc)
 		goto errout_free;
 		goto errout_free;
 
 

+ 8 - 2
drivers/ide/pci/cs5520.c

@@ -156,8 +156,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
 	ide_setup_pci_noise(dev, d);
 	ide_setup_pci_noise(dev, d);
 
 
 	/* We must not grab the entire device, it has 'ISA' space in its
 	/* We must not grab the entire device, it has 'ISA' space in its
-	   BARS too and we will freak out other bits of the kernel */
-	if (pci_enable_device_bars(dev, 1<<2)) {
+	 * BARS too and we will freak out other bits of the kernel
+	 *
+	 * pci_enable_device_bars() is going away. I replaced it with
+	 * IO only enable for now but I'll need confirmation this is
+	 * allright for that device. If not, it will need some kind of
+	 * quirk. --BenH.
+	 */
+	if (pci_enable_device_io(dev)) {
 		printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
 		printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}

+ 4 - 2
drivers/ide/setup-pci.c

@@ -228,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
  *	@d: IDE port info
  *	@d: IDE port info
  *
  *
  *	Enable the IDE PCI device. We attempt to enable the device in full
  *	Enable the IDE PCI device. We attempt to enable the device in full
- *	but if that fails then we only need BAR4 so we will enable that.
+ *	but if that fails then we only need IO space. The PCI code should
+ *	have setup the proper resources for us already for controllers in
+ *	legacy mode.
  *	
  *	
  *	Returns zero on success or an error code
  *	Returns zero on success or an error code
  */
  */
@@ -238,7 +240,7 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
 	int ret;
 	int ret;
 
 
 	if (pci_enable_device(dev)) {
 	if (pci_enable_device(dev)) {
-		ret = pci_enable_device_bars(dev, 1 << 4);
+		ret = pci_enable_device_io(dev);
 		if (ret < 0) {
 		if (ret < 0) {
 			printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
 			printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
 				"Could not enable device.\n", d->name);
 				"Could not enable device.\n", d->name);

+ 13 - 5
drivers/pci/bus.c

@@ -108,6 +108,7 @@ int pci_bus_add_device(struct pci_dev *dev)
 void pci_bus_add_devices(struct pci_bus *bus)
 void pci_bus_add_devices(struct pci_bus *bus)
 {
 {
 	struct pci_dev *dev;
 	struct pci_dev *dev;
+	struct pci_bus *child_bus;
 	int retval;
 	int retval;
 
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 	list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -138,11 +139,19 @@ void pci_bus_add_devices(struct pci_bus *bus)
 			       up_write(&pci_bus_sem);
 			       up_write(&pci_bus_sem);
 			}
 			}
 			pci_bus_add_devices(dev->subordinate);
 			pci_bus_add_devices(dev->subordinate);
-			retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
-						   &dev->dev.kobj, "bridge");
+
+			/* register the bus with sysfs as the parent is now
+			 * properly registered. */
+			child_bus = dev->subordinate;
+			child_bus->dev.parent = child_bus->bridge;
+			retval = device_register(&child_bus->dev);
+			if (!retval)
+				retval = device_create_file(&child_bus->dev,
+							&dev_attr_cpuaffinity);
 			if (retval)
 			if (retval)
-				dev_err(&dev->dev, "Error creating sysfs "
-					"bridge symlink, continuing...\n");
+				dev_err(&dev->dev, "Error registering pci_bus"
+					" device bridge symlink,"
+					" continuing...\n");
 		}
 		}
 	}
 	}
 }
 }
@@ -204,7 +213,6 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 	}
 	}
 	up_read(&pci_bus_sem);
 	up_read(&pci_bus_sem);
 }
 }
-EXPORT_SYMBOL_GPL(pci_walk_bus);
 
 
 EXPORT_SYMBOL(pci_bus_alloc_resource);
 EXPORT_SYMBOL(pci_bus_alloc_resource);
 EXPORT_SYMBOL_GPL(pci_bus_add_device);
 EXPORT_SYMBOL_GPL(pci_bus_add_device);

+ 17 - 3
drivers/pci/dmar.c

@@ -25,6 +25,7 @@
 
 
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/dmar.h>
 #include <linux/dmar.h>
+#include "iova.h"
 
 
 #undef PREFIX
 #undef PREFIX
 #define PREFIX "DMAR:"
 #define PREFIX "DMAR:"
@@ -263,8 +264,8 @@ parse_dmar_table(void)
 	if (!dmar)
 	if (!dmar)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	if (!dmar->width) {
-		printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
+	if (dmar->width < PAGE_SHIFT_4K - 1) {
+		printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
@@ -301,11 +302,24 @@ parse_dmar_table(void)
 int __init dmar_table_init(void)
 int __init dmar_table_init(void)
 {
 {
 
 
-	parse_dmar_table();
+	int ret;
+
+	ret = parse_dmar_table();
+	if (ret) {
+		printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+		return ret;
+	}
+
 	if (list_empty(&dmar_drhd_units)) {
 	if (list_empty(&dmar_drhd_units)) {
 		printk(KERN_INFO PREFIX "No DMAR devices found\n");
 		printk(KERN_INFO PREFIX "No DMAR devices found\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
+
+	if (list_empty(&dmar_rmrr_units)) {
+		printk(KERN_INFO PREFIX "No RMRR found\n");
+		return -ENODEV;
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 2 - 2
drivers/pci/hotplug/Kconfig

@@ -3,8 +3,8 @@
 #
 #
 
 
 menuconfig HOTPLUG_PCI
 menuconfig HOTPLUG_PCI
-	tristate "Support for PCI Hotplug (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL && HOTPLUG
+	tristate "Support for PCI Hotplug"
+	depends on PCI && HOTPLUG
 	---help---
 	---help---
 	  Say Y here if you have a motherboard with a PCI Hotplug controller.
 	  Say Y here if you have a motherboard with a PCI Hotplug controller.
 	  This allows you to add and remove PCI cards while the machine is
 	  This allows you to add and remove PCI cards while the machine is

+ 3 - 1
drivers/pci/hotplug/Makefile

@@ -3,7 +3,6 @@
 #
 #
 
 
 obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
 obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o 
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
@@ -16,6 +15,9 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA)		+= rpaphp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)	+= rpadlpar_io.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)	+= rpadlpar_io.o
 obj-$(CONFIG_HOTPLUG_PCI_SGI)		+= sgi_hotplug.o
 obj-$(CONFIG_HOTPLUG_PCI_SGI)		+= sgi_hotplug.o
 
 
+# Link this last so it doesn't claim devices that have a real hotplug driver
+obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o
+
 pci_hotplug-objs	:=	pci_hotplug_core.o
 pci_hotplug-objs	:=	pci_hotplug_core.o
 
 
 ifdef CONFIG_HOTPLUG_PCI_CPCI
 ifdef CONFIG_HOTPLUG_PCI_CPCI

+ 0 - 1
drivers/pci/hotplug/acpiphp.h

@@ -113,7 +113,6 @@ struct acpiphp_slot {
 	u8		device;		/* pci device# */
 	u8		device;		/* pci device# */
 
 
 	u32		sun;		/* ACPI _SUN (slot unique number) */
 	u32		sun;		/* ACPI _SUN (slot unique number) */
-	u32		slotno;		/* slot number relative to bridge */
 	u32		flags;		/* see below */
 	u32		flags;		/* see below */
 };
 };
 
 

+ 2 - 3
drivers/pci/hotplug/acpiphp_glue.c

@@ -102,7 +102,7 @@ static int is_ejectable(acpi_handle handle)
 }
 }
 
 
 
 
-/* callback routine to check the existence of ejectable slots */
+/* callback routine to check for the existence of ejectable slots */
 static acpi_status
 static acpi_status
 is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 {
@@ -117,7 +117,7 @@ is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 	}
 	}
 }
 }
 
 
-/* callback routine to check for the existance of a pci dock device */
+/* callback routine to check for the existence of a pci dock device */
 static acpi_status
 static acpi_status
 is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
 is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 {
@@ -1528,7 +1528,6 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
 		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 		dbg("%s: re-enumerating slots under %s\n",
 		dbg("%s: re-enumerating slots under %s\n",
 			__FUNCTION__, objname);
 			__FUNCTION__, objname);
-		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 		acpiphp_check_bridge(bridge);
 		acpiphp_check_bridge(bridge);
 	}
 	}
 	return AE_OK ;
 	return AE_OK ;

+ 35 - 4
drivers/pci/hotplug/fakephp.c

@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include "../pci.h"
 #include "../pci.h"
 
 
 #if !defined(MODULE)
 #if !defined(MODULE)
@@ -63,10 +64,16 @@ struct dummy_slot {
 	struct list_head node;
 	struct list_head node;
 	struct hotplug_slot *slot;
 	struct hotplug_slot *slot;
 	struct pci_dev *dev;
 	struct pci_dev *dev;
+	struct work_struct remove_work;
+	unsigned long removed;
 };
 };
 
 
 static int debug;
 static int debug;
 static LIST_HEAD(slot_list);
 static LIST_HEAD(slot_list);
+static struct workqueue_struct *dummyphp_wq;
+
+static void pci_rescan_worker(struct work_struct *work);
+static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
 
 
 static int enable_slot (struct hotplug_slot *slot);
 static int enable_slot (struct hotplug_slot *slot);
 static int disable_slot (struct hotplug_slot *slot);
 static int disable_slot (struct hotplug_slot *slot);
@@ -109,7 +116,7 @@ static int add_slot(struct pci_dev *dev)
 	slot->name = &dev->dev.bus_id[0];
 	slot->name = &dev->dev.bus_id[0];
 	dbg("slot->name = %s\n", slot->name);
 	dbg("slot->name = %s\n", slot->name);
 
 
-	dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
+	dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
 	if (!dslot)
 	if (!dslot)
 		goto error_info;
 		goto error_info;
 
 
@@ -164,6 +171,14 @@ static void remove_slot(struct dummy_slot *dslot)
 		err("Problem unregistering a slot %s\n", dslot->slot->name);
 		err("Problem unregistering a slot %s\n", dslot->slot->name);
 }
 }
 
 
+/* called from the single-threaded workqueue handler to remove a slot */
+static void remove_slot_worker(struct work_struct *work)
+{
+	struct dummy_slot *dslot =
+		container_of(work, struct dummy_slot, remove_work);
+	remove_slot(dslot);
+}
+
 /**
 /**
  * pci_rescan_slot - Rescan slot
  * pci_rescan_slot - Rescan slot
  * @temp: Device template. Should be set: bus and devfn.
  * @temp: Device template. Should be set: bus and devfn.
@@ -267,11 +282,17 @@ static inline void pci_rescan(void) {
 	pci_rescan_buses(&pci_root_buses);
 	pci_rescan_buses(&pci_root_buses);
 }
 }
 
 
+/* called from the single-threaded workqueue handler to rescan all pci buses */
+static void pci_rescan_worker(struct work_struct *work)
+{
+	pci_rescan();
+}
 
 
 static int enable_slot(struct hotplug_slot *hotplug_slot)
 static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
 {
 	/* mis-use enable_slot for rescanning of the pci bus */
 	/* mis-use enable_slot for rescanning of the pci bus */
-	pci_rescan();
+	cancel_work_sync(&pci_rescan_work);
+	queue_work(dummyphp_wq, &pci_rescan_work);
 	return -ENODEV;
 	return -ENODEV;
 }
 }
 
 
@@ -306,6 +327,10 @@ static int disable_slot(struct hotplug_slot *slot)
 		err("Can't remove PCI devices with other PCI devices behind it yet.\n");
 		err("Can't remove PCI devices with other PCI devices behind it yet.\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
+	if (test_and_set_bit(0, &dslot->removed)) {
+		dbg("Slot already scheduled for removal\n");
+		return -ENODEV;
+	}
 	/* search for subfunctions and disable them first */
 	/* search for subfunctions and disable them first */
 	if (!(dslot->dev->devfn & 7)) {
 	if (!(dslot->dev->devfn & 7)) {
 		for (func = 1; func < 8; func++) {
 		for (func = 1; func < 8; func++) {
@@ -328,8 +353,9 @@ static int disable_slot(struct hotplug_slot *slot)
 	/* remove the device from the pci core */
 	/* remove the device from the pci core */
 	pci_remove_bus_device(dslot->dev);
 	pci_remove_bus_device(dslot->dev);
 
 
-	/* blow away this sysfs entry and other parts. */
-	remove_slot(dslot);
+	/* queue work item to blow away this sysfs entry and other parts. */
+	INIT_WORK(&dslot->remove_work, remove_slot_worker);
+	queue_work(dummyphp_wq, &dslot->remove_work);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -340,6 +366,7 @@ static void cleanup_slots (void)
 	struct list_head *next;
 	struct list_head *next;
 	struct dummy_slot *dslot;
 	struct dummy_slot *dslot;
 
 
+	destroy_workqueue(dummyphp_wq);
 	list_for_each_safe (tmp, next, &slot_list) {
 	list_for_each_safe (tmp, next, &slot_list) {
 		dslot = list_entry (tmp, struct dummy_slot, node);
 		dslot = list_entry (tmp, struct dummy_slot, node);
 		remove_slot(dslot);
 		remove_slot(dslot);
@@ -351,6 +378,10 @@ static int __init dummyphp_init(void)
 {
 {
 	info(DRIVER_DESC "\n");
 	info(DRIVER_DESC "\n");
 
 
+	dummyphp_wq = create_singlethread_workqueue(MY_NAME);
+	if (!dummyphp_wq)
+		return -ENOMEM;
+
 	return pci_scan_buses();
 	return pci_scan_buses();
 }
 }
 
 

+ 7 - 4
drivers/pci/hotplug/ibmphp_core.c

@@ -761,10 +761,13 @@ static void ibm_unconfigure_device(struct pci_func *func)
 	debug("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);
 	debug("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);
 
 
 	for (j = 0; j < 0x08; j++) {
 	for (j = 0; j < 0x08; j++) {
-		temp = pci_find_slot(func->busno, (func->device << 3) | j);
-		if (temp)
+		temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
+		if (temp) {
 			pci_remove_bus_device(temp);
 			pci_remove_bus_device(temp);
+			pci_dev_put(temp);
+		}
 	}
 	}
+	pci_dev_put(func->dev);
 }
 }
 
 
 /*
 /*
@@ -823,7 +826,7 @@ static int ibm_configure_device(struct pci_func *func)
 	if (!(bus_structure_fixup(func->busno)))
 	if (!(bus_structure_fixup(func->busno)))
 		flag = 1;
 		flag = 1;
 	if (func->dev == NULL)
 	if (func->dev == NULL)
-		func->dev = pci_find_slot(func->busno,
+		func->dev = pci_get_bus_and_slot(func->busno,
 				PCI_DEVFN(func->device, func->function));
 				PCI_DEVFN(func->device, func->function));
 
 
 	if (func->dev == NULL) {
 	if (func->dev == NULL) {
@@ -836,7 +839,7 @@ static int ibm_configure_device(struct pci_func *func)
 		if (num)
 		if (num)
 			pci_bus_add_devices(bus);
 			pci_bus_add_devices(bus);
 
 
-		func->dev = pci_find_slot(func->busno,
+		func->dev = pci_get_bus_and_slot(func->busno,
 				PCI_DEVFN(func->device, func->function));
 				PCI_DEVFN(func->device, func->function));
 		if (func->dev == NULL) {
 		if (func->dev == NULL) {
 			err("ERROR... : pci_dev still NULL\n");
 			err("ERROR... : pci_dev still NULL\n");

+ 2 - 2
drivers/pci/hotplug/pci_hotplug_core.c

@@ -137,7 +137,7 @@ static int get_##name (struct hotplug_slot *slot, type *value)		\
 	int retval = 0;							\
 	int retval = 0;							\
 	if (try_module_get(ops->owner)) {				\
 	if (try_module_get(ops->owner)) {				\
 		if (ops->get_##name)					\
 		if (ops->get_##name)					\
-			retval = ops->get_##name (slot, value);		\
+			retval = ops->get_##name(slot, value);		\
 		else							\
 		else							\
 			*value = slot->info->name;			\
 			*value = slot->info->name;			\
 		module_put(ops->owner);					\
 		module_put(ops->owner);					\
@@ -625,7 +625,7 @@ int pci_hp_register (struct hotplug_slot *slot)
 	if ((slot->info == NULL) || (slot->ops == NULL))
 	if ((slot->info == NULL) || (slot->ops == NULL))
 		return -EINVAL;
 		return -EINVAL;
 	if (slot->release == NULL) {
 	if (slot->release == NULL) {
-		dbg("Why are you trying to register a hotplug slot"
+		dbg("Why are you trying to register a hotplug slot "
 		    "without a proper release function?\n");
 		    "without a proper release function?\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}

+ 3 - 6
drivers/pci/hotplug/pciehp.h

@@ -82,24 +82,18 @@ struct event_info {
 };
 };
 
 
 struct controller {
 struct controller {
-	struct controller *next;
 	struct mutex crit_sect;		/* critical section mutex */
 	struct mutex crit_sect;		/* critical section mutex */
 	struct mutex ctrl_lock;		/* controller lock */
 	struct mutex ctrl_lock;		/* controller lock */
 	int num_slots;			/* Number of slots on ctlr */
 	int num_slots;			/* Number of slots on ctlr */
 	int slot_num_inc;		/* 1 or -1 */
 	int slot_num_inc;		/* 1 or -1 */
 	struct pci_dev *pci_dev;
 	struct pci_dev *pci_dev;
 	struct list_head slot_list;
 	struct list_head slot_list;
-	struct slot *slot;
 	struct hpc_ops *hpc_ops;
 	struct hpc_ops *hpc_ops;
 	wait_queue_head_t queue;	/* sleep & wake process */
 	wait_queue_head_t queue;	/* sleep & wake process */
-	u8 bus;
-	u8 device;
-	u8 function;
 	u8 slot_device_offset;
 	u8 slot_device_offset;
 	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
 	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
 	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
 	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
 	u8 ctrlcap;
 	u8 ctrlcap;
-	u16 vendor_id;
 	u8 cap_base;
 	u8 cap_base;
 	struct timer_list poll_timer;
 	struct timer_list poll_timer;
 	volatile int cmd_busy;
 	volatile int cmd_busy;
@@ -161,6 +155,9 @@ extern int pciehp_configure_device(struct slot *p_slot);
 extern int pciehp_unconfigure_device(struct slot *p_slot);
 extern int pciehp_unconfigure_device(struct slot *p_slot);
 extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 int pcie_init(struct controller *ctrl, struct pcie_device *dev);
 int pcie_init(struct controller *ctrl, struct pcie_device *dev);
+int pciehp_enable_slot(struct slot *p_slot);
+int pciehp_disable_slot(struct slot *p_slot);
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev);
 
 
 static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
 static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
 {
 {

+ 26 - 7
drivers/pci/hotplug/pciehp_core.c

@@ -453,13 +453,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 
 
 	pci_set_drvdata(pdev, ctrl);
 	pci_set_drvdata(pdev, ctrl);
 
 
-	ctrl->bus = pdev->bus->number;  /* ctrl bus */
-	ctrl->slot_bus = pdev->subordinate->number;  /* bus controlled by this HPC */
-
-	ctrl->device = PCI_SLOT(pdev->devfn);
-	ctrl->function = PCI_FUNC(pdev->devfn);
-	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
-		ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+	    __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+	    PCI_FUNC(pdev->devfn), pdev->irq);
 
 
 	/* Setup the slot information structures */
 	/* Setup the slot information structures */
 	rc = init_slots(ctrl);
 	rc = init_slots(ctrl);
@@ -471,6 +467,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 
 
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+	if (value) {
+		rc = pciehp_enable_slot(t_slot);
+		if (rc)	/* -ENODEV: shouldn't happen, but deal with it */
+			value = 0;
+	}
 	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
 	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		if (rc)
 		if (rc)
@@ -509,6 +510,24 @@ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
 static int pciehp_resume (struct pcie_device *dev)
 static int pciehp_resume (struct pcie_device *dev)
 {
 {
 	printk("%s ENTRY\n", __FUNCTION__);
 	printk("%s ENTRY\n", __FUNCTION__);
+	if (pciehp_force) {
+		struct pci_dev *pdev = dev->port;
+		struct controller *ctrl = pci_get_drvdata(pdev);
+		struct slot *t_slot;
+		u8 status;
+
+		/* reinitialize the chipset's event detection logic */
+		pcie_init_hardware_part2(ctrl, dev);
+
+		t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
+
+		/* Check if slot is occupied */
+		t_slot->hpc_ops->get_adapter_status(t_slot, &status);
+		if (status)
+			pciehp_enable_slot(t_slot);
+		else
+			pciehp_disable_slot(t_slot);
+	}
 	return 0;
 	return 0;
 }
 }
 #endif
 #endif

+ 2 - 25
drivers/pci/hotplug/pciehp_ctrl.c

@@ -37,8 +37,6 @@
 #include "pciehp.h"
 #include "pciehp.h"
 
 
 static void interrupt_event_handler(struct work_struct *work);
 static void interrupt_event_handler(struct work_struct *work);
-static int pciehp_enable_slot(struct slot *p_slot);
-static int pciehp_disable_slot(struct slot *p_slot);
 
 
 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
 {
 {
@@ -197,12 +195,6 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 			    __FUNCTION__);
 			    __FUNCTION__);
 			return;
 			return;
 		}
 		}
-		/*
-		 * After turning power off, we must wait for at least
-		 * 1 second before taking any action that relies on
-		 * power having been removed from the slot/adapter.
-		 */
-		msleep(1000);
 	}
 	}
 }
 }
 
 
@@ -215,15 +207,12 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
  */
  */
 static int board_added(struct slot *p_slot)
 static int board_added(struct slot *p_slot)
 {
 {
-	u8 hp_slot;
 	int retval = 0;
 	int retval = 0;
 	struct controller *ctrl = p_slot->ctrl;
 	struct controller *ctrl = p_slot->ctrl;
 
 
-	hp_slot = p_slot->device - ctrl->slot_device_offset;
-
 	dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
 	dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
 			__FUNCTION__, p_slot->device,
 			__FUNCTION__, p_slot->device,
-			ctrl->slot_device_offset, hp_slot);
+			ctrl->slot_device_offset, p_slot->hp_slot);
 
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* Power on slot */
 		/* Power on slot */
@@ -281,8 +270,6 @@ err_exit:
  */
  */
 static int remove_board(struct slot *p_slot)
 static int remove_board(struct slot *p_slot)
 {
 {
-	u8 device;
-	u8 hp_slot;
 	int retval = 0;
 	int retval = 0;
 	struct controller *ctrl = p_slot->ctrl;
 	struct controller *ctrl = p_slot->ctrl;
 
 
@@ -290,11 +277,7 @@ static int remove_board(struct slot *p_slot)
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	device = p_slot->device;
-	hp_slot = p_slot->device - ctrl->slot_device_offset;
-	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+	dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
 
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* power off slot */
 		/* power off slot */
@@ -621,12 +604,6 @@ int pciehp_disable_slot(struct slot *p_slot)
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
-		/*
-		 * After turning power off, we must wait for at least
-		 * 1 second before taking any action that relies on
-		 * power having been removed from the slot/adapter.
-		 */
-		msleep(1000);
 	}
 	}
 
 
 	ret = remove_board(p_slot);
 	ret = remove_board(p_slot);

+ 202 - 112
drivers/pci/hotplug/pciehp_hpc.c

@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot)
 	return retval;
 	return retval;
 }
 }
 
 
+static inline int pcie_mask_bad_dllp(struct controller *ctrl)
+{
+	struct pci_dev *dev = ctrl->pci_dev;
+	int pos;
+	u32 reg;
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return 0;
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+	if (reg & PCI_ERR_COR_BAD_DLLP)
+		return 0;
+	reg |= PCI_ERR_COR_BAD_DLLP;
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+	return 1;
+}
+
+static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
+{
+	struct pci_dev *dev = ctrl->pci_dev;
+	u32 reg;
+	int pos;
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return;
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+	if (!(reg & PCI_ERR_COR_BAD_DLLP))
+		return;
+	reg &= ~PCI_ERR_COR_BAD_DLLP;
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+}
+
 static int hpc_power_off_slot(struct slot * slot)
 static int hpc_power_off_slot(struct slot * slot)
 {
 {
 	struct controller *ctrl = slot->ctrl;
 	struct controller *ctrl = slot->ctrl;
 	u16 slot_cmd;
 	u16 slot_cmd;
 	u16 cmd_mask;
 	u16 cmd_mask;
 	int retval = 0;
 	int retval = 0;
+	int changed;
 
 
 	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
 	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
 
 
+	/*
+	 * Set Bad DLLP Mask bit in Correctable Error Mask
+	 * Register. This is the workaround against Bad DLLP error
+	 * that sometimes happens during turning power off the slot
+	 * which conforms to PCI Express 1.0a spec.
+	 */
+	changed = pcie_mask_bad_dllp(ctrl);
+
 	slot_cmd = POWER_OFF;
 	slot_cmd = POWER_OFF;
 	cmd_mask = PWR_CTRL;
 	cmd_mask = PWR_CTRL;
 	/*
 	/*
@@ -674,6 +716,16 @@ static int hpc_power_off_slot(struct slot * slot)
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
 
+	/*
+	 * After turning power off, we must wait for at least 1 second
+	 * before taking any action that relies on power having been
+	 * removed from the slot/adapter.
+	 */
+	msleep(1000);
+
+	if (changed)
+		pcie_unmask_bad_dllp(ctrl);
+
 	return retval;
 	return retval;
 }
 }
 
 
@@ -1067,13 +1119,143 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 }
 }
 #endif
 #endif
 
 
-int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+static int pcie_init_hardware_part1(struct controller *ctrl,
+				    struct pcie_device *dev)
+{
+	int rc;
+	u16 temp_word;
+	u32 slot_cap;
+	u16 slot_status;
+
+	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+	if (rc) {
+		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+		return -1;
+	}
+
+	/* Mask Hot-plug Interrupt Enable */
+	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+	if (rc) {
+		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+		return -1;
+	}
+
+	dbg("%s: SLOTCTRL %x value read %x\n",
+	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
+	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+		0x00;
+
+	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+		return -1;
+	}
+
+	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+	if (rc) {
+		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+		return -1;
+	}
+
+	temp_word = 0x1F; /* Clear all events */
+	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+		return -1;
+	}
+	return 0;
+}
+
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
 {
 {
 	int rc;
 	int rc;
 	u16 temp_word;
 	u16 temp_word;
-	u16 cap_reg;
 	u16 intr_enable = 0;
 	u16 intr_enable = 0;
 	u32 slot_cap;
 	u32 slot_cap;
+	u16 slot_status;
+
+	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+	if (rc) {
+		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+		goto abort;
+	}
+
+	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+	if (rc) {
+		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+		goto abort;
+	}
+
+	if (ATTN_BUTTN(slot_cap))
+		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
+
+	if (POWER_CTRL(slot_cap))
+		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
+
+	if (MRL_SENS(slot_cap))
+		intr_enable = intr_enable | MRL_DETECT_ENABLE;
+
+	temp_word = (temp_word & ~intr_enable) | intr_enable;
+
+	if (pciehp_poll_mode) {
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
+	} else {
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+	}
+
+	/*
+	 * Unmask Hot-plug Interrupt Enable for the interrupt
+	 * notification mechanism case.
+	 */
+	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+		goto abort;
+	}
+	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+	if (rc) {
+		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+		goto abort_disable_intr;
+	}
+
+	temp_word =  0x1F; /* Clear all events */
+	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+		goto abort_disable_intr;
+	}
+
+	if (pciehp_force) {
+		dbg("Bypassing BIOS check for pciehp use on %s\n",
+				pci_name(ctrl->pci_dev));
+	} else {
+		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
+		if (rc)
+			goto abort_disable_intr;
+	}
+
+	return 0;
+
+	/* We end up here for the many possible ways to fail this API. */
+abort_disable_intr:
+	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+	if (!rc) {
+		temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+	}
+	if (rc)
+		err("%s : disabling interrupts failed\n", __FUNCTION__);
+abort:
+	return -1;
+}
+
+int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+{
+	int rc;
+	u16 cap_reg;
+	u32 slot_cap;
 	int cap_base;
 	int cap_base;
 	u16 slot_status, slot_ctrl;
 	u16 slot_status, slot_ctrl;
 	struct pci_dev *pdev;
 	struct pci_dev *pdev;
@@ -1084,9 +1266,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
 	dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
 			__FUNCTION__, pdev->vendor, pdev->device);
 			__FUNCTION__, pdev->vendor, pdev->device);
 
 
-	if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
+	cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	if (cap_base == 0) {
 		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
 		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	}
 
 
 	ctrl->cap_base = cap_base;
 	ctrl->cap_base = cap_base;
@@ -1096,7 +1279,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
 	rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
 	if (rc) {
 	if (rc) {
 		err("%s: Cannot read CAPREG register\n", __FUNCTION__);
 		err("%s: Cannot read CAPREG register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	}
 	dbg("%s: CAPREG offset %x cap_reg %x\n",
 	dbg("%s: CAPREG offset %x cap_reg %x\n",
 	    __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
 	    __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
@@ -1106,26 +1289,26 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 		&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
 		&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
 		dbg("%s : This is not a root port or the port is not "
 		dbg("%s : This is not a root port or the port is not "
 		    "connected to a slot\n", __FUNCTION__);
 		    "connected to a slot\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	}
 
 
 	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
 	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
 	if (rc) {
 	if (rc) {
 		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
 		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	}
 	dbg("%s: SLOTCAP offset %x slot_cap %x\n",
 	dbg("%s: SLOTCAP offset %x slot_cap %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
 	    __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
 
 
 	if (!(slot_cap & HP_CAP)) {
 	if (!(slot_cap & HP_CAP)) {
 		dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
 		dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	}
 	/* For debugging purpose */
 	/* For debugging purpose */
 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
 	if (rc) {
 	if (rc) {
 		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
 		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	}
 	dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
 	dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
 	    __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
@@ -1133,7 +1316,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
 	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
 	if (rc) {
 	if (rc) {
 		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
 		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	}
 	dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
 	dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
@@ -1161,36 +1344,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	ctrl->first_slot = slot_cap >> 19;
 	ctrl->first_slot = slot_cap >> 19;
 	ctrl->ctrlcap = slot_cap & 0x0000007f;
 	ctrl->ctrlcap = slot_cap & 0x0000007f;
 
 
-	/* Mask Hot-plug Interrupt Enable */
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	dbg("%s: SLOTCTRL %x value read %x\n",
-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
-	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
-		0x00;
-
-	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	temp_word = 0x1F; /* Clear all events */
-	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
+	rc = pcie_init_hardware_part1(ctrl, dev);
+	if (rc)
+		goto abort;
 
 
 	if (pciehp_poll_mode) {
 	if (pciehp_poll_mode) {
 		/* Install interrupt polling timer. Start with 10 sec delay */
 		/* Install interrupt polling timer. Start with 10 sec delay */
@@ -1206,7 +1362,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 		if (rc) {
 		if (rc) {
 			err("Can't get irq %d for the hotplug controller\n",
 			err("Can't get irq %d for the hotplug controller\n",
 			    ctrl->pci_dev->irq);
 			    ctrl->pci_dev->irq);
-			goto abort_free_ctlr;
+			goto abort;
 		}
 		}
 	}
 	}
 	dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
 	dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
@@ -1224,82 +1380,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 		}
 		}
 	}
 	}
 
 
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_irq;
+	rc = pcie_init_hardware_part2(ctrl, dev);
+	if (rc == 0) {
+		ctrl->hpc_ops = &pciehp_hpc_ops;
+		return 0;
 	}
 	}
-
-	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
-	if (ATTN_BUTTN(slot_cap))
-		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-
-	if (POWER_CTRL(slot_cap))
-		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-
-	if (MRL_SENS(slot_cap))
-		intr_enable = intr_enable | MRL_DETECT_ENABLE;
-
-	temp_word = (temp_word & ~intr_enable) | intr_enable;
-
-	if (pciehp_poll_mode) {
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
-	} else {
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
-	}
-
-	/*
-	 * Unmask Hot-plug Interrupt Enable for the interrupt
-	 * notification mechanism case.
-	 */
-	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_irq;
-	}
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_disable_intr;
-	}
-
-	temp_word =  0x1F; /* Clear all events */
-	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_disable_intr;
-	}
-
-	if (pciehp_force) {
-		dbg("Bypassing BIOS check for pciehp use on %s\n",
-				pci_name(ctrl->pci_dev));
-	} else {
-		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
-		if (rc)
-			goto abort_disable_intr;
-	}
-
-	ctrl->hpc_ops = &pciehp_hpc_ops;
-
-	return 0;
-
-	/* We end up here for the many possible ways to fail this API. */
-abort_disable_intr:
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (!rc) {
-		temp_word &= ~(intr_enable | HP_INTR_ENABLE);
-		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	}
-	if (rc)
-		err("%s : disabling interrupts failed\n", __FUNCTION__);
-
 abort_free_irq:
 abort_free_irq:
 	if (pciehp_poll_mode)
 	if (pciehp_poll_mode)
 		del_timer_sync(&ctrl->poll_timer);
 		del_timer_sync(&ctrl->poll_timer);
 	else
 	else
 		free_irq(ctrl->pci_dev->irq, ctrl);
 		free_irq(ctrl->pci_dev->irq, ctrl);
-
-abort_free_ctlr:
+abort:
 	return -1;
 	return -1;
 }
 }

+ 23 - 20
drivers/pci/hotplug/pciehp_pci.c

@@ -105,12 +105,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
 	}
 	}
 
 
 	/* Find Advanced Error Reporting Enhanced Capability */
 	/* Find Advanced Error Reporting Enhanced Capability */
-	pos = 256;
-	do {
-		pci_read_config_dword(dev, pos, &reg32);
-		if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
-			break;
-	} while ((pos = PCI_EXT_CAP_NEXT(reg32)));
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
 	if (!pos)
 	if (!pos)
 		return;
 		return;
 
 
@@ -248,11 +243,15 @@ int pciehp_unconfigure_device(struct slot *p_slot)
 	u8 bctl = 0;
 	u8 bctl = 0;
 	u8 presence = 0;
 	u8 presence = 0;
 	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+	u16 command;
 
 
 	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
 	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
 				p_slot->device);
 				p_slot->device);
+	ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
+	if (ret)
+		presence = 0;
 
 
-	for (j=0; j<8 ; j++) {
+	for (j = 0; j < 8; j++) {
 		struct pci_dev* temp = pci_get_slot(parent,
 		struct pci_dev* temp = pci_get_slot(parent,
 				(p_slot->device << 3) | j);
 				(p_slot->device << 3) | j);
 		if (!temp)
 		if (!temp)
@@ -263,21 +262,26 @@ int pciehp_unconfigure_device(struct slot *p_slot)
 			pci_dev_put(temp);
 			pci_dev_put(temp);
 			continue;
 			continue;
 		}
 		}
-		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-			ret = p_slot->hpc_ops->get_adapter_status(p_slot,
-								&presence);
-			if (!ret && presence) {
-				pci_read_config_byte(temp, PCI_BRIDGE_CONTROL,
-					&bctl);
-				if (bctl & PCI_BRIDGE_CTL_VGA) {
-					err("Cannot remove display device %s\n",
-						pci_name(temp));
-					pci_dev_put(temp);
-					continue;
-				}
+		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+			pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+			if (bctl & PCI_BRIDGE_CTL_VGA) {
+				err("Cannot remove display device %s\n",
+				    pci_name(temp));
+				pci_dev_put(temp);
+				continue;
 			}
 			}
 		}
 		}
 		pci_remove_bus_device(temp);
 		pci_remove_bus_device(temp);
+		/*
+		 * Ensure that no new Requests will be generated from
+		 * the device.
+		 */
+		if (presence) {
+			pci_read_config_word(temp, PCI_COMMAND, &command);
+			command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+			command |= PCI_COMMAND_INTX_DISABLE;
+			pci_write_config_word(temp, PCI_COMMAND, command);
+		}
 		pci_dev_put(temp);
 		pci_dev_put(temp);
 	}
 	}
 	/*
 	/*
@@ -288,4 +292,3 @@ int pciehp_unconfigure_device(struct slot *p_slot)
 
 
 	return rc;
 	return rc;
 }
 }
-

+ 0 - 1
drivers/pci/hotplug/rpaphp.h

@@ -74,7 +74,6 @@ struct slot {
 	u32 type;
 	u32 type;
 	u32 power_domain;
 	u32 power_domain;
 	char *name;
 	char *name;
-	char *location;
 	struct device_node *dn;
 	struct device_node *dn;
 	struct pci_bus *bus;
 	struct pci_bus *bus;
 	struct list_head *pci_devs;
 	struct list_head *pci_devs;

+ 0 - 14
drivers/pci/hotplug/rpaphp_pci.c

@@ -64,19 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
 	return rc;
 	return rc;
 }
 }
 
 
-static void set_slot_name(struct slot *slot)
-{
-	struct pci_bus *bus = slot->bus;
-	struct pci_dev *bridge;
-
-	bridge = bus->self;
-	if (bridge)
-		strcpy(slot->name, pci_name(bridge));
-	else
-		sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
-			bus->number);
-}
-
 /**
 /**
  * rpaphp_enable_slot - record slot state, config pci device
  * rpaphp_enable_slot - record slot state, config pci device
  * @slot: target &slot
  * @slot: target &slot
@@ -115,7 +102,6 @@ int rpaphp_enable_slot(struct slot *slot)
 	info->adapter_status = EMPTY;
 	info->adapter_status = EMPTY;
 	slot->bus = bus;
 	slot->bus = bus;
 	slot->pci_devs = &bus->devices;
 	slot->pci_devs = &bus->devices;
-	set_slot_name(slot);
 
 
 	/* if there's an adapter in the slot, go add the pci devices */
 	/* if there's an adapter in the slot, go add the pci devices */
 	if (state == PRESENT) {
 	if (state == PRESENT) {

+ 24 - 23
drivers/pci/hotplug/rpaphp_slot.c

@@ -33,23 +33,31 @@
 #include <asm/rtas.h>
 #include <asm/rtas.h>
 #include "rpaphp.h"
 #include "rpaphp.h"
 
 
-static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
+static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf)
 {
 {
-	char *value;
-	int retval = -ENOENT;
+	int retval;
 	struct slot *slot = (struct slot *)php_slot->private;
 	struct slot *slot = (struct slot *)php_slot->private;
+	struct pci_bus *bus;
 
 
 	if (!slot)
 	if (!slot)
-		return retval;
+		return -ENOENT;
+
+	bus = slot->bus;
+	if (!bus)
+		return -ENOENT;
+
+	if (bus->self)
+		retval = sprintf(buf, pci_name(bus->self));
+	else
+		retval = sprintf(buf, "%04x:%02x:00.0",
+		        pci_domain_nr(bus), bus->number);
 
 
-	value = slot->location;
-	retval = sprintf (buf, "%s\n", value);
 	return retval;
 	return retval;
 }
 }
 
 
-static struct hotplug_slot_attribute php_attr_location = {
-	.attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
-	.show = location_read_file,
+static struct hotplug_slot_attribute php_attr_address = {
+	.attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
+	.show = address_read_file,
 };
 };
 
 
 /* free up the memory used by a slot */
 /* free up the memory used by a slot */
@@ -64,7 +72,6 @@ void dealloc_slot_struct(struct slot *slot)
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->name);
 	kfree(slot->hotplug_slot->name);
 	kfree(slot->hotplug_slot);
 	kfree(slot->hotplug_slot);
-	kfree(slot->location);
 	kfree(slot);
 	kfree(slot);
 }
 }
 
 
@@ -83,16 +90,13 @@ struct slot *alloc_slot_struct(struct device_node *dn,
 					   GFP_KERNEL);
 					   GFP_KERNEL);
 	if (!slot->hotplug_slot->info)
 	if (!slot->hotplug_slot->info)
 		goto error_hpslot;
 		goto error_hpslot;
-	slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
+	slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
 	if (!slot->hotplug_slot->name)
 	if (!slot->hotplug_slot->name)
 		goto error_info;	
 		goto error_info;	
-	slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
-	if (!slot->location)
-		goto error_name;
 	slot->name = slot->hotplug_slot->name;
 	slot->name = slot->hotplug_slot->name;
+	strcpy(slot->name, drc_name);
 	slot->dn = dn;
 	slot->dn = dn;
 	slot->index = drc_index;
 	slot->index = drc_index;
-	strcpy(slot->location, drc_name);
 	slot->power_domain = power_domain;
 	slot->power_domain = power_domain;
 	slot->hotplug_slot->private = slot;
 	slot->hotplug_slot->private = slot;
 	slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
 	slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
@@ -100,8 +104,6 @@ struct slot *alloc_slot_struct(struct device_node *dn,
 	
 	
 	return (slot);
 	return (slot);
 
 
-error_name:
-	kfree(slot->hotplug_slot->name);
 error_info:
 error_info:
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->info);
 error_hpslot:
 error_hpslot:
@@ -133,8 +135,8 @@ int rpaphp_deregister_slot(struct slot *slot)
 
 
 	list_del(&slot->rpaphp_slot_list);
 	list_del(&slot->rpaphp_slot_list);
 	
 	
-	/* remove "phy_location" file */
-	sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr);
+	/* remove "address" file */
+	sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr);
 
 
 	retval = pci_hp_deregister(php_slot);
 	retval = pci_hp_deregister(php_slot);
 	if (retval)
 	if (retval)
@@ -166,8 +168,8 @@ int rpaphp_register_slot(struct slot *slot)
 		return retval;
 		return retval;
 	}
 	}
 
 
-	/* create "phy_location" file */
-	retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
+	/* create "address" file */
+	retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr);
 	if (retval) {
 	if (retval) {
 		err("sysfs_create_file failed with error %d\n", retval);
 		err("sysfs_create_file failed with error %d\n", retval);
 		goto sysfs_fail;
 		goto sysfs_fail;
@@ -175,8 +177,7 @@ int rpaphp_register_slot(struct slot *slot)
 
 
 	/* add slot to our internal list */
 	/* add slot to our internal list */
 	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
 	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
-	info("Slot [%s](PCI location=%s) registered\n", slot->name,
-			slot->location);
+	info("Slot [%s] registered\n", slot->name);
 	return 0;
 	return 0;
 
 
 sysfs_fail:
 sysfs_fail:

+ 1 - 1
drivers/pci/hotplug/shpchp_hpc.c

@@ -597,7 +597,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
 	cleanup_slots(ctrl);
 	cleanup_slots(ctrl);
 
 
 	/*
 	/*
-	 * Mask SERR and System Interrut generation
+	 * Mask SERR and System Interrupt generation
 	 */
 	 */
 	serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
 	serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
 	serr_int |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
 	serr_int |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |

+ 1 - 1
drivers/pci/intel-iommu.c

@@ -1781,7 +1781,7 @@ __intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
 		/*
 		/*
 		 * First try to allocate an io virtual address in
 		 * First try to allocate an io virtual address in
 		 * DMA_32BIT_MASK and if that fails then try allocating
 		 * DMA_32BIT_MASK and if that fails then try allocating
-		 * from higer range
+		 * from higher range
 		 */
 		 */
 		iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
 		iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
 		if (!iova)
 		if (!iova)

+ 46 - 48
drivers/pci/msi.c

@@ -25,6 +25,51 @@
 
 
 static int pci_msi_enable = 1;
 static int pci_msi_enable = 1;
 
 
+/* Arch hooks */
+
+int __attribute__ ((weak))
+arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+	return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+{
+	return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	struct msi_desc *entry;
+	int ret;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		ret = arch_setup_msi_irq(dev, entry);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+{
+	return;
+}
+
+void __attribute__ ((weak))
+arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		if (entry->irq != 0)
+			arch_teardown_msi_irq(entry->irq);
+	}
+}
+
 static void msi_set_enable(struct pci_dev *dev, int enable)
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
 {
 	int pos;
 	int pos;
@@ -230,7 +275,6 @@ static void pci_intx_for_msi(struct pci_dev *dev, int enable)
 		pci_intx(dev, enable);
 		pci_intx(dev, enable);
 }
 }
 
 
-#ifdef CONFIG_PM
 static void __pci_restore_msi_state(struct pci_dev *dev)
 static void __pci_restore_msi_state(struct pci_dev *dev)
 {
 {
 	int pos;
 	int pos;
@@ -288,7 +332,7 @@ void pci_restore_msi_state(struct pci_dev *dev)
 	__pci_restore_msi_state(dev);
 	__pci_restore_msi_state(dev);
 	__pci_restore_msix_state(dev);
 	__pci_restore_msix_state(dev);
 }
 }
-#endif	/* CONFIG_PM */
+EXPORT_SYMBOL_GPL(pci_restore_msi_state);
 
 
 /**
 /**
  * msi_capability_init - configure device's MSI capability structure
  * msi_capability_init - configure device's MSI capability structure
@@ -683,49 +727,3 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
 {
 {
 	INIT_LIST_HEAD(&dev->msi_list);
 	INIT_LIST_HEAD(&dev->msi_list);
 }
 }
-
-
-/* Arch hooks */
-
-int __attribute__ ((weak))
-arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
-{
-	return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
-{
-	return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	struct msi_desc *entry;
-	int ret;
-
-	list_for_each_entry(entry, &dev->msi_list, list) {
-		ret = arch_setup_msi_irq(dev, entry);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
-{
-	return;
-}
-
-void __attribute__ ((weak))
-arch_teardown_msi_irqs(struct pci_dev *dev)
-{
-	struct msi_desc *entry;
-
-	list_for_each_entry(entry, &dev->msi_list, list) {
-		if (entry->irq != 0)
-			arch_teardown_msi_irq(entry->irq);
-	}
-}

+ 3 - 4
drivers/pci/pci-acpi.c

@@ -156,13 +156,13 @@ run_osc_out:
 }
 }
 
 
 /**
 /**
- * pci_osc_support_set - register OS support to Firmware
+ * __pci_osc_support_set - register OS support to Firmware
  * @flags: OS support bits
  * @flags: OS support bits
  *
  *
  * Update OS support fields and doing a _OSC Query to obtain an update
  * Update OS support fields and doing a _OSC Query to obtain an update
  * from Firmware on supported control bits.
  * from Firmware on supported control bits.
  **/
  **/
-acpi_status pci_osc_support_set(u32 flags)
+acpi_status __pci_osc_support_set(u32 flags, const char *hid)
 {
 {
 	u32 temp;
 	u32 temp;
 	acpi_status retval;
 	acpi_status retval;
@@ -176,7 +176,7 @@ acpi_status pci_osc_support_set(u32 flags)
 	temp = ctrlset_buf[OSC_CONTROL_TYPE];
 	temp = ctrlset_buf[OSC_CONTROL_TYPE];
 	ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
 	ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
 	ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
 	ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
-	acpi_get_devices ( PCI_ROOT_HID_STRING,
+	acpi_get_devices(hid,
 			acpi_query_osc,
 			acpi_query_osc,
 			ctrlset_buf,
 			ctrlset_buf,
 			(void **) &retval );
 			(void **) &retval );
@@ -188,7 +188,6 @@ acpi_status pci_osc_support_set(u32 flags)
 	}
 	}
 	return AE_OK;
 	return AE_OK;
 }
 }
-EXPORT_SYMBOL(pci_osc_support_set);
 
 
 /**
 /**
  * pci_osc_control_set - commit requested control to Firmware
  * pci_osc_control_set - commit requested control to Firmware

+ 1 - 3
drivers/pci/pci-driver.c

@@ -186,13 +186,11 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
 	    set_cpus_allowed(current, node_to_cpumask(node));
 	    set_cpus_allowed(current, node_to_cpumask(node));
 	/* And set default memory allocation policy */
 	/* And set default memory allocation policy */
 	oldpol = current->mempolicy;
 	oldpol = current->mempolicy;
-	current->mempolicy = &default_policy;
-	mpol_get(current->mempolicy);
+	current->mempolicy = NULL;	/* fall back to system default policy */
 #endif
 #endif
 	error = drv->probe(dev, id);
 	error = drv->probe(dev, id);
 #ifdef CONFIG_NUMA
 #ifdef CONFIG_NUMA
 	set_cpus_allowed(current, oldmask);
 	set_cpus_allowed(current, oldmask);
-	mpol_free(current->mempolicy);
 	current->mempolicy = oldpol;
 	current->mempolicy = oldpol;
 #endif
 #endif
 	return error;
 	return error;

+ 8 - 3
drivers/pci/pci-sysfs.c

@@ -21,6 +21,7 @@
 #include <linux/topology.h>
 #include <linux/topology.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/capability.h>
 #include <linux/capability.h>
+#include <linux/aspm.h>
 #include "pci.h"
 #include "pci.h"
 
 
 static int sysfs_initialized;	/* = 0 */
 static int sysfs_initialized;	/* = 0 */
@@ -358,7 +359,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
 		   char *buf, loff_t off, size_t count)
 		   char *buf, loff_t off, size_t count)
 {
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                      struct class_device,
+                                                      struct device,
 						      kobj));
 						      kobj));
 
 
         /* Only support 1, 2 or 4 byte accesses */
         /* Only support 1, 2 or 4 byte accesses */
@@ -383,7 +384,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
 		    char *buf, loff_t off, size_t count)
 		    char *buf, loff_t off, size_t count)
 {
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-						      struct class_device,
+						      struct device,
 						      kobj));
 						      kobj));
         /* Only support 1, 2 or 4 byte accesses */
         /* Only support 1, 2 or 4 byte accesses */
         if (count != 1 && count != 2 && count != 4)
         if (count != 1 && count != 2 && count != 4)
@@ -407,7 +408,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
                     struct vm_area_struct *vma)
                     struct vm_area_struct *vma)
 {
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                      struct class_device,
+                                                      struct device,
 						      kobj));
 						      kobj));
 
 
         return pci_mmap_legacy_page_range(bus, vma);
         return pci_mmap_legacy_page_range(bus, vma);
@@ -650,6 +651,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 	if (pcibios_add_platform_entries(pdev))
 	if (pcibios_add_platform_entries(pdev))
 		goto err_rom_file;
 		goto err_rom_file;
 
 
+	pcie_aspm_create_sysfs_dev_files(pdev);
+
 	return 0;
 	return 0;
 
 
 err_rom_file:
 err_rom_file:
@@ -679,6 +682,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 	if (!sysfs_initialized)
 	if (!sysfs_initialized)
 		return;
 		return;
 
 
+	pcie_aspm_remove_sysfs_dev_files(pdev);
+
 	if (pdev->cfg_size < 4096)
 	if (pdev->cfg_size < 4096)
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 	else
 	else

+ 75 - 18
drivers/pci/pci.c

@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/log2.h>
 #include <linux/log2.h>
+#include <linux/aspm.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include "pci.h"
 #include "pci.h"
 
 
@@ -314,6 +315,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
 }
 }
 EXPORT_SYMBOL_GPL(pci_find_ht_capability);
 EXPORT_SYMBOL_GPL(pci_find_ht_capability);
 
 
+void pcie_wait_pending_transaction(struct pci_dev *dev)
+{
+	int pos;
+	u16 reg16;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!pos)
+		return;
+	while (1) {
+		pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+		if (!(reg16 & PCI_EXP_DEVSTA_TRPND))
+			break;
+		cpu_relax();
+	}
+
+}
+EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction);
+
 /**
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
  * pci_find_parent_resource - return resource region of parent bus of given region
  * @dev: PCI device structure contains resources to be searched
  * @dev: PCI device structure contains resources to be searched
@@ -353,7 +372,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
  * Restore the BAR values for a given device, so as to make it
  * Restore the BAR values for a given device, so as to make it
  * accessible by its driver.
  * accessible by its driver.
  */
  */
-void
+static void
 pci_restore_bars(struct pci_dev *dev)
 pci_restore_bars(struct pci_dev *dev)
 {
 {
 	int i, numres;
 	int i, numres;
@@ -501,6 +520,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 	if (need_restore)
 	if (need_restore)
 		pci_restore_bars(dev);
 		pci_restore_bars(dev);
 
 
+	if (dev->bus->self)
+		pcie_aspm_pm_state_change(dev->bus->self);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -551,6 +573,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
 	int pos, i = 0;
 	int pos, i = 0;
 	struct pci_cap_saved_state *save_state;
 	struct pci_cap_saved_state *save_state;
 	u16 *cap;
 	u16 *cap;
+	int found = 0;
 
 
 	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
 	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
 	if (pos <= 0)
 	if (pos <= 0)
@@ -559,6 +582,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
 	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
 	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
 	if (!save_state)
 	if (!save_state)
 		save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
 		save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+	else
+		found = 1;
 	if (!save_state) {
 	if (!save_state) {
 		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
 		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
 		return -ENOMEM;
 		return -ENOMEM;
@@ -569,7 +594,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
 	pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
-	pci_add_saved_cap(dev, save_state);
+	save_state->cap_nr = PCI_CAP_ID_EXP;
+	if (!found)
+		pci_add_saved_cap(dev, save_state);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -597,14 +624,17 @@ static int pci_save_pcix_state(struct pci_dev *dev)
 	int pos, i = 0;
 	int pos, i = 0;
 	struct pci_cap_saved_state *save_state;
 	struct pci_cap_saved_state *save_state;
 	u16 *cap;
 	u16 *cap;
+	int found = 0;
 
 
 	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
 	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
 	if (pos <= 0)
 	if (pos <= 0)
 		return 0;
 		return 0;
 
 
-	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
 	if (!save_state)
 	if (!save_state)
 		save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
 		save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+	else
+		found = 1;
 	if (!save_state) {
 	if (!save_state) {
 		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
 		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
 		return -ENOMEM;
 		return -ENOMEM;
@@ -612,7 +642,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
 	cap = (u16 *)&save_state->data[0];
 	cap = (u16 *)&save_state->data[0];
 
 
 	pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
-	pci_add_saved_cap(dev, save_state);
+	save_state->cap_nr = PCI_CAP_ID_PCIX;
+	if (!found)
+		pci_add_saved_cap(dev, save_state);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -713,29 +745,51 @@ int pci_reenable_device(struct pci_dev *dev)
 	return 0;
 	return 0;
 }
 }
 
 
-/**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
- * @bars: bitmask of BAR's that must be configured
- *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable selected I/O and memory resources. Wake up the device if it
- *  was suspended. Beware, this function can fail.
- */
-int
-pci_enable_device_bars(struct pci_dev *dev, int bars)
+static int __pci_enable_device_flags(struct pci_dev *dev,
+				     resource_size_t flags)
 {
 {
 	int err;
 	int err;
+	int i, bars = 0;
 
 
 	if (atomic_add_return(1, &dev->enable_cnt) > 1)
 	if (atomic_add_return(1, &dev->enable_cnt) > 1)
 		return 0;		/* already enabled */
 		return 0;		/* already enabled */
 
 
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+		if (dev->resource[i].flags & flags)
+			bars |= (1 << i);
+
 	err = do_pci_enable_device(dev, bars);
 	err = do_pci_enable_device(dev, bars);
 	if (err < 0)
 	if (err < 0)
 		atomic_dec(&dev->enable_cnt);
 		atomic_dec(&dev->enable_cnt);
 	return err;
 	return err;
 }
 }
 
 
+/**
+ * pci_enable_device_io - Initialize a device for use with IO space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable I/O resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_io(struct pci_dev *dev)
+{
+	return __pci_enable_device_flags(dev, IORESOURCE_IO);
+}
+
+/**
+ * pci_enable_device_mem - Initialize a device for use with Memory space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable Memory resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_mem(struct pci_dev *dev)
+{
+	return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+}
+
 /**
 /**
  * pci_enable_device - Initialize device before it's used by a driver.
  * pci_enable_device - Initialize device before it's used by a driver.
  * @dev: PCI device to be initialized
  * @dev: PCI device to be initialized
@@ -749,7 +803,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
  */
  */
 int pci_enable_device(struct pci_dev *dev)
 int pci_enable_device(struct pci_dev *dev)
 {
 {
-	return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+	return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
 }
 }
 
 
 /*
 /*
@@ -885,6 +939,9 @@ pci_disable_device(struct pci_dev *dev)
 	if (atomic_sub_return(1, &dev->enable_cnt) != 0)
 	if (atomic_sub_return(1, &dev->enable_cnt) != 0)
 		return;
 		return;
 
 
+	/* Wait for all transactions are finished before disabling the device */
+	pcie_wait_pending_transaction(dev);
+
 	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
 	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
 	if (pci_command & PCI_COMMAND_MASTER) {
 	if (pci_command & PCI_COMMAND_MASTER) {
 		pci_command &= ~PCI_COMMAND_MASTER;
 		pci_command &= ~PCI_COMMAND_MASTER;
@@ -1619,9 +1676,9 @@ early_param("pci", pci_setup);
 
 
 device_initcall(pci_init);
 device_initcall(pci_init);
 
 
-EXPORT_SYMBOL_GPL(pci_restore_bars);
 EXPORT_SYMBOL(pci_reenable_device);
 EXPORT_SYMBOL(pci_reenable_device);
-EXPORT_SYMBOL(pci_enable_device_bars);
+EXPORT_SYMBOL(pci_enable_device_io);
+EXPORT_SYMBOL(pci_enable_device_mem);
 EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pcim_enable_device);
 EXPORT_SYMBOL(pcim_enable_device);
 EXPORT_SYMBOL(pcim_pin_device);
 EXPORT_SYMBOL(pcim_pin_device);

+ 6 - 10
drivers/pci/pci.h

@@ -6,8 +6,10 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 
 
 /* Firmware callbacks */
 /* Firmware callbacks */
-extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
-extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
+extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev,
+						pm_message_t state);
+extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
+						pci_power_t state);
 
 
 extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
 extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
 extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
 extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
@@ -45,12 +47,6 @@ static inline void pci_no_msi(void) { }
 static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 #endif
 #endif
 
 
-#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
-void pci_restore_msi_state(struct pci_dev *dev);
-#else
-static inline void pci_restore_msi_state(struct pci_dev *dev) {}
-#endif
-
 #ifdef CONFIG_PCIEAER
 #ifdef CONFIG_PCIEAER
 void pci_no_aer(void);
 void pci_no_aer(void);
 #else
 #else
@@ -68,14 +64,14 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
 }
 }
 extern int pcie_mch_quirk;
 extern int pcie_mch_quirk;
 extern struct device_attribute pci_dev_attrs[];
 extern struct device_attribute pci_dev_attrs[];
-extern struct class_device_attribute class_device_attr_cpuaffinity;
+extern struct device_attribute dev_attr_cpuaffinity;
 
 
 /**
 /**
  * pci_match_one_device - Tell if a PCI device structure has a matching
  * pci_match_one_device - Tell if a PCI device structure has a matching
  *                        PCI device id structure
  *                        PCI device id structure
  * @id: single PCI device id structure to match
  * @id: single PCI device id structure to match
  * @dev: the PCI device structure to match against
  * @dev: the PCI device structure to match against
- * 
+ *
  * Returns the matching pci_device_id structure or %NULL if there is no match.
  * Returns the matching pci_device_id structure or %NULL if there is no match.
  */
  */
 static inline const struct pci_device_id *
 static inline const struct pci_device_id *

+ 20 - 0
drivers/pci/pcie/Kconfig

@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
 	  When in doubt, say N.
 	  When in doubt, say N.
 
 
 source "drivers/pci/pcie/aer/Kconfig"
 source "drivers/pci/pcie/aer/Kconfig"
+
+#
+# PCI Express ASPM
+#
+config PCIEASPM
+	bool "PCI Express ASPM support(Experimental)"
+	depends on PCI && EXPERIMENTAL
+	default y
+	help
+	  This enables PCI Express ASPM (Active State Power Management) and
+	  Clock Power Management. ASPM supports state L0/L0s/L1.
+
+	  When in doubt, say N.
+config PCIEASPM_DEBUG
+	bool "Debug PCI Express ASPM"
+	depends on PCIEASPM
+	default n
+	help
+	  This enables PCI Express ASPM debug support. It will add per-device
+	  interface to control ASPM.

+ 3 - 0
drivers/pci/pcie/Makefile

@@ -2,6 +2,9 @@
 # Makefile for PCI-Express PORT Driver
 # Makefile for PCI-Express PORT Driver
 #
 #
 
 
+# Build PCI Express ASPM if needed
+obj-$(CONFIG_PCIEASPM)		+= aspm.o
+
 pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
 pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
 
 
 obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
 obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o

+ 7 - 17
drivers/pci/pcie/aer/aerdrv_acpi.c

@@ -31,26 +31,16 @@ int aer_osc_setup(struct pcie_device *pciedev)
 {
 {
 	acpi_status status = AE_NOT_FOUND;
 	acpi_status status = AE_NOT_FOUND;
 	struct pci_dev *pdev = pciedev->port;
 	struct pci_dev *pdev = pciedev->port;
-	acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
-	struct pci_bus *parent;
+	acpi_handle handle = 0;
 
 
-	while (!handle) {
-		if (!pdev || !pdev->bus->parent)
-			break;
-		parent = pdev->bus->parent;
-		if (!parent->self)
-			/* Parent must be a host bridge */
-			handle = acpi_get_pci_rootbridge_handle(
-					pci_domain_nr(parent),
-					parent->number);
-		else
-			handle = DEVICE_ACPI_HANDLE(
-					&(parent->self->dev));
-		pdev = parent->self;
-	}
+	/* Find root host bridge */
+	while (pdev->bus && pdev->bus->self)
+		pdev = pdev->bus->self;
+	handle = acpi_get_pci_rootbridge_handle(
+		pci_domain_nr(pdev->bus), pdev->bus->number);
 
 
 	if (handle) {
 	if (handle) {
-		pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+		pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
 		status = pci_osc_control_set(handle,
 		status = pci_osc_control_set(handle,
 					OSC_PCI_EXPRESS_AER_CONTROL |
 					OSC_PCI_EXPRESS_AER_CONTROL |
 					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
 					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);

+ 802 - 0
drivers/pci/pcie/aspm.c

@@ -0,0 +1,802 @@
+/*
+ * File:	drivers/pci/pcie/aspm.c
+ * Enabling PCIE link L0s/L1 state and Clock Power Management
+ *
+ * Copyright (C) 2007 Intel
+ * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
+ * Copyright (C) Shaohua Li (shaohua.li@intel.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/aspm.h>
+#include <acpi/acpi_bus.h>
+#include <linux/pci-acpi.h>
+#include "../pci.h"
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "pcie_aspm."
+
+struct endpoint_state {
+	unsigned int l0s_acceptable_latency;
+	unsigned int l1_acceptable_latency;
+};
+
+struct pcie_link_state {
+	struct list_head sibiling;
+	struct pci_dev *pdev;
+
+	/* ASPM state */
+	unsigned int support_state;
+	unsigned int enabled_state;
+	unsigned int bios_aspm_state;
+	/* upstream component */
+	unsigned int l0s_upper_latency;
+	unsigned int l1_upper_latency;
+	/* downstream component */
+	unsigned int l0s_down_latency;
+	unsigned int l1_down_latency;
+	/* Clock PM state*/
+	unsigned int clk_pm_capable;
+	unsigned int clk_pm_enabled;
+	unsigned int bios_clk_state;
+
+	/*
+	 * A pcie downstream port only has one slot under it, so at most there
+	 * are 8 functions
+	 */
+	struct endpoint_state endpoints[8];
+};
+
+static int aspm_disabled;
+static DEFINE_MUTEX(aspm_lock);
+static LIST_HEAD(link_list);
+
+#define POLICY_DEFAULT 0	/* BIOS default setting */
+#define POLICY_PERFORMANCE 1	/* high performance */
+#define POLICY_POWERSAVE 2	/* high power saving */
+static int aspm_policy;
+static const char *policy_str[] = {
+	[POLICY_DEFAULT] = "default",
+	[POLICY_PERFORMANCE] = "performance",
+	[POLICY_POWERSAVE] = "powersave"
+};
+
+static int policy_to_aspm_state(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	switch (aspm_policy) {
+	case POLICY_PERFORMANCE:
+		/* Disable ASPM and Clock PM */
+		return 0;
+	case POLICY_POWERSAVE:
+		/* Enable ASPM L0s/L1 */
+		return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+	case POLICY_DEFAULT:
+		return link_state->bios_aspm_state;
+	}
+	return 0;
+}
+
+static int policy_to_clkpm_state(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	switch (aspm_policy) {
+	case POLICY_PERFORMANCE:
+		/* Disable ASPM and Clock PM */
+		return 0;
+	case POLICY_POWERSAVE:
+		/* Disable Clock PM */
+		return 1;
+	case POLICY_DEFAULT:
+		return link_state->bios_clk_state;
+	}
+	return 0;
+}
+
+static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
+{
+	struct pci_dev *child_dev;
+	int pos;
+	u16 reg16;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		if (!pos)
+			return;
+		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+		if (enable)
+			reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
+		else
+			reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+		pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
+	}
+	link_state->clk_pm_enabled = !!enable;
+}
+
+static void pcie_check_clock_pm(struct pci_dev *pdev)
+{
+	int pos;
+	u32 reg32;
+	u16 reg16;
+	int capable = 1, enabled = 1;
+	struct pci_dev *child_dev;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	/* All functions should have the same cap and state, take the worst */
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		if (!pos)
+			return;
+		pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
+		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
+			capable = 0;
+			enabled = 0;
+			break;
+		}
+		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
+			enabled = 0;
+	}
+	link_state->clk_pm_capable = capable;
+	link_state->clk_pm_enabled = enabled;
+	link_state->bios_clk_state = enabled;
+	pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+}
+
+/*
+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
+ *   could use common clock. If they are, configure them to use the
+ *   common clock. That will reduce the ASPM state exit latency.
+ */
+static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
+{
+	int pos, child_pos;
+	u16 reg16 = 0;
+	struct pci_dev *child_dev;
+	int same_clock = 1;
+
+	/*
+	 * all functions of a slot should have the same Slot Clock
+	 * Configuration, so just check one function
+	 * */
+	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+		bus_list);
+	BUG_ON(!child_dev->is_pcie);
+
+	/* Check downstream component if bit Slot Clock Configuration is 1 */
+	child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+	pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
+	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+		same_clock = 0;
+
+	/* Check upstream component if bit Slot Clock Configuration is 1 */
+	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+		same_clock = 0;
+
+	/* Configure downstream component, all functions */
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+			&reg16);
+		if (same_clock)
+			reg16 |= PCI_EXP_LNKCTL_CCC;
+		else
+			reg16 &= ~PCI_EXP_LNKCTL_CCC;
+		pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+			reg16);
+	}
+
+	/* Configure upstream component */
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+	if (same_clock)
+		reg16 |= PCI_EXP_LNKCTL_CCC;
+	else
+		reg16 &= ~PCI_EXP_LNKCTL_CCC;
+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+	/* retrain link */
+	reg16 |= PCI_EXP_LNKCTL_RL;
+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+	/* Wait for link training end */
+	while (1) {
+		pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+		if (!(reg16 & PCI_EXP_LNKSTA_LT))
+			break;
+		cpu_relax();
+	}
+}
+
+/*
+ * calc_L0S_latency: Convert L0s latency encoding to ns
+ */
+static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
+{
+	unsigned int ns = 64;
+
+	if (latency_encoding == 0x7) {
+		if (ac)
+			ns = -1U;
+		else
+			ns = 5*1000; /* > 4us */
+	} else
+		ns *= (1 << latency_encoding);
+	return ns;
+}
+
+/*
+ * calc_L1_latency: Convert L1 latency encoding to ns
+ */
+static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
+{
+	unsigned int ns = 1000;
+
+	if (latency_encoding == 0x7) {
+		if (ac)
+			ns = -1U;
+		else
+			ns = 65*1000; /* > 64us */
+	} else
+		ns *= (1 << latency_encoding);
+	return ns;
+}
+
+static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
+	unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
+{
+	int pos;
+	u16 reg16;
+	u32 reg32;
+	unsigned int latency;
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
+	*state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
+	if (*state != PCIE_LINK_STATE_L0S &&
+		*state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
+		* state = 0;
+	if (*state == 0)
+		return;
+
+	latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
+	*l0s = calc_L0S_latency(latency, 0);
+	if (*state & PCIE_LINK_STATE_L1) {
+		latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
+		*l1 = calc_L1_latency(latency, 0);
+	}
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+	*enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
+}
+
+static void pcie_aspm_cap_init(struct pci_dev *pdev)
+{
+	struct pci_dev *child_dev;
+	u32 state, tmp;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	/* upstream component states */
+	pcie_aspm_get_cap_device(pdev, &link_state->support_state,
+		&link_state->l0s_upper_latency,
+		&link_state->l1_upper_latency,
+		&link_state->enabled_state);
+	/* downstream component states, all functions have the same setting */
+	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+		bus_list);
+	pcie_aspm_get_cap_device(child_dev, &state,
+		&link_state->l0s_down_latency,
+		&link_state->l1_down_latency,
+		&tmp);
+	link_state->support_state &= state;
+	if (!link_state->support_state)
+		return;
+	link_state->enabled_state &= link_state->support_state;
+	link_state->bios_aspm_state = link_state->enabled_state;
+
+	/* ENDPOINT states*/
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		int pos;
+		u32 reg32;
+		unsigned int latency;
+		struct endpoint_state *ep_state =
+			&link_state->endpoints[PCI_FUNC(child_dev->devfn)];
+
+		if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
+			continue;
+
+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
+		latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
+		latency = calc_L0S_latency(latency, 1);
+		ep_state->l0s_acceptable_latency = latency;
+		if (link_state->support_state & PCIE_LINK_STATE_L1) {
+			latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
+			latency = calc_L1_latency(latency, 1);
+			ep_state->l1_acceptable_latency = latency;
+		}
+	}
+}
+
+static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
+	unsigned int state)
+{
+	struct pci_dev *parent_dev, *tmp_dev;
+	unsigned int latency, l1_latency = 0;
+	struct pcie_link_state *link_state;
+	struct endpoint_state *ep_state;
+
+	parent_dev = pdev->bus->self;
+	link_state = parent_dev->link_state;
+	state &= link_state->support_state;
+	if (state == 0)
+		return 0;
+	ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
+
+	/*
+	 * Check latency for endpoint device.
+	 * TBD: The latency from the endpoint to root complex vary per
+	 * switch's upstream link state above the device. Here we just do a
+	 * simple check which assumes all links above the device can be in L1
+	 * state, that is we just consider the worst case. If switch's upstream
+	 * link can't be put into L0S/L1, then our check is too strictly.
+	 */
+	tmp_dev = pdev;
+	while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+		parent_dev = tmp_dev->bus->self;
+		link_state = parent_dev->link_state;
+		if (state & PCIE_LINK_STATE_L0S) {
+			latency = max_t(unsigned int,
+					link_state->l0s_upper_latency,
+					link_state->l0s_down_latency);
+			if (latency > ep_state->l0s_acceptable_latency)
+				state &= ~PCIE_LINK_STATE_L0S;
+		}
+		if (state & PCIE_LINK_STATE_L1) {
+			latency = max_t(unsigned int,
+					link_state->l1_upper_latency,
+					link_state->l1_down_latency);
+			if (latency + l1_latency >
+					ep_state->l1_acceptable_latency)
+				state &= ~PCIE_LINK_STATE_L1;
+		}
+		if (!parent_dev->bus->self) /* parent_dev is a root port */
+			break;
+		else {
+			/*
+			 * parent_dev is the downstream port of a switch, make
+			 * tmp_dev the upstream port of the switch
+			 */
+			tmp_dev = parent_dev->bus->self;
+			/*
+			 * every switch on the path to root complex need 1 more
+			 * microsecond for L1. Spec doesn't mention L0S.
+			 */
+			if (state & PCIE_LINK_STATE_L1)
+				l1_latency += 1000;
+		}
+	}
+	return state;
+}
+
+static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
+	unsigned int state)
+{
+	struct pci_dev *child_dev;
+
+	/* If no child, disable the link */
+	if (list_empty(&pdev->subordinate->devices))
+		return 0;
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+			/*
+			 * If downstream component of a link is pci bridge, we
+			 * disable ASPM for now for the link
+			 * */
+			state = 0;
+			break;
+		}
+		if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
+			continue;
+		/* Device not in D0 doesn't need check latency */
+		if (child_dev->current_state == PCI_D1 ||
+			child_dev->current_state == PCI_D2 ||
+			child_dev->current_state == PCI_D3hot ||
+			child_dev->current_state == PCI_D3cold)
+			continue;
+		state = __pcie_aspm_check_state_one(child_dev, state);
+	}
+	return state;
+}
+
+static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
+{
+	u16 reg16;
+	int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+	reg16 &= ~0x3;
+	reg16 |= state;
+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+}
+
+static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
+{
+	struct pci_dev *child_dev;
+	int valid = 1;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	/*
+	 * if the downstream component has pci bridge function, don't do ASPM
+	 * now
+	 */
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+			valid = 0;
+			break;
+		}
+	}
+	if (!valid)
+		return;
+
+	/*
+	 * spec 2.0 suggests all functions should be configured the same
+	 * setting for ASPM. Enabling ASPM L1 should be done in upstream
+	 * component first and then downstream, and vice versa for disabling
+	 * ASPM L1. Spec doesn't mention L0S.
+	 */
+	if (state & PCIE_LINK_STATE_L1)
+		__pcie_aspm_config_one_dev(pdev, state);
+
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
+		__pcie_aspm_config_one_dev(child_dev, state);
+
+	if (!(state & PCIE_LINK_STATE_L1))
+		__pcie_aspm_config_one_dev(pdev, state);
+
+	link_state->enabled_state = state;
+}
+
+static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
+	unsigned int state)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (link_state->support_state == 0)
+		return;
+	state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+
+	/* state 0 means disabling aspm */
+	state = pcie_aspm_check_state(pdev, state);
+	if (link_state->enabled_state == state)
+		return;
+	__pcie_aspm_config_link(pdev, state);
+}
+
+/*
+ * pcie_aspm_configure_link_state: enable/disable PCI express link state
+ * @pdev: the root port or switch downstream port
+ */
+static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
+	unsigned int state)
+{
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	__pcie_aspm_configure_link_state(pdev, state);
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+}
+
+static void free_link_state(struct pci_dev *pdev)
+{
+	kfree(pdev->link_state);
+	pdev->link_state = NULL;
+}
+
+/*
+ * pcie_aspm_init_link_state: Initiate PCI express link state.
+ * It is called after the pcie and its children devices are scaned.
+ * @pdev: the root port or switch downstream port
+ */
+void pcie_aspm_init_link_state(struct pci_dev *pdev)
+{
+	unsigned int state;
+	struct pcie_link_state *link_state;
+	int error = 0;
+
+	if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
+		return;
+	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+	down_read(&pci_bus_sem);
+	if (list_empty(&pdev->subordinate->devices))
+		goto out;
+
+	mutex_lock(&aspm_lock);
+
+	link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
+	if (!link_state)
+		goto unlock_out;
+	pdev->link_state = link_state;
+
+	pcie_aspm_configure_common_clock(pdev);
+
+	pcie_aspm_cap_init(pdev);
+
+	/* config link state to avoid BIOS error */
+	state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
+	__pcie_aspm_config_link(pdev, state);
+
+	pcie_check_clock_pm(pdev);
+
+	link_state->pdev = pdev;
+	list_add(&link_state->sibiling, &link_list);
+
+unlock_out:
+	if (error)
+		free_link_state(pdev);
+	mutex_unlock(&aspm_lock);
+out:
+	up_read(&pci_bus_sem);
+}
+
+/* @pdev: the endpoint device */
+void pcie_aspm_exit_link_state(struct pci_dev *pdev)
+{
+	struct pci_dev *parent = pdev->bus->self;
+	struct pcie_link_state *link_state = parent->link_state;
+
+	if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
+		return;
+	if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+
+	/*
+	 * All PCIe functions are in one slot, remove one function will remove
+	 * the the whole slot, so just wait
+	 */
+	if (!list_empty(&parent->subordinate->devices))
+		goto out;
+
+	/* All functions are removed, so just disable ASPM for the link */
+	__pcie_aspm_config_one_dev(parent, 0);
+	list_del(&link_state->sibiling);
+	/* Clock PM is for endpoint device */
+
+	free_link_state(parent);
+out:
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+}
+
+/* @pdev: the root port or switch downstream port */
+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
+		return;
+	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+	/*
+	 * devices changed PM state, we should recheck if latency meets all
+	 * functions' requirement
+	 */
+	pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
+}
+
+/*
+ * pci_disable_link_state - disable pci device's link state, so the link will
+ * never enter specific states
+ */
+void pci_disable_link_state(struct pci_dev *pdev, int state)
+{
+	struct pci_dev *parent = pdev->bus->self;
+	struct pcie_link_state *link_state;
+
+	if (aspm_disabled || !pdev->is_pcie)
+		return;
+	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
+	    pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+		parent = pdev;
+	if (!parent)
+		return;
+
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	link_state = parent->link_state;
+	link_state->support_state &=
+		~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
+	if (state & PCIE_LINK_STATE_CLKPM)
+		link_state->clk_pm_capable = 0;
+
+	__pcie_aspm_configure_link_state(parent, link_state->enabled_state);
+	if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
+		pcie_set_clock_pm(parent, 0);
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+}
+EXPORT_SYMBOL(pci_disable_link_state);
+
+static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
+{
+	int i;
+	struct pci_dev *pdev;
+	struct pcie_link_state *link_state;
+
+	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+		if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
+			break;
+	if (i >= ARRAY_SIZE(policy_str))
+		return -EINVAL;
+	if (i == aspm_policy)
+		return 0;
+
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	aspm_policy = i;
+	list_for_each_entry(link_state, &link_list, sibiling) {
+		pdev = link_state->pdev;
+		__pcie_aspm_configure_link_state(pdev,
+			policy_to_aspm_state(pdev));
+		if (link_state->clk_pm_capable &&
+		    link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
+			pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+
+	}
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+	return 0;
+}
+
+static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
+{
+	int i, cnt = 0;
+	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+		if (i == aspm_policy)
+			cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
+		else
+			cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
+	return cnt;
+}
+
+module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
+	NULL, 0644);
+
+#ifdef CONFIG_PCIEASPM_DEBUG
+static ssize_t link_state_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	struct pcie_link_state *link_state = pci_device->link_state;
+
+	return sprintf(buf, "%d\n", link_state->enabled_state);
+}
+
+static ssize_t link_state_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	int state;
+
+	if (n < 1)
+		return -EINVAL;
+	state = buf[0]-'0';
+	if (state >= 0 && state <= 3) {
+		/* setup link aspm state */
+		pcie_aspm_configure_link_state(pci_device, state);
+		return n;
+	}
+
+	return -EINVAL;
+}
+
+static ssize_t clk_ctl_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	struct pcie_link_state *link_state = pci_device->link_state;
+
+	return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
+}
+
+static ssize_t clk_ctl_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	int state;
+
+	if (n < 1)
+		return -EINVAL;
+	state = buf[0]-'0';
+
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	pcie_set_clock_pm(pci_device, !!state);
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+
+	return n;
+}
+
+static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
+static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
+
+static char power_group[] = "power";
+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+		return;
+
+	if (link_state->support_state)
+		sysfs_add_file_to_group(&pdev->dev.kobj,
+			&dev_attr_link_state.attr, power_group);
+	if (link_state->clk_pm_capable)
+		sysfs_add_file_to_group(&pdev->dev.kobj,
+			&dev_attr_clk_ctl.attr, power_group);
+}
+
+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+		return;
+
+	if (link_state->support_state)
+		sysfs_remove_file_from_group(&pdev->dev.kobj,
+			&dev_attr_link_state.attr, power_group);
+	if (link_state->clk_pm_capable)
+		sysfs_remove_file_from_group(&pdev->dev.kobj,
+			&dev_attr_clk_ctl.attr, power_group);
+}
+#endif
+
+static int __init pcie_aspm_disable(char *str)
+{
+	aspm_disabled = 1;
+	return 1;
+}
+
+__setup("pcie_noaspm", pcie_aspm_disable);
+
+static int __init pcie_aspm_init(void)
+{
+	if (aspm_disabled)
+		return 0;
+	pci_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
+		OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
+	return 0;
+}
+
+fs_initcall(pcie_aspm_init);

+ 2 - 3
drivers/pci/pcie/portdrv_core.c

@@ -192,9 +192,8 @@ static int get_port_device_capability(struct pci_dev *dev)
 		if (reg32 & SLOT_HP_CAPABLE_MASK)
 		if (reg32 & SLOT_HP_CAPABLE_MASK)
 			services |= PCIE_PORT_SERVICE_HP;
 			services |= PCIE_PORT_SERVICE_HP;
 	} 
 	} 
-	/* PME Capable */
-	pos = pci_find_capability(dev, PCI_CAP_ID_PME);
-	if (pos) 
+	/* PME Capable - root port capability */
+	if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
 		services |= PCIE_PORT_SERVICE_PME;
 		services |= PCIE_PORT_SERVICE_PME;
 	
 	
 	pos = PCI_CFG_SPACE_SIZE;
 	pos = PCI_CFG_SPACE_SIZE;

+ 34 - 46
drivers/pci/probe.c

@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/cpumask.h>
+#include <linux/aspm.h>
 #include "pci.h"
 #include "pci.h"
 
 
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
@@ -53,7 +54,7 @@ static void pci_create_legacy_files(struct pci_bus *b)
 		b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
 		b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
 		b->legacy_io->read = pci_read_legacy_io;
 		b->legacy_io->read = pci_read_legacy_io;
 		b->legacy_io->write = pci_write_legacy_io;
 		b->legacy_io->write = pci_write_legacy_io;
-		class_device_create_bin_file(&b->class_dev, b->legacy_io);
+		device_create_bin_file(&b->dev, b->legacy_io);
 
 
 		/* Allocated above after the legacy_io struct */
 		/* Allocated above after the legacy_io struct */
 		b->legacy_mem = b->legacy_io + 1;
 		b->legacy_mem = b->legacy_io + 1;
@@ -61,15 +62,15 @@ static void pci_create_legacy_files(struct pci_bus *b)
 		b->legacy_mem->size = 1024*1024;
 		b->legacy_mem->size = 1024*1024;
 		b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
 		b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
 		b->legacy_mem->mmap = pci_mmap_legacy_mem;
 		b->legacy_mem->mmap = pci_mmap_legacy_mem;
-		class_device_create_bin_file(&b->class_dev, b->legacy_mem);
+		device_create_bin_file(&b->dev, b->legacy_mem);
 	}
 	}
 }
 }
 
 
 void pci_remove_legacy_files(struct pci_bus *b)
 void pci_remove_legacy_files(struct pci_bus *b)
 {
 {
 	if (b->legacy_io) {
 	if (b->legacy_io) {
-		class_device_remove_bin_file(&b->class_dev, b->legacy_io);
-		class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+		device_remove_bin_file(&b->dev, b->legacy_io);
+		device_remove_bin_file(&b->dev, b->legacy_mem);
 		kfree(b->legacy_io); /* both are allocated here */
 		kfree(b->legacy_io); /* both are allocated here */
 	}
 	}
 }
 }
@@ -81,26 +82,27 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
 /*
 /*
  * PCI Bus Class Devices
  * PCI Bus Class Devices
  */
  */
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+					struct device_attribute *attr,
 					char *buf)
 					char *buf)
 {
 {
 	int ret;
 	int ret;
 	cpumask_t cpumask;
 	cpumask_t cpumask;
 
 
-	cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
+	cpumask = pcibus_to_cpumask(to_pci_bus(dev));
 	ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
 	ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
 	if (ret < PAGE_SIZE)
 	if (ret < PAGE_SIZE)
 		buf[ret++] = '\n';
 		buf[ret++] = '\n';
 	return ret;
 	return ret;
 }
 }
-CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
+DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
 
 
 /*
 /*
  * PCI Bus Class
  * PCI Bus Class
  */
  */
-static void release_pcibus_dev(struct class_device *class_dev)
+static void release_pcibus_dev(struct device *dev)
 {
 {
-	struct pci_bus *pci_bus = to_pci_bus(class_dev);
+	struct pci_bus *pci_bus = to_pci_bus(dev);
 
 
 	if (pci_bus->bridge)
 	if (pci_bus->bridge)
 		put_device(pci_bus->bridge);
 		put_device(pci_bus->bridge);
@@ -109,7 +111,7 @@ static void release_pcibus_dev(struct class_device *class_dev)
 
 
 static struct class pcibus_class = {
 static struct class pcibus_class = {
 	.name		= "pci_bus",
 	.name		= "pci_bus",
-	.release	= &release_pcibus_dev,
+	.dev_release	= &release_pcibus_dev,
 };
 };
 
 
 static int __init pcibus_class_init(void)
 static int __init pcibus_class_init(void)
@@ -392,7 +394,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 {
 {
 	struct pci_bus *child;
 	struct pci_bus *child;
 	int i;
 	int i;
-	int retval;
 
 
 	/*
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 * Allocate a new bus, and inherit stuff from the parent..
@@ -408,15 +409,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 	child->bus_flags = parent->bus_flags;
 	child->bus_flags = parent->bus_flags;
 	child->bridge = get_device(&bridge->dev);
 	child->bridge = get_device(&bridge->dev);
 
 
-	child->class_dev.class = &pcibus_class;
-	sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
-	retval = class_device_register(&child->class_dev);
-	if (retval)
-		goto error_register;
-	retval = class_device_create_file(&child->class_dev,
-					  &class_device_attr_cpuaffinity);
-	if (retval)
-		goto error_file_create;
+	/* initialize some portions of the bus device, but don't register it
+	 * now as the parent is not properly set up yet.  This device will get
+	 * registered later in pci_bus_add_devices()
+	 */
+	child->dev.class = &pcibus_class;
+	sprintf(child->dev.bus_id, "%04x:%02x", pci_domain_nr(child), busnr);
 
 
 	/*
 	/*
 	 * Set up the primary, secondary and subordinate
 	 * Set up the primary, secondary and subordinate
@@ -434,12 +432,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 	bridge->subordinate = child;
 	bridge->subordinate = child;
 
 
 	return child;
 	return child;
-
-error_file_create:
-	class_device_unregister(&child->class_dev);
-error_register:
-	kfree(child);
-	return NULL;
 }
 }
 
 
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
@@ -471,8 +463,6 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
 	}
 	}
 }
 }
 
 
-unsigned int pci_scan_child_bus(struct pci_bus *bus);
-
 /*
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
  * For CardBus bridges, we don't scan behind as the devices will
@@ -641,13 +631,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
 		    (child->number > bus->subordinate) ||
 		    (child->number > bus->subordinate) ||
 		    (child->number < bus->number) ||
 		    (child->number < bus->number) ||
 		    (child->subordinate < bus->number)) {
 		    (child->subordinate < bus->number)) {
-			pr_debug("PCI: Bus #%02x (-#%02x) is %s"
+			pr_debug("PCI: Bus #%02x (-#%02x) is %s "
 				"hidden behind%s bridge #%02x (-#%02x)\n",
 				"hidden behind%s bridge #%02x (-#%02x)\n",
 				child->number, child->subordinate,
 				child->number, child->subordinate,
 				(bus->number > child->subordinate &&
 				(bus->number > child->subordinate &&
 				 bus->subordinate < child->number) ?
 				 bus->subordinate < child->number) ?
-					"wholly " : " partially",
-				bus->self->transparent ? " transparent" : " ",
+					"wholly" : "partially",
+				bus->self->transparent ? " transparent" : "",
 				bus->number, bus->subordinate);
 				bus->number, bus->subordinate);
 		}
 		}
 		bus = bus->parent;
 		bus = bus->parent;
@@ -971,6 +961,7 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
 
 
 	return dev;
 	return dev;
 }
 }
+EXPORT_SYMBOL(pci_scan_single_device);
 
 
 /**
 /**
  * pci_scan_slot - scan a PCI slot on a bus for devices.
  * pci_scan_slot - scan a PCI slot on a bus for devices.
@@ -1011,6 +1002,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
 				break;
 				break;
 		}
 		}
 	}
 	}
+
+	if (bus->self)
+		pcie_aspm_init_link_state(bus->self);
+
 	return nr;
 	return nr;
 }
 }
 
 
@@ -1103,32 +1098,27 @@ struct pci_bus * pci_create_bus(struct device *parent,
 		goto dev_reg_err;
 		goto dev_reg_err;
 	b->bridge = get_device(dev);
 	b->bridge = get_device(dev);
 
 
-	b->class_dev.class = &pcibus_class;
-	sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus);
-	error = class_device_register(&b->class_dev);
+	b->dev.class = &pcibus_class;
+	b->dev.parent = b->bridge;
+	sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
+	error = device_register(&b->dev);
 	if (error)
 	if (error)
 		goto class_dev_reg_err;
 		goto class_dev_reg_err;
-	error = class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);
+	error = device_create_file(&b->dev, &dev_attr_cpuaffinity);
 	if (error)
 	if (error)
-		goto class_dev_create_file_err;
+		goto dev_create_file_err;
 
 
 	/* Create legacy_io and legacy_mem files for this bus */
 	/* Create legacy_io and legacy_mem files for this bus */
 	pci_create_legacy_files(b);
 	pci_create_legacy_files(b);
 
 
-	error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
-	if (error)
-		goto sys_create_link_err;
-
 	b->number = b->secondary = bus;
 	b->number = b->secondary = bus;
 	b->resource[0] = &ioport_resource;
 	b->resource[0] = &ioport_resource;
 	b->resource[1] = &iomem_resource;
 	b->resource[1] = &iomem_resource;
 
 
 	return b;
 	return b;
 
 
-sys_create_link_err:
-	class_device_remove_file(&b->class_dev, &class_device_attr_cpuaffinity);
-class_dev_create_file_err:
-	class_device_unregister(&b->class_dev);
+dev_create_file_err:
+	device_unregister(&b->dev);
 class_dev_reg_err:
 class_dev_reg_err:
 	device_unregister(dev);
 	device_unregister(dev);
 dev_reg_err:
 dev_reg_err:
@@ -1140,7 +1130,6 @@ err_out:
 	kfree(b);
 	kfree(b);
 	return NULL;
 	return NULL;
 }
 }
-EXPORT_SYMBOL_GPL(pci_create_bus);
 
 
 struct pci_bus *pci_scan_bus_parented(struct device *parent,
 struct pci_bus *pci_scan_bus_parented(struct device *parent,
 		int bus, struct pci_ops *ops, void *sysdata)
 		int bus, struct pci_ops *ops, void *sysdata)
@@ -1159,7 +1148,6 @@ EXPORT_SYMBOL(pci_add_new_bus);
 EXPORT_SYMBOL(pci_do_scan_bus);
 EXPORT_SYMBOL(pci_do_scan_bus);
 EXPORT_SYMBOL(pci_scan_slot);
 EXPORT_SYMBOL(pci_scan_slot);
 EXPORT_SYMBOL(pci_scan_bridge);
 EXPORT_SYMBOL(pci_scan_bridge);
-EXPORT_SYMBOL(pci_scan_single_device);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 #endif
 #endif
 
 

+ 9 - 8
drivers/pci/proc.c

@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 #include <linux/capability.h>
 #include <linux/capability.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
@@ -202,15 +203,18 @@ struct pci_filp_private {
 	int write_combine;
 	int write_combine;
 };
 };
 
 
-static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
+			       unsigned long arg)
 {
 {
-	const struct proc_dir_entry *dp = PDE(inode);
+	const struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
 	struct pci_dev *dev = dp->data;
 	struct pci_dev *dev = dp->data;
 #ifdef HAVE_PCI_MMAP
 #ifdef HAVE_PCI_MMAP
 	struct pci_filp_private *fpriv = file->private_data;
 	struct pci_filp_private *fpriv = file->private_data;
 #endif /* HAVE_PCI_MMAP */
 #endif /* HAVE_PCI_MMAP */
 	int ret = 0;
 	int ret = 0;
 
 
+	lock_kernel();
+
 	switch (cmd) {
 	switch (cmd) {
 	case PCIIOC_CONTROLLER:
 	case PCIIOC_CONTROLLER:
 		ret = pci_domain_nr(dev->bus);
 		ret = pci_domain_nr(dev->bus);
@@ -239,6 +243,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i
 		break;
 		break;
 	};
 	};
 
 
+	unlock_kernel();
 	return ret;
 	return ret;
 }
 }
 
 
@@ -291,7 +296,7 @@ static const struct file_operations proc_bus_pci_operations = {
 	.llseek		= proc_bus_pci_lseek,
 	.llseek		= proc_bus_pci_lseek,
 	.read		= proc_bus_pci_read,
 	.read		= proc_bus_pci_read,
 	.write		= proc_bus_pci_write,
 	.write		= proc_bus_pci_write,
-	.ioctl		= proc_bus_pci_ioctl,
+	.unlocked_ioctl	= proc_bus_pci_ioctl,
 #ifdef HAVE_PCI_MMAP
 #ifdef HAVE_PCI_MMAP
 	.open		= proc_bus_pci_open,
 	.open		= proc_bus_pci_open,
 	.release	= proc_bus_pci_release,
 	.release	= proc_bus_pci_release,
@@ -370,7 +375,7 @@ static int show_device(struct seq_file *m, void *v)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct seq_operations proc_bus_pci_devices_op = {
+static const struct seq_operations proc_bus_pci_devices_op = {
 	.start	= pci_seq_start,
 	.start	= pci_seq_start,
 	.next	= pci_seq_next,
 	.next	= pci_seq_next,
 	.stop	= pci_seq_stop,
 	.stop	= pci_seq_stop,
@@ -480,7 +485,3 @@ static int __init pci_proc_init(void)
 
 
 __initcall(pci_proc_init);
 __initcall(pci_proc_init);
 
 
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_detach_bus);
-#endif
-

File diff ditekan karena terlalu besar
+ 259 - 195
drivers/pci/quirks.c


+ 6 - 4
drivers/pci/remove.c

@@ -1,5 +1,6 @@
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/aspm.h>
 #include "pci.h"
 #include "pci.h"
 
 
 static void pci_free_resources(struct pci_dev *dev)
 static void pci_free_resources(struct pci_dev *dev)
@@ -30,6 +31,9 @@ static void pci_stop_dev(struct pci_dev *dev)
 		dev->global_list.next = dev->global_list.prev = NULL;
 		dev->global_list.next = dev->global_list.prev = NULL;
 		up_write(&pci_bus_sem);
 		up_write(&pci_bus_sem);
 	}
 	}
+
+	if (dev->bus->self)
+		pcie_aspm_exit_link_state(dev);
 }
 }
 
 
 static void pci_destroy_dev(struct pci_dev *dev)
 static void pci_destroy_dev(struct pci_dev *dev)
@@ -74,10 +78,8 @@ void pci_remove_bus(struct pci_bus *pci_bus)
 	list_del(&pci_bus->node);
 	list_del(&pci_bus->node);
 	up_write(&pci_bus_sem);
 	up_write(&pci_bus_sem);
 	pci_remove_legacy_files(pci_bus);
 	pci_remove_legacy_files(pci_bus);
-	class_device_remove_file(&pci_bus->class_dev,
-		&class_device_attr_cpuaffinity);
-	sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge");
-	class_device_unregister(&pci_bus->class_dev);
+	device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
+	device_unregister(&pci_bus->dev);
 }
 }
 EXPORT_SYMBOL(pci_remove_bus);
 EXPORT_SYMBOL(pci_remove_bus);
 
 

+ 4 - 2
drivers/pci/rom.c

@@ -162,6 +162,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
 	return rom;
 	return rom;
 }
 }
 
 
+#if 0
 /**
 /**
  * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
  * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
  * @pdev: pointer to pci device struct
  * @pdev: pointer to pci device struct
@@ -196,6 +197,7 @@ void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
 
 
 	return (void __iomem *)(unsigned long)res->start;
 	return (void __iomem *)(unsigned long)res->start;
 }
 }
+#endif  /*  0  */
 
 
 /**
 /**
  * pci_unmap_rom - unmap the ROM from kernel space
  * pci_unmap_rom - unmap the ROM from kernel space
@@ -218,6 +220,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
 		pci_disable_rom(pdev);
 		pci_disable_rom(pdev);
 }
 }
 
 
+#if 0
 /**
 /**
  * pci_remove_rom - disable the ROM and remove its sysfs attribute
  * pci_remove_rom - disable the ROM and remove its sysfs attribute
  * @pdev: pointer to pci device struct
  * @pdev: pointer to pci device struct
@@ -236,6 +239,7 @@ void pci_remove_rom(struct pci_dev *pdev)
 			    IORESOURCE_ROM_COPY)))
 			    IORESOURCE_ROM_COPY)))
 		pci_disable_rom(pdev);
 		pci_disable_rom(pdev);
 }
 }
+#endif  /*  0  */
 
 
 /**
 /**
  * pci_cleanup_rom - internal routine for freeing the ROM copy created
  * pci_cleanup_rom - internal routine for freeing the ROM copy created
@@ -256,6 +260,4 @@ void pci_cleanup_rom(struct pci_dev *pdev)
 }
 }
 
 
 EXPORT_SYMBOL(pci_map_rom);
 EXPORT_SYMBOL(pci_map_rom);
-EXPORT_SYMBOL(pci_map_rom_copy);
 EXPORT_SYMBOL(pci_unmap_rom);
 EXPORT_SYMBOL(pci_unmap_rom);
-EXPORT_SYMBOL(pci_remove_rom);

+ 40 - 24
drivers/pci/setup-bus.c

@@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
 		 * The IO resource is allocated a range twice as large as it
 		 * The IO resource is allocated a range twice as large as it
 		 * would normally need.  This allows us to set both IO regs.
 		 * would normally need.  This allows us to set both IO regs.
 		 */
 		 */
-		printk("  IO window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  IO window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
 					region.start);
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
@@ -99,8 +100,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
 
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
 	pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
 	if (bus->resource[1]->flags & IORESOURCE_IO) {
 	if (bus->resource[1]->flags & IORESOURCE_IO) {
-		printk("  IO window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  IO window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
 					region.start);
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
@@ -109,8 +111,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
 
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_MEM) {
 	if (bus->resource[2]->flags & IORESOURCE_MEM) {
-		printk("  PREFETCH window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  PREFETCH window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
 					region.start);
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
@@ -119,8 +122,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
 
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
 	pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
 	if (bus->resource[3]->flags & IORESOURCE_MEM) {
 	if (bus->resource[3]->flags & IORESOURCE_MEM) {
-		printk("  MEM window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  MEM window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
 					region.start);
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
@@ -145,7 +149,7 @@ pci_setup_bridge(struct pci_bus *bus)
 {
 {
 	struct pci_dev *bridge = bus->self;
 	struct pci_dev *bridge = bus->self;
 	struct pci_bus_region region;
 	struct pci_bus_region region;
-	u32 l, io_upper16;
+	u32 l, bu, lu, io_upper16;
 
 
 	DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge));
 	DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge));
 
 
@@ -159,7 +163,8 @@ pci_setup_bridge(struct pci_bus *bus)
 		/* Set up upper 16 bits of I/O base/limit. */
 		/* Set up upper 16 bits of I/O base/limit. */
 		io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
 		io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
 		DBG(KERN_INFO "  IO window: %04lx-%04lx\n",
 		DBG(KERN_INFO "  IO window: %04lx-%04lx\n",
-				region.start, region.end);
+		    (unsigned long)region.start,
+		    (unsigned long)region.end);
 	}
 	}
 	else {
 	else {
 		/* Clear upper 16 bits of I/O base/limit. */
 		/* Clear upper 16 bits of I/O base/limit. */
@@ -180,8 +185,9 @@ pci_setup_bridge(struct pci_bus *bus)
 	if (bus->resource[1]->flags & IORESOURCE_MEM) {
 	if (bus->resource[1]->flags & IORESOURCE_MEM) {
 		l = (region.start >> 16) & 0xfff0;
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
 		l |= region.end & 0xfff00000;
-		DBG(KERN_INFO "  MEM window: %08lx-%08lx\n",
-				region.start, region.end);
+		DBG(KERN_INFO "  MEM window: 0x%08lx-0x%08lx\n",
+		    (unsigned long)region.start,
+		    (unsigned long)region.end);
 	}
 	}
 	else {
 	else {
 		l = 0x0000fff0;
 		l = 0x0000fff0;
@@ -195,12 +201,18 @@ pci_setup_bridge(struct pci_bus *bus)
 	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 
 
 	/* Set up PREF base/limit. */
 	/* Set up PREF base/limit. */
+	bu = lu = 0;
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
 	if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
 		l = (region.start >> 16) & 0xfff0;
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
 		l |= region.end & 0xfff00000;
-		DBG(KERN_INFO "  PREFETCH window: %08lx-%08lx\n",
-				region.start, region.end);
+#ifdef CONFIG_RESOURCES_64BIT
+		bu = region.start >> 32;
+		lu = region.end >> 32;
+#endif
+		DBG(KERN_INFO "  PREFETCH window: 0x%016llx-0x%016llx\n",
+		    (unsigned long long)region.start,
+		    (unsigned long long)region.end);
 	}
 	}
 	else {
 	else {
 		l = 0x0000fff0;
 		l = 0x0000fff0;
@@ -208,8 +220,9 @@ pci_setup_bridge(struct pci_bus *bus)
 	}
 	}
 	pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 	pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
 
-	/* Clear out the upper 32 bits of PREF base. */
-	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
+	/* Set the upper 32 bits of PREF base & limit. */
+	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
 
 
 	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
 }
@@ -323,8 +336,8 @@ static void pbus_size_io(struct pci_bus *bus)
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
 {
 {
 	struct pci_dev *dev;
 	struct pci_dev *dev;
-	unsigned long min_align, align, size;
-	unsigned long aligns[12];	/* Alignments from 1Mb to 2Gb */
+	resource_size_t min_align, align, size;
+	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
 	int order, max_order;
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus, type);
 	struct resource *b_res = find_free_bus_resource(bus, type);
 
 
@@ -340,7 +353,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 		
 		
 		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 			struct resource *r = &dev->resource[i];
 			struct resource *r = &dev->resource[i];
-			unsigned long r_size;
+			resource_size_t r_size;
 
 
 			if (r->parent || (r->flags & mask) != type)
 			if (r->parent || (r->flags & mask) != type)
 				continue;
 				continue;
@@ -350,10 +363,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 			order = __ffs(align) - 20;
 			order = __ffs(align) - 20;
 			if (order > 11) {
 			if (order > 11) {
 				printk(KERN_WARNING "PCI: region %s/%d "
 				printk(KERN_WARNING "PCI: region %s/%d "
-				       "too large: %llx-%llx\n",
+				       "too large: 0x%016llx-0x%016llx\n",
 					pci_name(dev), i,
 					pci_name(dev), i,
-					(unsigned long long)r->start,
-					(unsigned long long)r->end);
+				       (unsigned long long)r->start,
+				       (unsigned long long)r->end);
 				r->flags = 0;
 				r->flags = 0;
 				continue;
 				continue;
 			}
 			}
@@ -372,8 +385,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 	align = 0;
 	align = 0;
 	min_align = 0;
 	min_align = 0;
 	for (order = 0; order <= max_order; order++) {
 	for (order = 0; order <= max_order; order++) {
-		unsigned long align1 = 1UL << (order + 20);
-
+#ifdef CONFIG_RESOURCES_64BIT
+		resource_size_t align1 = 1ULL << (order + 20);
+#else
+		resource_size_t align1 = 1U << (order + 20);
+#endif
 		if (!align)
 		if (!align)
 			min_align = align1;
 			min_align = align1;
 		else if (ALIGN(align + min_align, min_align) < align1)
 		else if (ALIGN(align + min_align, min_align) < align1)

+ 4 - 3
drivers/pci/setup-res.c

@@ -51,10 +51,12 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
 
 
 	pcibios_resource_to_bus(dev, &region, res);
 	pcibios_resource_to_bus(dev, &region, res);
 
 
-	pr_debug("  got res [%llx:%llx] bus [%lx:%lx] flags %lx for "
+	pr_debug("  got res [%llx:%llx] bus [%llx:%llx] flags %lx for "
 		 "BAR %d of %s\n", (unsigned long long)res->start,
 		 "BAR %d of %s\n", (unsigned long long)res->start,
 		 (unsigned long long)res->end,
 		 (unsigned long long)res->end,
-		 region.start, region.end, res->flags, resno, pci_name(dev));
+		 (unsigned long long)region.start,
+		 (unsigned long long)region.end,
+		 (unsigned long)res->flags, resno, pci_name(dev));
 
 
 	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
 	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
 	if (res->flags & IORESOURCE_IO)
 	if (res->flags & IORESOURCE_IO)
@@ -125,7 +127,6 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
 
 
 	return err;
 	return err;
 }
 }
-EXPORT_SYMBOL_GPL(pci_claim_resource);
 
 
 int pci_assign_resource(struct pci_dev *dev, int resno)
 int pci_assign_resource(struct pci_dev *dev, int resno)
 {
 {

+ 0 - 5
drivers/pci/syscall.c

@@ -34,7 +34,6 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
 	if (!dev)
 	if (!dev)
 		goto error;
 		goto error;
 
 
-	lock_kernel();
 	switch (len) {
 	switch (len) {
 	case 1:
 	case 1:
 		cfg_ret = pci_user_read_config_byte(dev, off, &byte);
 		cfg_ret = pci_user_read_config_byte(dev, off, &byte);
@@ -47,10 +46,8 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
 		break;
 		break;
 	default:
 	default:
 		err = -EINVAL;
 		err = -EINVAL;
-		unlock_kernel();
 		goto error;
 		goto error;
 	};
 	};
-	unlock_kernel();
 
 
 	err = -EIO;
 	err = -EIO;
 	if (cfg_ret != PCIBIOS_SUCCESSFUL)
 	if (cfg_ret != PCIBIOS_SUCCESSFUL)
@@ -107,7 +104,6 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
 	if (!dev)
 	if (!dev)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	lock_kernel();
 	switch(len) {
 	switch(len) {
 	case 1:
 	case 1:
 		err = get_user(byte, (u8 __user *)buf);
 		err = get_user(byte, (u8 __user *)buf);
@@ -140,7 +136,6 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
 		err = -EINVAL;
 		err = -EINVAL;
 		break;
 		break;
 	}
 	}
-	unlock_kernel();
 	pci_dev_put(dev);
 	pci_dev_put(dev);
 	return err;
 	return err;
 }
 }

+ 1 - 2
drivers/scsi/lpfc/lpfc_init.c

@@ -2296,10 +2296,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
 	struct lpfc_sli *psli = &phba->sli;
 	struct lpfc_sli *psli = &phba->sli;
-	int bars = pci_select_bars(pdev, IORESOURCE_MEM);
 
 
 	dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
 	dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
-	if (pci_enable_device_bars(pdev, bars)) {
+	if (pci_enable_device_mem(pdev)) {
 		printk(KERN_ERR "lpfc: Cannot re-enable "
 		printk(KERN_ERR "lpfc: Cannot re-enable "
 			"PCI device after reset.\n");
 			"PCI device after reset.\n");
 		return PCI_ERS_RESULT_DISCONNECT;
 		return PCI_ERS_RESULT_DISCONNECT;

+ 1 - 0
drivers/scsi/qla2xxx/qla_def.h

@@ -2268,6 +2268,7 @@ typedef struct scsi_qla_host {
 	spinlock_t		hardware_lock ____cacheline_aligned;
 	spinlock_t		hardware_lock ____cacheline_aligned;
 
 
 	int		bars;
 	int		bars;
+	int		mem_only;
 	device_reg_t __iomem *iobase;		/* Base I/O address */
 	device_reg_t __iomem *iobase;		/* Base I/O address */
 	resource_size_t pio_address;
 	resource_size_t pio_address;
 #define MIN_IOBASE_LEN		0x100
 #define MIN_IOBASE_LEN		0x100

+ 17 - 4
drivers/scsi/qla2xxx/qla_os.c

@@ -1564,7 +1564,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	char pci_info[30];
 	char pci_info[30];
 	char fw_str[30];
 	char fw_str[30];
 	struct scsi_host_template *sht;
 	struct scsi_host_template *sht;
-	int bars;
+	int bars, mem_only = 0;
 
 
 	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
 	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
 	sht = &qla2x00_driver_template;
 	sht = &qla2x00_driver_template;
@@ -1575,10 +1575,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
 		bars = pci_select_bars(pdev, IORESOURCE_MEM);
 		bars = pci_select_bars(pdev, IORESOURCE_MEM);
 		sht = &qla24xx_driver_template;
 		sht = &qla24xx_driver_template;
+		mem_only = 1;
 	}
 	}
 
 
-	if (pci_enable_device_bars(pdev, bars))
-		goto probe_out;
+	if (mem_only) {
+		if (pci_enable_device_mem(pdev))
+			goto probe_out;
+	} else {
+		if (pci_enable_device(pdev))
+			goto probe_out;
+	}
 
 
 	if (pci_find_aer_capability(pdev))
 	if (pci_find_aer_capability(pdev))
 		if (pci_enable_pcie_error_reporting(pdev))
 		if (pci_enable_pcie_error_reporting(pdev))
@@ -1601,6 +1607,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
 	sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
 	ha->parent = NULL;
 	ha->parent = NULL;
 	ha->bars = bars;
 	ha->bars = bars;
+	ha->mem_only = mem_only;
 
 
 	/* Set ISP-type information. */
 	/* Set ISP-type information. */
 	qla2x00_set_isp_flags(ha);
 	qla2x00_set_isp_flags(ha);
@@ -2875,8 +2882,14 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
 {
 {
 	pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
 	pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
 	scsi_qla_host_t *ha = pci_get_drvdata(pdev);
 	scsi_qla_host_t *ha = pci_get_drvdata(pdev);
+	int rc;
+
+	if (ha->mem_only)
+		rc = pci_enable_device_mem(pdev);
+	else
+		rc = pci_enable_device(pdev);
 
 
-	if (pci_enable_device_bars(pdev, ha->bars)) {
+	if (rc) {
 		qla_printk(KERN_WARNING, ha,
 		qla_printk(KERN_WARNING, ha,
 		    "Can't re-enable PCI device after reset.\n");
 		    "Can't re-enable PCI device after reset.\n");
 
 

+ 8 - 14
drivers/usb/host/pci-quirks.c

@@ -190,9 +190,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 			msleep(10);
 			msleep(10);
 		}
 		}
 		if (wait_time <= 0)
 		if (wait_time <= 0)
-			printk(KERN_WARNING "%s %s: BIOS handoff "
-					"failed (BIOS bug ?) %08x\n",
-					pdev->dev.bus_id, "OHCI",
+			dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
+					" (BIOS bug?) %08x\n",
 					readl(base + OHCI_CONTROL));
 					readl(base + OHCI_CONTROL));
 
 
 		/* reset controller, preserving RWC */
 		/* reset controller, preserving RWC */
@@ -243,8 +242,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
 		switch (cap & 0xff) {
 		switch (cap & 0xff) {
 		case 1:			/* BIOS/SMM/... handoff support */
 		case 1:			/* BIOS/SMM/... handoff support */
 			if ((cap & EHCI_USBLEGSUP_BIOS)) {
 			if ((cap & EHCI_USBLEGSUP_BIOS)) {
-				pr_debug("%s %s: BIOS handoff\n",
-						pdev->dev.bus_id, "EHCI");
+				dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");
 
 
 #if 0
 #if 0
 /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
 /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
@@ -285,9 +283,8 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
 				/* well, possibly buggy BIOS... try to shut
 				/* well, possibly buggy BIOS... try to shut
 				 * it down, and hope nothing goes too wrong
 				 * it down, and hope nothing goes too wrong
 				 */
 				 */
-				printk(KERN_WARNING "%s %s: BIOS handoff "
-						"failed (BIOS bug ?) %08x\n",
-					pdev->dev.bus_id, "EHCI", cap);
+				dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
+						" (BIOS bug?) %08x\n", cap);
 				pci_write_config_byte(pdev, offset + 2, 0);
 				pci_write_config_byte(pdev, offset + 2, 0);
 			}
 			}
 
 
@@ -306,17 +303,14 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
 			cap = 0;
 			cap = 0;
 			/* FALLTHROUGH */
 			/* FALLTHROUGH */
 		default:
 		default:
-			printk(KERN_WARNING "%s %s: unrecognized "
-					"capability %02x\n",
-					pdev->dev.bus_id, "EHCI",
-					cap & 0xff);
+			dev_warn(&pdev->dev, "EHCI: unrecognized capability "
+					"%02x\n", cap & 0xff);
 			break;
 			break;
 		}
 		}
 		offset = (cap >> 8) & 0xff;
 		offset = (cap >> 8) & 0xff;
 	}
 	}
 	if (!count)
 	if (!count)
-		printk(KERN_DEBUG "%s %s: capability loop?\n",
-				pdev->dev.bus_id, "EHCI");
+		dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n");
 
 
 	/*
 	/*
 	 * halt EHCI & disable its interrupts in any case
 	 * halt EHCI & disable its interrupts in any case

+ 44 - 0
include/linux/aspm.h

@@ -0,0 +1,44 @@
+/*
+ *	aspm.h
+ *
+ *	PCI Express ASPM defines and function prototypes
+ *
+ *	Copyright (C) 2007 Intel Corp.
+ *		Zhang Yanmin (yanmin.zhang@intel.com)
+ *		Shaohua Li (shaohua.li@intel.com)
+ *
+ *	For more information, please consult the following manuals (look at
+ *	http://www.pcisig.com/ for how to get them):
+ *
+ *	PCI Express Specification
+ */
+
+#ifndef LINUX_ASPM_H
+#define LINUX_ASPM_H
+
+#include <linux/pci.h>
+
+#define PCIE_LINK_STATE_L0S	1
+#define PCIE_LINK_STATE_L1	2
+#define PCIE_LINK_STATE_CLKPM	4
+
+#ifdef CONFIG_PCIEASPM
+extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
+extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
+extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
+extern void pci_disable_link_state(struct pci_dev *pdev, int state);
+#else
+#define pcie_aspm_init_link_state(pdev)		do {} while (0)
+#define pcie_aspm_exit_link_state(pdev)		do {} while (0)
+#define pcie_aspm_pm_state_change(pdev)		do {} while (0)
+#define pci_disable_link_state(pdev, state)	do {} while (0)
+#endif
+
+#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
+extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
+extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
+#else
+#define pcie_aspm_create_sysfs_dev_files(pdev)	do {} while (0)
+#define pcie_aspm_remove_sysfs_dev_files(pdev)	do {} while (0)
+#endif
+#endif /* LINUX_ASPM_H */

+ 10 - 1
include/linux/pci-acpi.h

@@ -48,7 +48,15 @@
 
 
 #ifdef CONFIG_ACPI
 #ifdef CONFIG_ACPI
 extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
 extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
-extern acpi_status pci_osc_support_set(u32 flags);
+extern acpi_status __pci_osc_support_set(u32 flags, const char *hid);
+static inline acpi_status pci_osc_support_set(u32 flags)
+{
+	return __pci_osc_support_set(flags, PCI_ROOT_HID_STRING);
+}
+static inline acpi_status pcie_osc_support_set(u32 flags)
+{
+	return __pci_osc_support_set(flags, PCI_EXPRESS_ROOT_HID_STRING);
+}
 #else
 #else
 #if !defined(AE_ERROR)
 #if !defined(AE_ERROR)
 typedef u32 		acpi_status;
 typedef u32 		acpi_status;
@@ -57,6 +65,7 @@ typedef u32 		acpi_status;
 static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
 static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
 {return AE_ERROR;}
 {return AE_ERROR;}
 static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} 
 static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} 
+static inline acpi_status pcie_osc_support_set(u32 flags) {return AE_ERROR;}
 #endif
 #endif
 
 
 #endif	/* _PCI_ACPI_H_ */
 #endif	/* _PCI_ACPI_H_ */

+ 249 - 118
include/linux/pci.h

@@ -28,7 +28,7 @@
  *	7:3 = slot
  *	7:3 = slot
  *	2:0 = function
  *	2:0 = function
  */
  */
-#define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_DEVFN(slot, func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
 
 
@@ -66,7 +66,6 @@ enum pci_mmap_state {
 #define PCI_DMA_FROMDEVICE	2
 #define PCI_DMA_FROMDEVICE	2
 #define PCI_DMA_NONE		3
 #define PCI_DMA_NONE		3
 
 
-#define DEVICE_COUNT_COMPATIBLE	4
 #define DEVICE_COUNT_RESOURCE	12
 #define DEVICE_COUNT_RESOURCE	12
 
 
 typedef int __bitwise pci_power_t;
 typedef int __bitwise pci_power_t;
@@ -129,6 +128,7 @@ struct pci_cap_saved_state {
 	u32 data[0];
 	u32 data[0];
 };
 };
 
 
+struct pcie_link_state;
 /*
 /*
  * The pci_dev structure is used to describe PCI devices.
  * The pci_dev structure is used to describe PCI devices.
  */
  */
@@ -164,13 +164,13 @@ struct pci_dev {
 					   this is D0-D3, D0 being fully functional,
 					   this is D0-D3, D0 being fully functional,
 					   and D3 being off. */
 					   and D3 being off. */
 
 
+#ifdef CONFIG_PCIEASPM
+	struct pcie_link_state	*link_state;	/* ASPM link state. */
+#endif
+
 	pci_channel_state_t error_state;	/* current connectivity state */
 	pci_channel_state_t error_state;	/* current connectivity state */
 	struct	device	dev;		/* Generic device interface */
 	struct	device	dev;		/* Generic device interface */
 
 
-	/* device is compatible with these IDs */
-	unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
-	unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];
-
 	int		cfg_size;	/* Size of configuration space */
 	int		cfg_size;	/* Size of configuration space */
 
 
 	/*
 	/*
@@ -219,7 +219,7 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
 }
 }
 
 
 static inline struct pci_cap_saved_state *pci_find_saved_cap(
 static inline struct pci_cap_saved_state *pci_find_saved_cap(
-	struct pci_dev *pci_dev,char cap)
+	struct pci_dev *pci_dev, char cap)
 {
 {
 	struct pci_cap_saved_state *tmp;
 	struct pci_cap_saved_state *tmp;
 	struct hlist_node *pos;
 	struct hlist_node *pos;
@@ -278,13 +278,13 @@ struct pci_bus {
 	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
 	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
 	pci_bus_flags_t bus_flags;	/* Inherited by child busses */
 	pci_bus_flags_t bus_flags;	/* Inherited by child busses */
 	struct device		*bridge;
 	struct device		*bridge;
-	struct class_device	class_dev;
+	struct device		dev;
 	struct bin_attribute	*legacy_io; /* legacy I/O for this bus */
 	struct bin_attribute	*legacy_io; /* legacy I/O for this bus */
 	struct bin_attribute	*legacy_mem; /* legacy mem */
 	struct bin_attribute	*legacy_mem; /* legacy mem */
 };
 };
 
 
 #define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
 #define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
-#define to_pci_bus(n)	container_of(n, struct pci_bus, class_dev)
+#define to_pci_bus(n)	container_of(n, struct pci_bus, dev)
 
 
 /*
 /*
  * Error values that may be returned by PCI functions.
  * Error values that may be returned by PCI functions.
@@ -314,8 +314,8 @@ struct pci_raw_ops {
 extern struct pci_raw_ops *raw_pci_ops;
 extern struct pci_raw_ops *raw_pci_ops;
 
 
 struct pci_bus_region {
 struct pci_bus_region {
-	unsigned long start;
-	unsigned long end;
+	resource_size_t start;
+	resource_size_t end;
 };
 };
 
 
 struct pci_dynids {
 struct pci_dynids {
@@ -351,11 +351,10 @@ enum pci_ers_result {
 };
 };
 
 
 /* PCI bus error event callbacks */
 /* PCI bus error event callbacks */
-struct pci_error_handlers
-{
+struct pci_error_handlers {
 	/* PCI bus error detected on this device */
 	/* PCI bus error detected on this device */
 	pci_ers_result_t (*error_detected)(struct pci_dev *dev,
 	pci_ers_result_t (*error_detected)(struct pci_dev *dev,
-	                      enum pci_channel_state error);
+					   enum pci_channel_state error);
 
 
 	/* MMIO has been re-enabled, but not DMA */
 	/* MMIO has been re-enabled, but not DMA */
 	pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);
 	pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);
@@ -390,7 +389,7 @@ struct pci_driver {
 	struct pci_dynids dynids;
 	struct pci_dynids dynids;
 };
 };
 
 
-#define	to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
+#define	to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
 
 
 /**
 /**
  * PCI_DEVICE - macro used to describe a specific pci device
  * PCI_DEVICE - macro used to describe a specific pci device
@@ -448,7 +447,7 @@ extern int no_pci_devices(void);
 
 
 void pcibios_fixup_bus(struct pci_bus *);
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
-char *pcibios_setup (char *str);
+char *pcibios_setup(char *str);
 
 
 /* Used only when drivers/pci/setup.c is used */
 /* Used only when drivers/pci/setup.c is used */
 void pcibios_align_resource(void *, struct resource *, resource_size_t,
 void pcibios_align_resource(void *, struct resource *, resource_size_t,
@@ -459,8 +458,10 @@ void pcibios_update_irq(struct pci_dev *, int irq);
 
 
 extern struct pci_bus *pci_find_bus(int domain, int busnr);
 extern struct pci_bus *pci_find_bus(int domain, int busnr);
 void pci_bus_add_devices(struct pci_bus *bus);
 void pci_bus_add_devices(struct pci_bus *bus);
-struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
-static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
+				      struct pci_ops *ops, void *sysdata);
+static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
+					   void *sysdata)
 {
 {
 	struct pci_bus *root_bus;
 	struct pci_bus *root_bus;
 	root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
 	root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
@@ -468,15 +469,18 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s
 		pci_bus_add_devices(root_bus);
 		pci_bus_add_devices(root_bus);
 	return root_bus;
 	return root_bus;
 }
 }
-struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
-struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
+struct pci_bus *pci_create_bus(struct device *parent, int bus,
+			       struct pci_ops *ops, void *sysdata);
+struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
+				int busnr);
 int pci_scan_slot(struct pci_bus *bus, int devfn);
 int pci_scan_slot(struct pci_bus *bus, int devfn);
-struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
+struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn);
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
 unsigned int pci_scan_child_bus(struct pci_bus *bus);
 unsigned int pci_scan_child_bus(struct pci_bus *bus);
 int __must_check pci_bus_add_device(struct pci_dev *dev);
 int __must_check pci_bus_add_device(struct pci_dev *dev);
 void pci_read_bridge_bases(struct pci_bus *child);
 void pci_read_bridge_bases(struct pci_bus *child);
-struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res);
+struct resource *pci_find_parent_resource(const struct pci_dev *dev,
+					  struct resource *res);
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
 extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
@@ -489,15 +493,19 @@ extern void pci_sort_breadthfirst(void);
 /* Generic PCI functions exported to card drivers */
 /* Generic PCI functions exported to card drivers */
 
 
 #ifdef CONFIG_PCI_LEGACY
 #ifdef CONFIG_PCI_LEGACY
-struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
-struct pci_dev __deprecated *pci_find_slot (unsigned int bus, unsigned int devfn);
+struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
+					     unsigned int device,
+					     const struct pci_dev *from);
+struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
+					   unsigned int devfn);
 #endif /* CONFIG_PCI_LEGACY */
 #endif /* CONFIG_PCI_LEGACY */
 
 
-int pci_find_capability (struct pci_dev *dev, int cap);
-int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
-int pci_find_ext_capability (struct pci_dev *dev, int cap);
-int pci_find_ht_capability (struct pci_dev *dev, int ht_cap);
-int pci_find_next_ht_capability (struct pci_dev *dev, int pos, int ht_cap);
+int pci_find_capability(struct pci_dev *dev, int cap);
+int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
+int pci_find_ext_capability(struct pci_dev *dev, int cap);
+int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
+int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
+void pcie_wait_pending_transaction(struct pci_dev *dev);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 
 
 struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
@@ -505,49 +513,58 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
 struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
 				struct pci_dev *from);
 				struct pci_dev *from);
 
 
-struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
+struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
 				unsigned int ss_vendor, unsigned int ss_device,
 				unsigned int ss_vendor, unsigned int ss_device,
 				struct pci_dev *from);
 				struct pci_dev *from);
-struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
-struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn);
-struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
+struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
+struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
+struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
 int pci_dev_present(const struct pci_device_id *ids);
 int pci_dev_present(const struct pci_device_id *ids);
 const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
 const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
 
 
-int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
-int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
-int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
-int pci_bus_write_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 val);
-int pci_bus_write_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 val);
-int pci_bus_write_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 val);
+int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+			     int where, u8 *val);
+int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn,
+			     int where, u16 *val);
+int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+			      int where, u32 *val);
+int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn,
+			      int where, u8 val);
+int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn,
+			      int where, u16 val);
+int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+			       int where, u32 val);
 
 
 static inline int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
 static inline int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
 {
 {
-	return pci_bus_read_config_byte (dev->bus, dev->devfn, where, val);
+	return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
 }
 }
 static inline int pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
 static inline int pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
 {
 {
-	return pci_bus_read_config_word (dev->bus, dev->devfn, where, val);
+	return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
 }
 }
-static inline int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val)
+static inline int pci_read_config_dword(struct pci_dev *dev, int where,
+					u32 *val)
 {
 {
-	return pci_bus_read_config_dword (dev->bus, dev->devfn, where, val);
+	return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
 }
 }
 static inline int pci_write_config_byte(struct pci_dev *dev, int where, u8 val)
 static inline int pci_write_config_byte(struct pci_dev *dev, int where, u8 val)
 {
 {
-	return pci_bus_write_config_byte (dev->bus, dev->devfn, where, val);
+	return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
 }
 }
 static inline int pci_write_config_word(struct pci_dev *dev, int where, u16 val)
 static inline int pci_write_config_word(struct pci_dev *dev, int where, u16 val)
 {
 {
-	return pci_bus_write_config_word (dev->bus, dev->devfn, where, val);
+	return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
 }
 }
-static inline int pci_write_config_dword(struct pci_dev *dev, int where, u32 val)
+static inline int pci_write_config_dword(struct pci_dev *dev, int where,
+					 u32 val)
 {
 {
-	return pci_bus_write_config_dword (dev->bus, dev->devfn, where, val);
+	return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
 }
 }
 
 
 int __must_check pci_enable_device(struct pci_dev *dev);
 int __must_check pci_enable_device(struct pci_dev *dev);
-int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask);
+int __must_check pci_enable_device_io(struct pci_dev *dev);
+int __must_check pci_enable_device_mem(struct pci_dev *dev);
 int __must_check pci_reenable_device(struct pci_dev *);
 int __must_check pci_reenable_device(struct pci_dev *);
 int __must_check pcim_enable_device(struct pci_dev *pdev);
 int __must_check pcim_enable_device(struct pci_dev *pdev);
 void pcim_pin_device(struct pci_dev *pdev);
 void pcim_pin_device(struct pci_dev *pdev);
@@ -576,14 +593,11 @@ int pcie_set_readrq(struct pci_dev *dev, int rq);
 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
 int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
-void pci_restore_bars(struct pci_dev *dev);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
 
 
 /* ROM control related routines */
 /* ROM control related routines */
 void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
 void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
-void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
-void pci_remove_rom(struct pci_dev *pdev);
 size_t pci_get_rom_size(void __iomem *rom, size_t size);
 size_t pci_get_rom_size(void __iomem *rom, size_t size);
 
 
 /* Power management related routines */
 /* Power management related routines */
@@ -594,7 +608,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
 int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
 int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
 
 
 /* Functions for PCI Hotplug drivers to use */
 /* Functions for PCI Hotplug drivers to use */
-int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
+int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
 
 
 /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
 /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
 void pci_bus_assign_resources(struct pci_bus *bus);
 void pci_bus_assign_resources(struct pci_bus *bus);
@@ -631,16 +645,18 @@ static inline int __must_check pci_register_driver(struct pci_driver *driver)
 	return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
 	return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
 }
 }
 
 
-void pci_unregister_driver(struct pci_driver *);
-void pci_remove_behind_bridge(struct pci_dev *);
-struct pci_driver *pci_dev_driver(const struct pci_dev *);
-const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, struct pci_dev *dev);
-int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
+void pci_unregister_driver(struct pci_driver *dev);
+void pci_remove_behind_bridge(struct pci_dev *dev);
+struct pci_driver *pci_dev_driver(const struct pci_dev *dev);
+const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
+					 struct pci_dev *dev);
+int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
+		    int pass);
 
 
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 		  void *userdata);
 		  void *userdata);
 int pci_cfg_space_size(struct pci_dev *dev);
 int pci_cfg_space_size(struct pci_dev *dev);
-unsigned char pci_bus_max_busnr(struct pci_bus* bus);
+unsigned char pci_bus_max_busnr(struct pci_bus *bus);
 
 
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 
 
@@ -669,19 +685,36 @@ struct msix_entry {
 
 
 
 
 #ifndef CONFIG_PCI_MSI
 #ifndef CONFIG_PCI_MSI
-static inline int pci_enable_msi(struct pci_dev *dev) {return -1;}
-static inline void pci_disable_msi(struct pci_dev *dev) {}
-static inline int pci_enable_msix(struct pci_dev* dev,
-	struct msix_entry *entries, int nvec) {return -1;}
-static inline void pci_disable_msix(struct pci_dev *dev) {}
-static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+static inline int pci_enable_msi(struct pci_dev *dev)
+{
+	return -1;
+}
+
+static inline void pci_disable_msi(struct pci_dev *dev)
+{ }
+
+static inline int pci_enable_msix(struct pci_dev *dev,
+				  struct msix_entry *entries, int nvec)
+{
+	return -1;
+}
+
+static inline void pci_disable_msix(struct pci_dev *dev)
+{ }
+
+static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev)
+{ }
+
+static inline void pci_restore_msi_state(struct pci_dev *dev)
+{ }
 #else
 #else
 extern int pci_enable_msi(struct pci_dev *dev);
 extern int pci_enable_msi(struct pci_dev *dev);
 extern void pci_disable_msi(struct pci_dev *dev);
 extern void pci_disable_msi(struct pci_dev *dev);
-extern int pci_enable_msix(struct pci_dev* dev,
+extern int pci_enable_msix(struct pci_dev *dev,
 	struct msix_entry *entries, int nvec);
 	struct msix_entry *entries, int nvec);
 extern void pci_disable_msix(struct pci_dev *dev);
 extern void pci_disable_msix(struct pci_dev *dev);
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+extern void pci_restore_msi_state(struct pci_dev *dev);
 #endif
 #endif
 
 
 #ifdef CONFIG_HT_IRQ
 #ifdef CONFIG_HT_IRQ
@@ -702,7 +735,11 @@ extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
 extern int pci_domains_supported;
 extern int pci_domains_supported;
 #else
 #else
 enum { pci_domains_supported = 0 };
 enum { pci_domains_supported = 0 };
-static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+	return 0;
+}
+
 static inline int pci_proc_domain(struct pci_bus *bus)
 static inline int pci_proc_domain(struct pci_bus *bus)
 {
 {
 	return 0;
 	return 0;
@@ -716,67 +753,161 @@ static inline int pci_proc_domain(struct pci_bus *bus)
  *  these as simple inline functions to avoid hair in drivers.
  *  these as simple inline functions to avoid hair in drivers.
  */
  */
 
 
-#define _PCI_NOP(o,s,t) \
-	static inline int pci_##o##_config_##s (struct pci_dev *dev, int where, t val) \
+#define _PCI_NOP(o, s, t) \
+	static inline int pci_##o##_config_##s(struct pci_dev *dev, \
+						int where, t val) \
 		{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
 		{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
-#define _PCI_NOP_ALL(o,x)	_PCI_NOP(o,byte,u8 x) \
-				_PCI_NOP(o,word,u16 x) \
-				_PCI_NOP(o,dword,u32 x)
+
+#define _PCI_NOP_ALL(o, x)	_PCI_NOP(o, byte, u8 x) \
+				_PCI_NOP(o, word, u16 x) \
+				_PCI_NOP(o, dword, u32 x)
 _PCI_NOP_ALL(read, *)
 _PCI_NOP_ALL(read, *)
 _PCI_NOP_ALL(write,)
 _PCI_NOP_ALL(write,)
 
 
-static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_find_device(unsigned int vendor,
+					      unsigned int device,
+					      const struct pci_dev *from)
+{
+	return NULL;
+}
 
 
-static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
-{ return NULL; }
+static inline struct pci_dev *pci_find_slot(unsigned int bus,
+					    unsigned int devfn)
+{
+	return NULL;
+}
 
 
 static inline struct pci_dev *pci_get_device(unsigned int vendor,
 static inline struct pci_dev *pci_get_device(unsigned int vendor,
-				unsigned int device, struct pci_dev *from)
-{ return NULL; }
+					     unsigned int device,
+					     struct pci_dev *from)
+{
+	return NULL;
+}
 
 
 static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor,
 static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor,
-				unsigned int device, struct pci_dev *from)
-{ return NULL; }
+						     unsigned int device,
+						     struct pci_dev *from)
+{
+	return NULL;
+}
 
 
-static inline struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
-unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_get_subsys(unsigned int vendor,
+					     unsigned int device,
+					     unsigned int ss_vendor,
+					     unsigned int ss_device,
+					     struct pci_dev *from)
+{
+	return NULL;
+}
 
 
-static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_get_class(unsigned int class,
+					    struct pci_dev *from)
+{
+	return NULL;
+}
 
 
 #define pci_dev_present(ids)	(0)
 #define pci_dev_present(ids)	(0)
 #define no_pci_devices()	(1)
 #define no_pci_devices()	(1)
 #define pci_find_present(ids)	(NULL)
 #define pci_find_present(ids)	(NULL)
 #define pci_dev_put(dev)	do { } while (0)
 #define pci_dev_put(dev)	do { } while (0)
 
 
-static inline void pci_set_master(struct pci_dev *dev) { }
-static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
-static inline void pci_disable_device(struct pci_dev *dev) { }
-static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; }
-static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
-static inline int __pci_register_driver(struct pci_driver *drv, struct module *owner) { return 0;}
-static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
-static inline void pci_unregister_driver(struct pci_driver *drv) { }
-static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
-static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
-static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
+static inline void pci_set_master(struct pci_dev *dev)
+{ }
+
+static inline int pci_enable_device(struct pci_dev *dev)
+{
+	return -EIO;
+}
+
+static inline void pci_disable_device(struct pci_dev *dev)
+{ }
+
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+	return -EIO;
+}
+
+static inline int pci_assign_resource(struct pci_dev *dev, int i)
+{
+	return -EBUSY;
+}
+
+static inline int __pci_register_driver(struct pci_driver *drv,
+					struct module *owner)
+{
+	return 0;
+}
+
+static inline int pci_register_driver(struct pci_driver *drv)
+{
+	return 0;
+}
+
+static inline void pci_unregister_driver(struct pci_driver *drv)
+{ }
+
+static inline int pci_find_capability(struct pci_dev *dev, int cap)
+{
+	return 0;
+}
+
+static inline int pci_find_next_capability(struct pci_dev *dev, u8 post,
+					   int cap)
+{
+	return 0;
+}
+
+static inline int pci_find_ext_capability(struct pci_dev *dev, int cap)
+{
+	return 0;
+}
+
+static inline void pcie_wait_pending_transaction(struct pci_dev *dev)
+{ }
 
 
 /* Power management related routines */
 /* Power management related routines */
-static inline int pci_save_state(struct pci_dev *dev) { return 0; }
-static inline int pci_restore_state(struct pci_dev *dev) { return 0; }
-static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { return 0; }
-static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; }
-static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; }
+static inline int pci_save_state(struct pci_dev *dev)
+{
+	return 0;
+}
+
+static inline int pci_restore_state(struct pci_dev *dev)
+{
+	return 0;
+}
+
+static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+{
+	return 0;
+}
+
+static inline pci_power_t pci_choose_state(struct pci_dev *dev,
+					   pm_message_t state)
+{
+	return PCI_D0;
+}
+
+static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
+				  int enable)
+{
+	return 0;
+}
+
+static inline int pci_request_regions(struct pci_dev *dev, const char *res_name)
+{
+	return -EIO;
+}
 
 
-static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; }
-static inline void pci_release_regions(struct pci_dev *dev) { }
+static inline void pci_release_regions(struct pci_dev *dev)
+{ }
 
 
 #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
 #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
 
 
-static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
-static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { }
+static inline void pci_block_user_cfg_access(struct pci_dev *dev)
+{ }
+
+static inline void pci_unblock_user_cfg_access(struct pci_dev *dev)
+{ }
 
 
 static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
 static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
 { return NULL; }
 { return NULL; }
@@ -797,27 +928,27 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
 
 
 /* these helpers provide future and backwards compatibility
 /* these helpers provide future and backwards compatibility
  * for accessing popular PCI BAR info */
  * for accessing popular PCI BAR info */
-#define pci_resource_start(dev,bar)   ((dev)->resource[(bar)].start)
-#define pci_resource_end(dev,bar)     ((dev)->resource[(bar)].end)
-#define pci_resource_flags(dev,bar)   ((dev)->resource[(bar)].flags)
+#define pci_resource_start(dev, bar)	((dev)->resource[(bar)].start)
+#define pci_resource_end(dev, bar)	((dev)->resource[(bar)].end)
+#define pci_resource_flags(dev, bar)	((dev)->resource[(bar)].flags)
 #define pci_resource_len(dev,bar) \
 #define pci_resource_len(dev,bar) \
-	((pci_resource_start((dev),(bar)) == 0 &&	\
-	  pci_resource_end((dev),(bar)) ==		\
-	  pci_resource_start((dev),(bar))) ? 0 :	\
-	  						\
-	 (pci_resource_end((dev),(bar)) -		\
-	  pci_resource_start((dev),(bar)) + 1))
+	((pci_resource_start((dev), (bar)) == 0 &&	\
+	  pci_resource_end((dev), (bar)) ==		\
+	  pci_resource_start((dev), (bar))) ? 0 :	\
+							\
+	 (pci_resource_end((dev), (bar)) -		\
+	  pci_resource_start((dev), (bar)) + 1))
 
 
 /* Similar to the helpers above, these manipulate per-pci_dev
 /* Similar to the helpers above, these manipulate per-pci_dev
  * driver-specific data.  They are really just a wrapper around
  * driver-specific data.  They are really just a wrapper around
  * the generic device structure functions of these calls.
  * the generic device structure functions of these calls.
  */
  */
-static inline void *pci_get_drvdata (struct pci_dev *pdev)
+static inline void *pci_get_drvdata(struct pci_dev *pdev)
 {
 {
 	return dev_get_drvdata(&pdev->dev);
 	return dev_get_drvdata(&pdev->dev);
 }
 }
 
 
-static inline void pci_set_drvdata (struct pci_dev *pdev, void *data)
+static inline void pci_set_drvdata(struct pci_dev *pdev, void *data)
 {
 {
 	dev_set_drvdata(&pdev->dev, data);
 	dev_set_drvdata(&pdev->dev, data);
 }
 }
@@ -836,7 +967,7 @@ static inline char *pci_name(struct pci_dev *pdev)
  */
  */
 #ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
 #ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
 static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
 static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
-                const struct resource *rsrc, resource_size_t *start,
+		const struct resource *rsrc, resource_size_t *start,
 		resource_size_t *end)
 		resource_size_t *end)
 {
 {
 	*start = rsrc->start;
 	*start = rsrc->start;
@@ -888,9 +1019,9 @@ enum pci_fixup_pass {
 
 
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 
 
-void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
+void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
 void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
 void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
-void __iomem * const * pcim_iomap_table(struct pci_dev *pdev);
+void __iomem * const *pcim_iomap_table(struct pci_dev *pdev);
 int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
 int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
 void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask);
 void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask);
 
 

+ 8 - 0
include/linux/pci_regs.h

@@ -395,9 +395,17 @@
 #define  PCI_EXP_DEVSTA_AUXPD	0x10	/* AUX Power Detected */
 #define  PCI_EXP_DEVSTA_AUXPD	0x10	/* AUX Power Detected */
 #define  PCI_EXP_DEVSTA_TRPND	0x20	/* Transactions Pending */
 #define  PCI_EXP_DEVSTA_TRPND	0x20	/* Transactions Pending */
 #define PCI_EXP_LNKCAP		12	/* Link Capabilities */
 #define PCI_EXP_LNKCAP		12	/* Link Capabilities */
+#define  PCI_EXP_LNKCAP_ASPMS	0xc00	/* ASPM Support */
+#define  PCI_EXP_LNKCAP_L0SEL	0x7000	/* L0s Exit Latency */
+#define  PCI_EXP_LNKCAP_L1EL	0x38000	/* L1 Exit Latency */
+#define  PCI_EXP_LNKCAP_CLKPM	0x40000	/* L1 Clock Power Management */
 #define PCI_EXP_LNKCTL		16	/* Link Control */
 #define PCI_EXP_LNKCTL		16	/* Link Control */
+#define  PCI_EXP_LNKCTL_RL	0x20	/* Retrain Link */
+#define  PCI_EXP_LNKCTL_CCC	0x40	/* Common Clock COnfiguration */
 #define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100	/* Enable clkreq */
 #define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100	/* Enable clkreq */
 #define PCI_EXP_LNKSTA		18	/* Link Status */
 #define PCI_EXP_LNKSTA		18	/* Link Status */
+#define  PCI_EXP_LNKSTA_LT	0x800	/* Link Training */
+#define  PCI_EXP_LNKSTA_SLC	0x1000	/* Slot Clock Configuration */
 #define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
 #define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
 #define PCI_EXP_SLTCTL		24	/* Slot Control */
 #define PCI_EXP_SLTCTL		24	/* Slot Control */
 #define PCI_EXP_SLTSTA		26	/* Slot Status */
 #define PCI_EXP_SLTSTA		26	/* Slot Status */

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini