Merge branches 'pci/host-altera', 'pci/host-imx6', 'pci/host-keystone', 'pci/host...
authorBjorn Helgaas <bhelgaas@google.com>
Tue, 15 Mar 2016 13:55:19 +0000 (08:55 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 15 Mar 2016 13:55:19 +0000 (08:55 -0500)
* pci/host-altera:
  PCI: altera: Fix altera_pcie_link_is_up()

* pci/host-imx6:
  PCI: imx6: Add DT bindings to configure PHY Tx driver settings

* pci/host-keystone:
  PCI: keystone: Defer probing if devm_phy_get() returns -EPROBE_DEFER

* pci/host-rcar:
  PCI: rcar: Depend on ARCH_RENESAS, not ARCH_SHMOBILE

* pci/host-tegra:
  PCI: tegra: Remove misleading PHYS_OFFSET
  PCI: tegra: Track bus -> CPU mapping
  PCI: tegra: Remove unused struct tegra_pcie.num_ports field
  PCI: tegra: Implement ->{add,remove}_bus() callbacks
  PCI: Add pci_ops.{add,remove}_bus() callbacks

* pci/host-thunder:
  PCI: thunder: Add driver for ThunderX-pass{1,2} on-chip devices
  PCI: thunder: Add PCIe host driver for ThunderX processors
  PCI: generic: Expose pci_host_common_probe() for use by other drivers
  PCI: generic: Add pci_host_common_probe(), based on gen_pci_probe()
  PCI: generic: Move structure definitions to separate header file

* pci/host-vmd:
  x86/PCI: VMD: Attach VMD resources to parent domain's resource tree
  x86/PCI: VMD: Set bus resource start to 0
  x86/PCI: VMD: Document code for maintainability

* pci/host-xilinx:
  microblaze/PCI: Support generic Xilinx AXI PCIe Host Bridge IP driver
  PCI: xilinx: Update Zynq binding with Microblaze node
  PCI: xilinx: Don't call pci_fixup_irqs() on Microblaze
  PCI: xilinx: Remove dependency on ARM-specific struct hw_pci
  PCI: xilinx: Use of_pci_get_host_bridge_resources() to parse DT

* pci/host-xilinx-nwl:
  PCI: xilinx-nwl: Add support for Xilinx NWL PCIe Host Controller

107 files changed:
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
Documentation/devicetree/bindings/pci/pci-thunder-ecam.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/pci-thunder-pem.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt [new file with mode: 0644]
MAINTAINERS
arch/alpha/include/asm/pci.h
arch/arm/Kconfig
arch/arm/include/asm/pci.h
arch/arm64/Kconfig
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/pci.h
arch/arm64/kernel/pci.c
arch/avr32/include/asm/pci.h
arch/blackfin/Kconfig
arch/blackfin/include/asm/pci.h
arch/cris/include/asm/pci.h
arch/frv/include/asm/pci.h
arch/ia64/Kconfig
arch/ia64/include/asm/pci.h
arch/m32r/Kconfig
arch/m68k/include/asm/pci.h
arch/microblaze/include/asm/pci.h
arch/mips/Kconfig
arch/mips/include/asm/pci.h
arch/mn10300/include/asm/pci.h
arch/parisc/include/asm/pci.h
arch/powerpc/Kconfig
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/pci.h
arch/s390/Kconfig
arch/s390/include/asm/pci.h
arch/sh/Kconfig
arch/sh/include/asm/pci.h
arch/sparc/include/asm/pci.h
arch/tile/Kconfig
arch/tile/include/asm/pci.h
arch/unicore32/include/asm/pci.h
arch/unicore32/include/mach/hardware.h
arch/x86/Kconfig
arch/x86/include/asm/pci.h
arch/x86/pci/common.c
arch/x86/pci/vmd.c
arch/xtensa/Kconfig
arch/xtensa/include/asm/pci.h
drivers/ata/pata_macio.c
drivers/char/agp/uninorth-agp.c
drivers/gpu/drm/bochs/bochs_drv.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/ide/pdc202xx_new.c
drivers/ide/pmac.c
drivers/macintosh/macio_asic.c
drivers/misc/cxl/pci.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/of/of_pci.c
drivers/parisc/Kconfig
drivers/pci/Kconfig
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/host/Kconfig
drivers/pci/host/Makefile
drivers/pci/host/pci-host-common.c [new file with mode: 0644]
drivers/pci/host/pci-host-common.h [new file with mode: 0644]
drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-imx6.c
drivers/pci/host/pci-keystone.c
drivers/pci/host/pci-layerscape.c
drivers/pci/host/pci-tegra.c
drivers/pci/host/pci-thunder-ecam.c [new file with mode: 0644]
drivers/pci/host/pci-thunder-pem.c [new file with mode: 0644]
drivers/pci/host/pcie-altera.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-rcar.c
drivers/pci/host/pcie-xilinx-nwl.c [new file with mode: 0644]
drivers/pci/iov.c
drivers/pci/pci-label.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Kconfig
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/pcie/pme.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/setup-bus.c
drivers/scsi/mac53c94.c
drivers/scsi/mesh.c
drivers/usb/core/hcd-pci.c
drivers/usb/gadget/udc/amd5536udc.c
drivers/usb/gadget/udc/goku_udc.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/pch_udc.c
drivers/video/fbdev/aty/aty128fb.c
drivers/video/fbdev/aty/radeon_base.c
drivers/video/fbdev/imsttfb.c
drivers/video/fbdev/matrox/matroxfb_base.h
drivers/video/fbdev/offb.c
drivers/virtio/virtio_pci_common.c
include/asm-generic/pci-bridge.h [deleted file]
include/asm-generic/pci-dma-compat.h [deleted file]
include/linux/pci-dma-compat.h [new file with mode: 0644]
include/linux/pci.h
include/linux/pci_ids.h
sound/pci/intel8x0.c
sound/ppc/pmac.c

index 6fbba53a309b79da6aef780a35f58eedfe4ad019..3be80c68941a7aa1e19172e23d287b8c4bddd327 100644 (file)
@@ -13,6 +13,13 @@ Required properties:
 - clock-names: Must include the following additional entries:
        - "pcie_phy"
 
+Optional properties:
+- fsl,tx-deemph-gen1: Gen1 De-emphasis value. Default: 0
+- fsl,tx-deemph-gen2-3p5db: Gen2 (3.5db) De-emphasis value. Default: 0
+- fsl,tx-deemph-gen2-6db: Gen2 (6db) De-emphasis value. Default: 20
+- fsl,tx-swing-full: Gen2 TX SWING FULL value. Default: 127
+- fsl,tx-swing-low: TX launch amplitude swing_low value. Default: 127
+
 Example:
 
        pcie@0x01000000 {
diff --git a/Documentation/devicetree/bindings/pci/pci-thunder-ecam.txt b/Documentation/devicetree/bindings/pci/pci-thunder-ecam.txt
new file mode 100644 (file)
index 0000000..f478874
--- /dev/null
@@ -0,0 +1,30 @@
+* ThunderX PCI host controller for pass-1.x silicon
+
+Firmware-initialized PCI host controller to on-chip devices found on
+some Cavium ThunderX processors.  These devices have ECAM-based config
+access, but the BARs are all at fixed addresses.  We handle the fixed
+addresses by synthesizing Enhanced Allocation (EA) capabilities for
+these devices.
+
+The properties and their meanings are identical to those described in
+host-generic-pci.txt except as listed below.
+
+Properties of the host controller node that differ from
+host-generic-pci.txt:
+
+- compatible     : Must be "cavium,pci-host-thunder-ecam"
+
+Example:
+
+       pcie@84b000000000 {
+               compatible = "cavium,pci-host-thunder-ecam";
+               device_type = "pci";
+               msi-parent = <&its>;
+               msi-map = <0 &its 0x30000 0x10000>;
+               bus-range = <0 31>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               #stream-id-cells = <1>;
+               reg = <0x84b0 0x00000000 0 0x02000000>;  /* Configuration space */
+               ranges = <0x03000000 0x8180 0x00000000 0x8180 0x00000000 0x80 0x00000000>; /* mem ranges */
+       };
diff --git a/Documentation/devicetree/bindings/pci/pci-thunder-pem.txt b/Documentation/devicetree/bindings/pci/pci-thunder-pem.txt
new file mode 100644 (file)
index 0000000..f131fae
--- /dev/null
@@ -0,0 +1,43 @@
+* ThunderX PEM PCIe host controller
+
+Firmware-initialized PCI host controller found on some Cavium
+ThunderX processors.
+
+The properties and their meanings are identical to those described in
+host-generic-pci.txt except as listed below.
+
+Properties of the host controller node that differ from
+host-generic-pci.txt:
+
+- compatible     : Must be "cavium,pci-host-thunder-pem"
+
+- reg            : Two entries: First the configuration space for down
+                   stream devices base address and size, as accessed
+                   from the parent bus. Second, the register bank of
+                   the PEM device PCIe bridge.
+
+Example:
+
+    pci@87e0,c2000000 {
+       compatible = "cavium,pci-host-thunder-pem";
+       device_type = "pci";
+       msi-parent = <&its>;
+       msi-map = <0 &its 0x10000 0x10000>;
+       bus-range = <0x8f 0xc7>;
+       #size-cells = <2>;
+       #address-cells = <3>;
+
+       reg = <0x8880 0x8f000000 0x0 0x39000000>,  /* Configuration space */
+             <0x87e0 0xc2000000 0x0 0x00010000>; /* PEM space */
+       ranges = <0x01000000 0x00 0x00020000 0x88b0 0x00020000 0x00 0x00010000>, /* I/O */
+                <0x03000000 0x00 0x10000000 0x8890 0x10000000 0x0f 0xf0000000>, /* mem64 */
+                <0x43000000 0x10 0x00000000 0x88a0 0x00000000 0x10 0x00000000>, /* mem64-pref */
+                <0x03000000 0x87e0 0xc2f00000 0x87e0 0xc2000000 0x00 0x00100000>; /* mem64 PEM BAR4 */
+
+       #interrupt-cells = <1>;
+       interrupt-map-mask = <0 0 0 7>;
+       interrupt-map = <0 0 0 1 &gic0 0 0 0 24 4>, /* INTA */
+                       <0 0 0 2 &gic0 0 0 0 25 4>, /* INTB */
+                       <0 0 0 3 &gic0 0 0 0 26 4>, /* INTC */
+                       <0 0 0 4 &gic0 0 0 0 27 4>; /* INTD */
+    };
diff --git a/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt b/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
new file mode 100644 (file)
index 0000000..337fc97
--- /dev/null
@@ -0,0 +1,68 @@
+* Xilinx NWL PCIe Root Port Bridge DT description
+
+Required properties:
+- compatible: Should contain "xlnx,nwl-pcie-2.11"
+- #address-cells: Address representation for root ports, set to <3>
+- #size-cells: Size representation for root ports, set to <2>
+- #interrupt-cells: specifies the number of cells needed to encode an
+       interrupt source. The value must be 1.
+- reg: Should contain Bridge, PCIe Controller registers location,
+       configuration space, and length
+- reg-names: Must include the following entries:
+       "breg": bridge registers
+       "pcireg": PCIe controller registers
+       "cfg": configuration space region
+- device_type: must be "pci"
+- interrupts: Should contain NWL PCIe interrupt
+- interrupt-names: Must include the following entries:
+       "msi1, msi0": interrupt asserted when MSI is received
+       "intx": interrupt asserted when a legacy interrupt is received
+       "misc": interrupt asserted when miscellaneous is received
+- interrupt-map-mask and interrupt-map: standard PCI properties to define the
+       mapping of the PCI interface to interrupt numbers.
+- ranges: ranges for the PCI memory regions (I/O space region is not
+       supported by hardware)
+       Please refer to the standard PCI bus binding document for a more
+       detailed explanation
+- msi-controller: indicates that this is MSI controller node
+- msi-parent:  MSI parent of the root complex itself
+- legacy-interrupt-controller: Interrupt controller device node for Legacy interrupts
+       - interrupt-controller: identifies the node as an interrupt controller
+       - #interrupt-cells: should be set to 1
+       - #address-cells: specifies the number of cells needed to encode an
+               address. The value must be 0.
+
+
+Example:
+++++++++
+
+nwl_pcie: pcie@fd0e0000 {
+       #address-cells = <3>;
+       #size-cells = <2>;
+       compatible = "xlnx,nwl-pcie-2.11";
+       #interrupt-cells = <1>;
+       msi-controller;
+       device_type = "pci";
+       interrupt-parent = <&gic>;
+       interrupts = <0 114 4>, <0 115 4>, <0 116 4>, <0 117 4>, <0 118 4>;
+       interrupt-names = "msi0", "msi1", "intx", "dummy", "misc";
+       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+       interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc 0x1>,
+                       <0x0 0x0 0x0 0x2 &pcie_intc 0x2>,
+                       <0x0 0x0 0x0 0x3 &pcie_intc 0x3>,
+                       <0x0 0x0 0x0 0x4 &pcie_intc 0x4>;
+
+       msi-parent = <&nwl_pcie>;
+       reg = <0x0 0xfd0e0000 0x0 0x1000>,
+             <0x0 0xfd480000 0x0 0x1000>,
+             <0x0 0xe0000000 0x0 0x1000000>;
+       reg-names = "breg", "pcireg", "cfg";
+       ranges = <0x02000000 0x00000000 0xe1000000 0x00000000 0xe1000000 0 0x0f000000>;
+
+       pcie_intc: legacy-interrupt-controller {
+               interrupt-controller;
+               #address-cells = <0>;
+               #interrupt-cells = <1>;
+       };
+
+};
index 30aca4aa5467b53d6a171a27b57a4357fa09127b..1aa8f82837eae63ad97025a80d8851978007fdff 100644 (file)
@@ -8373,6 +8373,7 @@ L:        linux-pci@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/host-generic-pci.txt
+F:     drivers/pci/host/pci-host-common.c
 F:     drivers/pci/host/pci-host-generic.c
 
 PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
@@ -8418,6 +8419,14 @@ L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     drivers/pci/host/*qcom*
 
+PCIE DRIVER FOR CAVIUM THUNDERX
+M:     David Daney <david.daney@cavium.com>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Supported
+F:     Documentation/devicetree/bindings/pci/pci-thunder-*
+F:     drivers/pci/host/pci-thunder-*
+
 PCMCIA SUBSYSTEM
 P:     Linux PCMCIA Team
 L:     linux-pcmcia@lists.infradead.org
index 98f2eeee8f681117908a3958a4698de514388bd9..a06c24b3a2e13baaca1a4f41f16544a012f009a9 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <asm/machvec.h>
-#include <asm-generic/pci-bridge.h>
 
 /*
  * The following structure is used to manage multiple PCI busses.
@@ -66,13 +65,6 @@ extern void pcibios_set_master(struct pci_dev *dev);
    decisions.  */
 #define PCI_DMA_BUS_IS_PHYS  0
 
-#ifdef CONFIG_PCI
-
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
-#endif
-
 /* TODO: integrate with include/asm-generic/pci.h ? */
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
index 4f799e567fc870502ae147f3c26c5bb402315a9d..1d00da16d980707e633a2391fac51381254276a7 100644 (file)
@@ -1212,7 +1212,6 @@ config PCI_HOST_ITE8152
        select DMABOUNCE
 
 source "drivers/pci/Kconfig"
-source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
index a5635444ca410b49b5109a65535321d9c3df8d5c..057d381f4e57bb95167db49c9aea2b52ef303b76 100644 (file)
@@ -2,9 +2,6 @@
 #define ASMARM_PCI_H
 
 #ifdef __KERNEL__
-#include <asm-generic/pci-dma-compat.h>
-#include <asm-generic/pci-bridge.h>
-
 #include <asm/mach/pci.h> /* for pci_sys_data */
 
 extern unsigned long pcibios_min_io;
@@ -41,5 +38,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 }
 
 #endif /* __KERNEL__ */
 #endif
index 8cc62289a63ed9958c9623acaa5462048cc9287b..fc8089db20b1ae9d3f0f8b8ff7790f61fa3a8103 100644 (file)
@@ -235,8 +235,6 @@ config PCI_SYSCALL
        def_bool PCI
 
 source "drivers/pci/Kconfig"
-source "drivers/pci/pcie/Kconfig"
-source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
index 70fd9ffb58cfc08e82f3a978e6630c70eaeb1840..cff532a6744e937015371c80e5533a0fe660b611 100644 (file)
@@ -1,5 +1,3 @@
-
-
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += checksum.h
@@ -31,7 +29,6 @@ generic-y += msgbuf.h
 generic-y += msi.h
 generic-y += mutex.h
 generic-y += pci.h
-generic-y += pci-bridge.h
 generic-y += poll.h
 generic-y += preempt.h
 generic-y += resource.h
index b008a72f8bc02733347c782f5b9c286cff16f7a2..b9a7ba9ca44c42aef55bf77f8c0df533b9a0ab3b 100644 (file)
@@ -7,8 +7,6 @@
 #include <linux/dma-mapping.h>
 
 #include <asm/io.h>
-#include <asm-generic/pci-bridge.h>
-#include <asm-generic/pci-dma-compat.h>
 
 #define PCIBIOS_MIN_IO         0x1000
 #define PCIBIOS_MIN_MEM                0
index b3d098bd34aa3d2a57c3c9b2b3c7b63a6001be9d..c72de668e1d4d0fa549ef3b9f79d3c696ad40c07 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
-#include <asm/pci-bridge.h>
-
 /*
  * Called after each bus is probed, but before its children are examined
  */
index a32a02372017443d24db8848d2a559c548b1f13e..0f5f134b896a132635b412c83a772ba86ea78fa6 100644 (file)
@@ -5,6 +5,4 @@
 
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
-#include <asm-generic/pci-dma-compat.h>
-
 #endif /* __ASM_AVR32_PCI_H__ */
index af76634f8d9897fe61ae64a2b956d9ce07951c0c..a63c12259e77e03832c9d3c50da6ecbc9e62db18 100644 (file)
@@ -1233,8 +1233,6 @@ source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "Executable file formats"
index 14efc0db1ade134eb41e8566a6e4be76b0f94e6b..11ea1cb35036e68a580613c7032f12c5b62a20ef 100644 (file)
@@ -4,7 +4,6 @@
 #define _ASM_BFIN_PCI_H
 
 #include <linux/scatterlist.h>
-#include <asm-generic/pci-dma-compat.h>
 #include <asm-generic/pci.h>
 
 #define PCIBIOS_MIN_IO 0x00001000
index c15b4b4baafaa82295ebb1e637f7a242bce68a0b..b1b289df04c77f62575bd5be61968f1a784330fd 100644 (file)
@@ -48,9 +48,6 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 
 #endif /* __KERNEL__ */
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* generic pci stuff */
 #include <asm-generic/pci.h>
 
index e43d22c58ad52cc74d116291eef632508700460e..809cfc6707abf4f2402c0ae1e856cbca76ca211b 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
-#include <asm-generic/pci-dma-compat.h>
 #include <asm-generic/pci.h>
 
 struct pci_dev;
@@ -32,12 +31,6 @@ extern void consistent_sync_page(struct page *page, unsigned long offset,
                                 size_t size, int direction);
 #endif
 
-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                                 dma_addr_t *dma_handle);
-
-extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                               void *vaddr, dma_addr_t dma_handle);
-
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)       (0)
 
index fb0515eb639b55295c59b25ef1ce83554f35d7b4..b534ebab36eac7397ca29119e1545fc9bbf7b611 100644 (file)
@@ -574,12 +574,8 @@ config PCI_DOMAINS
 config PCI_SYSCALL
        def_bool PCI
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 source "drivers/pcmcia/Kconfig"
 
 endmenu
index 07039d168f37bfd14048e9e4a73d50bc4d20f35d..c0835b0dc72275adb47cae1dbcda19f098809320 100644 (file)
@@ -50,8 +50,6 @@ struct pci_dev;
 extern unsigned long ia64_max_iommu_merge_mask;
 #define PCI_DMA_BUS_IS_PHYS    (ia64_max_iommu_merge_mask == ~0UL)
 
-#include <asm-generic/pci-dma-compat.h>
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
                                enum pci_mmap_state mmap_state, int write_combine);
index 836ac5a963c83140d18dcd762459d19e1fd0c101..e1b12366481573098191e81b4dd088db51aa470f 100644 (file)
@@ -386,8 +386,6 @@ config ISA
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 
index 848c3dfaad504a4748d907aae5caf4b37c90c5c0..3a3dbcf4051dbb5aca1a5841762c69426146b85b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_M68K_PCI_H
 #define _ASM_M68K_PCI_H
 
-#include <asm-generic/pci-dma-compat.h>
 #include <asm-generic/pci.h>
 
 /* The PCI address space does equal the physical memory
index dc9eb6657e3a4a8e0763e3afabe0284bbd9bbbb2..fc3ecb55f1b23130efa35233e08ee77153e4a237 100644 (file)
@@ -22,8 +22,6 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 
-#include <asm-generic/pci-dma-compat.h>
-
 #define PCIBIOS_MIN_IO         0x1000
 #define PCIBIOS_MIN_MEM                0x10000000
 
index 57a945e832f43ff711fe04d1fa8a52fe1970f000..d16204d8b9266c0bd27b767246471d17a874dfab 100644 (file)
@@ -2876,8 +2876,6 @@ config PCI_DOMAINS
 
 source "drivers/pci/Kconfig"
 
-source "drivers/pci/pcie/Kconfig"
-
 #
 # ISA support is now enabled via select.  Too many systems still have the one
 # or other ISA chip on the board that users don't know about so don't expect
@@ -2937,8 +2935,6 @@ config ZONE_DMA32
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config RAPIDIO
        tristate "RapidIO support"
        depends on PCI
index 98c31e5d95793c68b50d594a5152bd0c2a730c82..8c16fb7b8fdbefd6fa9db170d4d1254bf44a9e4c 100644 (file)
@@ -102,7 +102,6 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <asm/io.h>
-#include <asm-generic/pci-bridge.h>
 
 struct pci_dev;
 
@@ -125,9 +124,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 
 #endif /* __KERNEL__ */
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* Do platform specific device initialization at pci_enable_device() time */
 extern int pcibios_plat_dev_init(struct pci_dev *dev);
 
index be3debb8fc02b1a1befbe6230249a6733aa98cfb..51159fff025ab8fad129efdd6adba0f99c38db25 100644 (file)
@@ -80,9 +80,6 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 
 #endif /* __KERNEL__ */
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
        return channel ? 15 : 14;
index 89c53bfff05547641fa55e8035c8311d653658c2..defebd956585495bf4b33117989bf05dd8699685 100644 (file)
@@ -194,9 +194,6 @@ extern void pcibios_init_bridge(struct pci_dev *);
 #define PCIBIOS_MIN_IO          0x10
 #define PCIBIOS_MIN_MEM         0x1000 /* NBPG - but pci/setup-res.c dies */
 
-/* export the pci_ DMA API in terms of the dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
        return channel ? 15 : 14;
index e4824fd04bb7449d262c1a7697b5f539b03f6bab..e28f86ee41b85c2c8ad1a4de22381b8dcf194811 100644 (file)
@@ -828,14 +828,10 @@ config PCI_8260
        select PPC_INDIRECT_PCI
        default y
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config HAS_RAPIDIO
        bool
        default n
index 54843ca5fa2bfa03871f28a3854b0d87f5685a76..78968c1ff931941d8244364cedd7f664f352e763 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
-#include <asm-generic/pci-bridge.h>
 
 struct device_node;
 
index 6f8065a7d487f3e72609c98cfd8a348853ee87d8..a6f3ac0d4602fd8b0ecb2db73ea3d6b52ef46efe 100644 (file)
@@ -20,8 +20,6 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 
-#include <asm-generic/pci-dma-compat.h>
-
 /* Return values for pci_controller_ops.probe_mode function */
 #define PCI_PROBE_NONE         -1      /* Don't look at this bus at all */
 #define PCI_PROBE_NORMAL       0       /* Do normal PCI probing */
index 3be9c832dec117a041378bd606f07df89ca44520..e70d49837fb0060761b52e41d78a523608b66da6 100644 (file)
@@ -605,8 +605,6 @@ config PCI_NR_MSI
          PCI devices.
 
 source "drivers/pci/Kconfig"
-source "drivers/pci/pcie/Kconfig"
-source "drivers/pci/hotplug/Kconfig"
 
 endif  # PCI
 
index c873e682b67f8e4063628a1726a896a167a9d8c4..fdba308649d79fc4e1d3cfb3c9f4ba396067d293 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <asm-generic/pci.h>
-#include <asm-generic/pci-dma-compat.h>
 #include <asm/pci_clp.h>
 #include <asm/pci_debug.h>
 
index e13da05505dcebc9501e97a34ec26057b1ffab90..17a4f1593d6564bcfb2f09e4c677f31931725516 100644 (file)
@@ -847,14 +847,10 @@ config PCI
 config PCI_DOMAINS
        bool
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "Executable file formats"
index e343dbd02e416d3ea1891374242b75781f546f73..644314f2b1ef0ba94e22bb1707f68036ac3968cc 100644 (file)
@@ -105,9 +105,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
        return channel ? 15 : 14;
 }
 
-/* generic DMA-mapping stuff */
-#include <asm-generic/pci-dma-compat.h>
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PCI_H */
 
index d9c031f9910f89bcc7ca1ba41115435cdf9a8534..6e14fd179335d0a24d05cc71293589b63331607f 100644 (file)
@@ -5,7 +5,4 @@
 #else
 #include <asm/pci_32.h>
 #endif
-
-#include <asm-generic/pci-dma-compat.h>
-
 #endif
index de4a4fff93237a1a9d14c6520f905a67c8ef7aad..81719302b056e095dda4c5cfd15e8a5efa18a70f 100644 (file)
@@ -455,8 +455,6 @@ config TILE_PCI_IO
 
 source "drivers/pci/Kconfig"
 
-source "drivers/pci/pcie/Kconfig"
-
 config TILE_USB
        tristate "Tilera USB host adapter support"
        default y
@@ -467,8 +465,6 @@ config TILE_USB
          Provides USB host adapter support for the built-in EHCI and OHCI
          interfaces on TILE-Gx chips.
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "Executable file formats"
index dfedd7ac7298dc93424a7862ef20b2c8ce73da1f..fe3de505b02477206af012a12fe938defc172be0 100644 (file)
@@ -226,7 +226,4 @@ static inline int pcibios_assign_all_busses(void)
 /* Use any cpu for PCI. */
 #define cpumask_of_pcibus(bus) cpu_online_mask
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 #endif /* _ASM_TILE_PCI_H */
index 38b3f3785c3c82c6c55a98192d67bc60bd1f45a9..37e55d018de5f979051ec6526f32f5722af87bb5 100644 (file)
@@ -13,8 +13,6 @@
 #define __UNICORE_PCI_H__
 
 #ifdef __KERNEL__
-#include <asm-generic/pci-dma-compat.h>
-#include <asm-generic/pci-bridge.h>
 #include <asm-generic/pci.h>
 #include <mach/hardware.h> /* for PCIBIOS_MIN_* */
 
@@ -23,5 +21,4 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        enum pci_mmap_state mmap_state, int write_combine);
 
 #endif /* __KERNEL__ */
-
 #endif
index 9e20b5d9ed5061fb91f1b56270dbd8239992aa8d..25146232c7cf19da2b1b87ac0837363cd29f7fb1 100644 (file)
 #define PCIBIOS_MIN_IO                 0x4000 /* should lower than 64KB */
 #define PCIBIOS_MIN_MEM                        io_v2p(PKUNITY_PCIMEM_BASE)
 
-/*
- * We override the standard dma-mask routines for bouncing.
- */
-#define        HAVE_ARCH_PCI_SET_DMA_MASK
-
 #define pcibios_assign_all_busses()    1
 
 #endif  /* __MACH_PUV3_HARDWARE_H__ */
index 330e738ccfc13633954a02677e46bb1b12605fa9..1912637d6178e4aca45a8c386957c2b052786dc3 100644 (file)
@@ -2431,8 +2431,6 @@ config PCI_CNB20LE_QUIRK
 
          You should say N unless you know you need this.
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
 # x86_64 have no ISA slots, but can have ISA-style DMA.
@@ -2588,8 +2586,6 @@ config AMD_NB
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config RAPIDIO
        tristate "RapidIO support"
        depends on PCI
index 462594320d39a93b835dde080d1b7ae9f9e9819a..7fd8eaa8714dfd9400269117b34749645086aaf4 100644 (file)
@@ -105,9 +105,6 @@ void native_restore_msi_irqs(struct pci_dev *dev);
 #include <asm/pci_64.h>
 #endif
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* generic pci stuff */
 #include <asm-generic/pci.h>
 
index 2879efc73a967bca70606547014decd3703c84bf..b4a9f23d77d9090eb715df2ee76c247bc5af6683 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/dmi.h>
 #include <linux/slab.h>
 
-#include <asm-generic/pci-bridge.h>
 #include <asm/acpi.h>
 #include <asm/segment.h>
 #include <asm/io.h>
index d57e48016f1578d8e1b04e22d0a30967faaf4e6e..7792aba266df695a6d6aca686c95fbbbc733fa57 100644 (file)
@@ -503,6 +503,18 @@ static struct pci_ops vmd_ops = {
        .write          = vmd_pci_write,
 };
 
+static void vmd_attach_resources(struct vmd_dev *vmd)
+{
+       vmd->dev->resource[VMD_MEMBAR1].child = &vmd->resources[1];
+       vmd->dev->resource[VMD_MEMBAR2].child = &vmd->resources[2];
+}
+
+static void vmd_detach_resources(struct vmd_dev *vmd)
+{
+       vmd->dev->resource[VMD_MEMBAR1].child = NULL;
+       vmd->dev->resource[VMD_MEMBAR2].child = NULL;
+}
+
 /*
  * VMD domains start at 0x1000 to not clash with ACPI _SEG domains.
  */
@@ -527,11 +539,28 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
        res = &vmd->dev->resource[VMD_CFGBAR];
        vmd->resources[0] = (struct resource) {
                .name  = "VMD CFGBAR",
-               .start = res->start,
+               .start = 0,
                .end   = (resource_size(res) >> 20) - 1,
                .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
        };
 
+       /*
+        * If the window is below 4GB, clear IORESOURCE_MEM_64 so we can
+        * put 32-bit resources in the window.
+        *
+        * There's no hardware reason why a 64-bit window *couldn't*
+        * contain a 32-bit resource, but pbus_size_mem() computes the
+        * bridge window size assuming a 64-bit window will contain no
+        * 32-bit resources.  __pci_assign_resource() enforces that
+        * artificial restriction to make sure everything will fit.
+        *
+        * The only way we could use a 64-bit non-prefechable MEMBAR is
+        * if its address is <4GB so that we can convert it to a 32-bit
+        * resource.  To be visible to the host OS, all VMD endpoints must
+        * be initially configured by platform BIOS, which includes setting
+        * up these resources.  We can assume the device is configured
+        * according to the platform needs.
+        */
        res = &vmd->dev->resource[VMD_MEMBAR1];
        upper_bits = upper_32_bits(res->end);
        flags = res->flags & ~IORESOURCE_SIZEALIGN;
@@ -542,6 +571,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
                .start = res->start,
                .end   = res->end,
                .flags = flags,
+               .parent = res,
        };
 
        res = &vmd->dev->resource[VMD_MEMBAR2];
@@ -554,6 +584,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
                .start = res->start + 0x2000,
                .end   = res->end,
                .flags = flags,
+               .parent = res,
        };
 
        sd->domain = vmd_find_free_domain();
@@ -578,6 +609,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
                return -ENODEV;
        }
 
+       vmd_attach_resources(vmd);
        vmd_setup_dma_ops(vmd);
        dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
        pci_rescan_bus(vmd->bus);
@@ -674,6 +706,7 @@ static void vmd_remove(struct pci_dev *dev)
 {
        struct vmd_dev *vmd = pci_get_drvdata(dev);
 
+       vmd_detach_resources(vmd);
        pci_set_drvdata(dev, NULL);
        sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
        pci_stop_root_bus(vmd->bus);
index e9df1567d778e2f87ecdb1a64df1c2dfeb874071..7e9464b0fc00bb3de3267d3e707647f760c852c5 100644 (file)
@@ -413,8 +413,6 @@ config FORCE_MAX_ZONEORDER
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config PLATFORM_WANT_DEFAULT_MEM
        def_bool n
 
index e438a00fbd6399117b7e525b6874508f9e298ec9..5d6bd932ba4e37eaf1ea19581b3e3a6320ee1099 100644 (file)
@@ -55,9 +55,6 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
 
 #endif /* __KERNEL__ */
 
-/* Implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* Generic PCI */
 #include <asm-generic/pci.h>
 
index e3d4b059fcd14bcb8f4a9e21809c5cb7d30ededa..e347e7acd8edb440d284d6309187bbb80cd90cd2 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/scatterlist.h>
 #include <linux/of.h>
 #include <linux/gfp.h>
+#include <linux/pci.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -30,7 +31,6 @@
 #include <asm/macio.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
-#include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/mediabay.h>
index 05755441250c1de8495725ea80253957b71abd07..fdced547ad5961ff722cfb438c0e33de9f5fabb2 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <asm/uninorth.h>
-#include <asm/pci-bridge.h>
 #include <asm/prom.h>
 #include <asm/pmac_feature.h>
 #include "agp.h"
index 7f1a3604b19f60295ded6b684159981c651ca322..b332b4d3b0e284463447519924ecfe08086615ef 100644 (file)
@@ -182,8 +182,8 @@ static const struct pci_device_id bochs_pci_tbl[] = {
        {
                .vendor      = 0x1234,
                .device      = 0x1111,
-               .subvendor   = 0x1af4,
-               .subdevice   = 0x1100,
+               .subvendor   = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
+               .subdevice   = PCI_SUBDEVICE_ID_QEMU,
                .driver_data = BOCHS_QEMU_STDVGA,
        },
        {
index b1619e29a564db97ef626fd2c32bceaa3a18cadc..7bc394ec9fb3af7985ab746eeb3b9f1d020a852e 100644 (file)
@@ -33,8 +33,9 @@ static struct drm_driver driver;
 
 /* only bind to the cirrus chip in qemu */
 static const struct pci_device_id pciidlist[] = {
-       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
-         0, 0 },
+       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
+         PCI_SUBVENDOR_ID_REDHAT_QUMRANET, PCI_SUBDEVICE_ID_QEMU,
+         0, 0, 0 },
        { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN,
          0x0001, 0, 0, 0 },
        {0,}
index a9b01bcf7d0a2242cf181ef31a77cf9150e6e8f8..432480ff9d228857d57170b3353c143bf0501c3f 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #endif /* CONFIG_PPC_PMAC */
 
 /* from radeon_legacy_encoder.c */
index 9ad014a7afc797b921d7b687b474cd4faaddfeba..b33646be699cbc090c028730e03ac8ac4b72c4e9 100644 (file)
@@ -28,7 +28,6 @@
 
 #ifdef CONFIG_PPC_PMAC
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #endif
 
 #define DRV_NAME "pdc202xx_new"
index 96a345248224b16fe78a2e71fed1920c8088edaa..7f0434f7e486666be6052e1c11c98c16f8f25174 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/dbdma.h>
 #include <asm/ide.h>
-#include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/sections.h>
index 4f12c6f01fe7d384d086321a09d73c1fb8fdd4a3..b6819f0fc6083266afd1d9fbea5c7e42c41b13fc 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/macio.h>
 #include <asm/pmac_feature.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 
 #undef DEBUG
 
index 4c1903f781fc1793bb7ddf7205d138e60ea2133a..a21403238a4a683a0062dabfea3a0fd3af9847ab 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <asm/opal.h>
 #include <asm/msi_bitmap.h>
-#include <asm/pci-bridge.h> /* for struct pci_controller */
 #include <asm/pnv-pci.h>
 #include <asm/io.h>
 
index e23a642357e7c01d7010ae070b47632b3a926ba9..2437227712dcd0ee5fd0404113e35527646a8b76 100644 (file)
@@ -51,7 +51,6 @@
 #endif
 
 #ifdef CONFIG_PPC_PMAC
-#include <asm/pci-bridge.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
index 3c54a2cae5dfd09e066205b945ae937a3cfabaee..67610270d171a69d5e1ecf5e0c027fe98d053bba 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
-#include <asm/pci-bridge.h>
 #include <net/checksum.h>
 
 #include "spider_net.h"
index b1449f71601cb257f1057b77c217a943da92cab8..13f4fed3804850804dfa9ad285c403e68729c150 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/of_device.h>
 #include <linux/of_pci.h>
 #include <linux/slab.h>
-#include <asm-generic/pci-bridge.h>
 
 static inline int __of_pci_pci_compare(struct device_node *node,
                                       unsigned int data)
index 592de566e72ff5dbd806d5cd314eead262841822..3a102a84d637e7fecb7c8e81b8cb3c4d64d3cbfe 100644 (file)
@@ -110,8 +110,6 @@ config IOMMU_HELPER
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "PA-RISC specific drivers"
index 73de4efcbe6edc85c8f3fb54e0c925a7ab30492b..616165d72a17f6fdf66f6a080e4f4b8d70bd66b5 100644 (file)
@@ -1,6 +1,9 @@
 #
 # PCI configuration
 #
+
+source "drivers/pci/pcie/Kconfig"
+
 config PCI_BUS_ADDR_T_64BIT
        def_bool y if (ARCH_DMA_ADDR_T_64BIT || 64BIT)
        depends on PCI
@@ -118,4 +121,5 @@ config PCI_LABEL
        def_bool y if (DMI || ACPI)
        select NLS
 
+source "drivers/pci/hotplug/Kconfig"
 source "drivers/pci/host/Kconfig"
index 8c05b5ceeaec2f2bf8db5fcc15c736d6ef93b0e2..01b9d0a00abcb06186bdb80d44c5aa9e5f05838c 100644 (file)
@@ -174,38 +174,6 @@ struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
 }
 EXPORT_SYMBOL(pci_bus_set_ops);
 
-/**
- * pci_read_vpd - Read one entry from Vital Product Data
- * @dev:       pci device struct
- * @pos:       offset in vpd space
- * @count:     number of bytes to read
- * @buf:       pointer to where to store result
- *
- */
-ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf)
-{
-       if (!dev->vpd || !dev->vpd->ops)
-               return -ENODEV;
-       return dev->vpd->ops->read(dev, pos, count, buf);
-}
-EXPORT_SYMBOL(pci_read_vpd);
-
-/**
- * pci_write_vpd - Write entry to Vital Product Data
- * @dev:       pci device struct
- * @pos:       offset in vpd space
- * @count:     number of bytes to write
- * @buf:       buffer containing write data
- *
- */
-ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
-{
-       if (!dev->vpd || !dev->vpd->ops)
-               return -ENODEV;
-       return dev->vpd->ops->write(dev, pos, count, buf);
-}
-EXPORT_SYMBOL(pci_write_vpd);
-
 /*
  * The following routines are to prevent the user from accessing PCI config
  * space when it's unsafe to do so.  Some devices require this during BIST and
@@ -277,15 +245,91 @@ PCI_USER_WRITE_CONFIG(dword, u32)
 
 /* VPD access through PCI 2.2+ VPD capability */
 
-#define PCI_VPD_PCI22_SIZE (PCI_VPD_ADDR_MASK + 1)
+/**
+ * pci_read_vpd - Read one entry from Vital Product Data
+ * @dev:       pci device struct
+ * @pos:       offset in vpd space
+ * @count:     number of bytes to read
+ * @buf:       pointer to where to store result
+ */
+ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf)
+{
+       if (!dev->vpd || !dev->vpd->ops)
+               return -ENODEV;
+       return dev->vpd->ops->read(dev, pos, count, buf);
+}
+EXPORT_SYMBOL(pci_read_vpd);
 
-struct pci_vpd_pci22 {
-       struct pci_vpd base;
-       struct mutex lock;
-       u16     flag;
-       bool    busy;
-       u8      cap;
-};
+/**
+ * pci_write_vpd - Write entry to Vital Product Data
+ * @dev:       pci device struct
+ * @pos:       offset in vpd space
+ * @count:     number of bytes to write
+ * @buf:       buffer containing write data
+ */
+ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
+{
+       if (!dev->vpd || !dev->vpd->ops)
+               return -ENODEV;
+       return dev->vpd->ops->write(dev, pos, count, buf);
+}
+EXPORT_SYMBOL(pci_write_vpd);
+
+#define PCI_VPD_MAX_SIZE (PCI_VPD_ADDR_MASK + 1)
+
+/**
+ * pci_vpd_size - determine actual size of Vital Product Data
+ * @dev:       pci device struct
+ * @old_size:  current assumed size, also maximum allowed size
+ */
+static size_t pci_vpd_size(struct pci_dev *dev, size_t old_size)
+{
+       size_t off = 0;
+       unsigned char header[1+2];      /* 1 byte tag, 2 bytes length */
+
+       while (off < old_size &&
+              pci_read_vpd(dev, off, 1, header) == 1) {
+               unsigned char tag;
+
+               if (header[0] & PCI_VPD_LRDT) {
+                       /* Large Resource Data Type Tag */
+                       tag = pci_vpd_lrdt_tag(header);
+                       /* Only read length from known tag items */
+                       if ((tag == PCI_VPD_LTIN_ID_STRING) ||
+                           (tag == PCI_VPD_LTIN_RO_DATA) ||
+                           (tag == PCI_VPD_LTIN_RW_DATA)) {
+                               if (pci_read_vpd(dev, off+1, 2,
+                                                &header[1]) != 2) {
+                                       dev_warn(&dev->dev,
+                                                "invalid large VPD tag %02x size at offset %zu",
+                                                tag, off + 1);
+                                       return 0;
+                               }
+                               off += PCI_VPD_LRDT_TAG_SIZE +
+                                       pci_vpd_lrdt_size(header);
+                       }
+               } else {
+                       /* Short Resource Data Type Tag */
+                       off += PCI_VPD_SRDT_TAG_SIZE +
+                               pci_vpd_srdt_size(header);
+                       tag = pci_vpd_srdt_tag(header);
+               }
+
+               if (tag == PCI_VPD_STIN_END)    /* End tag descriptor */
+                       return off;
+
+               if ((tag != PCI_VPD_LTIN_ID_STRING) &&
+                   (tag != PCI_VPD_LTIN_RO_DATA) &&
+                   (tag != PCI_VPD_LTIN_RW_DATA)) {
+                       dev_warn(&dev->dev,
+                                "invalid %s VPD tag %02x at offset %zu",
+                                (header[0] & PCI_VPD_LRDT) ? "large" : "short",
+                                tag, off);
+                       return 0;
+               }
+       }
+       return 0;
+}
 
 /*
  * Wait for last operation to complete.
@@ -295,55 +339,71 @@ struct pci_vpd_pci22 {
  *
  * Returns 0 on success, negative values indicate error.
  */
-static int pci_vpd_pci22_wait(struct pci_dev *dev)
+static int pci_vpd_wait(struct pci_dev *dev)
 {
-       struct pci_vpd_pci22 *vpd =
-               container_of(dev->vpd, struct pci_vpd_pci22, base);
-       unsigned long timeout = jiffies + HZ/20 + 2;
+       struct pci_vpd *vpd = dev->vpd;
+       unsigned long timeout = jiffies + msecs_to_jiffies(50);
+       unsigned long max_sleep = 16;
        u16 status;
        int ret;
 
        if (!vpd->busy)
                return 0;
 
-       for (;;) {
+       while (time_before(jiffies, timeout)) {
                ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
                                                &status);
                if (ret < 0)
                        return ret;
 
                if ((status & PCI_VPD_ADDR_F) == vpd->flag) {
-                       vpd->busy = false;
+                       vpd->busy = 0;
                        return 0;
                }
 
-               if (time_after(jiffies, timeout)) {
-                       dev_printk(KERN_DEBUG, &dev->dev, "vpd r/w failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update\n");
-                       return -ETIMEDOUT;
-               }
                if (fatal_signal_pending(current))
                        return -EINTR;
-               if (!cond_resched())
-                       udelay(10);
+
+               usleep_range(10, max_sleep);
+               if (max_sleep < 1024)
+                       max_sleep *= 2;
        }
+
+       dev_warn(&dev->dev, "VPD access failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update\n");
+       return -ETIMEDOUT;
 }
 
-static ssize_t pci_vpd_pci22_read(struct pci_dev *dev, loff_t pos, size_t count,
-                                 void *arg)
+static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
+                           void *arg)
 {
-       struct pci_vpd_pci22 *vpd =
-               container_of(dev->vpd, struct pci_vpd_pci22, base);
+       struct pci_vpd *vpd = dev->vpd;
        int ret;
        loff_t end = pos + count;
        u8 *buf = arg;
 
-       if (pos < 0 || pos > vpd->base.len || end > vpd->base.len)
+       if (pos < 0)
                return -EINVAL;
 
+       if (!vpd->valid) {
+               vpd->valid = 1;
+               vpd->len = pci_vpd_size(dev, vpd->len);
+       }
+
+       if (vpd->len == 0)
+               return -EIO;
+
+       if (pos > vpd->len)
+               return 0;
+
+       if (end > vpd->len) {
+               end = vpd->len;
+               count = end - pos;
+       }
+
        if (mutex_lock_killable(&vpd->lock))
                return -EINTR;
 
-       ret = pci_vpd_pci22_wait(dev);
+       ret = pci_vpd_wait(dev);
        if (ret < 0)
                goto out;
 
@@ -355,9 +415,9 @@ static ssize_t pci_vpd_pci22_read(struct pci_dev *dev, loff_t pos, size_t count,
                                                 pos & ~3);
                if (ret < 0)
                        break;
-               vpd->busy = true;
+               vpd->busy = 1;
                vpd->flag = PCI_VPD_ADDR_F;
-               ret = pci_vpd_pci22_wait(dev);
+               ret = pci_vpd_wait(dev);
                if (ret < 0)
                        break;
 
@@ -380,22 +440,32 @@ out:
        return ret ? ret : count;
 }
 
-static ssize_t pci_vpd_pci22_write(struct pci_dev *dev, loff_t pos, size_t count,
-                                  const void *arg)
+static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
+                            const void *arg)
 {
-       struct pci_vpd_pci22 *vpd =
-               container_of(dev->vpd, struct pci_vpd_pci22, base);
+       struct pci_vpd *vpd = dev->vpd;
        const u8 *buf = arg;
        loff_t end = pos + count;
        int ret = 0;
 
-       if (pos < 0 || (pos & 3) || (count & 3) || end > vpd->base.len)
+       if (pos < 0 || (pos & 3) || (count & 3))
+               return -EINVAL;
+
+       if (!vpd->valid) {
+               vpd->valid = 1;
+               vpd->len = pci_vpd_size(dev, vpd->len);
+       }
+
+       if (vpd->len == 0)
+               return -EIO;
+
+       if (end > vpd->len)
                return -EINVAL;
 
        if (mutex_lock_killable(&vpd->lock))
                return -EINTR;
 
-       ret = pci_vpd_pci22_wait(dev);
+       ret = pci_vpd_wait(dev);
        if (ret < 0)
                goto out;
 
@@ -415,9 +485,9 @@ static ssize_t pci_vpd_pci22_write(struct pci_dev *dev, loff_t pos, size_t count
                if (ret < 0)
                        break;
 
-               vpd->busy = true;
+               vpd->busy = 1;
                vpd->flag = 0;
-               ret = pci_vpd_pci22_wait(dev);
+               ret = pci_vpd_wait(dev);
                if (ret < 0)
                        break;
 
@@ -428,15 +498,9 @@ out:
        return ret ? ret : count;
 }
 
-static void pci_vpd_pci22_release(struct pci_dev *dev)
-{
-       kfree(container_of(dev->vpd, struct pci_vpd_pci22, base));
-}
-
-static const struct pci_vpd_ops pci_vpd_pci22_ops = {
-       .read = pci_vpd_pci22_read,
-       .write = pci_vpd_pci22_write,
-       .release = pci_vpd_pci22_release,
+static const struct pci_vpd_ops pci_vpd_ops = {
+       .read = pci_vpd_read,
+       .write = pci_vpd_write,
 };
 
 static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
@@ -472,12 +536,11 @@ static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
 static const struct pci_vpd_ops pci_vpd_f0_ops = {
        .read = pci_vpd_f0_read,
        .write = pci_vpd_f0_write,
-       .release = pci_vpd_pci22_release,
 };
 
-int pci_vpd_pci22_init(struct pci_dev *dev)
+int pci_vpd_init(struct pci_dev *dev)
 {
-       struct pci_vpd_pci22 *vpd;
+       struct pci_vpd *vpd;
        u8 cap;
 
        cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
@@ -488,18 +551,24 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
        if (!vpd)
                return -ENOMEM;
 
-       vpd->base.len = PCI_VPD_PCI22_SIZE;
+       vpd->len = PCI_VPD_MAX_SIZE;
        if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
-               vpd->base.ops = &pci_vpd_f0_ops;
+               vpd->ops = &pci_vpd_f0_ops;
        else
-               vpd->base.ops = &pci_vpd_pci22_ops;
+               vpd->ops = &pci_vpd_ops;
        mutex_init(&vpd->lock);
        vpd->cap = cap;
-       vpd->busy = false;
-       dev->vpd = &vpd->base;
+       vpd->busy = 0;
+       vpd->valid = 0;
+       dev->vpd = vpd;
        return 0;
 }
 
+void pci_vpd_release(struct pci_dev *dev)
+{
+       kfree(dev->vpd);
+}
+
 /**
  * pci_cfg_access_lock - Lock PCI config reads/writes
  * @dev:       pci device struct
index 89b3befc7155325b12f21d4667a675b52423bb6d..f2187d491475a6144cd4b11cff7c9589e1a6c82c 100644 (file)
@@ -291,7 +291,12 @@ void pci_bus_add_device(struct pci_dev *dev)
 
        dev->match_driver = true;
        retval = device_attach(&dev->dev);
-       WARN_ON(retval < 0);
+       if (retval < 0) {
+               dev_warn(&dev->dev, "device attach failed (%d)\n", retval);
+               pci_proc_detach_device(dev);
+               pci_remove_sysfs_dev_files(dev);
+               return;
+       }
 
        dev->is_added = 1;
 }
index ee8eadd62a41614ab5b4bb9dfd2c899c55da84a1..4f8e951d7252fa238e47bcae9b2851716348166f 100644 (file)
@@ -16,6 +16,16 @@ config PCI_MVEBU
        depends on ARCH_MVEBU || ARCH_DOVE
        depends on OF
 
+config PCIE_XILINX_NWL
+       bool "NWL PCIe Core"
+       depends on ARCH_ZYNQMP
+       select PCI_MSI_IRQ_DOMAIN if PCI_MSI
+       help
+        Say 'Y' here if you want kernel support for Xilinx
+        NWL PCIe controller. The controller can act as Root Port
+        or End Point. The current option selection will only
+        support root port enabling.
+
 config PCIE_DW
        bool
 
@@ -41,7 +51,7 @@ config PCI_TEGRA
 config PCI_RCAR_GEN2
        bool "Renesas R-Car Gen2 Internal PCI controller"
        depends on ARM
-       depends on ARCH_SHMOBILE || COMPILE_TEST
+       depends on ARCH_RENESAS || COMPILE_TEST
        help
          Say Y here if you want internal PCI support on R-Car Gen2 SoC.
          There are 3 internal PCI controllers available with a single
@@ -49,13 +59,17 @@ config PCI_RCAR_GEN2
 
 config PCI_RCAR_GEN2_PCIE
        bool "Renesas R-Car PCIe controller"
-       depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
+       depends on ARCH_RENESAS || (ARM && COMPILE_TEST)
        help
          Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
 
+config PCI_HOST_COMMON
+       bool
+
 config PCI_HOST_GENERIC
        bool "Generic PCI host controller"
        depends on (ARM || ARM64) && OF
+       select PCI_HOST_COMMON
        help
          Say Y here if you want to support a simple generic PCI host
          controller, such as the one emulated by kvmtool.
@@ -191,4 +205,18 @@ config PCIE_QCOM
          PCIe controller uses the Designware core plus Qualcomm-specific
          hardware wrappers.
 
+config PCI_HOST_THUNDER_PEM
+       bool "Cavium Thunder PCIe controller to off-chip devices"
+       depends on OF && ARM64
+       select PCI_HOST_COMMON
+       help
+         Say Y here if you want PCIe support for CN88XX Cavium Thunder SoCs.
+
+config PCI_HOST_THUNDER_ECAM
+       bool "Cavium Thunder ECAM controller to on-chip devices on pass-1.x silicon"
+       depends on OF && ARM64
+       select PCI_HOST_COMMON
+       help
+         Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs.
+
 endmenu
index 7b2f20c6ccc62bca6317d35e85579eba7429f85a..2c7efd8e0762e8fe20cd2647ee5ef81da70e72bd 100644 (file)
@@ -6,10 +6,12 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
 obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
+obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
 obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
 obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
 obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
 obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
+obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
 obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
@@ -22,3 +24,5 @@ obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
 obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
 obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
 obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
+obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o
+obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
new file mode 100644 (file)
index 0000000..e9f850f
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2014 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pci-host-common.h"
+
+static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
+{
+       pci_free_resource_list(&pci->resources);
+}
+
+static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
+{
+       int err, res_valid = 0;
+       struct device *dev = pci->host.dev.parent;
+       struct device_node *np = dev->of_node;
+       resource_size_t iobase;
+       struct resource_entry *win;
+
+       err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
+                                              &iobase);
+       if (err)
+               return err;
+
+       resource_list_for_each_entry(win, &pci->resources) {
+               struct resource *parent, *res = win->res;
+
+               switch (resource_type(res)) {
+               case IORESOURCE_IO:
+                       parent = &ioport_resource;
+                       err = pci_remap_iospace(res, iobase);
+                       if (err) {
+                               dev_warn(dev, "error %d: failed to map resource %pR\n",
+                                        err, res);
+                               continue;
+                       }
+                       break;
+               case IORESOURCE_MEM:
+                       parent = &iomem_resource;
+                       res_valid |= !(res->flags & IORESOURCE_PREFETCH);
+                       break;
+               case IORESOURCE_BUS:
+                       pci->cfg.bus_range = res;
+               default:
+                       continue;
+               }
+
+               err = devm_request_resource(dev, parent, res);
+               if (err)
+                       goto out_release_res;
+       }
+
+       if (!res_valid) {
+               dev_err(dev, "non-prefetchable memory resource required\n");
+               err = -EINVAL;
+               goto out_release_res;
+       }
+
+       return 0;
+
+out_release_res:
+       gen_pci_release_of_pci_ranges(pci);
+       return err;
+}
+
+static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
+{
+       int err;
+       u8 bus_max;
+       resource_size_t busn;
+       struct resource *bus_range;
+       struct device *dev = pci->host.dev.parent;
+       struct device_node *np = dev->of_node;
+       u32 sz = 1 << pci->cfg.ops->bus_shift;
+
+       err = of_address_to_resource(np, 0, &pci->cfg.res);
+       if (err) {
+               dev_err(dev, "missing \"reg\" property\n");
+               return err;
+       }
+
+       /* Limit the bus-range to fit within reg */
+       bus_max = pci->cfg.bus_range->start +
+                 (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
+       pci->cfg.bus_range->end = min_t(resource_size_t,
+                                       pci->cfg.bus_range->end, bus_max);
+
+       pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
+                                   sizeof(*pci->cfg.win), GFP_KERNEL);
+       if (!pci->cfg.win)
+               return -ENOMEM;
+
+       /* Map our Configuration Space windows */
+       if (!devm_request_mem_region(dev, pci->cfg.res.start,
+                                    resource_size(&pci->cfg.res),
+                                    "Configuration Space"))
+               return -ENOMEM;
+
+       bus_range = pci->cfg.bus_range;
+       for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
+               u32 idx = busn - bus_range->start;
+
+               pci->cfg.win[idx] = devm_ioremap(dev,
+                                                pci->cfg.res.start + idx * sz,
+                                                sz);
+               if (!pci->cfg.win[idx])
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+int pci_host_common_probe(struct platform_device *pdev,
+                         struct gen_pci *pci)
+{
+       int err;
+       const char *type;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct pci_bus *bus, *child;
+
+       type = of_get_property(np, "device_type", NULL);
+       if (!type || strcmp(type, "pci")) {
+               dev_err(dev, "invalid \"device_type\" %s\n", type);
+               return -EINVAL;
+       }
+
+       of_pci_check_probe_only();
+
+       pci->host.dev.parent = dev;
+       INIT_LIST_HEAD(&pci->host.windows);
+       INIT_LIST_HEAD(&pci->resources);
+
+       /* Parse our PCI ranges and request their resources */
+       err = gen_pci_parse_request_of_pci_ranges(pci);
+       if (err)
+               return err;
+
+       /* Parse and map our Configuration Space windows */
+       err = gen_pci_parse_map_cfg_windows(pci);
+       if (err) {
+               gen_pci_release_of_pci_ranges(pci);
+               return err;
+       }
+
+       /* Do not reassign resources if probe only */
+       if (!pci_has_flag(PCI_PROBE_ONLY))
+               pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
+
+
+       bus = pci_scan_root_bus(dev, pci->cfg.bus_range->start,
+                               &pci->cfg.ops->ops, pci, &pci->resources);
+       if (!bus) {
+               dev_err(dev, "Scanning rootbus failed");
+               return -ENODEV;
+       }
+
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+
+       if (!pci_has_flag(PCI_PROBE_ONLY)) {
+               pci_bus_size_bridges(bus);
+               pci_bus_assign_resources(bus);
+
+               list_for_each_entry(child, &bus->children, node)
+                       pcie_bus_configure_settings(child);
+       }
+
+       pci_bus_add_devices(bus);
+       return 0;
+}
+
+MODULE_DESCRIPTION("Generic PCI host driver common code");
+MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pci-host-common.h b/drivers/pci/host/pci-host-common.h
new file mode 100644 (file)
index 0000000..09f3fa0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2014 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#ifndef _PCI_HOST_COMMON_H
+#define _PCI_HOST_COMMON_H
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+struct gen_pci_cfg_bus_ops {
+       u32 bus_shift;
+       struct pci_ops ops;
+};
+
+struct gen_pci_cfg_windows {
+       struct resource                         res;
+       struct resource                         *bus_range;
+       void __iomem                            **win;
+
+       struct gen_pci_cfg_bus_ops              *ops;
+};
+
+struct gen_pci {
+       struct pci_host_bridge                  host;
+       struct gen_pci_cfg_windows              cfg;
+       struct list_head                        resources;
+};
+
+int pci_host_common_probe(struct platform_device *pdev,
+                         struct gen_pci *pci);
+
+#endif /* _PCI_HOST_COMMON_H */
index 1652bc70b1453663cc4a7614d68a3e7c5ea12524..e8aa78faa16df31becd8f717e0cdcee94c42e391 100644 (file)
 #include <linux/of_pci.h>
 #include <linux/platform_device.h>
 
-struct gen_pci_cfg_bus_ops {
-       u32 bus_shift;
-       struct pci_ops ops;
-};
-
-struct gen_pci_cfg_windows {
-       struct resource                         res;
-       struct resource                         *bus_range;
-       void __iomem                            **win;
-
-       struct gen_pci_cfg_bus_ops              *ops;
-};
-
-struct gen_pci {
-       struct pci_host_bridge                  host;
-       struct gen_pci_cfg_windows              cfg;
-       struct list_head                        resources;
-};
+#include "pci-host-common.h"
 
 static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
                                             unsigned int devfn,
@@ -93,175 +76,19 @@ static const struct of_device_id gen_pci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, gen_pci_of_match);
 
-static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
-{
-       pci_free_resource_list(&pci->resources);
-}
-
-static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
-{
-       int err, res_valid = 0;
-       struct device *dev = pci->host.dev.parent;
-       struct device_node *np = dev->of_node;
-       resource_size_t iobase;
-       struct resource_entry *win;
-
-       err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
-                                              &iobase);
-       if (err)
-               return err;
-
-       resource_list_for_each_entry(win, &pci->resources) {
-               struct resource *parent, *res = win->res;
-
-               switch (resource_type(res)) {
-               case IORESOURCE_IO:
-                       parent = &ioport_resource;
-                       err = pci_remap_iospace(res, iobase);
-                       if (err) {
-                               dev_warn(dev, "error %d: failed to map resource %pR\n",
-                                        err, res);
-                               continue;
-                       }
-                       break;
-               case IORESOURCE_MEM:
-                       parent = &iomem_resource;
-                       res_valid |= !(res->flags & IORESOURCE_PREFETCH);
-                       break;
-               case IORESOURCE_BUS:
-                       pci->cfg.bus_range = res;
-               default:
-                       continue;
-               }
-
-               err = devm_request_resource(dev, parent, res);
-               if (err)
-                       goto out_release_res;
-       }
-
-       if (!res_valid) {
-               dev_err(dev, "non-prefetchable memory resource required\n");
-               err = -EINVAL;
-               goto out_release_res;
-       }
-
-       return 0;
-
-out_release_res:
-       gen_pci_release_of_pci_ranges(pci);
-       return err;
-}
-
-static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
-{
-       int err;
-       u8 bus_max;
-       resource_size_t busn;
-       struct resource *bus_range;
-       struct device *dev = pci->host.dev.parent;
-       struct device_node *np = dev->of_node;
-       u32 sz = 1 << pci->cfg.ops->bus_shift;
-
-       err = of_address_to_resource(np, 0, &pci->cfg.res);
-       if (err) {
-               dev_err(dev, "missing \"reg\" property\n");
-               return err;
-       }
-
-       /* Limit the bus-range to fit within reg */
-       bus_max = pci->cfg.bus_range->start +
-                 (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
-       pci->cfg.bus_range->end = min_t(resource_size_t,
-                                       pci->cfg.bus_range->end, bus_max);
-
-       pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
-                                   sizeof(*pci->cfg.win), GFP_KERNEL);
-       if (!pci->cfg.win)
-               return -ENOMEM;
-
-       /* Map our Configuration Space windows */
-       if (!devm_request_mem_region(dev, pci->cfg.res.start,
-                                    resource_size(&pci->cfg.res),
-                                    "Configuration Space"))
-               return -ENOMEM;
-
-       bus_range = pci->cfg.bus_range;
-       for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
-               u32 idx = busn - bus_range->start;
-
-               pci->cfg.win[idx] = devm_ioremap(dev,
-                                                pci->cfg.res.start + idx * sz,
-                                                sz);
-               if (!pci->cfg.win[idx])
-                       return -ENOMEM;
-       }
-
-       return 0;
-}
-
 static int gen_pci_probe(struct platform_device *pdev)
 {
-       int err;
-       const char *type;
-       const struct of_device_id *of_id;
        struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
+       const struct of_device_id *of_id;
        struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
-       struct pci_bus *bus, *child;
 
        if (!pci)
                return -ENOMEM;
 
-       type = of_get_property(np, "device_type", NULL);
-       if (!type || strcmp(type, "pci")) {
-               dev_err(dev, "invalid \"device_type\" %s\n", type);
-               return -EINVAL;
-       }
-
-       of_pci_check_probe_only();
-
-       of_id = of_match_node(gen_pci_of_match, np);
+       of_id = of_match_node(gen_pci_of_match, dev->of_node);
        pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
-       pci->host.dev.parent = dev;
-       INIT_LIST_HEAD(&pci->host.windows);
-       INIT_LIST_HEAD(&pci->resources);
-
-       /* Parse our PCI ranges and request their resources */
-       err = gen_pci_parse_request_of_pci_ranges(pci);
-       if (err)
-               return err;
-
-       /* Parse and map our Configuration Space windows */
-       err = gen_pci_parse_map_cfg_windows(pci);
-       if (err) {
-               gen_pci_release_of_pci_ranges(pci);
-               return err;
-       }
-
-       /* Do not reassign resources if probe only */
-       if (!pci_has_flag(PCI_PROBE_ONLY))
-               pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
-
-
-       bus = pci_scan_root_bus(dev, pci->cfg.bus_range->start,
-                               &pci->cfg.ops->ops, pci, &pci->resources);
-       if (!bus) {
-               dev_err(dev, "Scanning rootbus failed");
-               return -ENODEV;
-       }
-
-       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
-
-       if (!pci_has_flag(PCI_PROBE_ONLY)) {
-               pci_bus_size_bridges(bus);
-               pci_bus_assign_resources(bus);
-
-               list_for_each_entry(child, &bus->children, node)
-                       pcie_bus_configure_settings(child);
-       }
 
-       pci_bus_add_devices(bus);
-       return 0;
+       return pci_host_common_probe(pdev, pci);
 }
 
 static struct platform_driver gen_pci_driver = {
index fe600964fa50177bc17b28627568268608896010..8c9b3896d6f53db3b7bdf9df38780ed6d249515e 100644 (file)
@@ -39,6 +39,11 @@ struct imx6_pcie {
        struct pcie_port        pp;
        struct regmap           *iomuxc_gpr;
        void __iomem            *mem_base;
+       u32                     tx_deemph_gen1;
+       u32                     tx_deemph_gen2_3p5db;
+       u32                     tx_deemph_gen2_6db;
+       u32                     tx_swing_full;
+       u32                     tx_swing_low;
 };
 
 /* PCIe Root Complex registers (memory-mapped) */
@@ -202,6 +207,23 @@ static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
        return 0;
 }
 
+static void imx6_pcie_reset_phy(struct pcie_port *pp)
+{
+       u32 tmp;
+
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
+       tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+               PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
+
+       usleep_range(2000, 3000);
+
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
+       tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+                 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
+}
+
 /*  Added for PCI abort handling */
 static int imx6q_pcie_abort_handler(unsigned long addr,
                unsigned int fsr, struct pt_regs *regs)
@@ -317,31 +339,50 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)
                        IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
 
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0);
+                          IMX6Q_GPR8_TX_DEEMPH_GEN1,
+                          imx6_pcie->tx_deemph_gen1 << 0);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6);
+                          IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
+                          imx6_pcie->tx_deemph_gen2_3p5db << 6);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12);
+                          IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
+                          imx6_pcie->tx_deemph_gen2_6db << 12);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_SWING_FULL, 127 << 18);
+                          IMX6Q_GPR8_TX_SWING_FULL,
+                          imx6_pcie->tx_swing_full << 18);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_SWING_LOW, 127 << 25);
+                          IMX6Q_GPR8_TX_SWING_LOW,
+                          imx6_pcie->tx_swing_low << 25);
 }
 
 static int imx6_pcie_wait_for_link(struct pcie_port *pp)
 {
        unsigned int retries;
 
+       /*
+        * Test if the PHY reports that the link is up and also that the LTSSM
+        * training finished. There are three possible states of the link when
+        * this code is called:
+        * 1) The link is DOWN (unlikely)
+        *    The link didn't come up yet for some reason. This usually means
+        *    we have a real problem somewhere, if it happens with a peripheral
+        *    connected. This state calls for inspection of the DEBUG registers.
+        * 2) The link is UP, but still in LTSSM training
+        *    Wait for the training to finish, which should take a very short
+        *    time. If the training does not finish, we have a problem and we
+        *    need to inspect the DEBUG registers. If the training does finish,
+        *    the link is up and operating correctly.
+        * 3) The link is UP and no longer in LTSSM training
+        *    The link is up and operating correctly.
+        */
        for (retries = 0; retries < 200; retries++) {
-               if (dw_pcie_link_up(pp))
+               u32 reg = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
+               if ((reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) &&
+                   !(reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
                        return 0;
-               usleep_range(100, 1000);
+               usleep_range(1000, 2000);
        }
 
-       dev_err(pp->dev, "phy link never came up\n");
-       dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
-               readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
-               readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
        return -EINVAL;
 }
 
@@ -390,8 +431,10 @@ static int imx6_pcie_establish_link(struct pcie_port *pp)
                        IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
 
        ret = imx6_pcie_wait_for_link(pp);
-       if (ret)
-               return ret;
+       if (ret) {
+               dev_info(pp->dev, "Link never came up\n");
+               goto err_reset_phy;
+       }
 
        /* Allow Gen2 mode after the link is up. */
        tmp = readl(pp->dbi_base + PCIE_RC_LCR);
@@ -410,19 +453,28 @@ static int imx6_pcie_establish_link(struct pcie_port *pp)
        ret = imx6_pcie_wait_for_speed_change(pp);
        if (ret) {
                dev_err(pp->dev, "Failed to bring link up!\n");
-               return ret;
+               goto err_reset_phy;
        }
 
        /* Make sure link training is finished as well! */
        ret = imx6_pcie_wait_for_link(pp);
        if (ret) {
                dev_err(pp->dev, "Failed to bring link up!\n");
-               return ret;
+               goto err_reset_phy;
        }
 
        tmp = readl(pp->dbi_base + PCIE_RC_LCSR);
        dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+
        return 0;
+
+err_reset_phy:
+       dev_dbg(pp->dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
+               readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
+               readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
+       imx6_pcie_reset_phy(pp);
+
+       return ret;
 }
 
 static void imx6_pcie_host_init(struct pcie_port *pp)
@@ -441,81 +493,10 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
                dw_pcie_msi_init(pp);
 }
 
-static void imx6_pcie_reset_phy(struct pcie_port *pp)
-{
-       u32 tmp;
-
-       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
-       tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
-               PHY_RX_OVRD_IN_LO_RX_PLL_EN);
-       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
-
-       usleep_range(2000, 3000);
-
-       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
-       tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
-                 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
-       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
-}
-
 static int imx6_pcie_link_up(struct pcie_port *pp)
 {
-       u32 rc, debug_r0, rx_valid;
-       int count = 5;
-
-       /*
-        * Test if the PHY reports that the link is up and also that the LTSSM
-        * training finished. There are three possible states of the link when
-        * this code is called:
-        * 1) The link is DOWN (unlikely)
-        *     The link didn't come up yet for some reason. This usually means
-        *     we have a real problem somewhere. Reset the PHY and exit. This
-        *     state calls for inspection of the DEBUG registers.
-        * 2) The link is UP, but still in LTSSM training
-        *     Wait for the training to finish, which should take a very short
-        *     time. If the training does not finish, we have a problem and we
-        *     need to inspect the DEBUG registers. If the training does finish,
-        *     the link is up and operating correctly.
-        * 3) The link is UP and no longer in LTSSM training
-        *     The link is up and operating correctly.
-        */
-       while (1) {
-               rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
-               if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
-                       break;
-               if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
-                       return 1;
-               if (!count--)
-                       break;
-               dev_dbg(pp->dev, "Link is up, but still in training\n");
-               /*
-                * Wait a little bit, then re-check if the link finished
-                * the training.
-                */
-               usleep_range(1000, 2000);
-       }
-       /*
-        * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
-        * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
-        * If (MAC/LTSSM.state == Recovery.RcvrLock)
-        * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition
-        * to gen2 is stuck
-        */
-       pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
-       debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
-
-       if (rx_valid & PCIE_PHY_RX_ASIC_OUT_VALID)
-               return 0;
-
-       if ((debug_r0 & 0x3f) != 0x0d)
-               return 0;
-
-       dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
-       dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
-
-       imx6_pcie_reset_phy(pp);
-
-       return 0;
+       return readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) &
+                       PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
 }
 
 static struct pcie_host_ops imx6_pcie_host_ops = {
@@ -562,6 +543,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
        struct imx6_pcie *imx6_pcie;
        struct pcie_port *pp;
        struct resource *dbi_base;
+       struct device_node *node = pdev->dev.of_node;
        int ret;
 
        imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL);
@@ -614,6 +596,27 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                return PTR_ERR(imx6_pcie->iomuxc_gpr);
        }
 
+       /* Grab PCIe PHY Tx Settings */
+       if (of_property_read_u32(node, "fsl,tx-deemph-gen1",
+                                &imx6_pcie->tx_deemph_gen1))
+               imx6_pcie->tx_deemph_gen1 = 0;
+
+       if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db",
+                                &imx6_pcie->tx_deemph_gen2_3p5db))
+               imx6_pcie->tx_deemph_gen2_3p5db = 0;
+
+       if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db",
+                                &imx6_pcie->tx_deemph_gen2_6db))
+               imx6_pcie->tx_deemph_gen2_6db = 20;
+
+       if (of_property_read_u32(node, "fsl,tx-swing-full",
+                                &imx6_pcie->tx_swing_full))
+               imx6_pcie->tx_swing_full = 127;
+
+       if (of_property_read_u32(node, "fsl,tx-swing-low",
+                                &imx6_pcie->tx_swing_low))
+               imx6_pcie->tx_swing_low = 127;
+
        ret = imx6_add_pcie_port(pp, pdev);
        if (ret < 0)
                return ret;
index 0aa81bd3de12d8eca876851e6f019a87f9b88f64..cd7034523f529eacf6737a244e86469482d0fe79 100644 (file)
@@ -359,6 +359,9 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
 
        /* initialize SerDes Phy if present */
        phy = devm_phy_get(dev, "pcie-phy");
+       if (PTR_ERR_OR_ZERO(phy) == -EPROBE_DEFER)
+               return PTR_ERR(phy);
+
        if (!IS_ERR_OR_NULL(phy)) {
                ret = phy_init(phy);
                if (ret < 0)
index 3923bed93c7e06fa8327cafef9429c34d1b063cb..c40d8b2ce3300c4b2e5b075ff3d13d14e7ca1e0e 100644 (file)
@@ -203,6 +203,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
        { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
        { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
        { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
+       { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
        { },
 };
 MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
index 30323114c53cca80b0c4f7bee7f361d65565fc26..68d1f41b3cbfb85750cae417739f7ff076ee4202 100644 (file)
@@ -281,6 +281,11 @@ struct tegra_pcie {
        struct resource prefetch;
        struct resource busn;
 
+       struct {
+               resource_size_t mem;
+               resource_size_t io;
+       } offset;
+
        struct clk *pex_clk;
        struct clk *afi_clk;
        struct clk *pll_e;
@@ -295,7 +300,6 @@ struct tegra_pcie {
        struct tegra_msi msi;
 
        struct list_head ports;
-       unsigned int num_ports;
        u32 xbar_config;
 
        struct regulator_bulk_data *supplies;
@@ -426,31 +430,38 @@ free:
        return ERR_PTR(err);
 }
 
-/*
- * Look up a virtual address mapping for the specified bus number. If no such
- * mapping exists, try to create one.
- */
-static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie,
-                                       unsigned int busnr)
+static int tegra_pcie_add_bus(struct pci_bus *bus)
 {
-       struct tegra_pcie_bus *bus;
+       struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata);
+       struct tegra_pcie_bus *b;
 
-       list_for_each_entry(bus, &pcie->buses, list)
-               if (bus->nr == busnr)
-                       return (void __iomem *)bus->area->addr;
+       b = tegra_pcie_bus_alloc(pcie, bus->number);
+       if (IS_ERR(b))
+               return PTR_ERR(b);
 
-       bus = tegra_pcie_bus_alloc(pcie, busnr);
-       if (IS_ERR(bus))
-               return NULL;
+       list_add_tail(&b->list, &pcie->buses);
 
-       list_add_tail(&bus->list, &pcie->buses);
+       return 0;
+}
 
-       return (void __iomem *)bus->area->addr;
+static void tegra_pcie_remove_bus(struct pci_bus *child)
+{
+       struct tegra_pcie *pcie = sys_to_pcie(child->sysdata);
+       struct tegra_pcie_bus *bus, *tmp;
+
+       list_for_each_entry_safe(bus, tmp, &pcie->buses, list) {
+               if (bus->nr == child->number) {
+                       vunmap(bus->area->addr);
+                       list_del(&bus->list);
+                       kfree(bus);
+                       break;
+               }
+       }
 }
 
-static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
-                                            unsigned int devfn,
-                                            int where)
+static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus,
+                                       unsigned int devfn,
+                                       int where)
 {
        struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata);
        void __iomem *addr = NULL;
@@ -466,7 +477,12 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
                        }
                }
        } else {
-               addr = tegra_pcie_bus_map(pcie, bus->number);
+               struct tegra_pcie_bus *b;
+
+               list_for_each_entry(b, &pcie->buses, list)
+                       if (b->nr == bus->number)
+                               addr = (void __iomem *)b->area->addr;
+
                if (!addr) {
                        dev_err(pcie->dev,
                                "failed to map cfg. space for bus %u\n",
@@ -481,7 +497,9 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
 }
 
 static struct pci_ops tegra_pcie_ops = {
-       .map_bus = tegra_pcie_conf_address,
+       .add_bus = tegra_pcie_add_bus,
+       .remove_bus = tegra_pcie_remove_bus,
+       .map_bus = tegra_pcie_map_bus,
        .read = pci_generic_config_read32,
        .write = pci_generic_config_write32,
 };
@@ -598,6 +616,17 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
        struct tegra_pcie *pcie = sys_to_pcie(sys);
        int err;
 
+       sys->mem_offset = pcie->offset.mem;
+       sys->io_offset = pcie->offset.io;
+
+       err = devm_request_resource(pcie->dev, &pcie->all, &pcie->io);
+       if (err < 0)
+               return err;
+
+       err = devm_request_resource(pcie->dev, &ioport_resource, &pcie->pio);
+       if (err < 0)
+               return err;
+
        err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem);
        if (err < 0)
                return err;
@@ -606,6 +635,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
        if (err)
                return err;
 
+       pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset);
        pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
        pci_add_resource_offset(&sys->resources, &pcie->prefetch,
                                sys->mem_offset);
@@ -741,7 +771,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
        afi_writel(pcie, 0, AFI_FPCI_BAR5);
 
        /* map all upstream transactions as uncached */
-       afi_writel(pcie, PHYS_OFFSET, AFI_CACHE_BAR0_ST);
+       afi_writel(pcie, 0, AFI_CACHE_BAR0_ST);
        afi_writel(pcie, 0, AFI_CACHE_BAR0_SZ);
        afi_writel(pcie, 0, AFI_CACHE_BAR1_ST);
        afi_writel(pcie, 0, AFI_CACHE_BAR1_SZ);
@@ -1601,6 +1631,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
 
                switch (res.flags & IORESOURCE_TYPE_BITS) {
                case IORESOURCE_IO:
+                       /* Track the bus -> CPU I/O mapping offset. */
+                       pcie->offset.io = res.start - range.pci_addr;
+
                        memcpy(&pcie->pio, &res, sizeof(res));
                        pcie->pio.name = np->full_name;
 
@@ -1621,6 +1654,14 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
                        break;
 
                case IORESOURCE_MEM:
+                       /*
+                        * Track the bus -> CPU memory mapping offset. This
+                        * assumes that the prefetchable and non-prefetchable
+                        * regions will be the last of type IORESOURCE_MEM in
+                        * the ranges property.
+                        * */
+                       pcie->offset.mem = res.start - range.pci_addr;
+
                        if (res.flags & IORESOURCE_PREFETCH) {
                                memcpy(&pcie->prefetch, &res, sizeof(res));
                                pcie->prefetch.name = "prefetchable";
diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
new file mode 100644 (file)
index 0000000..d71935c
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2015, 2016 Cavium, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/of_pci.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pci-host-common.h"
+
+/* Mapping is standard ECAM */
+static void __iomem *thunder_ecam_map_bus(struct pci_bus *bus,
+                                         unsigned int devfn,
+                                         int where)
+{
+       struct gen_pci *pci = bus->sysdata;
+       resource_size_t idx = bus->number - pci->cfg.bus_range->start;
+
+       return pci->cfg.win[idx] + ((devfn << 12) | where);
+}
+
+static void set_val(u32 v, int where, int size, u32 *val)
+{
+       int shift = (where & 3) * 8;
+
+       pr_debug("set_val %04x: %08x\n", (unsigned)(where & ~3), v);
+       v >>= shift;
+       if (size == 1)
+               v &= 0xff;
+       else if (size == 2)
+               v &= 0xffff;
+       *val = v;
+}
+
+static int handle_ea_bar(u32 e0, int bar, struct pci_bus *bus,
+                        unsigned int devfn, int where, int size, u32 *val)
+{
+       void __iomem *addr;
+       u32 v;
+
+       /* Entries are 16-byte aligned; bits[2,3] select word in entry */
+       int where_a = where & 0xc;
+
+       if (where_a == 0) {
+               set_val(e0, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       if (where_a == 0x4) {
+               addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               v = readl(addr);
+               v &= ~0xf;
+               v |= 2; /* EA entry-1. Base-L */
+               set_val(v, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       if (where_a == 0x8) {
+               u32 barl_orig;
+               u32 barl_rb;
+
+               addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               barl_orig = readl(addr + 0);
+               writel(0xffffffff, addr + 0);
+               barl_rb = readl(addr + 0);
+               writel(barl_orig, addr + 0);
+               /* zeros in unsettable bits */
+               v = ~barl_rb & ~3;
+               v |= 0xc; /* EA entry-2. Offset-L */
+               set_val(v, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       if (where_a == 0xc) {
+               addr = bus->ops->map_bus(bus, devfn, bar + 4); /* BAR 1 */
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               v = readl(addr); /* EA entry-3. Base-H */
+               set_val(v, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int thunder_ecam_p2_config_read(struct pci_bus *bus, unsigned int devfn,
+                                      int where, int size, u32 *val)
+{
+       struct gen_pci *pci = bus->sysdata;
+       int where_a = where & ~3;
+       void __iomem *addr;
+       u32 node_bits;
+       u32 v;
+
+       /* EA Base[63:32] may be missing some bits ... */
+       switch (where_a) {
+       case 0xa8:
+       case 0xbc:
+       case 0xd0:
+       case 0xe4:
+               break;
+       default:
+               return pci_generic_config_read(bus, devfn, where, size, val);
+       }
+
+       addr = bus->ops->map_bus(bus, devfn, where_a);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       v = readl(addr);
+
+       /*
+        * Bit 44 of the 64-bit Base must match the same bit in
+        * the config space access window.  Since we are working with
+        * the high-order 32 bits, shift everything down by 32 bits.
+        */
+       node_bits = (pci->cfg.res.start >> 32) & (1 << 12);
+
+       v |= node_bits;
+       set_val(v, where, size, val);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int thunder_ecam_config_read(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 *val)
+{
+       u32 v;
+       u32 vendor_device;
+       u32 class_rev;
+       void __iomem *addr;
+       int cfg_type;
+       int where_a = where & ~3;
+
+       addr = bus->ops->map_bus(bus, devfn, 0xc);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       v = readl(addr);
+
+       /* Check for non type-00 header */
+       cfg_type = (v >> 16) & 0x7f;
+
+       addr = bus->ops->map_bus(bus, devfn, 8);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       class_rev = readl(addr);
+       if (class_rev == 0xffffffff)
+               goto no_emulation;
+
+       if ((class_rev & 0xff) >= 8) {
+               /* Pass-2 handling */
+               if (cfg_type)
+                       goto no_emulation;
+               return thunder_ecam_p2_config_read(bus, devfn, where,
+                                                  size, val);
+       }
+
+       /*
+        * All BARs have fixed addresses specified by the EA
+        * capability; they must return zero on read.
+        */
+       if (cfg_type == 0 &&
+           ((where >= 0x10 && where < 0x2c) ||
+            (where >= 0x1a4 && where < 0x1bc))) {
+               /* BAR or SR-IOV BAR */
+               *val = 0;
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       addr = bus->ops->map_bus(bus, devfn, 0);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       vendor_device = readl(addr);
+       if (vendor_device == 0xffffffff)
+               goto no_emulation;
+
+       pr_debug("%04x:%04x - Fix pass#: %08x, where: %03x, devfn: %03x\n",
+                vendor_device & 0xffff, vendor_device >> 16, class_rev,
+                (unsigned) where, devfn);
+
+       /* Check for non type-00 header */
+       if (cfg_type == 0) {
+               bool has_msix;
+               bool is_nic = (vendor_device == 0xa01e177d);
+               bool is_tns = (vendor_device == 0xa01f177d);
+
+               addr = bus->ops->map_bus(bus, devfn, 0x70);
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               /* E_CAP */
+               v = readl(addr);
+               has_msix = (v & 0xff00) != 0;
+
+               if (!has_msix && where_a == 0x70) {
+                       v |= 0xbc00; /* next capability is EA at 0xbc */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xb0) {
+                       addr = bus->ops->map_bus(bus, devfn, where_a);
+                       if (!addr) {
+                               *val = ~0;
+                               return PCIBIOS_DEVICE_NOT_FOUND;
+                       }
+                       v = readl(addr);
+                       if (v & 0xff00)
+                               pr_err("Bad MSIX cap header: %08x\n", v);
+                       v |= 0xbc00; /* next capability is EA at 0xbc */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xbc) {
+                       if (is_nic)
+                               v = 0x40014; /* EA last in chain, 4 entries */
+                       else if (is_tns)
+                               v = 0x30014; /* EA last in chain, 3 entries */
+                       else if (has_msix)
+                               v = 0x20014; /* EA last in chain, 2 entries */
+                       else
+                               v = 0x10014; /* EA last in chain, 1 entry */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a >= 0xc0 && where_a < 0xd0)
+                       /* EA entry-0. PP=0, BAR0 Size:3 */
+                       return handle_ea_bar(0x80ff0003,
+                                            0x10, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xd0 && where_a < 0xe0 && has_msix)
+                        /* EA entry-1. PP=0, BAR4 Size:3 */
+                       return handle_ea_bar(0x80ff0043,
+                                            0x20, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xe0 && where_a < 0xf0 && is_tns)
+                       /* EA entry-2. PP=0, BAR2, Size:3 */
+                       return handle_ea_bar(0x80ff0023,
+                                            0x18, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xe0 && where_a < 0xf0 && is_nic)
+                       /* EA entry-2. PP=4, VF_BAR0 (9), Size:3 */
+                       return handle_ea_bar(0x80ff0493,
+                                            0x1a4, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xf0 && where_a < 0x100 && is_nic)
+                       /* EA entry-3. PP=4, VF_BAR4 (d), Size:3 */
+                       return handle_ea_bar(0x80ff04d3,
+                                            0x1b4, bus, devfn, where,
+                                            size, val);
+       } else if (cfg_type == 1) {
+               bool is_rsl_bridge = devfn == 0x08;
+               bool is_rad_bridge = devfn == 0xa0;
+               bool is_zip_bridge = devfn == 0xa8;
+               bool is_dfa_bridge = devfn == 0xb0;
+               bool is_nic_bridge = devfn == 0x10;
+
+               if (where_a == 0x70) {
+                       addr = bus->ops->map_bus(bus, devfn, where_a);
+                       if (!addr) {
+                               *val = ~0;
+                               return PCIBIOS_DEVICE_NOT_FOUND;
+                       }
+                       v = readl(addr);
+                       if (v & 0xff00)
+                               pr_err("Bad PCIe cap header: %08x\n", v);
+                       v |= 0xbc00; /* next capability is EA at 0xbc */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xbc) {
+                       if (is_nic_bridge)
+                               v = 0x10014; /* EA last in chain, 1 entry */
+                       else
+                               v = 0x00014; /* EA last in chain, no entries */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xc0) {
+                       if (is_rsl_bridge || is_nic_bridge)
+                               v = 0x0101; /* subordinate:secondary = 1:1 */
+                       else if (is_rad_bridge)
+                               v = 0x0202; /* subordinate:secondary = 2:2 */
+                       else if (is_zip_bridge)
+                               v = 0x0303; /* subordinate:secondary = 3:3 */
+                       else if (is_dfa_bridge)
+                               v = 0x0404; /* subordinate:secondary = 4:4 */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xc4 && is_nic_bridge) {
+                       /* Enabled, not-Write, SP=ff, PP=05, BEI=6, ES=4 */
+                       v = 0x80ff0564;
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xc8 && is_nic_bridge) {
+                       v = 0x00000002; /* Base-L 64-bit */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xcc && is_nic_bridge) {
+                       v = 0xfffffffe; /* MaxOffset-L 64-bit */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xd0 && is_nic_bridge) {
+                       v = 0x00008430; /* NIC Base-H */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xd4 && is_nic_bridge) {
+                       v = 0x0000000f; /* MaxOffset-H */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+       }
+no_emulation:
+       return pci_generic_config_read(bus, devfn, where, size, val);
+}
+
+static int thunder_ecam_config_write(struct pci_bus *bus, unsigned int devfn,
+                                    int where, int size, u32 val)
+{
+       /*
+        * All BARs have fixed addresses; ignore BAR writes so they
+        * don't get corrupted.
+        */
+       if ((where >= 0x10 && where < 0x2c) ||
+           (where >= 0x1a4 && where < 0x1bc))
+               /* BAR or SR-IOV BAR */
+               return PCIBIOS_SUCCESSFUL;
+
+       return pci_generic_config_write(bus, devfn, where, size, val);
+}
+
+static struct gen_pci_cfg_bus_ops thunder_ecam_bus_ops = {
+       .bus_shift      = 20,
+       .ops            = {
+               .map_bus        = thunder_ecam_map_bus,
+               .read           = thunder_ecam_config_read,
+               .write          = thunder_ecam_config_write,
+       }
+};
+
+static const struct of_device_id thunder_ecam_of_match[] = {
+       { .compatible = "cavium,pci-host-thunder-ecam",
+         .data = &thunder_ecam_bus_ops },
+
+       { },
+};
+MODULE_DEVICE_TABLE(of, thunder_ecam_of_match);
+
+static int thunder_ecam_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
+
+       if (!pci)
+               return -ENOMEM;
+
+       of_id = of_match_node(thunder_ecam_of_match, dev->of_node);
+       pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
+
+       return pci_host_common_probe(pdev, pci);
+}
+
+static struct platform_driver thunder_ecam_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .of_match_table = thunder_ecam_of_match,
+       },
+       .probe = thunder_ecam_probe,
+};
+module_platform_driver(thunder_ecam_driver);
+
+MODULE_DESCRIPTION("Thunder ECAM PCI host driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
new file mode 100644 (file)
index 0000000..cabb92a
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2015 - 2016 Cavium, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pci-host-common.h"
+
+#define PEM_CFG_WR 0x28
+#define PEM_CFG_RD 0x30
+
+struct thunder_pem_pci {
+       struct gen_pci  gen_pci;
+       u32             ea_entry[3];
+       void __iomem    *pem_reg_base;
+};
+
+static void __iomem *thunder_pem_map_bus(struct pci_bus *bus,
+                                        unsigned int devfn, int where)
+{
+       struct gen_pci *pci = bus->sysdata;
+       resource_size_t idx = bus->number - pci->cfg.bus_range->start;
+
+       return pci->cfg.win[idx] + ((devfn << 16) | where);
+}
+
+static int thunder_pem_bridge_read(struct pci_bus *bus, unsigned int devfn,
+                                  int where, int size, u32 *val)
+{
+       u64 read_val;
+       struct thunder_pem_pci *pem_pci;
+       struct gen_pci *pci = bus->sysdata;
+
+       pem_pci = container_of(pci, struct thunder_pem_pci, gen_pci);
+
+       if (devfn != 0 || where >= 2048) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       /*
+        * 32-bit accesses only.  Write the address to the low order
+        * bits of PEM_CFG_RD, then trigger the read by reading back.
+        * The config data lands in the upper 32-bits of PEM_CFG_RD.
+        */
+       read_val = where & ~3ull;
+       writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
+       read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
+       read_val >>= 32;
+
+       /*
+        * The config space contains some garbage, fix it up.  Also
+        * synthesize an EA capability for the BAR used by MSI-X.
+        */
+       switch (where & ~3) {
+       case 0x40:
+               read_val &= 0xffff00ff;
+               read_val |= 0x00007000; /* Skip MSI CAP */
+               break;
+       case 0x70: /* Express Cap */
+               /* PME interrupt on vector 2*/
+               read_val |= (2u << 25);
+               break;
+       case 0xb0: /* MSI-X Cap */
+               /* TableSize=4, Next Cap is EA */
+               read_val &= 0xc00000ff;
+               read_val |= 0x0003bc00;
+               break;
+       case 0xb4:
+               /* Table offset=0, BIR=0 */
+               read_val = 0x00000000;
+               break;
+       case 0xb8:
+               /* BPA offset=0xf0000, BIR=0 */
+               read_val = 0x000f0000;
+               break;
+       case 0xbc:
+               /* EA, 1 entry, no next Cap */
+               read_val = 0x00010014;
+               break;
+       case 0xc0:
+               /* DW2 for type-1 */
+               read_val = 0x00000000;
+               break;
+       case 0xc4:
+               /* Entry BEI=0, PP=0x00, SP=0xff, ES=3 */
+               read_val = 0x80ff0003;
+               break;
+       case 0xc8:
+               read_val = pem_pci->ea_entry[0];
+               break;
+       case 0xcc:
+               read_val = pem_pci->ea_entry[1];
+               break;
+       case 0xd0:
+               read_val = pem_pci->ea_entry[2];
+               break;
+       default:
+               break;
+       }
+       read_val >>= (8 * (where & 3));
+       switch (size) {
+       case 1:
+               read_val &= 0xff;
+               break;
+       case 2:
+               read_val &= 0xffff;
+               break;
+       default:
+               break;
+       }
+       *val = read_val;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int thunder_pem_config_read(struct pci_bus *bus, unsigned int devfn,
+                                  int where, int size, u32 *val)
+{
+       struct gen_pci *pci = bus->sysdata;
+
+       if (bus->number < pci->cfg.bus_range->start ||
+           bus->number > pci->cfg.bus_range->end)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * The first device on the bus is the PEM PCIe bridge.
+        * Special case its config access.
+        */
+       if (bus->number == pci->cfg.bus_range->start)
+               return thunder_pem_bridge_read(bus, devfn, where, size, val);
+
+       return pci_generic_config_read(bus, devfn, where, size, val);
+}
+
+/*
+ * Some of the w1c_bits below also include read-only or non-writable
+ * reserved bits, this makes the code simpler and is OK as the bits
+ * are not affected by writing zeros to them.
+ */
+static u32 thunder_pem_bridge_w1c_bits(int where)
+{
+       u32 w1c_bits = 0;
+
+       switch (where & ~3) {
+       case 0x04: /* Command/Status */
+       case 0x1c: /* Base and I/O Limit/Secondary Status */
+               w1c_bits = 0xff000000;
+               break;
+       case 0x44: /* Power Management Control and Status */
+               w1c_bits = 0xfffffe00;
+               break;
+       case 0x78: /* Device Control/Device Status */
+       case 0x80: /* Link Control/Link Status */
+       case 0x88: /* Slot Control/Slot Status */
+       case 0x90: /* Root Status */
+       case 0xa0: /* Link Control 2 Registers/Link Status 2 */
+               w1c_bits = 0xffff0000;
+               break;
+       case 0x104: /* Uncorrectable Error Status */
+       case 0x110: /* Correctable Error Status */
+       case 0x130: /* Error Status */
+       case 0x160: /* Link Control 4 */
+               w1c_bits = 0xffffffff;
+               break;
+       default:
+               break;
+       }
+       return w1c_bits;
+}
+
+static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 val)
+{
+       struct gen_pci *pci = bus->sysdata;
+       struct thunder_pem_pci *pem_pci;
+       u64 write_val, read_val;
+       u32 mask = 0;
+
+       pem_pci = container_of(pci, struct thunder_pem_pci, gen_pci);
+
+       if (devfn != 0 || where >= 2048)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * 32-bit accesses only.  If the write is for a size smaller
+        * than 32-bits, we must first read the 32-bit value and merge
+        * in the desired bits and then write the whole 32-bits back
+        * out.
+        */
+       switch (size) {
+       case 1:
+               read_val = where & ~3ull;
+               writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val >>= 32;
+               mask = ~(0xff << (8 * (where & 3)));
+               read_val &= mask;
+               val = (val & 0xff) << (8 * (where & 3));
+               val |= (u32)read_val;
+               break;
+       case 2:
+               read_val = where & ~3ull;
+               writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val >>= 32;
+               mask = ~(0xffff << (8 * (where & 3)));
+               read_val &= mask;
+               val = (val & 0xffff) << (8 * (where & 3));
+               val |= (u32)read_val;
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * By expanding the write width to 32 bits, we may
+        * inadvertently hit some W1C bits that were not intended to
+        * be written.  Calculate the mask that must be applied to the
+        * data to be written to avoid these cases.
+        */
+       if (mask) {
+               u32 w1c_bits = thunder_pem_bridge_w1c_bits(where);
+
+               if (w1c_bits) {
+                       mask &= w1c_bits;
+                       val &= ~mask;
+               }
+       }
+
+       /*
+        * Low order bits are the config address, the high order 32
+        * bits are the data to be written.
+        */
+       write_val = where & ~3ull;
+       write_val |= (((u64)val) << 32);
+       writeq(write_val, pem_pci->pem_reg_base + PEM_CFG_WR);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 val)
+{
+       struct gen_pci *pci = bus->sysdata;
+
+       if (bus->number < pci->cfg.bus_range->start ||
+           bus->number > pci->cfg.bus_range->end)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       /*
+        * The first device on the bus is the PEM PCIe bridge.
+        * Special case its config access.
+        */
+       if (bus->number == pci->cfg.bus_range->start)
+               return thunder_pem_bridge_write(bus, devfn, where, size, val);
+
+
+       return pci_generic_config_write(bus, devfn, where, size, val);
+}
+
+static struct gen_pci_cfg_bus_ops thunder_pem_bus_ops = {
+       .bus_shift      = 24,
+       .ops            = {
+               .map_bus        = thunder_pem_map_bus,
+               .read           = thunder_pem_config_read,
+               .write          = thunder_pem_config_write,
+       }
+};
+
+static const struct of_device_id thunder_pem_of_match[] = {
+       { .compatible = "cavium,pci-host-thunder-pem",
+         .data = &thunder_pem_bus_ops },
+
+       { },
+};
+MODULE_DEVICE_TABLE(of, thunder_pem_of_match);
+
+static int thunder_pem_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       resource_size_t bar4_start;
+       struct resource *res_pem;
+       struct thunder_pem_pci *pem_pci;
+
+       pem_pci = devm_kzalloc(dev, sizeof(*pem_pci), GFP_KERNEL);
+       if (!pem_pci)
+               return -ENOMEM;
+
+       of_id = of_match_node(thunder_pem_of_match, dev->of_node);
+       pem_pci->gen_pci.cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
+
+       /*
+        * The second register range is the PEM bridge to the PCIe
+        * bus.  It has a different config access method than those
+        * devices behind the bridge.
+        */
+       res_pem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!res_pem) {
+               dev_err(dev, "missing \"reg[1]\"property\n");
+               return -EINVAL;
+       }
+
+       pem_pci->pem_reg_base = devm_ioremap(dev, res_pem->start, 0x10000);
+       if (!pem_pci->pem_reg_base)
+               return -ENOMEM;
+
+       /*
+        * The MSI-X BAR for the PEM and AER interrupts is located at
+        * a fixed offset from the PEM register base.  Generate a
+        * fragment of the synthesized Enhanced Allocation capability
+        * structure here for the BAR.
+        */
+       bar4_start = res_pem->start + 0xf00000;
+       pem_pci->ea_entry[0] = (u32)bar4_start | 2;
+       pem_pci->ea_entry[1] = (u32)(res_pem->end - bar4_start) & ~3u;
+       pem_pci->ea_entry[2] = (u32)(bar4_start >> 32);
+
+       return pci_host_common_probe(pdev, &pem_pci->gen_pci);
+}
+
+static struct platform_driver thunder_pem_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .of_match_table = thunder_pem_of_match,
+       },
+       .probe = thunder_pem_probe,
+};
+module_platform_driver(thunder_pem_driver);
+
+MODULE_DESCRIPTION("Thunder PEM PCIe host driver");
+MODULE_LICENSE("GPL v2");
index 99da549d5d06a067b58d3bbe08c39041a9d90605..dbac6fb3f0bdfbccaaceefc0c1467e80ce0345df 100644 (file)
@@ -40,6 +40,7 @@
 #define P2A_INT_ENABLE                 0x3070
 #define P2A_INT_ENA_ALL                        0xf
 #define RP_LTSSM                       0x3c64
+#define RP_LTSSM_MASK                  0x1f
 #define LTSSM_L0                       0xf
 
 /* TLP configuration type 0 and 1 */
@@ -140,7 +141,7 @@ static void tlp_write_tx(struct altera_pcie *pcie,
 
 static bool altera_pcie_link_is_up(struct altera_pcie *pcie)
 {
-       return !!(cra_readl(pcie, RP_LTSSM) & LTSSM_L0);
+       return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0);
 }
 
 static bool altera_pcie_valid_config(struct altera_pcie *pcie,
index 21716827847a8ab02f1123a49ffc23141571ebc9..f85f10d220490308be8413faf9c69aeca26c9c1e 100644 (file)
@@ -517,6 +517,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
        if (pp->ops->host_init)
                pp->ops->host_init(pp);
 
+       /*
+        * If the platform provides ->rd_other_conf, it means the platform
+        * uses its own address translation component rather than ATU, so
+        * we should not program the ATU here.
+        */
        if (!pp->ops->rd_other_conf)
                dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
                                          PCIE_ATU_TYPE_MEM, pp->mem_base,
@@ -551,13 +556,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
        pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
 #endif
 
-       if (!pci_has_flag(PCI_PROBE_ONLY)) {
-               pci_bus_size_bridges(bus);
-               pci_bus_assign_resources(bus);
+       pci_bus_size_bridges(bus);
+       pci_bus_assign_resources(bus);
 
-               list_for_each_entry(child, &bus->children, node)
-                       pcie_bus_configure_settings(child);
-       }
+       list_for_each_entry(child, &bus->children, node)
+               pcie_bus_configure_settings(child);
 
        pci_bus_add_devices(bus);
        return 0;
index 4edb5181f4e2ca64dc24d8c2cc1ebec46b2d7384..35092188039b99264f7911a3fdd91005c043d4d0 100644 (file)
@@ -390,9 +390,7 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie)
 
        rcar_pcie_setup(&res, pcie);
 
-       /* Do not reassign resources if probe only */
-       if (!pci_has_flag(PCI_PROBE_ONLY))
-               pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
 
        if (IS_ENABLED(CONFIG_PCI_MSI))
                bus = pci_scan_root_bus_msi(pcie->dev, pcie->root_bus_nr,
@@ -408,13 +406,11 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie)
 
        pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
 
-       if (!pci_has_flag(PCI_PROBE_ONLY)) {
-               pci_bus_size_bridges(bus);
-               pci_bus_assign_resources(bus);
+       pci_bus_size_bridges(bus);
+       pci_bus_assign_resources(bus);
 
-               list_for_each_entry(child, &bus->children, node)
-                       pcie_bus_configure_settings(child);
-       }
+       list_for_each_entry(child, &bus->children, node)
+               pcie_bus_configure_settings(child);
 
        pci_bus_add_devices(bus);
 
diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c
new file mode 100644 (file)
index 0000000..5139e64
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ * PCIe host controller driver for NWL PCIe Bridge
+ * Based on pcie-xilinx.c, pci-tegra.c
+ *
+ * (C) Copyright 2014 - 2015, Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/irqchip/chained_irq.h>
+
+/* Bridge core config registers */
+#define BRCFG_PCIE_RX0                 0x00000000
+#define BRCFG_INTERRUPT                        0x00000010
+#define BRCFG_PCIE_RX_MSG_FILTER       0x00000020
+
+/* Egress - Bridge translation registers */
+#define E_BREG_CAPABILITIES            0x00000200
+#define E_BREG_CONTROL                 0x00000208
+#define E_BREG_BASE_LO                 0x00000210
+#define E_BREG_BASE_HI                 0x00000214
+#define E_ECAM_CAPABILITIES            0x00000220
+#define E_ECAM_CONTROL                 0x00000228
+#define E_ECAM_BASE_LO                 0x00000230
+#define E_ECAM_BASE_HI                 0x00000234
+
+/* Ingress - address translations */
+#define I_MSII_CAPABILITIES            0x00000300
+#define I_MSII_CONTROL                 0x00000308
+#define I_MSII_BASE_LO                 0x00000310
+#define I_MSII_BASE_HI                 0x00000314
+
+#define I_ISUB_CONTROL                 0x000003E8
+#define SET_ISUB_CONTROL               BIT(0)
+/* Rxed msg fifo  - Interrupt status registers */
+#define MSGF_MISC_STATUS               0x00000400
+#define MSGF_MISC_MASK                 0x00000404
+#define MSGF_LEG_STATUS                        0x00000420
+#define MSGF_LEG_MASK                  0x00000424
+#define MSGF_MSI_STATUS_LO             0x00000440
+#define MSGF_MSI_STATUS_HI             0x00000444
+#define MSGF_MSI_MASK_LO               0x00000448
+#define MSGF_MSI_MASK_HI               0x0000044C
+
+/* Msg filter mask bits */
+#define CFG_ENABLE_PM_MSG_FWD          BIT(1)
+#define CFG_ENABLE_INT_MSG_FWD         BIT(2)
+#define CFG_ENABLE_ERR_MSG_FWD         BIT(3)
+#define CFG_ENABLE_SLT_MSG_FWD         BIT(5)
+#define CFG_ENABLE_VEN_MSG_FWD         BIT(7)
+#define CFG_ENABLE_OTH_MSG_FWD         BIT(13)
+#define CFG_ENABLE_VEN_MSG_EN          BIT(14)
+#define CFG_ENABLE_VEN_MSG_VEN_INV     BIT(15)
+#define CFG_ENABLE_VEN_MSG_VEN_ID      GENMASK(31, 16)
+#define CFG_ENABLE_MSG_FILTER_MASK     (CFG_ENABLE_PM_MSG_FWD | \
+                                       CFG_ENABLE_INT_MSG_FWD | \
+                                       CFG_ENABLE_ERR_MSG_FWD | \
+                                       CFG_ENABLE_SLT_MSG_FWD | \
+                                       CFG_ENABLE_VEN_MSG_FWD | \
+                                       CFG_ENABLE_OTH_MSG_FWD | \
+                                       CFG_ENABLE_VEN_MSG_EN | \
+                                       CFG_ENABLE_VEN_MSG_VEN_INV | \
+                                       CFG_ENABLE_VEN_MSG_VEN_ID)
+
+/* Misc interrupt status mask bits */
+#define MSGF_MISC_SR_RXMSG_AVAIL       BIT(0)
+#define MSGF_MISC_SR_RXMSG_OVER                BIT(1)
+#define MSGF_MISC_SR_SLAVE_ERR         BIT(4)
+#define MSGF_MISC_SR_MASTER_ERR                BIT(5)
+#define MSGF_MISC_SR_I_ADDR_ERR                BIT(6)
+#define MSGF_MISC_SR_E_ADDR_ERR                BIT(7)
+#define MSGF_MISC_SR_UR_DETECT          BIT(20)
+
+#define MSGF_MISC_SR_PCIE_CORE         GENMASK(18, 16)
+#define MSGF_MISC_SR_PCIE_CORE_ERR     GENMASK(31, 22)
+
+#define MSGF_MISC_SR_MASKALL           (MSGF_MISC_SR_RXMSG_AVAIL | \
+                                       MSGF_MISC_SR_RXMSG_OVER | \
+                                       MSGF_MISC_SR_SLAVE_ERR | \
+                                       MSGF_MISC_SR_MASTER_ERR | \
+                                       MSGF_MISC_SR_I_ADDR_ERR | \
+                                       MSGF_MISC_SR_E_ADDR_ERR | \
+                                       MSGF_MISC_SR_UR_DETECT | \
+                                       MSGF_MISC_SR_PCIE_CORE | \
+                                       MSGF_MISC_SR_PCIE_CORE_ERR)
+
+/* Legacy interrupt status mask bits */
+#define MSGF_LEG_SR_INTA               BIT(0)
+#define MSGF_LEG_SR_INTB               BIT(1)
+#define MSGF_LEG_SR_INTC               BIT(2)
+#define MSGF_LEG_SR_INTD               BIT(3)
+#define MSGF_LEG_SR_MASKALL            (MSGF_LEG_SR_INTA | MSGF_LEG_SR_INTB | \
+                                       MSGF_LEG_SR_INTC | MSGF_LEG_SR_INTD)
+
+/* MSI interrupt status mask bits */
+#define MSGF_MSI_SR_LO_MASK            BIT(0)
+#define MSGF_MSI_SR_HI_MASK            BIT(0)
+
+#define MSII_PRESENT                   BIT(0)
+#define MSII_ENABLE                    BIT(0)
+#define MSII_STATUS_ENABLE             BIT(15)
+
+/* Bridge config interrupt mask */
+#define BRCFG_INTERRUPT_MASK           BIT(0)
+#define BREG_PRESENT                   BIT(0)
+#define BREG_ENABLE                    BIT(0)
+#define BREG_ENABLE_FORCE              BIT(1)
+
+/* E_ECAM status mask bits */
+#define E_ECAM_PRESENT                 BIT(0)
+#define E_ECAM_CR_ENABLE               BIT(0)
+#define E_ECAM_SIZE_LOC                        GENMASK(20, 16)
+#define E_ECAM_SIZE_SHIFT              16
+#define ECAM_BUS_LOC_SHIFT             20
+#define ECAM_DEV_LOC_SHIFT             12
+#define NWL_ECAM_VALUE_DEFAULT         12
+
+#define CFG_DMA_REG_BAR                        GENMASK(2, 0)
+
+#define INT_PCI_MSI_NR                 (2 * 32)
+#define INTX_NUM                       4
+
+/* Readin the PS_LINKUP */
+#define PS_LINKUP_OFFSET               0x00000238
+#define PCIE_PHY_LINKUP_BIT            BIT(0)
+#define PHY_RDY_LINKUP_BIT             BIT(1)
+
+/* Parameters for the waiting for link up routine */
+#define LINK_WAIT_MAX_RETRIES          10
+#define LINK_WAIT_USLEEP_MIN           90000
+#define LINK_WAIT_USLEEP_MAX           100000
+
+struct nwl_msi {                       /* MSI information */
+       struct irq_domain *msi_domain;
+       unsigned long *bitmap;
+       struct irq_domain *dev_domain;
+       struct mutex lock;              /* protect bitmap variable */
+       int irq_msi0;
+       int irq_msi1;
+};
+
+struct nwl_pcie {
+       struct device *dev;
+       void __iomem *breg_base;
+       void __iomem *pcireg_base;
+       void __iomem *ecam_base;
+       phys_addr_t phys_breg_base;     /* Physical Bridge Register Base */
+       phys_addr_t phys_pcie_reg_base; /* Physical PCIe Controller Base */
+       phys_addr_t phys_ecam_base;     /* Physical Configuration Base */
+       u32 breg_size;
+       u32 pcie_reg_size;
+       u32 ecam_size;
+       int irq_intx;
+       int irq_misc;
+       u32 ecam_value;
+       u8 last_busno;
+       u8 root_busno;
+       struct nwl_msi msi;
+       struct irq_domain *legacy_irq_domain;
+};
+
+static inline u32 nwl_bridge_readl(struct nwl_pcie *pcie, u32 off)
+{
+       return readl(pcie->breg_base + off);
+}
+
+static inline void nwl_bridge_writel(struct nwl_pcie *pcie, u32 val, u32 off)
+{
+       writel(val, pcie->breg_base + off);
+}
+
+static bool nwl_pcie_link_up(struct nwl_pcie *pcie)
+{
+       if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PCIE_PHY_LINKUP_BIT)
+               return true;
+       return false;
+}
+
+static bool nwl_phy_link_up(struct nwl_pcie *pcie)
+{
+       if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PHY_RDY_LINKUP_BIT)
+               return true;
+       return false;
+}
+
+static int nwl_wait_for_link(struct nwl_pcie *pcie)
+{
+       int retries;
+
+       /* check if the link is up or not */
+       for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+               if (nwl_phy_link_up(pcie))
+                       return 0;
+               usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+       }
+
+       dev_err(pcie->dev, "PHY link never came up\n");
+       return -ETIMEDOUT;
+}
+
+static bool nwl_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
+{
+       struct nwl_pcie *pcie = bus->sysdata;
+
+       /* Check link before accessing downstream ports */
+       if (bus->number != pcie->root_busno) {
+               if (!nwl_pcie_link_up(pcie))
+                       return false;
+       }
+
+       /* Only one device down on each root port */
+       if (bus->number == pcie->root_busno && devfn > 0)
+               return false;
+
+       return true;
+}
+
+/**
+ * nwl_pcie_map_bus - Get configuration base
+ *
+ * @bus: Bus structure of current bus
+ * @devfn: Device/function
+ * @where: Offset from base
+ *
+ * Return: Base address of the configuration space needed to be
+ *        accessed.
+ */
+static void __iomem *nwl_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+                                     int where)
+{
+       struct nwl_pcie *pcie = bus->sysdata;
+       int relbus;
+
+       if (!nwl_pcie_valid_device(bus, devfn))
+               return NULL;
+
+       relbus = (bus->number << ECAM_BUS_LOC_SHIFT) |
+                       (devfn << ECAM_DEV_LOC_SHIFT);
+
+       return pcie->ecam_base + relbus + where;
+}
+
+/* PCIe operations */
+static struct pci_ops nwl_pcie_ops = {
+       .map_bus = nwl_pcie_map_bus,
+       .read  = pci_generic_config_read,
+       .write = pci_generic_config_write,
+};
+
+static irqreturn_t nwl_pcie_misc_handler(int irq, void *data)
+{
+       struct nwl_pcie *pcie = data;
+       u32 misc_stat;
+
+       /* Checking for misc interrupts */
+       misc_stat = nwl_bridge_readl(pcie, MSGF_MISC_STATUS) &
+                                    MSGF_MISC_SR_MASKALL;
+       if (!misc_stat)
+               return IRQ_NONE;
+
+       if (misc_stat & MSGF_MISC_SR_RXMSG_OVER)
+               dev_err(pcie->dev, "Received Message FIFO Overflow\n");
+
+       if (misc_stat & MSGF_MISC_SR_SLAVE_ERR)
+               dev_err(pcie->dev, "Slave error\n");
+
+       if (misc_stat & MSGF_MISC_SR_MASTER_ERR)
+               dev_err(pcie->dev, "Master error\n");
+
+       if (misc_stat & MSGF_MISC_SR_I_ADDR_ERR)
+               dev_err(pcie->dev,
+                       "In Misc Ingress address translation error\n");
+
+       if (misc_stat & MSGF_MISC_SR_E_ADDR_ERR)
+               dev_err(pcie->dev,
+                       "In Misc Egress address translation error\n");
+
+       if (misc_stat & MSGF_MISC_SR_PCIE_CORE_ERR)
+               dev_err(pcie->dev, "PCIe Core error\n");
+
+       /* Clear misc interrupt status */
+       nwl_bridge_writel(pcie, misc_stat, MSGF_MISC_STATUS);
+
+       return IRQ_HANDLED;
+}
+
+static void nwl_pcie_leg_handler(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct nwl_pcie *pcie;
+       unsigned long status;
+       u32 bit;
+       u32 virq;
+
+       chained_irq_enter(chip, desc);
+       pcie = irq_desc_get_handler_data(desc);
+
+       while ((status = nwl_bridge_readl(pcie, MSGF_LEG_STATUS) &
+                               MSGF_LEG_SR_MASKALL) != 0) {
+               for_each_set_bit(bit, &status, INTX_NUM) {
+                       virq = irq_find_mapping(pcie->legacy_irq_domain,
+                                               bit + 1);
+                       if (virq)
+                               generic_handle_irq(virq);
+               }
+       }
+
+       chained_irq_exit(chip, desc);
+}
+
+static void nwl_pcie_handle_msi_irq(struct nwl_pcie *pcie, u32 status_reg)
+{
+       struct nwl_msi *msi;
+       unsigned long status;
+       u32 bit;
+       u32 virq;
+
+       msi = &pcie->msi;
+
+       while ((status = nwl_bridge_readl(pcie, status_reg)) != 0) {
+               for_each_set_bit(bit, &status, 32) {
+                       nwl_bridge_writel(pcie, 1 << bit, status_reg);
+                       virq = irq_find_mapping(msi->dev_domain, bit);
+                       if (virq)
+                               generic_handle_irq(virq);
+               }
+       }
+}
+
+static void nwl_pcie_msi_handler_high(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct nwl_pcie *pcie = irq_desc_get_handler_data(desc);
+
+       chained_irq_enter(chip, desc);
+       nwl_pcie_handle_msi_irq(pcie, MSGF_MSI_STATUS_HI);
+       chained_irq_exit(chip, desc);
+}
+
+static void nwl_pcie_msi_handler_low(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct nwl_pcie *pcie = irq_desc_get_handler_data(desc);
+
+       chained_irq_enter(chip, desc);
+       nwl_pcie_handle_msi_irq(pcie, MSGF_MSI_STATUS_LO);
+       chained_irq_exit(chip, desc);
+}
+
+static int nwl_legacy_map(struct irq_domain *domain, unsigned int irq,
+                         irq_hw_number_t hwirq)
+{
+       irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+       irq_set_chip_data(irq, domain->host_data);
+
+       return 0;
+}
+
+static const struct irq_domain_ops legacy_domain_ops = {
+       .map = nwl_legacy_map,
+};
+
+#ifdef CONFIG_PCI_MSI
+static struct irq_chip nwl_msi_irq_chip = {
+       .name = "nwl_pcie:msi",
+       .irq_enable = unmask_msi_irq,
+       .irq_disable = mask_msi_irq,
+       .irq_mask = mask_msi_irq,
+       .irq_unmask = unmask_msi_irq,
+
+};
+
+static struct msi_domain_info nwl_msi_domain_info = {
+       .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+                 MSI_FLAG_MULTI_PCI_MSI),
+       .chip = &nwl_msi_irq_chip,
+};
+#endif
+
+static void nwl_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+       struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data);
+       phys_addr_t msi_addr = pcie->phys_pcie_reg_base;
+
+       msg->address_lo = lower_32_bits(msi_addr);
+       msg->address_hi = upper_32_bits(msi_addr);
+       msg->data = data->hwirq;
+}
+
+static int nwl_msi_set_affinity(struct irq_data *irq_data,
+                               const struct cpumask *mask, bool force)
+{
+       return -EINVAL;
+}
+
+static struct irq_chip nwl_irq_chip = {
+       .name = "Xilinx MSI",
+       .irq_compose_msi_msg = nwl_compose_msi_msg,
+       .irq_set_affinity = nwl_msi_set_affinity,
+};
+
+static int nwl_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+                               unsigned int nr_irqs, void *args)
+{
+       struct nwl_pcie *pcie = domain->host_data;
+       struct nwl_msi *msi = &pcie->msi;
+       int bit;
+       int i;
+
+       mutex_lock(&msi->lock);
+       bit = bitmap_find_next_zero_area(msi->bitmap, INT_PCI_MSI_NR, 0,
+                                        nr_irqs, 0);
+       if (bit >= INT_PCI_MSI_NR) {
+               mutex_unlock(&msi->lock);
+               return -ENOSPC;
+       }
+
+       bitmap_set(msi->bitmap, bit, nr_irqs);
+
+       for (i = 0; i < nr_irqs; i++) {
+               irq_domain_set_info(domain, virq + i, bit + i, &nwl_irq_chip,
+                               domain->host_data, handle_simple_irq,
+                               NULL, NULL);
+       }
+       mutex_unlock(&msi->lock);
+       return 0;
+}
+
+static void nwl_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+                                       unsigned int nr_irqs)
+{
+       struct irq_data *data = irq_domain_get_irq_data(domain, virq);
+       struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data);
+       struct nwl_msi *msi = &pcie->msi;
+
+       mutex_lock(&msi->lock);
+       bitmap_clear(msi->bitmap, data->hwirq, nr_irqs);
+       mutex_unlock(&msi->lock);
+}
+
+static const struct irq_domain_ops dev_msi_domain_ops = {
+       .alloc  = nwl_irq_domain_alloc,
+       .free   = nwl_irq_domain_free,
+};
+
+static void nwl_msi_free_irq_domain(struct nwl_pcie *pcie)
+{
+       struct nwl_msi *msi = &pcie->msi;
+
+       if (msi->irq_msi0)
+               irq_set_chained_handler_and_data(msi->irq_msi0, NULL, NULL);
+       if (msi->irq_msi1)
+               irq_set_chained_handler_and_data(msi->irq_msi1, NULL, NULL);
+
+       if (msi->msi_domain)
+               irq_domain_remove(msi->msi_domain);
+       if (msi->dev_domain)
+               irq_domain_remove(msi->dev_domain);
+
+       kfree(msi->bitmap);
+       msi->bitmap = NULL;
+}
+
+static void nwl_pcie_free_irq_domain(struct nwl_pcie *pcie)
+{
+       int i;
+       u32 irq;
+
+       for (i = 0; i < INTX_NUM; i++) {
+               irq = irq_find_mapping(pcie->legacy_irq_domain, i + 1);
+               if (irq > 0)
+                       irq_dispose_mapping(irq);
+       }
+       if (pcie->legacy_irq_domain)
+               irq_domain_remove(pcie->legacy_irq_domain);
+
+       nwl_msi_free_irq_domain(pcie);
+}
+
+static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie)
+{
+#ifdef CONFIG_PCI_MSI
+       struct fwnode_handle *fwnode = of_node_to_fwnode(pcie->dev->of_node);
+       struct nwl_msi *msi = &pcie->msi;
+
+       msi->dev_domain = irq_domain_add_linear(NULL, INT_PCI_MSI_NR,
+                                               &dev_msi_domain_ops, pcie);
+       if (!msi->dev_domain) {
+               dev_err(pcie->dev, "failed to create dev IRQ domain\n");
+               return -ENOMEM;
+       }
+       msi->msi_domain = pci_msi_create_irq_domain(fwnode,
+                                                   &nwl_msi_domain_info,
+                                                   msi->dev_domain);
+       if (!msi->msi_domain) {
+               dev_err(pcie->dev, "failed to create msi IRQ domain\n");
+               irq_domain_remove(msi->dev_domain);
+               return -ENOMEM;
+       }
+#endif
+       return 0;
+}
+
+static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie)
+{
+       struct device_node *node = pcie->dev->of_node;
+       struct device_node *legacy_intc_node;
+
+       legacy_intc_node = of_get_next_child(node, NULL);
+       if (!legacy_intc_node) {
+               dev_err(pcie->dev, "No legacy intc node found\n");
+               return -EINVAL;
+       }
+
+       pcie->legacy_irq_domain = irq_domain_add_linear(legacy_intc_node,
+                                                       INTX_NUM,
+                                                       &legacy_domain_ops,
+                                                       pcie);
+
+       if (!pcie->legacy_irq_domain) {
+               dev_err(pcie->dev, "failed to create IRQ domain\n");
+               return -ENOMEM;
+       }
+
+       nwl_pcie_init_msi_irq_domain(pcie);
+       return 0;
+}
+
+static int nwl_pcie_enable_msi(struct nwl_pcie *pcie, struct pci_bus *bus)
+{
+       struct platform_device *pdev = to_platform_device(pcie->dev);
+       struct nwl_msi *msi = &pcie->msi;
+       unsigned long base;
+       int ret;
+       int size = BITS_TO_LONGS(INT_PCI_MSI_NR) * sizeof(long);
+
+       mutex_init(&msi->lock);
+
+       msi->bitmap = kzalloc(size, GFP_KERNEL);
+       if (!msi->bitmap)
+               return -ENOMEM;
+
+       /* Get msi_1 IRQ number */
+       msi->irq_msi1 = platform_get_irq_byname(pdev, "msi1");
+       if (msi->irq_msi1 < 0) {
+               dev_err(&pdev->dev, "failed to get IRQ#%d\n", msi->irq_msi1);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       irq_set_chained_handler_and_data(msi->irq_msi1,
+                                        nwl_pcie_msi_handler_high, pcie);
+
+       /* Get msi_0 IRQ number */
+       msi->irq_msi0 = platform_get_irq_byname(pdev, "msi0");
+       if (msi->irq_msi0 < 0) {
+               dev_err(&pdev->dev, "failed to get IRQ#%d\n", msi->irq_msi0);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       irq_set_chained_handler_and_data(msi->irq_msi0,
+                                        nwl_pcie_msi_handler_low, pcie);
+
+       /* Check for msii_present bit */
+       ret = nwl_bridge_readl(pcie, I_MSII_CAPABILITIES) & MSII_PRESENT;
+       if (!ret) {
+               dev_err(pcie->dev, "MSI not present\n");
+               ret = -EIO;
+               goto err;
+       }
+
+       /* Enable MSII */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, I_MSII_CONTROL) |
+                         MSII_ENABLE, I_MSII_CONTROL);
+
+       /* Enable MSII status */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, I_MSII_CONTROL) |
+                         MSII_STATUS_ENABLE, I_MSII_CONTROL);
+
+       /* setup AFI/FPCI range */
+       base = pcie->phys_pcie_reg_base;
+       nwl_bridge_writel(pcie, lower_32_bits(base), I_MSII_BASE_LO);
+       nwl_bridge_writel(pcie, upper_32_bits(base), I_MSII_BASE_HI);
+
+       /*
+        * For high range MSI interrupts: disable, clear any pending,
+        * and enable
+        */
+       nwl_bridge_writel(pcie, (u32)~MSGF_MSI_SR_HI_MASK, MSGF_MSI_MASK_HI);
+
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie,  MSGF_MSI_STATUS_HI) &
+                         MSGF_MSI_SR_HI_MASK, MSGF_MSI_STATUS_HI);
+
+       nwl_bridge_writel(pcie, MSGF_MSI_SR_HI_MASK, MSGF_MSI_MASK_HI);
+
+       /*
+        * For low range MSI interrupts: disable, clear any pending,
+        * and enable
+        */
+       nwl_bridge_writel(pcie, (u32)~MSGF_MSI_SR_LO_MASK, MSGF_MSI_MASK_LO);
+
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_MSI_STATUS_LO) &
+                         MSGF_MSI_SR_LO_MASK, MSGF_MSI_STATUS_LO);
+
+       nwl_bridge_writel(pcie, MSGF_MSI_SR_LO_MASK, MSGF_MSI_MASK_LO);
+
+       return 0;
+err:
+       kfree(msi->bitmap);
+       msi->bitmap = NULL;
+       return ret;
+}
+
+static int nwl_pcie_bridge_init(struct nwl_pcie *pcie)
+{
+       struct platform_device *pdev = to_platform_device(pcie->dev);
+       u32 breg_val, ecam_val, first_busno = 0;
+       int err;
+
+       breg_val = nwl_bridge_readl(pcie, E_BREG_CAPABILITIES) & BREG_PRESENT;
+       if (!breg_val) {
+               dev_err(pcie->dev, "BREG is not present\n");
+               return breg_val;
+       }
+
+       /* Write bridge_off to breg base */
+       nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_breg_base),
+                         E_BREG_BASE_LO);
+       nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_breg_base),
+                         E_BREG_BASE_HI);
+
+       /* Enable BREG */
+       nwl_bridge_writel(pcie, ~BREG_ENABLE_FORCE & BREG_ENABLE,
+                         E_BREG_CONTROL);
+
+       /* Disable DMA channel registers */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_PCIE_RX0) |
+                         CFG_DMA_REG_BAR, BRCFG_PCIE_RX0);
+
+       /* Enable Ingress subtractive decode translation */
+       nwl_bridge_writel(pcie, SET_ISUB_CONTROL, I_ISUB_CONTROL);
+
+       /* Enable msg filtering details */
+       nwl_bridge_writel(pcie, CFG_ENABLE_MSG_FILTER_MASK,
+                         BRCFG_PCIE_RX_MSG_FILTER);
+
+       err = nwl_wait_for_link(pcie);
+       if (err)
+               return err;
+
+       ecam_val = nwl_bridge_readl(pcie, E_ECAM_CAPABILITIES) & E_ECAM_PRESENT;
+       if (!ecam_val) {
+               dev_err(pcie->dev, "ECAM is not present\n");
+               return ecam_val;
+       }
+
+       /* Enable ECAM */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) |
+                         E_ECAM_CR_ENABLE, E_ECAM_CONTROL);
+
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) |
+                         (pcie->ecam_value << E_ECAM_SIZE_SHIFT),
+                         E_ECAM_CONTROL);
+
+       nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_ecam_base),
+                         E_ECAM_BASE_LO);
+       nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_ecam_base),
+                         E_ECAM_BASE_HI);
+
+       /* Get bus range */
+       ecam_val = nwl_bridge_readl(pcie, E_ECAM_CONTROL);
+       pcie->last_busno = (ecam_val & E_ECAM_SIZE_LOC) >> E_ECAM_SIZE_SHIFT;
+       /* Write primary, secondary and subordinate bus numbers */
+       ecam_val = first_busno;
+       ecam_val |= (first_busno + 1) << 8;
+       ecam_val |= (pcie->last_busno << E_ECAM_SIZE_SHIFT);
+       writel(ecam_val, (pcie->ecam_base + PCI_PRIMARY_BUS));
+
+       if (nwl_pcie_link_up(pcie))
+               dev_info(pcie->dev, "Link is UP\n");
+       else
+               dev_info(pcie->dev, "Link is DOWN\n");
+
+       /* Get misc IRQ number */
+       pcie->irq_misc = platform_get_irq_byname(pdev, "misc");
+       if (pcie->irq_misc < 0) {
+               dev_err(&pdev->dev, "failed to get misc IRQ %d\n",
+                       pcie->irq_misc);
+               return -EINVAL;
+       }
+
+       err = devm_request_irq(pcie->dev, pcie->irq_misc,
+                              nwl_pcie_misc_handler, IRQF_SHARED,
+                              "nwl_pcie:misc", pcie);
+       if (err) {
+               dev_err(pcie->dev, "fail to register misc IRQ#%d\n",
+                       pcie->irq_misc);
+               return err;
+       }
+
+       /* Disable all misc interrupts */
+       nwl_bridge_writel(pcie, (u32)~MSGF_MISC_SR_MASKALL, MSGF_MISC_MASK);
+
+       /* Clear pending misc interrupts */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_MISC_STATUS) &
+                         MSGF_MISC_SR_MASKALL, MSGF_MISC_STATUS);
+
+       /* Enable all misc interrupts */
+       nwl_bridge_writel(pcie, MSGF_MISC_SR_MASKALL, MSGF_MISC_MASK);
+
+
+       /* Disable all legacy interrupts */
+       nwl_bridge_writel(pcie, (u32)~MSGF_LEG_SR_MASKALL, MSGF_LEG_MASK);
+
+       /* Clear pending legacy interrupts */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_LEG_STATUS) &
+                         MSGF_LEG_SR_MASKALL, MSGF_LEG_STATUS);
+
+       /* Enable all legacy interrupts */
+       nwl_bridge_writel(pcie, MSGF_LEG_SR_MASKALL, MSGF_LEG_MASK);
+
+       /* Enable the bridge config interrupt */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_INTERRUPT) |
+                         BRCFG_INTERRUPT_MASK, BRCFG_INTERRUPT);
+
+       return 0;
+}
+
+static int nwl_pcie_parse_dt(struct nwl_pcie *pcie,
+                            struct platform_device *pdev)
+{
+       struct device_node *node = pcie->dev->of_node;
+       struct resource *res;
+       const char *type;
+
+       /* Check for device type */
+       type = of_get_property(node, "device_type", NULL);
+       if (!type || strcmp(type, "pci")) {
+               dev_err(pcie->dev, "invalid \"device_type\" %s\n", type);
+               return -EINVAL;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "breg");
+       pcie->breg_base = devm_ioremap_resource(pcie->dev, res);
+       if (IS_ERR(pcie->breg_base))
+               return PTR_ERR(pcie->breg_base);
+       pcie->phys_breg_base = res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcireg");
+       pcie->pcireg_base = devm_ioremap_resource(pcie->dev, res);
+       if (IS_ERR(pcie->pcireg_base))
+               return PTR_ERR(pcie->pcireg_base);
+       pcie->phys_pcie_reg_base = res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
+       pcie->ecam_base = devm_ioremap_resource(pcie->dev, res);
+       if (IS_ERR(pcie->ecam_base))
+               return PTR_ERR(pcie->ecam_base);
+       pcie->phys_ecam_base = res->start;
+
+       /* Get intx IRQ number */
+       pcie->irq_intx = platform_get_irq_byname(pdev, "intx");
+       if (pcie->irq_intx < 0) {
+               dev_err(&pdev->dev, "failed to get intx IRQ %d\n",
+                       pcie->irq_intx);
+               return -EINVAL;
+       }
+
+       irq_set_chained_handler_and_data(pcie->irq_intx,
+                                        nwl_pcie_leg_handler, pcie);
+
+       return 0;
+}
+
+static const struct of_device_id nwl_pcie_of_match[] = {
+       { .compatible = "xlnx,nwl-pcie-2.11", },
+       {}
+};
+
+static int nwl_pcie_probe(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct nwl_pcie *pcie;
+       struct pci_bus *bus;
+       struct pci_bus *child;
+       int err;
+       resource_size_t iobase = 0;
+       LIST_HEAD(res);
+
+       pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
+       if (!pcie)
+               return -ENOMEM;
+
+       pcie->dev = &pdev->dev;
+       pcie->ecam_value = NWL_ECAM_VALUE_DEFAULT;
+
+       err = nwl_pcie_parse_dt(pcie, pdev);
+       if (err) {
+               dev_err(pcie->dev, "Parsing DT failed\n");
+               return err;
+       }
+
+       err = nwl_pcie_bridge_init(pcie);
+       if (err) {
+               dev_err(pcie->dev, "HW Initalization failed\n");
+               return err;
+       }
+
+       err = of_pci_get_host_bridge_resources(node, 0, 0xff, &res, &iobase);
+       if (err) {
+               pr_err("Getting bridge resources failed\n");
+               return err;
+       }
+
+       err = nwl_pcie_init_irq_domain(pcie);
+       if (err) {
+               dev_err(pcie->dev, "Failed creating IRQ Domain\n");
+               return err;
+       }
+
+       bus = pci_create_root_bus(&pdev->dev, pcie->root_busno,
+                                 &nwl_pcie_ops, pcie, &res);
+       if (!bus)
+               return -ENOMEM;
+
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               err = nwl_pcie_enable_msi(pcie, bus);
+               if (err < 0) {
+                       dev_err(&pdev->dev,
+                               "failed to enable MSI support: %d\n", err);
+                       return err;
+               }
+       }
+       pci_scan_child_bus(bus);
+       pci_assign_unassigned_bus_resources(bus);
+       list_for_each_entry(child, &bus->children, node)
+               pcie_bus_configure_settings(child);
+       pci_bus_add_devices(bus);
+       platform_set_drvdata(pdev, pcie);
+       return 0;
+}
+
+static int nwl_pcie_remove(struct platform_device *pdev)
+{
+       struct nwl_pcie *pcie = platform_get_drvdata(pdev);
+
+       nwl_pcie_free_irq_domain(pcie);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct platform_driver nwl_pcie_driver = {
+       .driver = {
+               .name = "nwl-pcie",
+               .of_match_table = nwl_pcie_of_match,
+       },
+       .probe = nwl_pcie_probe,
+       .remove = nwl_pcie_remove,
+};
+module_platform_driver(nwl_pcie_driver);
+
+MODULE_AUTHOR("Xilinx, Inc");
+MODULE_DESCRIPTION("NWL PCIe driver");
+MODULE_LICENSE("GPL");
index 31f31d460fc9de789d28d72365122224fa3b2551..fe4bd0aa91a622eb5ac185ef664d1ee9db698e41 100644 (file)
@@ -387,10 +387,6 @@ static int sriov_init(struct pci_dev *dev, int pos)
        struct resource *res;
        struct pci_dev *pdev;
 
-       if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END &&
-           pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT)
-               return -ENODEV;
-
        pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl);
        if (ctrl & PCI_SRIOV_CTRL_VFE) {
                pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, 0);
index 0ae74d96ed8577b5980484f0c0c9ecbea1e60c84..51357377efbce65d4ad8454ffd678fc4df8de7a2 100644 (file)
@@ -16,7 +16,7 @@
  * the instance number and string from the type 41 record and exports
  * it to sysfs.
  *
- * Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname for more
+ * Please see http://linux.dell.com/files/biosdevname/ for more
  * information.
  */
 
index 95d9e7bd933bc880315d3584033c4ea2ca41a3b9..ed39c093aa1511741bce018ad0b13175b4770e5f 100644 (file)
@@ -769,10 +769,12 @@ static ssize_t read_vpd_attr(struct file *filp, struct kobject *kobj,
 {
        struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
 
-       if (off > bin_attr->size)
-               count = 0;
-       else if (count > bin_attr->size - off)
-               count = bin_attr->size - off;
+       if (bin_attr->size > 0) {
+               if (off > bin_attr->size)
+                       count = 0;
+               else if (count > bin_attr->size - off)
+                       count = bin_attr->size - off;
+       }
 
        return pci_read_vpd(dev, off, count, buf);
 }
@@ -783,10 +785,12 @@ static ssize_t write_vpd_attr(struct file *filp, struct kobject *kobj,
 {
        struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
 
-       if (off > bin_attr->size)
-               count = 0;
-       else if (count > bin_attr->size - off)
-               count = bin_attr->size - off;
+       if (bin_attr->size > 0) {
+               if (off > bin_attr->size)
+                       count = 0;
+               else if (count > bin_attr->size - off)
+                       count = bin_attr->size - off;
+       }
 
        return pci_write_vpd(dev, off, count, buf);
 }
@@ -1319,7 +1323,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
                        return -ENOMEM;
 
                sysfs_bin_attr_init(attr);
-               attr->size = dev->vpd->len;
+               attr->size = 0;
                attr->attr.name = "vpd";
                attr->attr.mode = S_IRUSR | S_IWUSR;
                attr->read = read_vpd_attr;
index 602eb422351060c611967538359b8409885397a1..eaf4ffc0c27363bcde85fc4141f882fede59fcde 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci_hotplug.h>
-#include <asm-generic/pci-bridge.h>
 #include <asm/setup.h>
 #include <linux/aer.h>
 #include "pci.h"
@@ -3386,18 +3385,6 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
 
-int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
-{
-       return dma_set_max_seg_size(&dev->dev, size);
-}
-EXPORT_SYMBOL(pci_set_dma_max_seg_size);
-
-int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
-{
-       return dma_set_seg_boundary(&dev->dev, mask);
-}
-EXPORT_SYMBOL(pci_set_dma_seg_boundary);
-
 /**
  * pci_wait_for_pending_transaction - waits for pending transaction
  * @dev: the PCI device to operate on
@@ -3414,6 +3401,29 @@ int pci_wait_for_pending_transaction(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 
+/*
+ * We should only need to wait 100ms after FLR, but some devices take longer.
+ * Wait for up to 1000ms for config space to return something other than -1.
+ * Intel IGD requires this when an LCD panel is attached.  We read the 2nd
+ * dword because VFs don't implement the 1st dword.
+ */
+static void pci_flr_wait(struct pci_dev *dev)
+{
+       int i = 0;
+       u32 id;
+
+       do {
+               msleep(100);
+               pci_read_config_dword(dev, PCI_COMMAND, &id);
+       } while (i++ < 10 && id == ~0);
+
+       if (id == ~0)
+               dev_warn(&dev->dev, "Failed to return from FLR\n");
+       else if (i > 1)
+               dev_info(&dev->dev, "Required additional %dms to return from FLR\n",
+                        (i - 1) * 100);
+}
+
 static int pcie_flr(struct pci_dev *dev, int probe)
 {
        u32 cap;
@@ -3429,7 +3439,7 @@ static int pcie_flr(struct pci_dev *dev, int probe)
                dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
 
        pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
-       msleep(100);
+       pci_flr_wait(dev);
        return 0;
 }
 
@@ -3459,7 +3469,7 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
                dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
 
        pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
-       msleep(100);
+       pci_flr_wait(dev);
        return 0;
 }
 
index 9a1660f592ef75f061d154c68629d9bd795c538a..d0fb93481573ad3282e917e09d4852c723ecbd15 100644 (file)
@@ -97,21 +97,21 @@ static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
 struct pci_vpd_ops {
        ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
        ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
-       void (*release)(struct pci_dev *dev);
 };
 
 struct pci_vpd {
-       unsigned int len;
        const struct pci_vpd_ops *ops;
        struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
+       struct mutex    lock;
+       unsigned int    len;
+       u16             flag;
+       u8              cap;
+       u8              busy:1;
+       u8              valid:1;
 };
 
-int pci_vpd_pci22_init(struct pci_dev *dev);
-static inline void pci_vpd_release(struct pci_dev *dev)
-{
-       if (dev->vpd)
-               dev->vpd->ops->release(dev);
-}
+int pci_vpd_init(struct pci_dev *dev);
+void pci_vpd_release(struct pci_dev *dev);
 
 /* PCI /proc functions */
 #ifdef CONFIG_PROC_FS
index e294713c8143bf4e5513872881e11aae0048bf54..72db7f4209cad52181cc80b38558f4827955a866 100644 (file)
@@ -44,6 +44,7 @@ config PCIEASPM
          /sys/module/pcie_aspm/parameters/policy
 
          When in doubt, say Y.
+
 config PCIEASPM_DEBUG
        bool "Debug PCI Express ASPM"
        depends on PCIEASPM
@@ -58,20 +59,20 @@ choice
        depends on PCIEASPM
 
 config PCIEASPM_DEFAULT
-        bool "BIOS default"
+       bool "BIOS default"
        depends on PCIEASPM
        help
          Use the BIOS defaults for PCI Express ASPM.
 
 config PCIEASPM_POWERSAVE
-        bool "Powersave"
+       bool "Powersave"
        depends on PCIEASPM
        help
          Enable PCI Express ASPM L0s and L1 where possible, even if the
          BIOS did not.
 
 config PCIEASPM_PERFORMANCE
-        bool "Performance"
+       bool "Performance"
        depends on PCIEASPM
        help
          Disable PCI Express ASPM L0s and L1, even if the BIOS enabled them.
index 20db790465dd682efae0ade88d7ac42cfd52b060..db553dc22c8e0fca49ad98ff2f9fd3111e18918a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <linux/stddef.h>
+#include <linux/device.h>
 #include "aerdrv.h"
 
 /* Override the existing corrected and uncorrected error masks */
@@ -124,16 +125,13 @@ static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus)
 static struct pci_bus_ops *pci_bus_ops_pop(void)
 {
        unsigned long flags;
-       struct pci_bus_ops *bus_ops = NULL;
+       struct pci_bus_ops *bus_ops;
 
        spin_lock_irqsave(&inject_lock, flags);
-       if (list_empty(&pci_bus_ops_list))
-               bus_ops = NULL;
-       else {
-               struct list_head *lh = pci_bus_ops_list.next;
-               list_del(lh);
-               bus_ops = list_entry(lh, struct pci_bus_ops, list);
-       }
+       bus_ops = list_first_entry_or_null(&pci_bus_ops_list,
+                                          struct pci_bus_ops, list);
+       if (bus_ops)
+               list_del(&bus_ops->list);
        spin_unlock_irqrestore(&inject_lock, flags);
        return bus_ops;
 }
@@ -181,14 +179,16 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where,
        return target;
 }
 
-static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
-                       int size, u32 *val)
+static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn,
+                              int where, int size, u32 *val)
 {
        u32 *sim;
        struct aer_error *err;
        unsigned long flags;
        struct pci_ops *ops;
+       struct pci_ops *my_ops;
        int domain;
+       int rv;
 
        spin_lock_irqsave(&inject_lock, flags);
        if (size != sizeof(u32))
@@ -208,19 +208,32 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
        }
 out:
        ops = __find_pci_bus_ops(bus);
+       /*
+        * pci_lock must already be held, so we can directly
+        * manipulate bus->ops.  Many config access functions,
+        * including pci_generic_config_read() require the original
+        * bus->ops be installed to function, so temporarily put them
+        * back.
+        */
+       my_ops = bus->ops;
+       bus->ops = ops;
+       rv = ops->read(bus, devfn, where, size, val);
+       bus->ops = my_ops;
        spin_unlock_irqrestore(&inject_lock, flags);
-       return ops->read(bus, devfn, where, size, val);
+       return rv;
 }
 
-static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where,
-                        int size, u32 val)
+static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn,
+                               int where, int size, u32 val)
 {
        u32 *sim;
        struct aer_error *err;
        unsigned long flags;
        int rw1cs;
        struct pci_ops *ops;
+       struct pci_ops *my_ops;
        int domain;
+       int rv;
 
        spin_lock_irqsave(&inject_lock, flags);
        if (size != sizeof(u32))
@@ -243,13 +256,24 @@ static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where,
        }
 out:
        ops = __find_pci_bus_ops(bus);
+       /*
+        * pci_lock must already be held, so we can directly
+        * manipulate bus->ops.  Many config access functions,
+        * including pci_generic_config_write() require the original
+        * bus->ops be installed to function, so temporarily put them
+        * back.
+        */
+       my_ops = bus->ops;
+       bus->ops = ops;
+       rv = ops->write(bus, devfn, where, size, val);
+       bus->ops = my_ops;
        spin_unlock_irqrestore(&inject_lock, flags);
-       return ops->write(bus, devfn, where, size, val);
+       return rv;
 }
 
-static struct pci_ops pci_ops_aer = {
-       .read = pci_read_aer,
-       .write = pci_write_aer,
+static struct pci_ops aer_inj_pci_ops = {
+       .read = aer_inj_read_config,
+       .write = aer_inj_write_config,
 };
 
 static void pci_bus_ops_init(struct pci_bus_ops *bus_ops,
@@ -270,9 +294,9 @@ static int pci_bus_set_aer_ops(struct pci_bus *bus)
        bus_ops = kmalloc(sizeof(*bus_ops), GFP_KERNEL);
        if (!bus_ops)
                return -ENOMEM;
-       ops = pci_bus_set_ops(bus, &pci_ops_aer);
+       ops = pci_bus_set_ops(bus, &aer_inj_pci_ops);
        spin_lock_irqsave(&inject_lock, flags);
-       if (ops == &pci_ops_aer)
+       if (ops == &aer_inj_pci_ops)
                goto out;
        pci_bus_ops_init(bus_ops, bus, ops);
        list_add(&bus_ops->list, &pci_bus_ops_list);
@@ -334,13 +358,15 @@ static int aer_inject(struct aer_error_inj *einj)
                return -ENODEV;
        rpdev = pcie_find_root_port(dev);
        if (!rpdev) {
+               dev_err(&dev->dev, "aer_inject: Root port not found\n");
                ret = -ENODEV;
                goto out_put;
        }
 
        pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos_cap_err) {
-               ret = -EPERM;
+               dev_err(&dev->dev, "aer_inject: Device doesn't support AER\n");
+               ret = -EPROTONOSUPPORT;
                goto out_put;
        }
        pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
@@ -350,7 +376,9 @@ static int aer_inject(struct aer_error_inj *einj)
 
        rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
        if (!rp_pos_cap_err) {
-               ret = -EPERM;
+               dev_err(&rpdev->dev,
+                       "aer_inject: Root port doesn't support AER\n");
+               ret = -EPROTONOSUPPORT;
                goto out_put;
        }
 
@@ -397,14 +425,16 @@ static int aer_inject(struct aer_error_inj *einj)
        if (!aer_mask_override && einj->cor_status &&
            !(einj->cor_status & ~cor_mask)) {
                ret = -EINVAL;
-               printk(KERN_WARNING "The correctable error(s) is masked by device\n");
+               dev_warn(&dev->dev,
+                        "aer_inject: The correctable error(s) is masked by device\n");
                spin_unlock_irqrestore(&inject_lock, flags);
                goto out_put;
        }
        if (!aer_mask_override && einj->uncor_status &&
            !(einj->uncor_status & ~uncor_mask)) {
                ret = -EINVAL;
-               printk(KERN_WARNING "The uncorrectable error(s) is masked by device\n");
+               dev_warn(&dev->dev,
+                        "aer_inject: The uncorrectable error(s) is masked by device\n");
                spin_unlock_irqrestore(&inject_lock, flags);
                goto out_put;
        }
@@ -457,13 +487,19 @@ static int aer_inject(struct aer_error_inj *einj)
 
        if (find_aer_device(rpdev, &edev)) {
                if (!get_service_data(edev)) {
-                       printk(KERN_WARNING "AER service is not initialized\n");
-                       ret = -EINVAL;
+                       dev_warn(&edev->device,
+                                "aer_inject: AER service is not initialized\n");
+                       ret = -EPROTONOSUPPORT;
                        goto out_put;
                }
+               dev_info(&edev->device,
+                        "aer_inject: Injecting errors %08x/%08x into device %s\n",
+                        einj->cor_status, einj->uncor_status, pci_name(dev));
                aer_irq(-1, edev);
-       } else
-               ret = -EINVAL;
+       } else {
+               dev_err(&rpdev->dev, "aer_inject: AER device not found\n");
+               ret = -ENODEV;
+       }
 out_put:
        kfree(err_alloc);
        kfree(rperr_alloc);
index 63fc63911295e7c0be875b39436c889c6850234e..1ae4c73e7a3c3037f5430df3159b606f69287c77 100644 (file)
@@ -396,7 +396,7 @@ static int pcie_pme_suspend(struct pcie_device *srv)
 {
        struct pcie_pme_service_data *data = get_service_data(srv);
        struct pci_dev *port = srv->port;
-       bool wakeup;
+       bool wakeup, wake_irq_enabled = false;
        int ret;
 
        if (device_may_wakeup(&port->dev)) {
@@ -409,11 +409,12 @@ static int pcie_pme_suspend(struct pcie_device *srv)
        spin_lock_irq(&data->lock);
        if (wakeup) {
                ret = enable_irq_wake(srv->irq);
-               data->suspend_level = PME_SUSPEND_WAKEUP;
+               if (ret == 0) {
+                       data->suspend_level = PME_SUSPEND_WAKEUP;
+                       wake_irq_enabled = true;
+               }
        }
-       if (!wakeup || ret) {
-               struct pci_dev *port = srv->port;
-
+       if (!wake_irq_enabled) {
                pcie_pme_interrupt_enable(port, false);
                pcie_clear_root_pme_status(port);
                data->suspend_level = PME_SUSPEND_NOIRQ;
index 6d7ab9bb0d5a6f002debd5a3b83e569f78c44c96..b23449902a17d2dc6facf12817925449327a708a 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/pci-aspm.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
-#include <asm-generic/pci-bridge.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
@@ -758,6 +757,12 @@ add_dev:
 
        pcibios_add_bus(child);
 
+       if (child->ops->add_bus) {
+               ret = child->ops->add_bus(child);
+               if (WARN_ON(ret < 0))
+                       dev_err(&child->dev, "failed to add bus: %d\n", ret);
+       }
+
        /* Create legacy_io and legacy_mem files for this bus */
        pci_create_legacy_files(child);
 
@@ -1608,7 +1613,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
        pci_pm_init(dev);
 
        /* Vital Product Data */
-       pci_vpd_pci22_init(dev);
+       pci_vpd_init(dev);
 
        /* Alternative Routing-ID Forwarding */
        pci_configure_ari(dev);
@@ -1803,6 +1808,13 @@ static int only_one_child(struct pci_bus *bus)
                return 0;
        if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT)
                return 1;
+
+       /*
+        * PCIe downstream ports are bridges that normally lead to only a
+        * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all
+        * possible devices, not just device 0.  See PCIe spec r3.0,
+        * sec 7.3.1.
+        */
        if (parent->has_secondary_link &&
            !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
                return 1;
index 0575a1e026b4c4550ee07655910cc64d0e0e9341..8e678027b9008ee15e741967313332db2818c8d8 100644 (file)
@@ -438,7 +438,7 @@ static void quirk_amd_nl_class(struct pci_dev *pdev)
        u32 class = pdev->class;
 
        /* Use "USB Device (not host controller)" class */
-       pdev->class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe;
+       pdev->class = PCI_CLASS_SERIAL_USB_DEVICE;
        dev_info(&pdev->dev, "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
                 class, pdev->class);
 }
@@ -2134,6 +2134,35 @@ static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
 
+/*
+ * If a device follows the VPD format spec, the PCI core will not read or
+ * write past the VPD End Tag.  But some vendors do not follow the VPD
+ * format spec, so we can't tell how much data is safe to access.  Devices
+ * may behave unpredictably if we access too much.  Blacklist these devices
+ * so we don't touch VPD at all.
+ */
+static void quirk_blacklist_vpd(struct pci_dev *dev)
+{
+       if (dev->vpd) {
+               dev->vpd->len = 0;
+               dev_warn(&dev->dev, FW_BUG "VPD access disabled\n");
+       }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0060, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x007c, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0413, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0078, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0079, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0073, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0071, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005b, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x002f, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005d, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005f, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, PCI_ANY_ID,
+               quirk_blacklist_vpd);
+
 /*
  * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the
  * VPD end tag will hang the device.  This problem was initially
@@ -3832,6 +3861,19 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
 #endif
 }
 
+static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
+{
+       /*
+        * Cavium devices matching this quirk do not perform peer-to-peer
+        * with other functions, allowing masking out these bits as if they
+        * were unimplemented in the ACS capability.
+        */
+       acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
+                      PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
+
+       return acs_flags ? 0 : 1;
+}
+
 /*
  * Many Intel PCH root ports do provide ACS-like features to disable peer
  * transactions and validate bus numbers in requests, but do not provide an
@@ -3984,6 +4026,8 @@ static const struct pci_dev_acs_enabled {
        { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
        { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
        { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */
+       /* Cavium ThunderX */
+       { PCI_VENDOR_ID_CAVIUM, PCI_ANY_ID, pci_quirk_cavium_acs },
        { 0 }
 };
 
index 8a280e9c2ad1e00b1cca15b4592d79c7460e1363..d35c7fcde3affdc0bdfaab15f635ebe59a118efe 100644 (file)
@@ -54,6 +54,10 @@ void pci_remove_bus(struct pci_bus *bus)
        pci_bus_release_busn_res(bus);
        up_write(&pci_bus_sem);
        pci_remove_legacy_files(bus);
+
+       if (bus->ops->remove_bus)
+               bus->ops->remove_bus(bus);
+
        pcibios_remove_bus(bus);
        device_unregister(&bus->dev);
 }
index 7796d0a5befafb958c8bae6193b4bca56da96203..55641a39a3e94f3eab29a5494d943afc9614d3e6 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/ioport.h>
 #include <linux/cache.h>
 #include <linux/slab.h>
-#include <asm-generic/pci-bridge.h>
 #include "pci.h"
 
 unsigned int pci_flags;
index 1412266314292dfa59bf473cf2ed3fdb2edebe65..a6682c508c4cbb800a19fd8b010a551f404d55b3 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include <asm/macio.h>
 
 #include <scsi/scsi.h>
index 555367f002282b238f8da84ab20100526ba7b1c1..1753e42826dd99bf7d69e1ea83f54a9b5ba34309 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
+#include <linux/pci.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -38,7 +39,6 @@
 #include <asm/processor.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
 #include <asm/macio.h>
 
 #include <scsi/scsi.h>
index 9eb1cff28bd4b2499e4dfd9ed8b91e53901df184..c3640f8a8fb34440a8cb96b0320c26835131cbef 100644 (file)
@@ -28,7 +28,6 @@
 #ifdef CONFIG_PPC_PMAC
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
 #include <asm/prom.h>
 #endif
 
index cd8764150861cf1c677bb25a52f4a1b00294b52e..39d70b4a89581620d329444af1af61367d8b40ea 100644 (file)
@@ -3397,7 +3397,7 @@ err_pcidev:
 static const struct pci_device_id pci_id[] = {
        {
                PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
-               .class =        (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class =        PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask =   0xffffffff,
        },
        {},
index 1fdfec14a3ba13eea57dfced8b170752e452fdb2..d2205d9e0c8b43265901352548342b0e8646ca97 100644 (file)
@@ -1846,7 +1846,7 @@ err:
 /*-------------------------------------------------------------------------*/
 
 static const struct pci_device_id pci_ids[] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       0x102f,         /* Toshiba */
        .device =       0x0107,         /* this UDC */
index 6706aef907f4bdb32b308f148612a2566c2eb3b9..c894b94b234bf58aba86cea8a341abb88941e61a 100644 (file)
@@ -3735,7 +3735,7 @@ static void net2280_shutdown(struct pci_dev *pdev)
 /*-------------------------------------------------------------------------*/
 
 static const struct pci_device_id pci_ids[] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
        .device =       0x2280,
@@ -3743,7 +3743,7 @@ static const struct pci_device_id pci_ids[] = { {
        .subdevice =    PCI_ANY_ID,
        .driver_data =  PLX_LEGACY | PLX_2280,
        }, {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
        .device =       0x2282,
@@ -3752,7 +3752,7 @@ static const struct pci_device_id pci_ids[] = { {
        .driver_data =  PLX_LEGACY,
        },
        {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX,
        .device =       0x3380,
@@ -3761,7 +3761,7 @@ static const struct pci_device_id pci_ids[] = { {
        .driver_data =  PLX_SUPERSPEED,
         },
        {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX,
        .device =       0x3382,
index 7a04157ff5796883f8c9ec3835b43c16155fbc3d..9571ef54b86b53fcda4ba6517ed75e02f1751abb 100644 (file)
@@ -3234,22 +3234,22 @@ static const struct pci_device_id pch_udc_pcidev_id[] = {
        {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL,
                           PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        {
                PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7213_IOH_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        {
                PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        { 0 },
index c42ce2fdfd441de6a88f7e3ecbc46fa2514028d7..0a4626886b00c1402bc2bbc234fe691bb549ff8a 100644 (file)
@@ -68,7 +68,6 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include "../macmodes.h"
 #endif
 
index ce0b1d05a388cefc309e177de53b6b936226ae74..218339a4edaac46e5b223d07f12f335b8966c66f 100644 (file)
@@ -76,7 +76,6 @@
 
 #ifdef CONFIG_PPC
 
-#include <asm/pci-bridge.h>
 #include "../macmodes.h"
 
 #ifdef CONFIG_BOOTX_TEXT
index 9b167f7ef6c698854a8fe4d05fdf4c3d2e9fffc7..4363c64d74e8c1481842735aa2fc0d1831344b05 100644 (file)
@@ -33,7 +33,6 @@
 #if defined(CONFIG_PPC)
 #include <linux/nvram.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include "macmodes.h"
 #endif
 
index 09b02cd1eb0e270f7dc654116167101202b00a27..7a90ea2c4613c772d4b14584a483fd2bbaed92bc 100644 (file)
@@ -47,7 +47,6 @@
 
 #if defined(CONFIG_PPC_PMAC)
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include "../macmodes.h"
 #endif
 
index 43a0a52fc52703c18244dc2b25e54d6dd22c1f61..fb60a8f0cc94c8103d8dc141b25c5eecec5db39c 100644 (file)
 #include <linux/pci.h>
 #include <asm/io.h>
 
-#ifdef CONFIG_PPC64
-#include <asm/pci-bridge.h>
-#endif
-
 #ifdef CONFIG_PPC32
 #include <asm/bootx.h>
 #endif
index 36205c27c4d0f19ab61a4aa4175de3dd8785de66..127dfe4e86942f15b9d54db2228345c3e4a16823 100644 (file)
@@ -467,7 +467,7 @@ static const struct dev_pm_ops virtio_pci_pm_ops = {
 
 /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
 static const struct pci_device_id virtio_pci_id_table[] = {
-       { PCI_DEVICE(0x1af4, PCI_ANY_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) },
        { 0 }
 };
 
diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h
deleted file mode 100644 (file)
index 20db2e5..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _ASM_GENERIC_PCI_BRIDGE_H
-#define _ASM_GENERIC_PCI_BRIDGE_H
-
-#ifdef __KERNEL__
-
-enum {
-       /* Force re-assigning all resources (ignore firmware
-        * setup completely)
-        */
-       PCI_REASSIGN_ALL_RSRC   = 0x00000001,
-
-       /* Re-assign all bus numbers */
-       PCI_REASSIGN_ALL_BUS    = 0x00000002,
-
-       /* Do not try to assign, just use existing setup */
-       PCI_PROBE_ONLY          = 0x00000004,
-
-       /* Don't bother with ISA alignment unless the bridge has
-        * ISA forwarding enabled
-        */
-       PCI_CAN_SKIP_ISA_ALIGN  = 0x00000008,
-
-       /* Enable domain numbers in /proc */
-       PCI_ENABLE_PROC_DOMAINS = 0x00000010,
-       /* ... except for domain 0 */
-       PCI_COMPAT_DOMAIN_0     = 0x00000020,
-
-       /* PCIe downstream ports are bridges that normally lead to only a
-        * device 0, but if this is set, we scan all possible devices, not
-        * just device 0.
-        */
-       PCI_SCAN_ALL_PCIE_DEVS  = 0x00000040,
-};
-
-#ifdef CONFIG_PCI
-extern unsigned int pci_flags;
-
-static inline void pci_set_flags(int flags)
-{
-       pci_flags = flags;
-}
-
-static inline void pci_add_flags(int flags)
-{
-       pci_flags |= flags;
-}
-
-static inline void pci_clear_flags(int flags)
-{
-       pci_flags &= ~flags;
-}
-
-static inline int pci_has_flag(int flag)
-{
-       return pci_flags & flag;
-}
-#else
-static inline void pci_set_flags(int flags) { }
-static inline void pci_add_flags(int flags) { }
-static inline void pci_clear_flags(int flags) { }
-static inline int pci_has_flag(int flag)
-{
-       return 0;
-}
-#endif /* CONFIG_PCI */
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_GENERIC_PCI_BRIDGE_H */
diff --git a/include/asm-generic/pci-dma-compat.h b/include/asm-generic/pci-dma-compat.h
deleted file mode 100644 (file)
index eafce7b..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/* include this file if the platform implements the dma_ DMA Mapping API
- * and wants to provide the pci_ DMA Mapping API in terms of it */
-
-#ifndef _ASM_GENERIC_PCI_DMA_COMPAT_H
-#define _ASM_GENERIC_PCI_DMA_COMPAT_H
-
-#include <linux/dma-mapping.h>
-
-static inline void *
-pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                    dma_addr_t *dma_handle)
-{
-       return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
-}
-
-static inline void *
-pci_zalloc_consistent(struct pci_dev *hwdev, size_t size,
-                     dma_addr_t *dma_handle)
-{
-       return dma_zalloc_coherent(hwdev == NULL ? NULL : &hwdev->dev,
-                                  size, dma_handle, GFP_ATOMIC);
-}
-
-static inline void
-pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                   void *vaddr, dma_addr_t dma_handle)
-{
-       dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
-}
-
-static inline dma_addr_t
-pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
-{
-       return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-                size_t size, int direction)
-{
-       dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
-}
-
-static inline dma_addr_t
-pci_map_page(struct pci_dev *hwdev, struct page *page,
-            unsigned long offset, size_t size, int direction)
-{
-       return dma_map_page(hwdev == NULL ? NULL : &hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
-              size_t size, int direction)
-{
-       dma_unmap_page(hwdev == NULL ? NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
-}
-
-static inline int
-pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-          int nents, int direction)
-{
-       return dma_map_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-            int nents, int direction)
-{
-       dma_unmap_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
-                   size_t size, int direction)
-{
-       dma_sync_single_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
-                   size_t size, int direction)
-{
-       dma_sync_single_for_device(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
-               int nelems, int direction)
-{
-       dma_sync_sg_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
-               int nelems, int direction)
-{
-       dma_sync_sg_for_device(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
-}
-
-static inline int
-pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr)
-{
-       return dma_mapping_error(&pdev->dev, dma_addr);
-}
-
-#ifdef CONFIG_PCI
-static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       return dma_set_mask(&dev->dev, mask);
-}
-
-static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       return dma_set_coherent_mask(&dev->dev, mask);
-}
-#endif
-
-#endif
diff --git a/include/linux/pci-dma-compat.h b/include/linux/pci-dma-compat.h
new file mode 100644 (file)
index 0000000..39726ca
--- /dev/null
@@ -0,0 +1,147 @@
+/* include this file if the platform implements the dma_ DMA Mapping API
+ * and wants to provide the pci_ DMA Mapping API in terms of it */
+
+#ifndef _ASM_GENERIC_PCI_DMA_COMPAT_H
+#define _ASM_GENERIC_PCI_DMA_COMPAT_H
+
+#include <linux/dma-mapping.h>
+
+/* This defines the direction arg to the DMA mapping routines. */
+#define PCI_DMA_BIDIRECTIONAL  0
+#define PCI_DMA_TODEVICE       1
+#define PCI_DMA_FROMDEVICE     2
+#define PCI_DMA_NONE           3
+
+static inline void *
+pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+                    dma_addr_t *dma_handle)
+{
+       return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
+}
+
+static inline void *
+pci_zalloc_consistent(struct pci_dev *hwdev, size_t size,
+                     dma_addr_t *dma_handle)
+{
+       return dma_zalloc_coherent(hwdev == NULL ? NULL : &hwdev->dev,
+                                  size, dma_handle, GFP_ATOMIC);
+}
+
+static inline void
+pci_free_consistent(struct pci_dev *hwdev, size_t size,
+                   void *vaddr, dma_addr_t dma_handle)
+{
+       dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
+}
+
+static inline dma_addr_t
+pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+{
+       return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+                size_t size, int direction)
+{
+       dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
+}
+
+static inline dma_addr_t
+pci_map_page(struct pci_dev *hwdev, struct page *page,
+            unsigned long offset, size_t size, int direction)
+{
+       return dma_map_page(hwdev == NULL ? NULL : &hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
+              size_t size, int direction)
+{
+       dma_unmap_page(hwdev == NULL ? NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
+}
+
+static inline int
+pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+          int nents, int direction)
+{
+       return dma_map_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+            int nents, int direction)
+{
+       dma_unmap_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
+                   size_t size, int direction)
+{
+       dma_sync_single_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
+                   size_t size, int direction)
+{
+       dma_sync_single_for_device(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
+               int nelems, int direction)
+{
+       dma_sync_sg_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
+               int nelems, int direction)
+{
+       dma_sync_sg_for_device(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
+}
+
+static inline int
+pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr)
+{
+       return dma_mapping_error(&pdev->dev, dma_addr);
+}
+
+#ifdef CONFIG_PCI
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+       return dma_set_mask(&dev->dev, mask);
+}
+
+static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{
+       return dma_set_coherent_mask(&dev->dev, mask);
+}
+
+static inline int pci_set_dma_max_seg_size(struct pci_dev *dev,
+                                          unsigned int size)
+{
+       return dma_set_max_seg_size(&dev->dev, size);
+}
+
+static inline int pci_set_dma_seg_boundary(struct pci_dev *dev,
+                                          unsigned long mask)
+{
+       return dma_set_seg_boundary(&dev->dev, mask);
+}
+#else
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{ return -EIO; }
+static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{ return -EIO; }
+static inline int pci_set_dma_max_seg_size(struct pci_dev *dev,
+                                          unsigned int size)
+{ return -EIO; }
+static inline int pci_set_dma_seg_boundary(struct pci_dev *dev,
+                                          unsigned long mask)
+{ return -EIO; }
+#endif
+
+#endif
index 27df4a6585daedcc6a74865bf048cfd06a0593ba..d6709831efb9b5d2ed34d4e553f8f4a86fc7afaa 100644 (file)
@@ -70,12 +70,6 @@ enum pci_mmap_state {
        pci_mmap_mem
 };
 
-/* This defines the direction arg to the DMA mapping routines. */
-#define PCI_DMA_BIDIRECTIONAL  0
-#define PCI_DMA_TODEVICE       1
-#define PCI_DMA_FROMDEVICE     2
-#define PCI_DMA_NONE           3
-
 /*
  *  For PCI devices, the region numbers are assigned this way:
  */
@@ -578,6 +572,8 @@ static inline int pcibios_err_to_errno(int err)
 /* Low-level architecture-dependent routines */
 
 struct pci_ops {
+       int (*add_bus)(struct pci_bus *bus);
+       void (*remove_bus)(struct pci_bus *bus);
        void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int where);
        int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
        int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
@@ -746,9 +742,26 @@ struct pci_driver {
        .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \
        .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0
 
+enum {
+       PCI_REASSIGN_ALL_RSRC   = 0x00000001,   /* ignore firmware setup */
+       PCI_REASSIGN_ALL_BUS    = 0x00000002,   /* reassign all bus numbers */
+       PCI_PROBE_ONLY          = 0x00000004,   /* use existing setup */
+       PCI_CAN_SKIP_ISA_ALIGN  = 0x00000008,   /* don't do ISA alignment */
+       PCI_ENABLE_PROC_DOMAINS = 0x00000010,   /* enable domains in /proc */
+       PCI_COMPAT_DOMAIN_0     = 0x00000020,   /* ... except domain 0 */
+       PCI_SCAN_ALL_PCIE_DEVS  = 0x00000040,   /* scan all, not just dev 0 */
+};
+
 /* these external functions are only available when PCI support is enabled */
 #ifdef CONFIG_PCI
 
+extern unsigned int pci_flags;
+
+static inline void pci_set_flags(int flags) { pci_flags = flags; }
+static inline void pci_add_flags(int flags) { pci_flags |= flags; }
+static inline void pci_clear_flags(int flags) { pci_flags &= ~flags; }
+static inline int pci_has_flag(int flag) { return pci_flags & flag; }
+
 void pcie_bus_configure_settings(struct pci_bus *bus);
 
 enum pcie_bus_config_types {
@@ -1021,8 +1034,6 @@ void pci_intx(struct pci_dev *dev, int enable);
 bool pci_intx_mask_supported(struct pci_dev *dev);
 bool pci_check_and_mask_intx(struct pci_dev *dev);
 bool pci_check_and_unmask_intx(struct pci_dev *dev);
-int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
-int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
 int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);
 int pci_wait_for_pending_transaction(struct pci_dev *dev);
 int pcix_get_max_mmrbc(struct pci_dev *dev);
@@ -1238,6 +1249,7 @@ resource_size_t pcibios_iov_resource_alignment(struct pci_dev *dev, int resno);
 
 int pci_set_vga_state(struct pci_dev *pdev, bool decode,
                      unsigned int command_bits, u32 flags);
+
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 
 #include <linux/pci-dma.h>
@@ -1405,6 +1417,11 @@ void pci_register_set_vga_state(arch_set_vga_state_t func);
 
 #else /* CONFIG_PCI is not enabled */
 
+static inline void pci_set_flags(int flags) { }
+static inline void pci_add_flags(int flags) { }
+static inline void pci_clear_flags(int flags) { }
+static inline int pci_has_flag(int flag) { return 0; }
+
 /*
  *  If the system does not have PCI, clearly these return errors.  Define
  *  these as simple inline functions to avoid hair in drivers.
@@ -1444,16 +1461,6 @@ static inline struct pci_dev *pci_get_class(unsigned int class,
 static inline void pci_set_master(struct pci_dev *dev) { }
 static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
 static inline void pci_disable_device(struct pci_dev *dev) { }
-static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{ return -EIO; }
-static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{ return -EIO; }
-static inline int pci_set_dma_max_seg_size(struct pci_dev *dev,
-                                       unsigned int size)
-{ return -EIO; }
-static inline int pci_set_dma_seg_boundary(struct pci_dev *dev,
-                                       unsigned long mask)
-{ return -EIO; }
 static inline int pci_assign_resource(struct pci_dev *dev, int i)
 { return -EBUSY; }
 static inline int __pci_register_driver(struct pci_driver *drv,
@@ -1834,12 +1841,13 @@ bool pci_acs_path_enabled(struct pci_dev *start,
 #define PCI_VPD_LRDT_RW_DATA           PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RW_DATA)
 
 /* Small Resource Data Type Tag Item Names */
-#define PCI_VPD_STIN_END               0x78    /* End */
+#define PCI_VPD_STIN_END               0x0f    /* End */
 
-#define PCI_VPD_SRDT_END               PCI_VPD_STIN_END
+#define PCI_VPD_SRDT_END               (PCI_VPD_STIN_END << 3)
 
 #define PCI_VPD_SRDT_TIN_MASK          0x78
 #define PCI_VPD_SRDT_LEN_MASK          0x07
+#define PCI_VPD_LRDT_TIN_MASK          0x7f
 
 #define PCI_VPD_LRDT_TAG_SIZE          3
 #define PCI_VPD_SRDT_TAG_SIZE          1
@@ -1862,6 +1870,17 @@ static inline u16 pci_vpd_lrdt_size(const u8 *lrdt)
        return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
 }
 
+/**
+ * pci_vpd_lrdt_tag - Extracts the Large Resource Data Type Tag Item
+ * @lrdt: Pointer to the beginning of the Large Resource Data Type tag
+ *
+ * Returns the extracted Large Resource Data Type Tag item.
+ */
+static inline u16 pci_vpd_lrdt_tag(const u8 *lrdt)
+{
+    return (u16)(lrdt[0] & PCI_VPD_LRDT_TIN_MASK);
+}
+
 /**
  * pci_vpd_srdt_size - Extracts the Small Resource Data Type length
  * @lrdt: Pointer to the beginning of the Small Resource Data Type tag
@@ -1873,6 +1892,17 @@ static inline u8 pci_vpd_srdt_size(const u8 *srdt)
        return (*srdt) & PCI_VPD_SRDT_LEN_MASK;
 }
 
+/**
+ * pci_vpd_srdt_tag - Extracts the Small Resource Data Type Tag Item
+ * @lrdt: Pointer to the beginning of the Small Resource Data Type tag
+ *
+ * Returns the extracted Small Resource Data Type Tag Item.
+ */
+static inline u8 pci_vpd_srdt_tag(const u8 *srdt)
+{
+       return ((*srdt) & PCI_VPD_SRDT_TIN_MASK) >> 3;
+}
+
 /**
  * pci_vpd_info_field_size - Extracts the information field length
  * @lrdt: Pointer to the beginning of an information field header
@@ -1989,4 +2019,8 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
 {
        return bus->self && bus->self->ari_enabled;
 }
+
+/* provide the legacy pci_dma_* API */
+#include <linux/pci-dma-compat.h>
+
 #endif /* LINUX_PCI_H */
index 37f05cb1dfd6d93cae1ceeffc8a3de1c0fcb0529..247da8c9586073d6759d333051909c5c4d050315 100644 (file)
 #define PCI_CLASS_SERIAL_USB_OHCI      0x0c0310
 #define PCI_CLASS_SERIAL_USB_EHCI      0x0c0320
 #define PCI_CLASS_SERIAL_USB_XHCI      0x0c0330
+#define PCI_CLASS_SERIAL_USB_DEVICE    0x0c03fe
 #define PCI_CLASS_SERIAL_FIBER         0x0c04
 #define PCI_CLASS_SERIAL_SMBUS         0x0c05
 
 
 #define PCI_VENDOR_ID_AZWAVE           0x1a3b
 
+#define PCI_VENDOR_ID_REDHAT_QUMRANET    0x1af4
+#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_SUBDEVICE_ID_QEMU            0x1100
+
 #define PCI_VENDOR_ID_ASMEDIA          0x1b21
 
 #define PCI_VENDOR_ID_CIRCUITCO                0x1cc8
index 42bcbac801a322d0f7cf8df6961e9c6129ae0093..12c2c180e4072755ba17a4826070093669b45723 100644 (file)
@@ -2980,8 +2980,8 @@ static int snd_intel8x0_inside_vm(struct pci_dev *pci)
                goto fini;
 
        /* check for known (emulated) devices */
-       if (pci->subsystem_vendor == 0x1af4 &&
-           pci->subsystem_device == 0x1100) {
+       if (pci->subsystem_vendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
+           pci->subsystem_device == PCI_SUBDEVICE_ID_QEMU) {
                /* KVM emulated sound, PCI SSID: 1af4:1100 */
                msg = "enable KVM";
        } else if (pci->subsystem_vendor == 0x1ab8) {
index 0095a80a997fc157e97b70d3c12051d65d0ee4ab..a5843fc5ff204ee6efb32becd35e671927903f59 100644 (file)
@@ -34,7 +34,6 @@
 #include "pmac.h"
 #include <sound/pcm_params.h>
 #include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
 
 
 /* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */