提交 215e871a 编写于 作者: L Linus Torvalds

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()
  ...
...@@ -274,8 +274,6 @@ the PCI device by calling pci_enable_device(). This will: ...@@ -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. ...@@ -605,40 +603,7 @@ device lists. This is still possible but discouraged.
10. pci_enable_device_bars() and Legacy I/O Port space 10. MMIO Space and "Write Posting"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
......
...@@ -318,11 +318,6 @@ config PCI ...@@ -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
......
...@@ -577,11 +577,6 @@ config PCI ...@@ -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
......
...@@ -322,11 +322,6 @@ config PCI ...@@ -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
......
...@@ -359,11 +359,6 @@ config PCI ...@@ -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
......
...@@ -145,11 +145,6 @@ config PCI ...@@ -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
......
...@@ -1961,11 +1961,6 @@ config PCI ...@@ -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
......
...@@ -6,11 +6,6 @@ config PCI ...@@ -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
......
...@@ -351,11 +351,6 @@ config PCI ...@@ -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
......
...@@ -1369,11 +1369,6 @@ config PCI ...@@ -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
......
...@@ -30,8 +30,8 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) ...@@ -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. " dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
"Disabling irq balancing and affinity\n"); "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) ...@@ -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) ...@@ -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", dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
force_hpet_address); "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) ...@@ -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", dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
force_hpet_address); "0x%lx\n", force_hpet_address);
} }
} }
...@@ -208,8 +211,8 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev) ...@@ -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", dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
force_hpet_address); force_hpet_address);
return; return;
} }
...@@ -229,14 +232,14 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev) ...@@ -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", dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
force_hpet_address); "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) ...@@ -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", dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
force_hpet_address); force_hpet_address);
return; return;
} }
...@@ -309,14 +312,14 @@ static void vt8237_force_enable_hpet(struct pci_dev *dev) ...@@ -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", dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
force_hpet_address); "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) ...@@ -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;
......
...@@ -17,7 +17,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, " dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
"enabled onboard soundcard.\n"); "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,
......
...@@ -174,11 +174,6 @@ config PCI ...@@ -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
......
...@@ -229,7 +229,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi ...@@ -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;
} }
......
...@@ -492,7 +492,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev, ...@@ -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;
......
...@@ -156,8 +156,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ...@@ -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 */ * BARS too and we will freak out other bits of the kernel
if (pci_enable_device_bars(dev, 1<<2)) { *
* 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;
} }
......
...@@ -228,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); ...@@ -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) ...@@ -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);
......
...@@ -108,6 +108,7 @@ int pci_bus_add_device(struct pci_dev *dev) ...@@ -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) ...@@ -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 " dev_err(&dev->dev, "Error registering pci_bus"
"bridge symlink, continuing...\n"); " device bridge symlink,"
" continuing...\n");
} }
} }
} }
...@@ -204,7 +213,6 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), ...@@ -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);
......
...@@ -25,6 +25,7 @@ ...@@ -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) ...@@ -263,8 +264,8 @@ parse_dmar_table(void)
if (!dmar) if (!dmar)
return -ENODEV; return -ENODEV;
if (!dmar->width) { if (dmar->width < PAGE_SHIFT_4K - 1) {
printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n"); printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
return -EINVAL; return -EINVAL;
} }
...@@ -301,11 +302,24 @@ parse_dmar_table(void) ...@@ -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;
} }
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
# #
menuconfig HOTPLUG_PCI menuconfig HOTPLUG_PCI
tristate "Support for PCI Hotplug (EXPERIMENTAL)" tristate "Support for PCI Hotplug"
depends on PCI && EXPERIMENTAL && 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,7 +3,6 @@ ...@@ -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 ...@@ -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
......
...@@ -113,7 +113,6 @@ struct acpiphp_slot { ...@@ -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 */
}; };
......
...@@ -102,7 +102,7 @@ static int is_ejectable(acpi_handle handle) ...@@ -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) ...@@ -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) ...@@ -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 ;
......
...@@ -39,6 +39,7 @@ ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) { ...@@ -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) ...@@ -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) ...@@ -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. */ /* queue work item to blow away this sysfs entry and other parts. */
remove_slot(dslot); 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) ...@@ -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) ...@@ -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();
} }
......
...@@ -761,10 +761,13 @@ static void ibm_unconfigure_device(struct pci_func *func) ...@@ -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); temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
if (temp) 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) ...@@ -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) ...@@ -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");
......
...@@ -137,7 +137,7 @@ static int get_##name (struct hotplug_slot *slot, type *value) \ ...@@ -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) ...@@ -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;
} }
......
...@@ -82,24 +82,18 @@ struct event_info { ...@@ -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); ...@@ -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)
{ {
......
...@@ -453,13 +453,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ ...@@ -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 */ dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn), pdev->irq);
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);
/* 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_ ...@@ -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) ...@@ -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
......
...@@ -37,8 +37,6 @@ ...@@ -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) ...@@ -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) ...@@ -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 @@ static int board_added(struct slot *p_slot) ...@@ -281,8 +270,6 @@ static int board_added(struct slot *p_slot)
*/ */
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) ...@@ -290,11 +277,7 @@ static int remove_board(struct slot *p_slot)
if (retval) if (retval)
return retval; return retval;
device = p_slot->device; dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
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);
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) ...@@ -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);
......
...@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = pcie_init_hardware_part1(ctrl, dev);
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); if (rc)
if (rc) { goto abort;
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;
}
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) ...@@ -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) ...@@ -1224,82 +1380,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
} }
} }
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); rc = pcie_init_hardware_part2(ctrl, dev);
if (rc) { if (rc == 0) {
err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); ctrl->hpc_ops = &pciehp_hpc_ops;
goto abort_free_irq; 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:
abort_free_ctlr:
return -1; return -1;
} }
...@@ -105,12 +105,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) ...@@ -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; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
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)));
if (!pos) if (!pos)
return; return;
...@@ -248,11 +243,15 @@ int pciehp_unconfigure_device(struct slot *p_slot) ...@@ -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) ...@@ -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) { if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
ret = p_slot->hpc_ops->get_adapter_status(p_slot, pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
&presence); if (bctl & PCI_BRIDGE_CTL_VGA) {
if (!ret && presence) { err("Cannot remove display device %s\n",
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, pci_name(temp));
&bctl); pci_dev_put(temp);
if (bctl & PCI_BRIDGE_CTL_VGA) { continue;
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) ...@@ -288,4 +292,3 @@ int pciehp_unconfigure_device(struct slot *p_slot)
return rc; return rc;
} }
...@@ -74,7 +74,6 @@ struct slot { ...@@ -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;
......
...@@ -64,19 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state) ...@@ -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) ...@@ -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) {
......
...@@ -33,23 +33,31 @@ ...@@ -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;
int retval = -ENOENT;
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 = { static struct hotplug_slot_attribute php_attr_address = {
.attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO}, .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
.show = location_read_file, .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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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 */ /* remove "address" file */
sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr); 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) ...@@ -166,8 +168,8 @@ int rpaphp_register_slot(struct slot *slot)
return retval; return retval;
} }
/* create "phy_location" file */ /* create "address" file */
retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr); 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) ...@@ -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, info("Slot [%s] registered\n", slot->name);
slot->location);
return 0; return 0;
sysfs_fail: sysfs_fail:
......
...@@ -597,7 +597,7 @@ static void hpc_release_ctlr(struct controller *ctrl) ...@@ -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 |
......
...@@ -1781,7 +1781,7 @@ __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, ...@@ -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)
......
...@@ -25,6 +25,51 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
}
}
...@@ -156,13 +156,13 @@ acpi_run_osc ( ...@@ -156,13 +156,13 @@ acpi_run_osc (
} }
/** /**
* 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) ...@@ -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) ...@@ -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
......
...@@ -186,13 +186,11 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, ...@@ -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; current->mempolicy = NULL; /* fall back to system default policy */
mpol_get(current->mempolicy);
#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;
......
...@@ -21,6 +21,7 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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
......
...@@ -18,6 +18,7 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -713,29 +745,51 @@ int pci_reenable_device(struct pci_dev *dev)
return 0; return 0;
} }
/** static int __pci_enable_device_flags(struct pci_dev *dev,
* pci_enable_device_bars - Initialize some of a device for use resource_size_t flags)
* @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)
{ {
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) ...@@ -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) ...@@ -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); ...@@ -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,8 +6,10 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); ...@@ -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 pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev,
extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); 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) { } ...@@ -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) ...@@ -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 *
......
...@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE ...@@ -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.
...@@ -2,6 +2,9 @@ ...@@ -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
......
...@@ -31,26 +31,16 @@ int aer_osc_setup(struct pcie_device *pciedev) ...@@ -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); acpi_handle handle = 0;
struct pci_bus *parent;
while (!handle) { /* Find root host bridge */
if (!pdev || !pdev->bus->parent) while (pdev->bus && pdev->bus->self)
break; pdev = pdev->bus->self;
parent = pdev->bus->parent; handle = acpi_get_pci_rootbridge_handle(
if (!parent->self) pci_domain_nr(pdev->bus), pdev->bus->number);
/* 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;
}
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);
......
此差异已折叠。
...@@ -192,9 +192,8 @@ static int get_port_device_capability(struct pci_dev *dev) ...@@ -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 */ /* PME Capable - root port capability */
pos = pci_find_capability(dev, PCI_CAP_ID_PME); if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
if (pos)
services |= PCIE_PORT_SERVICE_PME; services |= PCIE_PORT_SERVICE_PME;
pos = PCI_CFG_SPACE_SIZE; pos = PCI_CFG_SPACE_SIZE;
......
...@@ -9,6 +9,7 @@ ...@@ -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) ...@@ -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) ...@@ -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); device_remove_bin_file(&b->dev, b->legacy_io);
class_device_remove_bin_file(&b->class_dev, b->legacy_mem); 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; } ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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; /* initialize some portions of the bus device, but don't register it
sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr); * now as the parent is not properly set up yet. This device will get
retval = class_device_register(&child->class_dev); * registered later in pci_bus_add_devices()
if (retval) */
goto error_register; child->dev.class = &pcibus_class;
retval = class_device_create_file(&child->class_dev, sprintf(child->dev.bus_id, "%04x:%02x", pci_domain_nr(child), busnr);
&class_device_attr_cpuaffinity);
if (retval)
goto error_file_create;
/* /*
* 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) ...@@ -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) ...@@ -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 ...@@ -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", "wholly" : "partially",
bus->self->transparent ? " transparent" : " ", 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) ...@@ -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) ...@@ -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, ...@@ -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; b->dev.class = &pcibus_class;
sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus); b->dev.parent = b->bridge;
error = class_device_register(&b->class_dev); 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: dev_create_file_err:
class_device_remove_file(&b->class_dev, &class_device_attr_cpuaffinity); device_unregister(&b->dev);
class_dev_create_file_err:
class_device_unregister(&b->class_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 @@ struct pci_bus * pci_create_bus(struct device *parent, ...@@ -1140,7 +1130,6 @@ struct pci_bus * pci_create_bus(struct device *parent,
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); ...@@ -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
......
...@@ -11,6 +11,7 @@ ...@@ -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 { ...@@ -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 ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -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
此差异已折叠。
#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) ...@@ -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) ...@@ -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, device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
&class_device_attr_cpuaffinity); device_unregister(&pci_bus->dev);
sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge");
class_device_unregister(&pci_bus->class_dev);
} }
EXPORT_SYMBOL(pci_remove_bus); EXPORT_SYMBOL(pci_remove_bus);
......
...@@ -162,6 +162,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
...@@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus) ...@@ -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", printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
region.start, region.end); (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) ...@@ -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", printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
region.start, region.end); (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) ...@@ -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", printk(KERN_INFO " PREFETCH window: 0x%08lx-0x%08lx\n",
region.start, region.end); (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) ...@@ -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", printk(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
region.start, region.end); (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) ...@@ -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) ...@@ -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) ...@@ -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", DBG(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
region.start, region.end); (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) ...@@ -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", #ifdef CONFIG_RESOURCES_64BIT
region.start, region.end); 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) ...@@ -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. */ /* Set the upper 32 bits of PREF base & limit. */
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); 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) ...@@ -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; resource_size_t min_align, align, size;
unsigned long aligns[12]; /* Alignments from 1Mb to 2Gb */ 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 ...@@ -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 ...@@ -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->start,
(unsigned long long)r->end); (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 ...@@ -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)
......
...@@ -51,10 +51,12 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) ...@@ -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) ...@@ -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)
{ {
......
...@@ -34,7 +34,6 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
...@@ -2296,10 +2296,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) ...@@ -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;
......
...@@ -2268,6 +2268,7 @@ typedef struct scsi_qla_host { ...@@ -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
......
...@@ -1564,7 +1564,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -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) ...@@ -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)) if (mem_only) {
goto probe_out; 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) ...@@ -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) ...@@ -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");
......
...@@ -190,9 +190,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) ...@@ -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 " dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
"failed (BIOS bug ?) %08x\n", " (BIOS bug?) %08x\n",
pdev->dev.bus_id, "OHCI",
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) ...@@ -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", dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");
pdev->dev.bus_id, "EHCI");
#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) ...@@ -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 " dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
"failed (BIOS bug ?) %08x\n", " (BIOS bug?) %08x\n", cap);
pdev->dev.bus_id, "EHCI", 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) ...@@ -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 " dev_warn(&pdev->dev, "EHCI: unrecognized capability "
"capability %02x\n", "%02x\n", cap & 0xff);
pdev->dev.bus_id, "EHCI",
cap & 0xff);
break; break;
} }
offset = (cap >> 8) & 0xff; offset = (cap >> 8) & 0xff;
} }
if (!count) if (!count)
printk(KERN_DEBUG "%s %s: capability loop?\n", dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n");
pdev->dev.bus_id, "EHCI");
/* /*
* halt EHCI & disable its interrupts in any case * halt EHCI & disable its interrupts in any case
......
/*
* 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 */
...@@ -48,7 +48,15 @@ ...@@ -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; ...@@ -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_ */
此差异已折叠。
...@@ -395,9 +395,17 @@ ...@@ -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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册