]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'pci/host-mvebu' into next
authorBjorn Helgaas <bhelgaas@google.com>
Fri, 20 Dec 2013 19:40:54 +0000 (12:40 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 20 Dec 2013 19:40:54 +0000 (12:40 -0700)
* pci/host-mvebu:
  PCI: mvebu: Remove redundant of_match_ptr

47 files changed:
Documentation/devicetree/bindings/pci/designware-pcie.txt
MAINTAINERS
arch/alpha/kernel/pci_iommu.c
arch/arm/common/it8152.c
arch/arm/mach-ixp4xx/common-pci.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/sn/pci/pci_dma.c
arch/parisc/kernel/drivers.c
arch/sparc/kernel/iommu.c
arch/sparc/kernel/ioport.c
arch/x86/include/asm/pci.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/x86_init.c
arch/x86/pci/xen.c
drivers/eisa/eisa-bus.c
drivers/pci/Makefile
drivers/pci/bus.c
drivers/pci/host/pci-imx6.c
drivers/pci/host/pci-mvebu.c
drivers/pci/host/pci-rcar-gen2.c
drivers/pci/host/pci-tegra.c
drivers/pci/host/pcie-designware.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/iov.c
drivers/pci/msi.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/pcie/aer/aerdrv_acpi.c
drivers/pci/pcie/aer/aerdrv_errprint.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/probe.c
drivers/pci/remove.c
drivers/pci/setup-bus.c
drivers/pci/vc.c [new file with mode: 0644]
drivers/vfio/pci/vfio_pci_config.c
include/linux/kexec.h
include/linux/msi.h
include/linux/pci.h
include/uapi/linux/pci_regs.h
kernel/kexec.c
kernel/workqueue.c

index d5d26d443693ce70db814c9466bbc72d87d6b7fe..d6fae13ff0628bef56a69d671a9a684fa7ab2280 100644 (file)
@@ -19,6 +19,8 @@ Required properties:
        to define the mapping of the PCIe interface to interrupt
        numbers.
 - num-lanes: number of lanes to use
+
+Optional properties:
 - reset-gpio: gpio pin number of power good signal
 
 Optional properties for fsl,imx6q-pcie
index 8285ed4676b6388502be84ddde71d1e201827ce8..624e6516fdd328dd66730df883618dbd54c7e8e2 100644 (file)
@@ -6449,19 +6449,52 @@ F:      drivers/pci/
 F:     include/linux/pci*
 F:     arch/x86/pci/
 
+PCI DRIVER FOR IMX6
+M:     Richard Zhu <r65037@freescale.com>
+M:     Shawn Guo <shawn.guo@linaro.org>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/pci/host/*imx6*
+
+PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
+M:     Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+M:     Jason Cooper <jason@lakedaemon.net>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/pci/host/*mvebu*
+
 PCI DRIVER FOR NVIDIA TEGRA
 M:     Thierry Reding <thierry.reding@gmail.com>
 L:     linux-tegra@vger.kernel.org
+L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
 F:     drivers/pci/host/pci-tegra.c
 
+PCI DRIVER FOR RENESAS R-CAR
+M:     Simon Horman <horms@verge.net.au>
+L:     linux-pci@vger.kernel.org
+L:     linux-sh@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/host/*rcar*
+
 PCI DRIVER FOR SAMSUNG EXYNOS
 M:     Jingoo Han <jg1.han@samsung.com>
 L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/pci/host/pci-exynos.c
 
+PCI DRIVER FOR SYNOPSIS DESIGNWARE
+M:     Mohit Kumar <mohit.kumar@st.com>
+M:     Jingoo Han <jg1.han@samsung.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/host/*designware*
+
 PCMCIA SUBSYSTEM
 P:     Linux PCMCIA Team
 L:     linux-pcmcia@lists.infradead.org
index a21d0ab3b19e1cf3f57f7c95e2a0b5dbe4ab8e9d..eddee77203431fb9d50d7c0feb313f26d5985d8e 100644 (file)
@@ -325,7 +325,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
 /* Helper for generic DMA-mapping functions. */
 static struct pci_dev *alpha_gendev_to_pci(struct device *dev)
 {
-       if (dev && dev->bus == &pci_bus_type)
+       if (dev && dev_is_pci(dev))
                return to_pci_dev(dev);
 
        /* Assume that non-PCI devices asking for DMA are either ISA or EISA,
index 001f4913799c5a6c0d59159d4cc619456061f235..5114b68e99d5215bd7db38daa6b57a2e4b305f4a 100644 (file)
@@ -257,7 +257,7 @@ static int it8152_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t s
  */
 static int it8152_pci_platform_notify(struct device *dev)
 {
-       if (dev->bus == &pci_bus_type) {
+       if (dev_is_pci(dev)) {
                if (dev->dma_mask)
                        *dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
                dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
@@ -268,7 +268,7 @@ static int it8152_pci_platform_notify(struct device *dev)
 
 static int it8152_pci_platform_notify_remove(struct device *dev)
 {
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                dmabounce_unregister_dev(dev);
 
        return 0;
index 6d6bde3e15fad4e4cf094a22c6ae6b8837a1580f..200970d56f6d8c7c0b9a166584ee38eddad4fe31 100644 (file)
@@ -326,7 +326,7 @@ static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t s
  */
 static int ixp4xx_pci_platform_notify(struct device *dev)
 {
-       if(dev->bus == &pci_bus_type) {
+       if (dev_is_pci(dev)) {
                *dev->dma_mask =  SZ_64M - 1;
                dev->coherent_dma_mask = SZ_64M - 1;
                dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
@@ -336,9 +336,9 @@ static int ixp4xx_pci_platform_notify(struct device *dev)
 
 static int ixp4xx_pci_platform_notify_remove(struct device *dev)
 {
-       if(dev->bus == &pci_bus_type) {
+       if (dev_is_pci(dev))
                dmabounce_unregister_dev(dev);
-       }
+
        return 0;
 }
 
index 4c530a82fc469f976b8a38a341f077a43f9c9998..8e858b593e4f13cf79fb34fda2903531e02fd1dc 100644 (file)
@@ -255,7 +255,7 @@ static u64 prefetch_spill_page;
 #endif
 
 #ifdef CONFIG_PCI
-# define GET_IOC(dev)  (((dev)->bus == &pci_bus_type)                                          \
+# define GET_IOC(dev)  ((dev_is_pci(dev))                                              \
                         ? ((struct ioc *) PCI_CONTROLLER(to_pci_dev(dev))->iommu) : NULL)
 #else
 # define GET_IOC(dev)  NULL
index 3290d6e00c3164674e2d2d018c9b992dbc5fc152..d0853e8e8623e46a4a5e7ad87072e7ca354af0a0 100644 (file)
@@ -34,7 +34,7 @@
  */
 static int sn_dma_supported(struct device *dev, u64 mask)
 {
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        if (mask < 0x7fffffff)
                return 0;
@@ -50,7 +50,7 @@ static int sn_dma_supported(struct device *dev, u64 mask)
  */
 int sn_dma_set_mask(struct device *dev, u64 dma_mask)
 {
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        if (!sn_dma_supported(dev, dma_mask))
                return 0;
@@ -85,7 +85,7 @@ static void *sn_dma_alloc_coherent(struct device *dev, size_t size,
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        /*
         * Allocate the memory.
@@ -143,7 +143,7 @@ static void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        provider->dma_unmap(pdev, dma_handle, 0);
        free_pages((unsigned long)cpu_addr, get_order(size));
@@ -187,7 +187,7 @@ static dma_addr_t sn_dma_map_page(struct device *dev, struct page *page,
 
        dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
 
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        phys_addr = __pa(cpu_addr);
        if (dmabarr)
@@ -223,7 +223,7 @@ static void sn_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        provider->dma_unmap(pdev, dma_addr, dir);
 }
@@ -247,7 +247,7 @@ static void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
        struct scatterlist *sg;
 
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        for_each_sg(sgl, sg, nhwentries, i) {
                provider->dma_unmap(pdev, sg->dma_address, dir);
@@ -284,7 +284,7 @@ static int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl,
 
        dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
 
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 
        /*
         * Setup a DMA address for each entry in the scatterlist.
@@ -323,26 +323,26 @@ static int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl,
 static void sn_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
                                       size_t size, enum dma_data_direction dir)
 {
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 }
 
 static void sn_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
                                          size_t size,
                                          enum dma_data_direction dir)
 {
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 }
 
 static void sn_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
                                   int nelems, enum dma_data_direction dir)
 {
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 }
 
 static void sn_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
                                      int nelems, enum dma_data_direction dir)
 {
-       BUG_ON(dev->bus != &pci_bus_type);
+       BUG_ON(!dev_is_pci(dev));
 }
 
 static int sn_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
index 14285caec71a4360b5b061f87a43077675f0ce1e..dba508fe1683d8153ed9ca7a0539246f7f6d52a2 100644 (file)
@@ -282,18 +282,6 @@ find_pa_parent_type(const struct parisc_device *padev, int type)
        return NULL;
 }
 
-#ifdef CONFIG_PCI
-static inline int is_pci_dev(struct device *dev)
-{
-       return dev->bus == &pci_bus_type;
-}
-#else
-static inline int is_pci_dev(struct device *dev)
-{
-       return 0;
-}
-#endif
-
 /*
  * get_node_path fills in @path with the firmware path to the device.
  * Note that if @node is a parisc device, we don't fill in the 'mod' field.
@@ -306,7 +294,7 @@ static void get_node_path(struct device *dev, struct hardware_path *path)
        int i = 5;
        memset(&path->bc, -1, 6);
 
-       if (is_pci_dev(dev)) {
+       if (dev_is_pci(dev)) {
                unsigned int devfn = to_pci_dev(dev)->devfn;
                path->mod = PCI_FUNC(devfn);
                path->bc[i--] = PCI_SLOT(devfn);
@@ -314,7 +302,7 @@ static void get_node_path(struct device *dev, struct hardware_path *path)
        }
 
        while (dev != &root) {
-               if (is_pci_dev(dev)) {
+               if (dev_is_pci(dev)) {
                        unsigned int devfn = to_pci_dev(dev)->devfn;
                        path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn)<< 5);
                } else if (dev->bus == &parisc_bus_type) {
@@ -695,7 +683,7 @@ static int check_parent(struct device * dev, void * data)
                if (dev->bus == &parisc_bus_type) {
                        if (match_parisc_device(dev, d->index, d->modpath))
                                d->dev = dev;
-               } else if (is_pci_dev(dev)) {
+               } else if (dev_is_pci(dev)) {
                        if (match_pci_device(dev, d->index, d->modpath))
                                d->dev = dev;
                } else if (dev->bus == NULL) {
@@ -753,7 +741,7 @@ struct device *hwpath_to_device(struct hardware_path *modpath)
                if (!parent)
                        return NULL;
        }
-       if (is_pci_dev(parent)) /* pci devices already parse MOD */
+       if (dev_is_pci(parent)) /* pci devices already parse MOD */
                return parent;
        else
                return parse_tree_node(parent, 6, modpath);
@@ -772,7 +760,7 @@ void device_to_hwpath(struct device *dev, struct hardware_path *path)
                padev = to_parisc_device(dev);
                get_node_path(dev->parent, path);
                path->mod = padev->hw_path;
-       } else if (is_pci_dev(dev)) {
+       } else if (dev_is_pci(dev)) {
                get_node_path(dev, path);
        }
 }
index 070ed141aac79728da15f406289219a9c385fe27..76663b019eb5207f389655dac5133afce6e553aa 100644 (file)
@@ -854,7 +854,7 @@ int dma_supported(struct device *dev, u64 device_mask)
                return 1;
 
 #ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return pci64_dma_supported(to_pci_dev(dev), device_mask);
 #endif
 
index 2096468de9b27f7dd2bb54f17e3b308f8d359836..e7e215dfa86668750c9490331d94b288ab78857c 100644 (file)
@@ -666,10 +666,9 @@ EXPORT_SYMBOL(dma_ops);
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-#ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return 1;
-#endif
+
        return 0;
 }
 EXPORT_SYMBOL(dma_supported);
index 947b5c417e830ae0ead192964ef07f8a68d88851..0de52c5bf9a2089a58a70a2b2d1f8ee55648207c 100644 (file)
@@ -104,7 +104,7 @@ extern void pci_iommu_alloc(void);
 struct msi_desc;
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void native_teardown_msi_irq(unsigned int irq);
-void native_restore_msi_irqs(struct pci_dev *dev, int irq);
+void native_restore_msi_irqs(struct pci_dev *dev);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
                  unsigned int irq_base, unsigned int irq_offset);
 #else
index 0f1be11e43d2f69fa16321fbf49004bed959e6fa..e45e4da96bf1b89e2f0e7edbf95e4cd821932e71 100644 (file)
@@ -181,7 +181,7 @@ struct x86_msi_ops {
                               u8 hpet_id);
        void (*teardown_msi_irq)(unsigned int irq);
        void (*teardown_msi_irqs)(struct pci_dev *dev);
-       void (*restore_msi_irqs)(struct pci_dev *dev, int irq);
+       void (*restore_msi_irqs)(struct pci_dev *dev);
        int  (*setup_hpet_msi)(unsigned int irq, unsigned int id);
        u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag);
        u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag);
index 6c0b43bd024bb5890230ca45c61b3de082b611ef..d359d0fffa50cfea2539593f68649552df587622 100644 (file)
@@ -1034,9 +1034,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
 
        if (!acpi_ioapic)
                return 0;
-       if (!dev)
-               return 0;
-       if (dev->bus != &pci_bus_type)
+       if (!dev || !dev_is_pci(dev))
                return 0;
 
        pdev = to_pci_dev(dev);
index 021783b1f46a572d210a4d84f2ad3a5a622cb39d..e48b674639ccdff745e2920ec44929ec5d8c59b7 100644 (file)
@@ -136,9 +136,9 @@ void arch_teardown_msi_irq(unsigned int irq)
        x86_msi.teardown_msi_irq(irq);
 }
 
-void arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+void arch_restore_msi_irqs(struct pci_dev *dev)
 {
-       x86_msi.restore_msi_irqs(dev, irq);
+       x86_msi.restore_msi_irqs(dev);
 }
 u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
index 5eee4959785d574456955062d8dbfb9d16baf39c..103e702ec5a75d2274395ca0058e1a68b59ecc5b 100644 (file)
@@ -337,7 +337,7 @@ out:
        return ret;
 }
 
-static void xen_initdom_restore_msi_irqs(struct pci_dev *dev, int irq)
+static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
 {
        int ret = 0;
 
index 272a3ec3595703b6dbdaa440108eb569410cf65f..8842cde69177d76afc4681bb697b1d044026960c 100644 (file)
@@ -232,8 +232,10 @@ static int __init eisa_init_device(struct eisa_root_device *root,
 static int __init eisa_register_device(struct eisa_device *edev)
 {
        int rc = device_register(&edev->dev);
-       if (rc)
+       if (rc) {
+               put_device(&edev->dev);
                return rc;
+       }
 
        rc = device_create_file(&edev->dev, &dev_attr_signature);
        if (rc)
index 6ebf5bf8e7a7d149fa8c091ed4071ba1b7e6af69..17d2b07ee67c2db583a650b2ffbada55324faa53 100644 (file)
@@ -4,7 +4,7 @@
 
 obj-y          += access.o bus.o probe.o host-bridge.o remove.o pci.o \
                        pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
-                       irq.o vpd.o setup-bus.o
+                       irq.o vpd.o setup-bus.o vc.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
index fc1b740137430b703a348b03d1c9420d19d21d7a..a037d81f21edb8c8f9c2b45bffcb6c45f5187537 100644 (file)
@@ -176,6 +176,7 @@ int pci_bus_add_device(struct pci_dev *dev)
         */
        pci_fixup_device(pci_fixup_final, dev);
        pci_create_sysfs_dev_files(dev);
+       pci_proc_attach_device(dev);
 
        dev->match_driver = true;
        retval = device_attach(&dev->dev);
index bd70af8f31ac22827c85365cb0f9a8e7be1a4bf8..e8663a8c3406a0cb73b5c4a2e1f7380e7fc9f898 100644 (file)
@@ -44,10 +44,18 @@ struct imx6_pcie {
        void __iomem            *mem_base;
 };
 
+/* PCIe Root Complex registers (memory-mapped) */
+#define PCIE_RC_LCR                            0x7c
+#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1       0x1
+#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2       0x2
+#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK       0xf
+
 /* PCIe Port Logic registers (memory-mapped) */
 #define PL_OFFSET 0x700
 #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
 #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
+#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING        (1 << 29)
+#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP         (1 << 4)
 
 #define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
 #define PCIE_PHY_CTRL_DATA_LOC 0
@@ -59,6 +67,9 @@ struct imx6_pcie {
 #define PCIE_PHY_STAT (PL_OFFSET + 0x110)
 #define PCIE_PHY_STAT_ACK_LOC 16
 
+#define PCIE_LINK_WIDTH_SPEED_CONTROL  0x80C
+#define PORT_LOGIC_SPEED_CHANGE                (0x1 << 17)
+
 /* PHY registers (not memory-mapped) */
 #define PCIE_PHY_RX_ASIC_OUT 0x100D
 
@@ -209,15 +220,9 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
 
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
                        IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
                        IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
 
-       gpio_set_value(imx6_pcie->reset_gpio, 0);
-       msleep(100);
-       gpio_set_value(imx6_pcie->reset_gpio, 1);
-
        return 0;
 }
 
@@ -261,6 +266,12 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
        /* allow the clocks to stabilize */
        usleep_range(200, 500);
 
+       /* Some boards don't have PCIe reset GPIO. */
+       if (gpio_is_valid(imx6_pcie->reset_gpio)) {
+               gpio_set_value(imx6_pcie->reset_gpio, 0);
+               msleep(100);
+               gpio_set_value(imx6_pcie->reset_gpio, 1);
+       }
        return 0;
 
 err_pcie_axi:
@@ -299,11 +310,90 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)
                        IMX6Q_GPR8_TX_SWING_LOW, 127 << 25);
 }
 
-static void imx6_pcie_host_init(struct pcie_port *pp)
+static int imx6_pcie_wait_for_link(struct pcie_port *pp)
+{
+       int count = 200;
+
+       while (!dw_pcie_link_up(pp)) {
+               usleep_range(100, 1000);
+               if (--count)
+                       continue;
+
+               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;
+       }
+
+       return 0;
+}
+
+static int imx6_pcie_start_link(struct pcie_port *pp)
 {
-       int count = 0;
        struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+       uint32_t tmp;
+       int ret, count;
 
+       /*
+        * Force Gen1 operation when starting the link.  In case the link is
+        * started in Gen2 mode, there is a possibility the devices on the
+        * bus will not be detected at all.  This happens with PCIe switches.
+        */
+       tmp = readl(pp->dbi_base + PCIE_RC_LCR);
+       tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
+       tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
+       writel(tmp, pp->dbi_base + PCIE_RC_LCR);
+
+       /* Start LTSSM. */
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+
+       ret = imx6_pcie_wait_for_link(pp);
+       if (ret)
+               return ret;
+
+       /* Allow Gen2 mode after the link is up. */
+       tmp = readl(pp->dbi_base + PCIE_RC_LCR);
+       tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
+       tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
+       writel(tmp, pp->dbi_base + PCIE_RC_LCR);
+
+       /*
+        * Start Directed Speed Change so the best possible speed both link
+        * partners support can be negotiated.
+        */
+       tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+       tmp |= PORT_LOGIC_SPEED_CHANGE;
+       writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+
+       count = 200;
+       while (count--) {
+               tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+               /* Test if the speed change finished. */
+               if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
+                       break;
+               usleep_range(100, 1000);
+       }
+
+       /* Make sure link training is finished as well! */
+       if (count)
+               ret = imx6_pcie_wait_for_link(pp);
+       else
+               ret = -EINVAL;
+
+       if (ret) {
+               dev_err(pp->dev, "Failed to bring link up!\n");
+       } else {
+               tmp = readl(pp->dbi_base + 0x80);
+               dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+       }
+
+       return ret;
+}
+
+static void imx6_pcie_host_init(struct pcie_port *pp)
+{
        imx6_pcie_assert_core_reset(pp);
 
        imx6_pcie_init_phy(pp);
@@ -312,33 +402,41 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
 
        dw_pcie_setup_rc(pp);
 
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+       imx6_pcie_start_link(pp);
+}
 
-       while (!dw_pcie_link_up(pp)) {
-               usleep_range(100, 1000);
-               count++;
-               if (count >= 200) {
-                       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));
-                       break;
-               }
-       }
+static void imx6_pcie_reset_phy(struct pcie_port *pp)
+{
+       uint32_t temp;
+
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp);
+       temp |= (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, temp);
+
+       usleep_range(2000, 3000);
 
-       return;
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp);
+       temp &= ~(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, temp);
 }
 
 static int imx6_pcie_link_up(struct pcie_port *pp)
 {
-       u32 rc, ltssm, rx_valid, temp;
+       u32 rc, ltssm, rx_valid;
 
-       /* link is debug bit 36, debug register 1 starts at bit 32 */
-       rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32));
-       if (rc)
-               return -EAGAIN;
+       /*
+        * Test if the PHY reports that the link is up and also that
+        * the link training finished.  It might happen that the PHY
+        * reports the link is already up, but the link training bit
+        * is still set, so make sure to check the training is done
+        * as well here.
+        */
+       rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
+       if ((rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) &&
+           !(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
+               return 1;
 
        /*
         * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
@@ -358,21 +456,7 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
 
        dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
 
-       pcie_phy_read(pp->dbi_base,
-               PHY_RX_OVRD_IN_LO, &temp);
-       temp |= (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, temp);
-
-       usleep_range(2000, 3000);
-
-       pcie_phy_read(pp->dbi_base,
-               PHY_RX_OVRD_IN_LO, &temp);
-       temp &= ~(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, temp);
+       imx6_pcie_reset_phy(pp);
 
        return 0;
 }
@@ -426,30 +510,19 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                "imprecise external abort");
 
        dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!dbi_base) {
-               dev_err(&pdev->dev, "dbi_base memory resource not found\n");
-               return -ENODEV;
-       }
-
        pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
-       if (IS_ERR(pp->dbi_base)) {
-               ret = PTR_ERR(pp->dbi_base);
-               goto err;
-       }
+       if (IS_ERR(pp->dbi_base))
+               return PTR_ERR(pp->dbi_base);
 
        /* Fetch GPIOs */
        imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
-       if (!gpio_is_valid(imx6_pcie->reset_gpio)) {
-               dev_err(&pdev->dev, "no reset-gpio defined\n");
-               ret = -ENODEV;
-       }
-       ret = devm_gpio_request_one(&pdev->dev,
-                               imx6_pcie->reset_gpio,
-                               GPIOF_OUT_INIT_LOW,
-                               "PCIe reset");
-       if (ret) {
-               dev_err(&pdev->dev, "unable to get reset gpio\n");
-               goto err;
+       if (gpio_is_valid(imx6_pcie->reset_gpio)) {
+               ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio,
+                                           GPIOF_OUT_INIT_LOW, "PCIe reset");
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to get reset gpio\n");
+                       return ret;
+               }
        }
 
        imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0);
@@ -460,7 +533,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                                        "PCIe power enable");
                if (ret) {
                        dev_err(&pdev->dev, "unable to get power-on gpio\n");
-                       goto err;
+                       return ret;
                }
        }
 
@@ -472,7 +545,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                                        "PCIe wake up");
                if (ret) {
                        dev_err(&pdev->dev, "unable to get wake-up gpio\n");
-                       goto err;
+                       return ret;
                }
        }
 
@@ -484,7 +557,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                                        "PCIe disable endpoint");
                if (ret) {
                        dev_err(&pdev->dev, "unable to get disable-ep gpio\n");
-                       goto err;
+                       return ret;
                }
        }
 
@@ -493,32 +566,28 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
        if (IS_ERR(imx6_pcie->lvds_gate)) {
                dev_err(&pdev->dev,
                        "lvds_gate clock select missing or invalid\n");
-               ret = PTR_ERR(imx6_pcie->lvds_gate);
-               goto err;
+               return PTR_ERR(imx6_pcie->lvds_gate);
        }
 
        imx6_pcie->sata_ref_100m = devm_clk_get(&pdev->dev, "sata_ref_100m");
        if (IS_ERR(imx6_pcie->sata_ref_100m)) {
                dev_err(&pdev->dev,
                        "sata_ref_100m clock source missing or invalid\n");
-               ret = PTR_ERR(imx6_pcie->sata_ref_100m);
-               goto err;
+               return PTR_ERR(imx6_pcie->sata_ref_100m);
        }
 
        imx6_pcie->pcie_ref_125m = devm_clk_get(&pdev->dev, "pcie_ref_125m");
        if (IS_ERR(imx6_pcie->pcie_ref_125m)) {
                dev_err(&pdev->dev,
                        "pcie_ref_125m clock source missing or invalid\n");
-               ret = PTR_ERR(imx6_pcie->pcie_ref_125m);
-               goto err;
+               return PTR_ERR(imx6_pcie->pcie_ref_125m);
        }
 
        imx6_pcie->pcie_axi = devm_clk_get(&pdev->dev, "pcie_axi");
        if (IS_ERR(imx6_pcie->pcie_axi)) {
                dev_err(&pdev->dev,
                        "pcie_axi clock source missing or invalid\n");
-               ret = PTR_ERR(imx6_pcie->pcie_axi);
-               goto err;
+               return PTR_ERR(imx6_pcie->pcie_axi);
        }
 
        /* Grab GPR config register range */
@@ -526,19 +595,15 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
        if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
                dev_err(&pdev->dev, "unable to find iomuxc registers\n");
-               ret = PTR_ERR(imx6_pcie->iomuxc_gpr);
-               goto err;
+               return PTR_ERR(imx6_pcie->iomuxc_gpr);
        }
 
        ret = imx6_add_pcie_port(pp, pdev);
        if (ret < 0)
-               goto err;
+               return ret;
 
        platform_set_drvdata(pdev, imx6_pcie);
        return 0;
-
-err:
-       return ret;
 }
 
 static const struct of_device_id imx6_pcie_of_match[] = {
index afd2af04980ce56060f3644a145f03c57d04a7e3..bedc0b1562b9bee2be8ed647d41bd88cd934e2f9 100644 (file)
@@ -463,6 +463,11 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
                *value = 0;
                break;
 
+       case PCI_INTERRUPT_LINE:
+               /* LINE PIN MIN_GNT MAX_LAT */
+               *value = 0;
+               break;
+
        default:
                *value = 0xffffffff;
                return PCIBIOS_BAD_REGISTER_NUMBER;
index cbaa5c4397e3c56cd6718b969715a93cc8df6cb3..ceec147baec3560abf5cc07198ab3cc6b1d32d43 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 /* AHB-PCI Bridge PCI communication registers */
@@ -77,6 +78,7 @@
 #define RCAR_PCI_NR_CONTROLLERS                3
 
 struct rcar_pci_priv {
+       struct device *dev;
        void __iomem *reg;
        struct resource io_res;
        struct resource mem_res;
@@ -169,8 +171,11 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
        void __iomem *reg = priv->reg;
        u32 val;
 
+       pm_runtime_enable(priv->dev);
+       pm_runtime_get_sync(priv->dev);
+
        val = ioread32(reg + RCAR_PCI_UNIT_REV_REG);
-       pr_info("PCI: bus%u revision %x\n", sys->busnr, val);
+       dev_info(priv->dev, "PCI: bus%u revision %x\n", sys->busnr, val);
 
        /* Disable Direct Power Down State and assert reset */
        val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD;
@@ -276,8 +281,8 @@ static int __init rcar_pci_probe(struct platform_device *pdev)
 
        cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        reg = devm_ioremap_resource(&pdev->dev, cfg_res);
-       if (!reg)
-               return -ENODEV;
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
 
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (!mem_res || !mem_res->start)
@@ -301,6 +306,7 @@ static int __init rcar_pci_probe(struct platform_device *pdev)
 
        priv->irq = platform_get_irq(pdev, 0);
        priv->reg = reg;
+       priv->dev = &pdev->dev;
 
        return rcar_pci_add_controller(priv);
 }
index 0afbbbc55c81e4bca1ab5ef4f9b556fcad0dc6b1..b8ba2f794559c65fba1aed5b6eebfd82f4c364b5 100644 (file)
@@ -805,7 +805,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
        afi_writel(pcie, value, AFI_PCIE_CONFIG);
 
        value = afi_readl(pcie, AFI_FUSE);
-       value &= ~AFI_FUSE_PCIE_T0_GEN2_DIS;
+       value |= AFI_FUSE_PCIE_T0_GEN2_DIS;
        afi_writel(pcie, value, AFI_FUSE);
 
        /* initialize internal PHY, enable up to 16 PCIE lanes */
index e33b68be03912e1a3659d8a5aa90aa9b2c70ef66..1c92833a4ed3fe2ab452d4de9b1dfcec72ff522e 100644 (file)
@@ -209,6 +209,23 @@ static int find_valid_pos0(struct pcie_port *pp, int msgvec, int pos, int *pos0)
        return 0;
 }
 
+static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base,
+                            unsigned int nvec, unsigned int pos)
+{
+       unsigned int i, res, bit, val;
+
+       for (i = 0; i < nvec; i++) {
+               irq_set_msi_desc_off(irq_base, i, NULL);
+               clear_bit(pos + i, pp->msi_irq_in_use);
+               /* Disable corresponding interrupt on MSI interrupt controller */
+               res = ((pos + i) / 32) * 12;
+               bit = (pos + i) % 32;
+               dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+               val &= ~(1 << bit);
+               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+       }
+}
+
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
        int res, bit, irq, pos0, pos1, i;
@@ -242,18 +259,25 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
        if (!irq)
                goto no_valid_irq;
 
-       i = 0;
-       while (i < no_irqs) {
+       /*
+        * irq_create_mapping (called from dw_pcie_host_init) pre-allocates
+        * descs so there is no need to allocate descs here. We can therefore
+        * assume that if irq_find_mapping above returns non-zero, then the
+        * descs are also successfully allocated.
+        */
+
+       for (i = 0; i < no_irqs; i++) {
+               if (irq_set_msi_desc_off(irq, i, desc) != 0) {
+                       clear_irq_range(pp, irq, i, pos0);
+                       goto no_valid_irq;
+               }
                set_bit(pos0 + i, pp->msi_irq_in_use);
-               irq_alloc_descs((irq + i), (irq + i), 1, 0);
-               irq_set_msi_desc(irq + i, desc);
                /*Enable corresponding interrupt in MSI interrupt controller */
                res = ((pos0 + i) / 32) * 12;
                bit = (pos0 + i) % 32;
                dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
                val |= 1 << bit;
                dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
-               i++;
        }
 
        *pos = pos0;
@@ -266,7 +290,7 @@ no_valid_irq:
 
 static void clear_irq(unsigned int irq)
 {
-       int res, bit, val, pos;
+       unsigned int pos, nvec;
        struct irq_desc *desc;
        struct msi_desc *msi;
        struct pcie_port *pp;
@@ -281,18 +305,15 @@ static void clear_irq(unsigned int irq)
                return;
        }
 
+       /* undo what was done in assign_irq */
        pos = data->hwirq;
+       nvec = 1 << msi->msi_attrib.multiple;
 
-       irq_free_desc(irq);
+       clear_irq_range(pp, irq, nvec, pos);
 
-       clear_bit(pos, pp->msi_irq_in_use);
-
-       /* Disable corresponding interrupt on MSI interrupt controller */
-       res = (pos / 32) * 12;
-       bit = pos % 32;
-       dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
-       val &= ~(1 << bit);
-       dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+       /* all irqs cleared; reset attributes */
+       msi->irq = 0;
+       msi->msi_attrib.multiple = 0;
 }
 
 static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
@@ -320,10 +341,10 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
        if (irq < 0)
                return irq;
 
-       msg_ctr &= ~PCI_MSI_FLAGS_QSIZE;
-       msg_ctr |= msgvec << 4;
-       pci_write_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
-                               msg_ctr);
+       /*
+        * write_msi_msg() will update PCI_MSI_FLAGS so there is
+        * no need to explicitly call pci_write_config_word().
+        */
        desc->msi_attrib.multiple = msgvec;
 
        msg.address_lo = virt_to_phys((void *)pp->msi_data);
index 21e865ded1dce01fde77bb29312e2a653be6b4fa..ffe6a6b336cf97bf4f24a89493f1f6d31d298e3d 100644 (file)
@@ -140,15 +140,15 @@ struct controller *pcie_init(struct pcie_device *dev);
 int pcie_init_notification(struct controller *ctrl);
 int pciehp_enable_slot(struct slot *p_slot);
 int pciehp_disable_slot(struct slot *p_slot);
-int pcie_enable_notification(struct controller *ctrl);
+void pcie_enable_notification(struct controller *ctrl);
 int pciehp_power_on_slot(struct slot *slot);
-int pciehp_power_off_slot(struct slot *slot);
-int pciehp_get_power_status(struct slot *slot, u8 *status);
-int pciehp_get_attention_status(struct slot *slot, u8 *status);
+void pciehp_power_off_slot(struct slot *slot);
+void pciehp_get_power_status(struct slot *slot, u8 *status);
+void pciehp_get_attention_status(struct slot *slot, u8 *status);
 
-int pciehp_set_attention_status(struct slot *slot, u8 status);
-int pciehp_get_latch_status(struct slot *slot, u8 *status);
-int pciehp_get_adapter_status(struct slot *slot, u8 *status);
+void pciehp_set_attention_status(struct slot *slot, u8 status);
+void pciehp_get_latch_status(struct slot *slot, u8 *status);
+void pciehp_get_adapter_status(struct slot *slot, u8 *status);
 int pciehp_query_power_fault(struct slot *slot);
 void pciehp_green_led_on(struct slot *slot);
 void pciehp_green_led_off(struct slot *slot);
index bbd48bbe4e9be2fe9dacdd52388f0256bad25203..143a389d81fa107f7e8fbac494b7284b4b13066b 100644 (file)
@@ -160,7 +160,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                  __func__, slot_name(slot));
 
-       return pciehp_set_attention_status(slot, status);
+       pciehp_set_attention_status(slot, status);
+       return 0;
 }
 
 
@@ -192,7 +193,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                  __func__, slot_name(slot));
 
-       return pciehp_get_power_status(slot, value);
+       pciehp_get_power_status(slot, value);
+       return 0;
 }
 
 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -202,7 +204,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                  __func__, slot_name(slot));
 
-       return pciehp_get_attention_status(slot, value);
+       pciehp_get_attention_status(slot, value);
+       return 0;
 }
 
 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -212,7 +215,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                 __func__, slot_name(slot));
 
-       return pciehp_get_latch_status(slot, value);
+       pciehp_get_latch_status(slot, value);
+       return 0;
 }
 
 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -222,7 +226,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                 __func__, slot_name(slot));
 
-       return pciehp_get_adapter_status(slot, value);
+       pciehp_get_adapter_status(slot, value);
+       return 0;
 }
 
 static int reset_slot(struct hotplug_slot *hotplug_slot, int probe)
index 38f01867917521a6402e92dbaaf5add19b27a640..50628487597deb2fe9de2b7499bc7dc253c7c388 100644 (file)
@@ -158,11 +158,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 {
        /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
        if (POWER_CTRL(ctrl)) {
-               if (pciehp_power_off_slot(pslot)) {
-                       ctrl_err(ctrl,
-                                "Issue of Slot Power Off command failed\n");
-                       return;
-               }
+               pciehp_power_off_slot(pslot);
+
                /*
                 * After turning power off, we must wait for at least 1 second
                 * before taking any action that relies on power having been
@@ -171,16 +168,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
                msleep(1000);
        }
 
-       if (PWR_LED(ctrl))
-               pciehp_green_led_off(pslot);
-
-       if (ATTN_LED(ctrl)) {
-               if (pciehp_set_attention_status(pslot, 1)) {
-                       ctrl_err(ctrl,
-                                "Issue of Set Attention Led command failed\n");
-                       return;
-               }
-       }
+       pciehp_green_led_off(pslot);
+       pciehp_set_attention_status(pslot, 1);
 }
 
 /**
@@ -203,8 +192,7 @@ static int board_added(struct slot *p_slot)
                        return retval;
        }
 
-       if (PWR_LED(ctrl))
-               pciehp_green_led_blink(p_slot);
+       pciehp_green_led_blink(p_slot);
 
        /* Check link training status */
        retval = pciehp_check_link_status(ctrl);
@@ -227,9 +215,7 @@ static int board_added(struct slot *p_slot)
                goto err_exit;
        }
 
-       if (PWR_LED(ctrl))
-               pciehp_green_led_on(p_slot);
-
+       pciehp_green_led_on(p_slot);
        return 0;
 
 err_exit:
@@ -243,7 +229,7 @@ err_exit:
  */
 static int remove_board(struct slot *p_slot)
 {
-       int retval = 0;
+       int retval;
        struct controller *ctrl = p_slot->ctrl;
 
        retval = pciehp_unconfigure_device(p_slot);
@@ -251,13 +237,8 @@ static int remove_board(struct slot *p_slot)
                return retval;
 
        if (POWER_CTRL(ctrl)) {
-               /* power off slot */
-               retval = pciehp_power_off_slot(p_slot);
-               if (retval) {
-                       ctrl_err(ctrl,
-                                "Issue of Slot Disable command failed\n");
-                       return retval;
-               }
+               pciehp_power_off_slot(p_slot);
+
                /*
                 * After turning power off, we must wait for at least 1 second
                 * before taking any action that relies on power having been
@@ -267,9 +248,7 @@ static int remove_board(struct slot *p_slot)
        }
 
        /* turn off Green LED */
-       if (PWR_LED(ctrl))
-               pciehp_green_led_off(p_slot);
-
+       pciehp_green_led_off(p_slot);
        return 0;
 }
 
@@ -305,7 +284,7 @@ static void pciehp_power_thread(struct work_struct *work)
                break;
        case POWERON_STATE:
                mutex_unlock(&p_slot->lock);
-               if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl))
+               if (pciehp_enable_slot(p_slot))
                        pciehp_green_led_off(p_slot);
                mutex_lock(&p_slot->lock);
                p_slot->state = STATIC_STATE;
@@ -372,11 +351,8 @@ static void handle_button_press_event(struct slot *p_slot)
                                  "press.\n", slot_name(p_slot));
                }
                /* blink green LED and turn off amber */
-               if (PWR_LED(ctrl))
-                       pciehp_green_led_blink(p_slot);
-               if (ATTN_LED(ctrl))
-                       pciehp_set_attention_status(p_slot, 0);
-
+               pciehp_green_led_blink(p_slot);
+               pciehp_set_attention_status(p_slot, 0);
                queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
                break;
        case BLINKINGOFF_STATE:
@@ -389,14 +365,11 @@ static void handle_button_press_event(struct slot *p_slot)
                ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
                cancel_delayed_work(&p_slot->work);
                if (p_slot->state == BLINKINGOFF_STATE) {
-                       if (PWR_LED(ctrl))
-                               pciehp_green_led_on(p_slot);
+                       pciehp_green_led_on(p_slot);
                } else {
-                       if (PWR_LED(ctrl))
-                               pciehp_green_led_off(p_slot);
+                       pciehp_green_led_off(p_slot);
                }
-               if (ATTN_LED(ctrl))
-                       pciehp_set_attention_status(p_slot, 0);
+               pciehp_set_attention_status(p_slot, 0);
                ctrl_info(ctrl, "PCI slot #%s - action canceled "
                          "due to button press\n", slot_name(p_slot));
                p_slot->state = STATIC_STATE;
@@ -456,10 +429,8 @@ static void interrupt_event_handler(struct work_struct *work)
        case INT_POWER_FAULT:
                if (!POWER_CTRL(ctrl))
                        break;
-               if (ATTN_LED(ctrl))
-                       pciehp_set_attention_status(p_slot, 1);
-               if (PWR_LED(ctrl))
-                       pciehp_green_led_off(p_slot);
+               pciehp_set_attention_status(p_slot, 1);
+               pciehp_green_led_off(p_slot);
                break;
        case INT_PRESENCE_ON:
        case INT_PRESENCE_OFF:
@@ -482,14 +453,14 @@ int pciehp_enable_slot(struct slot *p_slot)
        int rc;
        struct controller *ctrl = p_slot->ctrl;
 
-       rc = pciehp_get_adapter_status(p_slot, &getstatus);
-       if (rc || !getstatus) {
+       pciehp_get_adapter_status(p_slot, &getstatus);
+       if (!getstatus) {
                ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
                return -ENODEV;
        }
        if (MRL_SENS(p_slot->ctrl)) {
-               rc = pciehp_get_latch_status(p_slot, &getstatus);
-               if (rc || getstatus) {
+               pciehp_get_latch_status(p_slot, &getstatus);
+               if (getstatus) {
                        ctrl_info(ctrl, "Latch open on slot(%s)\n",
                                  slot_name(p_slot));
                        return -ENODEV;
@@ -497,8 +468,8 @@ int pciehp_enable_slot(struct slot *p_slot)
        }
 
        if (POWER_CTRL(p_slot->ctrl)) {
-               rc = pciehp_get_power_status(p_slot, &getstatus);
-               if (rc || getstatus) {
+               pciehp_get_power_status(p_slot, &getstatus);
+               if (getstatus) {
                        ctrl_info(ctrl, "Already enabled on slot(%s)\n",
                                  slot_name(p_slot));
                        return -EINVAL;
@@ -518,15 +489,14 @@ int pciehp_enable_slot(struct slot *p_slot)
 int pciehp_disable_slot(struct slot *p_slot)
 {
        u8 getstatus = 0;
-       int ret = 0;
        struct controller *ctrl = p_slot->ctrl;
 
        if (!p_slot->ctrl)
                return 1;
 
        if (!HP_SUPR_RM(p_slot->ctrl)) {
-               ret = pciehp_get_adapter_status(p_slot, &getstatus);
-               if (ret || !getstatus) {
+               pciehp_get_adapter_status(p_slot, &getstatus);
+               if (!getstatus) {
                        ctrl_info(ctrl, "No adapter on slot(%s)\n",
                                  slot_name(p_slot));
                        return -ENODEV;
@@ -534,8 +504,8 @@ int pciehp_disable_slot(struct slot *p_slot)
        }
 
        if (MRL_SENS(p_slot->ctrl)) {
-               ret = pciehp_get_latch_status(p_slot, &getstatus);
-               if (ret || getstatus) {
+               pciehp_get_latch_status(p_slot, &getstatus);
+               if (getstatus) {
                        ctrl_info(ctrl, "Latch open on slot(%s)\n",
                                  slot_name(p_slot));
                        return -ENODEV;
@@ -543,8 +513,8 @@ int pciehp_disable_slot(struct slot *p_slot)
        }
 
        if (POWER_CTRL(p_slot->ctrl)) {
-               ret = pciehp_get_power_status(p_slot, &getstatus);
-               if (ret || !getstatus) {
+               pciehp_get_power_status(p_slot, &getstatus);
+               if (!getstatus) {
                        ctrl_info(ctrl, "Already disabled on slot(%s)\n",
                                  slot_name(p_slot));
                        return -EINVAL;
index 3eea3fdd4b0b78381c5c9604bac5556e514213b7..14acfccb767072bb58b00417413afb55747ac0e5 100644 (file)
 #include "../pci.h"
 #include "pciehp.h"
 
-static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
+static inline struct pci_dev *ctrl_dev(struct controller *ctrl)
 {
-       struct pci_dev *dev = ctrl->pcie->port;
-       return pcie_capability_read_word(dev, reg, value);
+       return ctrl->pcie->port;
 }
 
-static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value)
-{
-       struct pci_dev *dev = ctrl->pcie->port;
-       return pcie_capability_read_dword(dev, reg, value);
-}
-
-static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value)
-{
-       struct pci_dev *dev = ctrl->pcie->port;
-       return pcie_capability_write_word(dev, reg, value);
-}
-
-static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
-{
-       struct pci_dev *dev = ctrl->pcie->port;
-       return pcie_capability_write_dword(dev, reg, value);
-}
-
-/* Power Control Command */
-#define POWER_ON       0
-#define POWER_OFF      PCI_EXP_SLTCTL_PCC
-
 static irqreturn_t pcie_isr(int irq, void *dev_id);
 static void start_int_poll_timer(struct controller *ctrl, int sec);
 
@@ -129,20 +106,23 @@ static inline void pciehp_free_irq(struct controller *ctrl)
 
 static int pcie_poll_cmd(struct controller *ctrl)
 {
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 slot_status;
-       int err, timeout = 1000;
+       int timeout = 1000;
 
-       err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-       if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) {
-               pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC);
+       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
+       if (slot_status & PCI_EXP_SLTSTA_CC) {
+               pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
+                                          PCI_EXP_SLTSTA_CC);
                return 1;
        }
        while (timeout > 0) {
                msleep(10);
                timeout -= 10;
-               err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-               if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) {
-                       pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC);
+               pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
+               if (slot_status & PCI_EXP_SLTSTA_CC) {
+                       pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
+                                                  PCI_EXP_SLTSTA_CC);
                        return 1;
                }
        }
@@ -169,21 +149,15 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll)
  * @cmd:  command value written to slot control register
  * @mask: bitmask of slot control register to be modified
  */
-static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
+static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
 {
-       int retval = 0;
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 slot_status;
        u16 slot_ctrl;
 
        mutex_lock(&ctrl->ctrl_lock);
 
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
-                        __func__);
-               goto out;
-       }
-
+       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
        if (slot_status & PCI_EXP_SLTSTA_CC) {
                if (!ctrl->no_cmd_complete) {
                        /*
@@ -207,24 +181,17 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
                }
        }
 
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
-               goto out;
-       }
-
+       pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
        slot_ctrl &= ~mask;
        slot_ctrl |= (cmd & mask);
        ctrl->cmd_busy = 1;
        smp_mb();
-       retval = pciehp_writew(ctrl, PCI_EXP_SLTCTL, slot_ctrl);
-       if (retval)
-               ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n");
+       pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);
 
        /*
         * Wait for command completion.
         */
-       if (!retval && !ctrl->no_cmd_complete) {
+       if (!ctrl->no_cmd_complete) {
                int poll = 0;
                /*
                 * if hotplug interrupt is not enabled or command
@@ -236,19 +203,16 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
                        poll = 1;
                 pcie_wait_cmd(ctrl, poll);
        }
- out:
        mutex_unlock(&ctrl->ctrl_lock);
-       return retval;
 }
 
 static bool check_link_active(struct controller *ctrl)
 {
-       bool ret = false;
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 lnk_status;
+       bool ret;
 
-       if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status))
-               return ret;
-
+       pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
        ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
 
        if (ret)
@@ -311,9 +275,9 @@ static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
 
 int pciehp_check_link_status(struct controller *ctrl)
 {
+       struct pci_dev *pdev = ctrl_dev(ctrl);
+       bool found;
        u16 lnk_status;
-       int retval = 0;
-       bool found = false;
 
         /*
          * Data Link Layer Link Active Reporting must be capable for
@@ -330,52 +294,37 @@ int pciehp_check_link_status(struct controller *ctrl)
        found = pci_bus_check_dev(ctrl->pcie->port->subordinate,
                                        PCI_DEVFN(0, 0));
 
-       retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
-       if (retval) {
-               ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
-               return retval;
-       }
-
+       pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
        ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
        if ((lnk_status & PCI_EXP_LNKSTA_LT) ||
            !(lnk_status & PCI_EXP_LNKSTA_NLW)) {
                ctrl_err(ctrl, "Link Training Error occurs \n");
-               retval = -1;
-               return retval;
+               return -1;
        }
 
        pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
 
-       if (!found && !retval)
-               retval = -1;
+       if (!found)
+               return -1;
 
-       return retval;
+       return 0;
 }
 
 static int __pciehp_link_set(struct controller *ctrl, bool enable)
 {
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 lnk_ctrl;
-       int retval = 0;
 
-       retval = pciehp_readw(ctrl, PCI_EXP_LNKCTL, &lnk_ctrl);
-       if (retval) {
-               ctrl_err(ctrl, "Cannot read LNKCTRL register\n");
-               return retval;
-       }
+       pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl);
 
        if (enable)
                lnk_ctrl &= ~PCI_EXP_LNKCTL_LD;
        else
                lnk_ctrl |= PCI_EXP_LNKCTL_LD;
 
-       retval = pciehp_writew(ctrl, PCI_EXP_LNKCTL, lnk_ctrl);
-       if (retval) {
-               ctrl_err(ctrl, "Cannot write LNKCTRL register\n");
-               return retval;
-       }
+       pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl);
        ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl);
-
-       return retval;
+       return 0;
 }
 
 static int pciehp_link_enable(struct controller *ctrl)
@@ -388,223 +337,165 @@ static int pciehp_link_disable(struct controller *ctrl)
        return __pciehp_link_set(ctrl, false);
 }
 
-int pciehp_get_attention_status(struct slot *slot, u8 *status)
+void pciehp_get_attention_status(struct slot *slot, u8 *status)
 {
        struct controller *ctrl = slot->ctrl;
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 slot_ctrl;
-       u8 atten_led_state;
-       int retval = 0;
-
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
-               return retval;
-       }
 
+       pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__,
                 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
 
-       atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6;
-
-       switch (atten_led_state) {
-       case 0:
-               *status = 0xFF; /* Reserved */
-               break;
-       case 1:
+       switch (slot_ctrl & PCI_EXP_SLTCTL_AIC) {
+       case PCI_EXP_SLTCTL_ATTN_IND_ON:
                *status = 1;    /* On */
                break;
-       case 2:
+       case PCI_EXP_SLTCTL_ATTN_IND_BLINK:
                *status = 2;    /* Blink */
                break;
-       case 3:
+       case PCI_EXP_SLTCTL_ATTN_IND_OFF:
                *status = 0;    /* Off */
                break;
        default:
                *status = 0xFF;
                break;
        }
-
-       return 0;
 }
 
-int pciehp_get_power_status(struct slot *slot, u8 *status)
+void pciehp_get_power_status(struct slot *slot, u8 *status)
 {
        struct controller *ctrl = slot->ctrl;
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 slot_ctrl;
-       u8 pwr_state;
-       int     retval = 0;
 
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
-               return retval;
-       }
+       pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__,
                 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
 
-       pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10;
-
-       switch (pwr_state) {
-       case 0:
-               *status = 1;
+       switch (slot_ctrl & PCI_EXP_SLTCTL_PCC) {
+       case PCI_EXP_SLTCTL_PWR_ON:
+               *status = 1;    /* On */
                break;
-       case 1:
-               *status = 0;
+       case PCI_EXP_SLTCTL_PWR_OFF:
+               *status = 0;    /* Off */
                break;
        default:
                *status = 0xFF;
                break;
        }
-
-       return retval;
 }
 
-int pciehp_get_latch_status(struct slot *slot, u8 *status)
+void pciehp_get_latch_status(struct slot *slot, u8 *status)
 {
-       struct controller *ctrl = slot->ctrl;
+       struct pci_dev *pdev = ctrl_dev(slot->ctrl);
        u16 slot_status;
-       int retval;
 
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
-                        __func__);
-               return retval;
-       }
+       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
        *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS);
-       return 0;
 }
 
-int pciehp_get_adapter_status(struct slot *slot, u8 *status)
+void pciehp_get_adapter_status(struct slot *slot, u8 *status)
 {
-       struct controller *ctrl = slot->ctrl;
+       struct pci_dev *pdev = ctrl_dev(slot->ctrl);
        u16 slot_status;
-       int retval;
 
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
-                        __func__);
-               return retval;
-       }
+       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
        *status = !!(slot_status & PCI_EXP_SLTSTA_PDS);
-       return 0;
 }
 
 int pciehp_query_power_fault(struct slot *slot)
 {
-       struct controller *ctrl = slot->ctrl;
+       struct pci_dev *pdev = ctrl_dev(slot->ctrl);
        u16 slot_status;
-       int retval;
 
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-       if (retval) {
-               ctrl_err(ctrl, "Cannot check for power fault\n");
-               return retval;
-       }
+       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
        return !!(slot_status & PCI_EXP_SLTSTA_PFD);
 }
 
-int pciehp_set_attention_status(struct slot *slot, u8 value)
+void pciehp_set_attention_status(struct slot *slot, u8 value)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
-       u16 cmd_mask;
 
-       cmd_mask = PCI_EXP_SLTCTL_AIC;
+       if (!ATTN_LED(ctrl))
+               return;
+
        switch (value) {
        case 0 :        /* turn off */
-               slot_cmd = 0x00C0;
+               slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_OFF;
                break;
        case 1:         /* turn on */
-               slot_cmd = 0x0040;
+               slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_ON;
                break;
        case 2:         /* turn blink */
-               slot_cmd = 0x0080;
+               slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_BLINK;
                break;
        default:
-               return -EINVAL;
+               return;
        }
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
                 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
-       return pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
+       pcie_write_cmd(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC);
 }
 
 void pciehp_green_led_on(struct slot *slot)
 {
        struct controller *ctrl = slot->ctrl;
-       u16 slot_cmd;
-       u16 cmd_mask;
 
-       slot_cmd = 0x0100;
-       cmd_mask = PCI_EXP_SLTCTL_PIC;
-       pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
+       if (!PWR_LED(ctrl))
+               return;
+
+       pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_PIC);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
+                PCI_EXP_SLTCTL_PWR_IND_ON);
 }
 
 void pciehp_green_led_off(struct slot *slot)
 {
        struct controller *ctrl = slot->ctrl;
-       u16 slot_cmd;
-       u16 cmd_mask;
 
-       slot_cmd = 0x0300;
-       cmd_mask = PCI_EXP_SLTCTL_PIC;
-       pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
+       if (!PWR_LED(ctrl))
+               return;
+
+       pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_PIC);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
+                PCI_EXP_SLTCTL_PWR_IND_OFF);
 }
 
 void pciehp_green_led_blink(struct slot *slot)
 {
        struct controller *ctrl = slot->ctrl;
-       u16 slot_cmd;
-       u16 cmd_mask;
 
-       slot_cmd = 0x0200;
-       cmd_mask = PCI_EXP_SLTCTL_PIC;
-       pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
+       if (!PWR_LED(ctrl))
+               return;
+
+       pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK, PCI_EXP_SLTCTL_PIC);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
+                PCI_EXP_SLTCTL_PWR_IND_BLINK);
 }
 
 int pciehp_power_on_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
-       u16 slot_cmd;
-       u16 cmd_mask;
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 slot_status;
-       int retval = 0;
+       int retval;
 
        /* Clear sticky power-fault bit from previous power failures */
-       retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
-                        __func__);
-               return retval;
-       }
-       slot_status &= PCI_EXP_SLTSTA_PFD;
-       if (slot_status) {
-               retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status);
-               if (retval) {
-                       ctrl_err(ctrl,
-                                "%s: Cannot write to SLOTSTATUS register\n",
-                                __func__);
-                       return retval;
-               }
-       }
+       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
+       if (slot_status & PCI_EXP_SLTSTA_PFD)
+               pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
+                                          PCI_EXP_SLTSTA_PFD);
        ctrl->power_fault_detected = 0;
 
-       slot_cmd = POWER_ON;
-       cmd_mask = PCI_EXP_SLTCTL_PCC;
-       retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
-       if (retval) {
-               ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
-               return retval;
-       }
+       pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_ON, PCI_EXP_SLTCTL_PCC);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
+                PCI_EXP_SLTCTL_PWR_ON);
 
        retval = pciehp_link_enable(ctrl);
        if (retval)
@@ -613,12 +504,9 @@ int pciehp_power_on_slot(struct slot * slot)
        return retval;
 }
 
-int pciehp_power_off_slot(struct slot * slot)
+void pciehp_power_off_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
-       u16 slot_cmd;
-       u16 cmd_mask;
-       int retval;
 
        /* Disable the link at first */
        pciehp_link_disable(ctrl);
@@ -628,21 +516,16 @@ int pciehp_power_off_slot(struct slot * slot)
        else
                msleep(1000);
 
-       slot_cmd = POWER_OFF;
-       cmd_mask = PCI_EXP_SLTCTL_PCC;
-       retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
-       if (retval) {
-               ctrl_err(ctrl, "Write command failed!\n");
-               return retval;
-       }
+       pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
-       return 0;
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
+                PCI_EXP_SLTCTL_PWR_OFF);
 }
 
 static irqreturn_t pcie_isr(int irq, void *dev_id)
 {
        struct controller *ctrl = (struct controller *)dev_id;
+       struct pci_dev *pdev = ctrl_dev(ctrl);
        struct slot *slot = ctrl->slot;
        u16 detected, intr_loc;
 
@@ -653,11 +536,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
         */
        intr_loc = 0;
        do {
-               if (pciehp_readw(ctrl, PCI_EXP_SLTSTA, &detected)) {
-                       ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n",
-                                __func__);
-                       return IRQ_NONE;
-               }
+               pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected);
 
                detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
                             PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
@@ -666,11 +545,9 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                intr_loc |= detected;
                if (!intr_loc)
                        return IRQ_NONE;
-               if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, intr_loc)) {
-                       ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n",
-                                __func__);
-                       return IRQ_NONE;
-               }
+               if (detected)
+                       pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
+                                                  intr_loc);
        } while (detected);
 
        ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc);
@@ -705,7 +582,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-int pcie_enable_notification(struct controller *ctrl)
+void pcie_enable_notification(struct controller *ctrl)
 {
        u16 cmd, mask;
 
@@ -731,22 +608,18 @@ int pcie_enable_notification(struct controller *ctrl)
                PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
                PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
 
-       if (pcie_write_cmd(ctrl, cmd, mask)) {
-               ctrl_err(ctrl, "Cannot enable software notification\n");
-               return -1;
-       }
-       return 0;
+       pcie_write_cmd(ctrl, cmd, mask);
 }
 
 static void pcie_disable_notification(struct controller *ctrl)
 {
        u16 mask;
+
        mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
                PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
                PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
                PCI_EXP_SLTCTL_DLLSCE);
-       if (pcie_write_cmd(ctrl, 0, mask))
-               ctrl_warn(ctrl, "Cannot disable software notification\n");
+       pcie_write_cmd(ctrl, 0, mask);
 }
 
 /*
@@ -758,6 +631,7 @@ static void pcie_disable_notification(struct controller *ctrl)
 int pciehp_reset_slot(struct slot *slot, int probe)
 {
        struct controller *ctrl = slot->ctrl;
+       struct pci_dev *pdev = ctrl_dev(ctrl);
 
        if (probe)
                return 0;
@@ -771,7 +645,8 @@ int pciehp_reset_slot(struct slot *slot, int probe)
        pci_reset_bridge_secondary_bus(ctrl->pcie->port);
 
        if (HP_SUPR_RM(ctrl)) {
-               pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDC);
+               pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
+                                          PCI_EXP_SLTSTA_PDC);
                pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE);
                if (pciehp_poll_mode)
                        int_poll_timeout(ctrl->poll_timer.data);
@@ -784,10 +659,7 @@ int pcie_init_notification(struct controller *ctrl)
 {
        if (pciehp_request_irq(ctrl))
                return -1;
-       if (pcie_enable_notification(ctrl)) {
-               pciehp_free_irq(ctrl);
-               return -1;
-       }
+       pcie_enable_notification(ctrl);
        ctrl->notification_enabled = 1;
        return 0;
 }
@@ -875,12 +747,14 @@ static inline void dbg_ctrl(struct controller *ctrl)
                  EMI(ctrl)        ? "yes" : "no");
        ctrl_info(ctrl, "  Command Completed    : %3s\n",
                  NO_CMD_CMPL(ctrl) ? "no" : "yes");
-       pciehp_readw(ctrl, PCI_EXP_SLTSTA, &reg16);
+       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &reg16);
        ctrl_info(ctrl, "Slot Status            : 0x%04x\n", reg16);
-       pciehp_readw(ctrl, PCI_EXP_SLTCTL, &reg16);
+       pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &reg16);
        ctrl_info(ctrl, "Slot Control           : 0x%04x\n", reg16);
 }
 
+#define FLAG(x,y)      (((x) & (y)) ? '+' : '-')
+
 struct controller *pcie_init(struct pcie_device *dev)
 {
        struct controller *ctrl;
@@ -893,11 +767,7 @@ struct controller *pcie_init(struct pcie_device *dev)
                goto abort;
        }
        ctrl->pcie = dev;
-       if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) {
-               ctrl_err(ctrl, "Cannot read SLOTCAP register\n");
-               goto abort_ctrl;
-       }
-
+       pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
        ctrl->slot_cap = slot_cap;
        mutex_init(&ctrl->ctrl_lock);
        init_waitqueue_head(&ctrl->queue);
@@ -913,25 +783,31 @@ struct controller *pcie_init(struct pcie_device *dev)
            ctrl->no_cmd_complete = 1;
 
         /* Check if Data Link Layer Link Active Reporting is implemented */
-        if (pciehp_readl(ctrl, PCI_EXP_LNKCAP, &link_cap)) {
-                ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
-                goto abort_ctrl;
-        }
+        pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);
         if (link_cap & PCI_EXP_LNKCAP_DLLLARC) {
                 ctrl_dbg(ctrl, "Link Active Reporting supported\n");
                 ctrl->link_active_reporting = 1;
         }
 
        /* Clear all remaining event bits in Slot Status register */
-       if (pciehp_writew(ctrl, PCI_EXP_SLTSTA, 0x1f))
-               goto abort_ctrl;
+       pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
+               PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
+               PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
+               PCI_EXP_SLTSTA_CC);
 
        /* Disable software notification */
        pcie_disable_notification(ctrl);
 
-       ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
-                 pdev->vendor, pdev->device, pdev->subsystem_vendor,
-                 pdev->subsystem_device);
+       ctrl_info(ctrl, "Slot #%d AttnBtn%c AttnInd%c PwrInd%c PwrCtrl%c MRL%c Interlock%c NoCompl%c LLActRep%c\n",
+               (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19,
+               FLAG(slot_cap, PCI_EXP_SLTCAP_ABP),
+               FLAG(slot_cap, PCI_EXP_SLTCAP_AIP),
+               FLAG(slot_cap, PCI_EXP_SLTCAP_PIP),
+               FLAG(slot_cap, PCI_EXP_SLTCAP_PCP),
+               FLAG(slot_cap, PCI_EXP_SLTCAP_MRLSP),
+               FLAG(slot_cap, PCI_EXP_SLTCAP_EIP),
+               FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS),
+               FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC));
 
        if (pcie_init_slot(ctrl))
                goto abort_ctrl;
index 0e0d0f7f63fdd83aa551549d38b174cdca8d034d..198355112ee7f36101cf36b1482f87fc0e964487 100644 (file)
@@ -78,7 +78,7 @@ int pciehp_configure_device(struct slot *p_slot)
 
 int pciehp_unconfigure_device(struct slot *p_slot)
 {
-       int ret, rc = 0;
+       int rc = 0;
        u8 bctl = 0;
        u8 presence = 0;
        struct pci_dev *dev, *temp;
@@ -88,9 +88,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
 
        ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:00\n",
                 __func__, pci_domain_nr(parent), parent->number);
-       ret = pciehp_get_adapter_status(p_slot, &presence);
-       if (ret)
-               presence = 0;
+       pciehp_get_adapter_status(p_slot, &presence);
 
        /*
         * Stopping an SR-IOV PF device removes all the associated VFs,
index 1fe2d6fb19d5046ae78aaa6df3f26f37c12bf6bf..68311ec849ee5ea21da0a221800a331dcfd7a65b 100644 (file)
@@ -441,6 +441,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
 
 found:
        pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl);
+       pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, 0);
        pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
        pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
        if (!offset || (total > 1 && !stride))
index 3fcd67a16677afc4b73495347b38e2fc418b7a04..51bf0400a8891ba53c1fc6f32a81229b4110db00 100644 (file)
@@ -116,7 +116,7 @@ void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
        return default_teardown_msi_irqs(dev);
 }
 
-void default_restore_msi_irqs(struct pci_dev *dev, int irq)
+static void default_restore_msi_irq(struct pci_dev *dev, int irq)
 {
        struct msi_desc *entry;
 
@@ -134,9 +134,9 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
                write_msi_msg(irq, &entry->msg);
 }
 
-void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+void __weak arch_restore_msi_irqs(struct pci_dev *dev)
 {
-       return default_restore_msi_irqs(dev, irq);
+       return default_restore_msi_irqs(dev);
 }
 
 static void msi_set_enable(struct pci_dev *dev, int enable)
@@ -262,6 +262,15 @@ void unmask_msi_irq(struct irq_data *data)
        msi_set_mask_bit(data, 0);
 }
 
+void default_restore_msi_irqs(struct pci_dev *dev)
+{
+       struct msi_desc *entry;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               default_restore_msi_irq(dev, entry->irq);
+       }
+}
+
 void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
        BUG_ON(entry->dev->current_state != PCI_D0);
@@ -430,7 +439,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
 
        pci_intx_for_msi(dev, 0);
        msi_set_enable(dev, 0);
-       arch_restore_msi_irqs(dev, dev->irq);
+       arch_restore_msi_irqs(dev);
 
        pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
        msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
@@ -455,8 +464,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
        control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
        pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
 
+       arch_restore_msi_irqs(dev);
        list_for_each_entry(entry, &dev->msi_list, list) {
-               arch_restore_msi_irqs(dev, entry->irq);
                msix_mask_irq(entry, entry->masked);
        }
 
index 577074efbe62f93f39ac00c6f5c4963d53bd2b0d..e0431f1af33bc81a386cd7c9bd77226818804746 100644 (file)
@@ -358,7 +358,7 @@ static void pci_acpi_cleanup(struct device *dev)
 
 static bool pci_acpi_bus_match(struct device *dev)
 {
-       return dev->bus == &pci_bus_type;
+       return dev_is_pci(dev);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {
index 9042fdbd724405bc96808ed699a1d543fcf17c17..25f0bc6591645707bb3b452bbaa4c28bee0efc59 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
+#include <linux/kexec.h>
 #include "pci.h"
 
 struct pci_dynid {
@@ -288,12 +289,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
        int error, node;
        struct drv_dev_and_id ddi = { drv, dev, id };
 
-       /* Execute driver initialization on node where the device's
-          bus is attached to.  This way the driver likely allocates
-          its local memory on the right node without any need to
-          change it. */
+       /*
+        * Execute driver initialization on node where the device is
+        * attached.  This way the driver likely allocates its local memory
+        * on the right node.
+        */
        node = dev_to_node(&dev->dev);
-       if (node >= 0) {
+
+       /*
+        * On NUMA systems, we are likely to call a PF probe function using
+        * work_on_cpu().  If that probe calls pci_enable_sriov() (which
+        * adds the VF devices via pci_bus_add_device()), we may re-enter
+        * this function to call the VF probe function.  Calling
+        * work_on_cpu() again will cause a lockdep warning.  Since VFs are
+        * always on the same node as the PF, we can work around this by
+        * avoiding work_on_cpu() when we're already on the correct node.
+        *
+        * Preemption is enabled, so it's theoretically unsafe to use
+        * numa_node_id(), but even if we run the probe function on the
+        * wrong node, it should be functionally correct.
+        */
+       if (node >= 0 && node != numa_node_id()) {
                int cpu;
 
                get_online_cpus();
@@ -305,6 +321,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
                put_online_cpus();
        } else
                error = local_pci_probe(&ddi);
+
        return error;
 }
 
@@ -399,12 +416,17 @@ static void pci_device_shutdown(struct device *dev)
        pci_msi_shutdown(pci_dev);
        pci_msix_shutdown(pci_dev);
 
+#ifdef CONFIG_KEXEC
        /*
-        * Turn off Bus Master bit on the device to tell it to not
-        * continue to do DMA. Don't touch devices in D3cold or unknown states.
+        * If this is a kexec reboot, turn off Bus Master bit on the
+        * device to tell it to not continue to do DMA. Don't touch
+        * devices in D3cold or unknown states.
+        * If it is not a kexec reboot, firmware will hit the PCI
+        * devices with big hammer and stop their DMA any way.
         */
-       if (pci_dev->current_state <= PCI_D3hot)
+       if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot))
                pci_clear_master(pci_dev);
+#endif
 }
 
 #ifdef CONFIG_PM
index 33120d15666895a2b48aec1c83f7b41f7b93c3be..508e560b7d2a2a922ba5725462fc1f2845ce4835 100644 (file)
@@ -430,6 +430,32 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
        return best;
 }
 
+/**
+ * pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos
+ * @dev: the PCI device to operate on
+ * @pos: config space offset of status word
+ * @mask: mask of bit(s) to care about in status word
+ *
+ * Return 1 when mask bit(s) in status word clear, 0 otherwise.
+ */
+int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
+{
+       int i;
+
+       /* Wait for Transaction Pending bit clean */
+       for (i = 0; i < 4; i++) {
+               u16 status;
+               if (i)
+                       msleep((1 << (i - 1)) * 100);
+
+               pci_read_config_word(dev, pos, &status);
+               if (!(status & mask))
+                       return 1;
+       }
+
+       return 0;
+}
+
 /**
  * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
  * @dev: PCI device to have its BARs restored
@@ -835,18 +861,28 @@ EXPORT_SYMBOL(pci_choose_state);
 #define PCI_EXP_SAVE_REGS      7
 
 
-static struct pci_cap_saved_state *pci_find_saved_cap(
-       struct pci_dev *pci_dev, char cap)
+static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev,
+                                                      u16 cap, bool extended)
 {
        struct pci_cap_saved_state *tmp;
 
        hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) {
-               if (tmp->cap.cap_nr == cap)
+               if (tmp->cap.cap_extended == extended && tmp->cap.cap_nr == cap)
                        return tmp;
        }
        return NULL;
 }
 
+struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap)
+{
+       return _pci_find_saved_cap(dev, cap, false);
+}
+
+struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, u16 cap)
+{
+       return _pci_find_saved_cap(dev, cap, true);
+}
+
 static int pci_save_pcie_state(struct pci_dev *dev)
 {
        int i = 0;
@@ -948,6 +984,8 @@ pci_save_state(struct pci_dev *dev)
                return i;
        if ((i = pci_save_pcix_state(dev)) != 0)
                return i;
+       if ((i = pci_save_vc_state(dev)) != 0)
+               return i;
        return 0;
 }
 
@@ -1010,6 +1048,7 @@ void pci_restore_state(struct pci_dev *dev)
        /* PCI Express register must be restored first */
        pci_restore_pcie_state(dev);
        pci_restore_ats_state(dev);
+       pci_restore_vc_state(dev);
 
        pci_restore_config_space(dev);
 
@@ -1087,7 +1126,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
        while (cap->size) {
                struct pci_cap_saved_state *tmp;
 
-               tmp = pci_find_saved_cap(dev, cap->cap_nr);
+               tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended);
                if (!tmp || tmp->cap.size != cap->size)
                        return -EINVAL;
 
@@ -2021,18 +2060,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev,
 }
 
 /**
- * pci_add_cap_save_buffer - allocate buffer for saving given capability registers
+ * _pci_add_cap_save_buffer - allocate buffer for saving given
+ *                            capability registers
  * @dev: the PCI device
  * @cap: the capability to allocate the buffer for
+ * @extended: Standard or Extended capability ID
  * @size: requested size of the buffer
  */
-static int pci_add_cap_save_buffer(
-       struct pci_dev *dev, char cap, unsigned int size)
+static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
+                                   bool extended, unsigned int size)
 {
        int pos;
        struct pci_cap_saved_state *save_state;
 
-       pos = pci_find_capability(dev, cap);
+       if (extended)
+               pos = pci_find_ext_capability(dev, cap);
+       else
+               pos = pci_find_capability(dev, cap);
+
        if (pos <= 0)
                return 0;
 
@@ -2041,12 +2086,23 @@ static int pci_add_cap_save_buffer(
                return -ENOMEM;
 
        save_state->cap.cap_nr = cap;
+       save_state->cap.cap_extended = extended;
        save_state->cap.size = size;
        pci_add_saved_cap(dev, save_state);
 
        return 0;
 }
 
+int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size)
+{
+       return _pci_add_cap_save_buffer(dev, cap, false, size);
+}
+
+int pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size)
+{
+       return _pci_add_cap_save_buffer(dev, cap, true, size);
+}
+
 /**
  * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities
  * @dev: the PCI device
@@ -2065,6 +2121,8 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
        if (error)
                dev_err(&dev->dev,
                        "unable to preallocate PCI-X save buffer\n");
+
+       pci_allocate_vc_save_buffers(dev);
 }
 
 void pci_free_cap_save_buffers(struct pci_dev *dev)
@@ -3204,20 +3262,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
  */
 int pci_wait_for_pending_transaction(struct pci_dev *dev)
 {
-       int i;
-       u16 status;
-
-       /* Wait for Transaction Pending bit clean */
-       for (i = 0; i < 4; i++) {
-               if (i)
-                       msleep((1 << (i - 1)) * 100);
-
-               pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
-               if (!(status & PCI_EXP_DEVSTA_TRPND))
-                       return 1;
-       }
+       if (!pci_is_pcie(dev))
+               return 1;
 
-       return 0;
+       return pci_wait_for_pending(dev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_TRPND);
 }
 EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 
@@ -3244,10 +3292,8 @@ static int pcie_flr(struct pci_dev *dev, int probe)
 
 static int pci_af_flr(struct pci_dev *dev, int probe)
 {
-       int i;
        int pos;
        u8 cap;
-       u8 status;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_AF);
        if (!pos)
@@ -3261,14 +3307,8 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
                return 0;
 
        /* Wait for Transaction Pending bit clean */
-       for (i = 0; i < 4; i++) {
-               if (i)
-                       msleep((1 << (i - 1)) * 100);
-
-               pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status);
-               if (!(status & PCI_AF_STATUS_TP))
-                       goto clear;
-       }
+       if (pci_wait_for_pending(dev, PCI_AF_STATUS, PCI_AF_STATUS_TP))
+               goto clear;
 
        dev_err(&dev->dev, "transaction is not cleared; "
                        "proceeding with reset anyway\n");
index cf611ab2193a618880e94303d9bdbe93cd1fdf7e..4d6991794fa2cbc1c09ff5a21098c0c111145cfd 100644 (file)
@@ -50,14 +50,37 @@ struct aer_hest_parse_info {
        int firmware_first;
 };
 
+static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr)
+{
+       if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT ||
+           hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT ||
+           hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE)
+               return 1;
+       return 0;
+}
+
 static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
 {
        struct aer_hest_parse_info *info = data;
        struct acpi_hest_aer_common *p;
        int ff;
 
+       if (!hest_source_is_pcie_aer(hest_hdr))
+               return 0;
+
        p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
        ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
+
+       /*
+        * If no specific device is supplied, determine whether
+        * FIRMWARE_FIRST is set for *any* PCIe device.
+        */
+       if (!info->pci_dev) {
+               info->firmware_first |= ff;
+               return 0;
+       }
+
+       /* Otherwise, check the specific device */
        if (p->flags & ACPI_HEST_GLOBAL) {
                if (hest_match_type(hest_hdr, info->pci_dev))
                        info->firmware_first = ff;
@@ -97,33 +120,20 @@ int pcie_aer_get_firmware_first(struct pci_dev *dev)
 
 static bool aer_firmware_first;
 
-static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data)
-{
-       struct acpi_hest_aer_common *p;
-
-       if (aer_firmware_first)
-               return 0;
-
-       switch (hest_hdr->type) {
-       case ACPI_HEST_TYPE_AER_ROOT_PORT:
-       case ACPI_HEST_TYPE_AER_ENDPOINT:
-       case ACPI_HEST_TYPE_AER_BRIDGE:
-               p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
-               aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
-       default:
-               return 0;
-       }
-}
-
 /**
  * aer_acpi_firmware_first - Check if APEI should control AER.
  */
 bool aer_acpi_firmware_first(void)
 {
        static bool parsed = false;
+       struct aer_hest_parse_info info = {
+               .pci_dev        = NULL, /* Check all PCIe devices */
+               .firmware_first = 0,
+       };
 
        if (!parsed) {
-               apei_hest_parse(aer_hest_parse_aff, NULL);
+               apei_hest_parse(aer_hest_parse, &info);
+               aer_firmware_first = info.firmware_first;
                parsed = true;
        }
        return aer_firmware_first;
index 2c7c9f5f592caa4253b862775bfbb2ee3854af7d..34ff7026440cac0e929df3db06cba8f93b2a5c00 100644 (file)
@@ -124,6 +124,21 @@ static const char *aer_agent_string[] = {
        "Transmitter ID"
 };
 
+static void __print_tlp_header(struct pci_dev *dev,
+                              struct aer_header_log_regs *t)
+{
+       unsigned char *tlp = (unsigned char *)&t;
+
+       dev_err(&dev->dev, "  TLP Header:"
+               " %02x%02x%02x%02x %02x%02x%02x%02x"
+               " %02x%02x%02x%02x %02x%02x%02x%02x\n",
+               *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+               *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
+               *(tlp + 11), *(tlp + 10), *(tlp + 9),
+               *(tlp + 8), *(tlp + 15), *(tlp + 14),
+               *(tlp + 13), *(tlp + 12));
+}
+
 static void __aer_print_error(struct pci_dev *dev,
                              struct aer_err_info *info)
 {
@@ -153,48 +168,39 @@ static void __aer_print_error(struct pci_dev *dev,
 
 void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
 {
+       int layer, agent;
        int id = ((dev->bus->number << 8) | dev->devfn);
 
-       if (info->status == 0) {
+       if (!info->status) {
                dev_err(&dev->dev,
                        "PCIe Bus Error: severity=%s, type=Unaccessible, "
                        "id=%04x(Unregistered Agent ID)\n",
                        aer_error_severity_string[info->severity], id);
-       } else {
-               int layer, agent;
+               goto out;
+       }
 
-               layer = AER_GET_LAYER_ERROR(info->severity, info->status);
-               agent = AER_GET_AGENT(info->severity, info->status);
+       layer = AER_GET_LAYER_ERROR(info->severity, info->status);
+       agent = AER_GET_AGENT(info->severity, info->status);
 
-               dev_err(&dev->dev,
-                       "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
-                       aer_error_severity_string[info->severity],
-                       aer_error_layer[layer], id, aer_agent_string[agent]);
+       dev_err(&dev->dev,
+               "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
+               aer_error_severity_string[info->severity],
+               aer_error_layer[layer], id, aer_agent_string[agent]);
 
-               dev_err(&dev->dev,
-                       "  device [%04x:%04x] error status/mask=%08x/%08x\n",
-                       dev->vendor, dev->device,
-                       info->status, info->mask);
-
-               __aer_print_error(dev, info);
-
-               if (info->tlp_header_valid) {
-                       unsigned char *tlp = (unsigned char *) &info->tlp;
-                       dev_err(&dev->dev, "  TLP Header:"
-                               " %02x%02x%02x%02x %02x%02x%02x%02x"
-                               " %02x%02x%02x%02x %02x%02x%02x%02x\n",
-                               *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
-                               *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
-                               *(tlp + 11), *(tlp + 10), *(tlp + 9),
-                               *(tlp + 8), *(tlp + 15), *(tlp + 14),
-                               *(tlp + 13), *(tlp + 12));
-               }
-       }
+       dev_err(&dev->dev,
+               "  device [%04x:%04x] error status/mask=%08x/%08x\n",
+               dev->vendor, dev->device,
+               info->status, info->mask);
+
+       __aer_print_error(dev, info);
 
+       if (info->tlp_header_valid)
+               __print_tlp_header(dev, &info->tlp);
+
+out:
        if (info->id && info->error_dev_num > 1 && info->id == id)
-               dev_err(&dev->dev,
-                          "  Error of this Agent(%04x) is reported first\n",
-                       id);
+               dev_err(&dev->dev, "  Error of this Agent(%04x) is reported first\n", id);
+
        trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
                        info->severity);
 }
@@ -228,6 +234,7 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity,
        const char **status_strs;
 
        aer_severity = cper_severity_to_aer(cper_severity);
+
        if (aer_severity == AER_CORRECTABLE) {
                status = aer->cor_status;
                mask = aer->cor_mask;
@@ -240,28 +247,22 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity,
                status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string);
                tlp_header_valid = status & AER_LOG_TLP_MASKS;
        }
+
        layer = AER_GET_LAYER_ERROR(aer_severity, status);
        agent = AER_GET_AGENT(aer_severity, status);
-       dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n",
-              status, mask);
+
+       dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask);
        cper_print_bits("", status, status_strs, status_strs_size);
        dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n",
-              aer_error_layer[layer], aer_agent_string[agent]);
+               aer_error_layer[layer], aer_agent_string[agent]);
+
        if (aer_severity != AER_CORRECTABLE)
                dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n",
-                      aer->uncor_severity);
-       if (tlp_header_valid) {
-               const unsigned char *tlp;
-               tlp = (const unsigned char *)&aer->header_log;
-               dev_err(&dev->dev, "aer_tlp_header:"
-                       " %02x%02x%02x%02x %02x%02x%02x%02x"
-                       " %02x%02x%02x%02x %02x%02x%02x%02x\n",
-                       *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
-                       *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
-                       *(tlp + 11), *(tlp + 10), *(tlp + 9),
-                       *(tlp + 8), *(tlp + 15), *(tlp + 14),
-                       *(tlp + 13), *(tlp + 12));
-       }
+                       aer->uncor_severity);
+
+       if (tlp_header_valid)
+               __print_tlp_header(dev, &aer->header_log);
+
        trace_aer_event(dev_name(&dev->dev), (status & ~mask),
                        aer_severity);
 }
index 0b6e76604068043d9c261ddb9461757d4e64c279..ce9d9ae17bfdad92a0cf8d95bdf25e141b073251 100644 (file)
@@ -554,7 +554,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new)
        if (pcie_ports_disabled)
                return -ENODEV;
 
-       new->driver.name = (char *)new->name;
+       new->driver.name = new->name;
        new->driver.bus = &pcie_port_bus_type;
        new->driver.probe = pcie_port_probe_service;
        new->driver.remove = pcie_port_remove_service;
index 38e403dddf6e0e07166585e226d47f2793bd86f8..12ec56c9a913fd3b22040b28f1cdcbf91e008c57 100644 (file)
@@ -1154,6 +1154,18 @@ static void pci_release_capabilities(struct pci_dev *dev)
        pci_free_cap_save_buffers(dev);
 }
 
+static void pci_free_resources(struct pci_dev *dev)
+{
+       int i;
+
+       pci_cleanup_rom(dev);
+       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+               struct resource *res = dev->resource + i;
+               if (res->parent)
+                       release_resource(res);
+       }
+}
+
 /**
  * pci_release_dev - free a pci device structure when all users of it are finished.
  * @dev: device that's been disconnected
@@ -1163,9 +1175,14 @@ static void pci_release_capabilities(struct pci_dev *dev)
  */
 static void pci_release_dev(struct device *dev)
 {
-       struct pci_dev *pci_dev;
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+
+       down_write(&pci_bus_sem);
+       list_del(&pci_dev->bus_list);
+       up_write(&pci_bus_sem);
+
+       pci_free_resources(pci_dev);
 
-       pci_dev = to_pci_dev(dev);
        pci_release_capabilities(pci_dev);
        pci_release_of_node(pci_dev);
        pcibios_release_device(pci_dev);
@@ -1381,8 +1398,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        dev->match_driver = false;
        ret = device_add(&dev->dev);
        WARN_ON(ret < 0);
-
-       pci_proc_attach_device(dev);
 }
 
 struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
index 1576851028db700be2413b01e815cc8387b3cd47..f452148e6d55ac3fef4c634e1255572c952d7886 100644 (file)
@@ -3,20 +3,6 @@
 #include <linux/pci-aspm.h>
 #include "pci.h"
 
-static void pci_free_resources(struct pci_dev *dev)
-{
-       int i;
-
-       msi_remove_pci_irq_vectors(dev);
-
-       pci_cleanup_rom(dev);
-       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-               struct resource *res = dev->resource + i;
-               if (res->parent)
-                       release_resource(res);
-       }
-}
-
 static void pci_stop_dev(struct pci_dev *dev)
 {
        pci_pme_active(dev, false);
@@ -24,7 +10,7 @@ static void pci_stop_dev(struct pci_dev *dev)
        if (dev->is_added) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
-               device_del(&dev->dev);
+               device_release_driver(&dev->dev);
                dev->is_added = 0;
        }
 
@@ -34,11 +20,8 @@ static void pci_stop_dev(struct pci_dev *dev)
 
 static void pci_destroy_dev(struct pci_dev *dev)
 {
-       down_write(&pci_bus_sem);
-       list_del(&dev->bus_list);
-       up_write(&pci_bus_sem);
+       device_del(&dev->dev);
 
-       pci_free_resources(dev);
        put_device(&dev->dev);
 }
 
@@ -126,7 +109,7 @@ void pci_stop_root_bus(struct pci_bus *bus)
                pci_stop_bus_device(child);
 
        /* stop the host bridge */
-       device_del(&host_bridge->dev);
+       device_release_driver(&host_bridge->dev);
 }
 
 void pci_remove_root_bus(struct pci_bus *bus)
@@ -145,5 +128,5 @@ void pci_remove_root_bus(struct pci_bus *bus)
        host_bridge->bus = NULL;
 
        /* remove the host bridge */
-       put_device(&host_bridge->dev);
+       device_unregister(&host_bridge->dev);
 }
index 219a4106480a5c568b6e9ad11023f735c1ccc1c9..2e344a5581ae0416054a934aba274802947a99c7 100644 (file)
@@ -538,7 +538,8 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
        struct pci_bus_region region;
        unsigned long io_mask;
        u8 io_base_lo, io_limit_lo;
-       u32 l, io_upper16;
+       u16 l;
+       u32 io_upper16;
 
        io_mask = PCI_IO_RANGE_MASK;
        if (bridge->io_window_1k)
@@ -548,11 +549,10 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
        res = bus->resource[0];
        pcibios_resource_to_bus(bridge, &region, res);
        if (res->flags & IORESOURCE_IO) {
-               pci_read_config_dword(bridge, PCI_IO_BASE, &l);
-               l &= 0xffff0000;
+               pci_read_config_word(bridge, PCI_IO_BASE, &l);
                io_base_lo = (region.start >> 8) & io_mask;
                io_limit_lo = (region.end >> 8) & io_mask;
-               l |= ((u32) io_limit_lo << 8) | io_base_lo;
+               l = ((u16) io_limit_lo << 8) | io_base_lo;
                /* Set up upper 16 bits of I/O base/limit. */
                io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
                dev_info(&bridge->dev, "  bridge window %pR\n", res);
@@ -564,7 +564,7 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
        /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
        /* Update lower 16 bits of I/O base/limit. */
-       pci_write_config_dword(bridge, PCI_IO_BASE, l);
+       pci_write_config_word(bridge, PCI_IO_BASE, l);
        /* Update upper 16 bits of I/O base/limit. */
        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
 }
@@ -665,21 +665,23 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
 
        pci_read_config_word(bridge, PCI_IO_BASE, &io);
        if (!io) {
-               pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
+               pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0);
                pci_read_config_word(bridge, PCI_IO_BASE, &io);
                pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
        }
        if (io)
                b_res[0].flags |= IORESOURCE_IO;
+
        /*  DECchip 21050 pass 2 errata: the bridge may miss an address
            disconnect boundary by one PCI data phase.
            Workaround: do not use prefetching on this device. */
        if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
                return;
+
        pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
        if (!pmem) {
                pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
-                                              0xfff0fff0);
+                                              0xffe0fff0);
                pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
                pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
        }
diff --git a/drivers/pci/vc.c b/drivers/pci/vc.c
new file mode 100644 (file)
index 0000000..7e1304d
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * PCI Virtual Channel support
+ *
+ * Copyright (C) 2013 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <alex.williamson@redhat.com>
+ *
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/types.h>
+
+/**
+ * pci_vc_save_restore_dwords - Save or restore a series of dwords
+ * @dev: device
+ * @pos: starting config space position
+ * @buf: buffer to save to or restore from
+ * @dwords: number of dwords to save/restore
+ * @save: whether to save or restore
+ */
+static void pci_vc_save_restore_dwords(struct pci_dev *dev, int pos,
+                                      u32 *buf, int dwords, bool save)
+{
+       int i;
+
+       for (i = 0; i < dwords; i++, buf++) {
+               if (save)
+                       pci_read_config_dword(dev, pos + (i * 4), buf);
+               else
+                       pci_write_config_dword(dev, pos + (i * 4), *buf);
+       }
+}
+
+/**
+ * pci_vc_load_arb_table - load and wait for VC arbitration table
+ * @dev: device
+ * @pos: starting position of VC capability (VC/VC9/MFVC)
+ *
+ * Set Load VC Arbitration Table bit requesting hardware to apply the VC
+ * Arbitration Table (previously loaded).  When the VC Arbitration Table
+ * Status clears, hardware has latched the table into VC arbitration logic.
+ */
+static void pci_vc_load_arb_table(struct pci_dev *dev, int pos)
+{
+       u16 ctrl;
+
+       pci_read_config_word(dev, pos + PCI_VC_PORT_CTRL, &ctrl);
+       pci_write_config_word(dev, pos + PCI_VC_PORT_CTRL,
+                             ctrl | PCI_VC_PORT_CTRL_LOAD_TABLE);
+       if (pci_wait_for_pending(dev, pos + PCI_VC_PORT_STATUS,
+                                PCI_VC_PORT_STATUS_TABLE))
+               return;
+
+       dev_err(&dev->dev, "VC arbitration table failed to load\n");
+}
+
+/**
+ * pci_vc_load_port_arb_table - Load and wait for VC port arbitration table
+ * @dev: device
+ * @pos: starting position of VC capability (VC/VC9/MFVC)
+ * @res: VC resource number, ie. VCn (0-7)
+ *
+ * Set Load Port Arbitration Table bit requesting hardware to apply the Port
+ * Arbitration Table (previously loaded).  When the Port Arbitration Table
+ * Status clears, hardware has latched the table into port arbitration logic.
+ */
+static void pci_vc_load_port_arb_table(struct pci_dev *dev, int pos, int res)
+{
+       int ctrl_pos, status_pos;
+       u32 ctrl;
+
+       ctrl_pos = pos + PCI_VC_RES_CTRL + (res * PCI_CAP_VC_PER_VC_SIZEOF);
+       status_pos = pos + PCI_VC_RES_STATUS + (res * PCI_CAP_VC_PER_VC_SIZEOF);
+
+       pci_read_config_dword(dev, ctrl_pos, &ctrl);
+       pci_write_config_dword(dev, ctrl_pos,
+                              ctrl | PCI_VC_RES_CTRL_LOAD_TABLE);
+
+       if (pci_wait_for_pending(dev, status_pos, PCI_VC_RES_STATUS_TABLE))
+               return;
+
+       dev_err(&dev->dev, "VC%d port arbitration table failed to load\n", res);
+}
+
+/**
+ * pci_vc_enable - Enable virtual channel
+ * @dev: device
+ * @pos: starting position of VC capability (VC/VC9/MFVC)
+ * @res: VC res number, ie. VCn (0-7)
+ *
+ * A VC is enabled by setting the enable bit in matching resource control
+ * registers on both sides of a link.  We therefore need to find the opposite
+ * end of the link.  To keep this simple we enable from the downstream device.
+ * RC devices do not have an upstream device, nor does it seem that VC9 do
+ * (spec is unclear).  Once we find the upstream device, match the VC ID to
+ * get the correct resource, disable and enable on both ends.
+ */
+static void pci_vc_enable(struct pci_dev *dev, int pos, int res)
+{
+       int ctrl_pos, status_pos, id, pos2, evcc, i, ctrl_pos2, status_pos2;
+       u32 ctrl, header, cap1, ctrl2;
+       struct pci_dev *link = NULL;
+
+       /* Enable VCs from the downstream device */
+       if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
+           pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)
+               return;
+
+       ctrl_pos = pos + PCI_VC_RES_CTRL + (res * PCI_CAP_VC_PER_VC_SIZEOF);
+       status_pos = pos + PCI_VC_RES_STATUS + (res * PCI_CAP_VC_PER_VC_SIZEOF);
+
+       pci_read_config_dword(dev, ctrl_pos, &ctrl);
+       id = ctrl & PCI_VC_RES_CTRL_ID;
+
+       pci_read_config_dword(dev, pos, &header);
+
+       /* If there is no opposite end of the link, skip to enable */
+       if (PCI_EXT_CAP_ID(header) == PCI_EXT_CAP_ID_VC9 ||
+           pci_is_root_bus(dev->bus))
+               goto enable;
+
+       pos2 = pci_find_ext_capability(dev->bus->self, PCI_EXT_CAP_ID_VC);
+       if (!pos2)
+               goto enable;
+
+       pci_read_config_dword(dev->bus->self, pos2 + PCI_VC_PORT_CAP1, &cap1);
+       evcc = cap1 & PCI_VC_CAP1_EVCC;
+
+       /* VC0 is hardwired enabled, so we can start with 1 */
+       for (i = 1; i < evcc + 1; i++) {
+               ctrl_pos2 = pos2 + PCI_VC_RES_CTRL +
+                               (i * PCI_CAP_VC_PER_VC_SIZEOF);
+               status_pos2 = pos2 + PCI_VC_RES_STATUS +
+                               (i * PCI_CAP_VC_PER_VC_SIZEOF);
+               pci_read_config_dword(dev->bus->self, ctrl_pos2, &ctrl2);
+               if ((ctrl2 & PCI_VC_RES_CTRL_ID) == id) {
+                       link = dev->bus->self;
+                       break;
+               }
+       }
+
+       if (!link)
+               goto enable;
+
+       /* Disable if enabled */
+       if (ctrl2 & PCI_VC_RES_CTRL_ENABLE) {
+               ctrl2 &= ~PCI_VC_RES_CTRL_ENABLE;
+               pci_write_config_dword(link, ctrl_pos2, ctrl2);
+       }
+
+       /* Enable on both ends */
+       ctrl2 |= PCI_VC_RES_CTRL_ENABLE;
+       pci_write_config_dword(link, ctrl_pos2, ctrl2);
+enable:
+       ctrl |= PCI_VC_RES_CTRL_ENABLE;
+       pci_write_config_dword(dev, ctrl_pos, ctrl);
+
+       if (!pci_wait_for_pending(dev, status_pos, PCI_VC_RES_STATUS_NEGO))
+               dev_err(&dev->dev, "VC%d negotiation stuck pending\n", id);
+
+       if (link && !pci_wait_for_pending(link, status_pos2,
+                                         PCI_VC_RES_STATUS_NEGO))
+               dev_err(&link->dev, "VC%d negotiation stuck pending\n", id);
+}
+
+/**
+ * pci_vc_do_save_buffer - Size, save, or restore VC state
+ * @dev: device
+ * @pos: starting position of VC capability (VC/VC9/MFVC)
+ * @save_state: buffer for save/restore
+ * @name: for error message
+ * @save: if provided a buffer, this indicates what to do with it
+ *
+ * Walking Virtual Channel config space to size, save, or restore it
+ * is complicated, so we do it all from one function to reduce code and
+ * guarantee ordering matches in the buffer.  When called with NULL
+ * @save_state, return the size of the necessary save buffer.  When called
+ * with a non-NULL @save_state, @save determines whether we save to the
+ * buffer or restore from it.
+ */
+static int pci_vc_do_save_buffer(struct pci_dev *dev, int pos,
+                                struct pci_cap_saved_state *save_state,
+                                bool save)
+{
+       u32 cap1;
+       char evcc, lpevcc, parb_size;
+       int i, len = 0;
+       u8 *buf = save_state ? (u8 *)save_state->cap.data : NULL;
+
+       /* Sanity check buffer size for save/restore */
+       if (buf && save_state->cap.size !=
+           pci_vc_do_save_buffer(dev, pos, NULL, save)) {
+               dev_err(&dev->dev,
+                       "VC save buffer size does not match @0x%x\n", pos);
+               return -ENOMEM;
+       }
+
+       pci_read_config_dword(dev, pos + PCI_VC_PORT_CAP1, &cap1);
+       /* Extended VC Count (not counting VC0) */
+       evcc = cap1 & PCI_VC_CAP1_EVCC;
+       /* Low Priority Extended VC Count (not counting VC0) */
+       lpevcc = (cap1 & PCI_VC_CAP1_LPEVCC) >> 4;
+       /* Port Arbitration Table Entry Size (bits) */
+       parb_size = 1 << ((cap1 & PCI_VC_CAP1_ARB_SIZE) >> 10);
+
+       /*
+        * Port VC Control Register contains VC Arbitration Select, which
+        * cannot be modified when more than one LPVC is in operation.  We
+        * therefore save/restore it first, as only VC0 should be enabled
+        * after device reset.
+        */
+       if (buf) {
+               if (save)
+                       pci_read_config_word(dev, pos + PCI_VC_PORT_CTRL,
+                                            (u16 *)buf);
+               else
+                       pci_write_config_word(dev, pos + PCI_VC_PORT_CTRL,
+                                             *(u16 *)buf);
+               buf += 2;
+       }
+       len += 2;
+
+       /*
+        * If we have any Low Priority VCs and a VC Arbitration Table Offset
+        * in Port VC Capability Register 2 then save/restore it next.
+        */
+       if (lpevcc) {
+               u32 cap2;
+               int vcarb_offset;
+
+               pci_read_config_dword(dev, pos + PCI_VC_PORT_CAP2, &cap2);
+               vcarb_offset = ((cap2 & PCI_VC_CAP2_ARB_OFF) >> 24) * 16;
+
+               if (vcarb_offset) {
+                       int size, vcarb_phases = 0;
+
+                       if (cap2 & PCI_VC_CAP2_128_PHASE)
+                               vcarb_phases = 128;
+                       else if (cap2 & PCI_VC_CAP2_64_PHASE)
+                               vcarb_phases = 64;
+                       else if (cap2 & PCI_VC_CAP2_32_PHASE)
+                               vcarb_phases = 32;
+
+                       /* Fixed 4 bits per phase per lpevcc (plus VC0) */
+                       size = ((lpevcc + 1) * vcarb_phases * 4) / 8;
+
+                       if (size && buf) {
+                               pci_vc_save_restore_dwords(dev,
+                                                          pos + vcarb_offset,
+                                                          (u32 *)buf,
+                                                          size / 4, save);
+                               /*
+                                * On restore, we need to signal hardware to
+                                * re-load the VC Arbitration Table.
+                                */
+                               if (!save)
+                                       pci_vc_load_arb_table(dev, pos);
+
+                               buf += size;
+                       }
+                       len += size;
+               }
+       }
+
+       /*
+        * In addition to each VC Resource Control Register, we may have a
+        * Port Arbitration Table attached to each VC.  The Port Arbitration
+        * Table Offset in each VC Resource Capability Register tells us if
+        * it exists.  The entry size is global from the Port VC Capability
+        * Register1 above.  The number of phases is determined per VC.
+        */
+       for (i = 0; i < evcc + 1; i++) {
+               u32 cap;
+               int parb_offset;
+
+               pci_read_config_dword(dev, pos + PCI_VC_RES_CAP +
+                                     (i * PCI_CAP_VC_PER_VC_SIZEOF), &cap);
+               parb_offset = ((cap & PCI_VC_RES_CAP_ARB_OFF) >> 24) * 16;
+               if (parb_offset) {
+                       int size, parb_phases = 0;
+
+                       if (cap & PCI_VC_RES_CAP_256_PHASE)
+                               parb_phases = 256;
+                       else if (cap & (PCI_VC_RES_CAP_128_PHASE |
+                                       PCI_VC_RES_CAP_128_PHASE_TB))
+                               parb_phases = 128;
+                       else if (cap & PCI_VC_RES_CAP_64_PHASE)
+                               parb_phases = 64;
+                       else if (cap & PCI_VC_RES_CAP_32_PHASE)
+                               parb_phases = 32;
+
+                       size = (parb_size * parb_phases) / 8;
+
+                       if (size && buf) {
+                               pci_vc_save_restore_dwords(dev,
+                                                          pos + parb_offset,
+                                                          (u32 *)buf,
+                                                          size / 4, save);
+                               buf += size;
+                       }
+                       len += size;
+               }
+
+               /* VC Resource Control Register */
+               if (buf) {
+                       int ctrl_pos = pos + PCI_VC_RES_CTRL +
+                                               (i * PCI_CAP_VC_PER_VC_SIZEOF);
+                       if (save)
+                               pci_read_config_dword(dev, ctrl_pos,
+                                                     (u32 *)buf);
+                       else {
+                               u32 tmp, ctrl = *(u32 *)buf;
+                               /*
+                                * For an FLR case, the VC config may remain.
+                                * Preserve enable bit, restore the rest.
+                                */
+                               pci_read_config_dword(dev, ctrl_pos, &tmp);
+                               tmp &= PCI_VC_RES_CTRL_ENABLE;
+                               tmp |= ctrl & ~PCI_VC_RES_CTRL_ENABLE;
+                               pci_write_config_dword(dev, ctrl_pos, tmp);
+                               /* Load port arbitration table if used */
+                               if (ctrl & PCI_VC_RES_CTRL_ARB_SELECT)
+                                       pci_vc_load_port_arb_table(dev, pos, i);
+                               /* Re-enable if needed */
+                               if ((ctrl ^ tmp) & PCI_VC_RES_CTRL_ENABLE)
+                                       pci_vc_enable(dev, pos, i);
+                       }
+                       buf += 4;
+               }
+               len += 4;
+       }
+
+       return buf ? 0 : len;
+}
+
+static struct {
+       u16 id;
+       const char *name;
+} vc_caps[] = { { PCI_EXT_CAP_ID_MFVC, "MFVC" },
+               { PCI_EXT_CAP_ID_VC, "VC" },
+               { PCI_EXT_CAP_ID_VC9, "VC9" } };
+
+/**
+ * pci_save_vc_state - Save VC state to pre-allocate save buffer
+ * @dev: device
+ *
+ * For each type of VC capability, VC/VC9/MFVC, find the capability and
+ * save it to the pre-allocated save buffer.
+ */
+int pci_save_vc_state(struct pci_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(vc_caps); i++) {
+               int pos, ret;
+               struct pci_cap_saved_state *save_state;
+
+               pos = pci_find_ext_capability(dev, vc_caps[i].id);
+               if (!pos)
+                       continue;
+
+               save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id);
+               if (!save_state) {
+                       dev_err(&dev->dev, "%s buffer not found in %s\n",
+                               vc_caps[i].name, __func__);
+                       return -ENOMEM;
+               }
+
+               ret = pci_vc_do_save_buffer(dev, pos, save_state, true);
+               if (ret) {
+                       dev_err(&dev->dev, "%s save unsuccessful %s\n",
+                               vc_caps[i].name, __func__);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * pci_restore_vc_state - Restore VC state from save buffer
+ * @dev: device
+ *
+ * For each type of VC capability, VC/VC9/MFVC, find the capability and
+ * restore it from the previously saved buffer.
+ */
+void pci_restore_vc_state(struct pci_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(vc_caps); i++) {
+               int pos;
+               struct pci_cap_saved_state *save_state;
+
+               pos = pci_find_ext_capability(dev, vc_caps[i].id);
+               save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id);
+               if (!save_state || !pos)
+                       continue;
+
+               pci_vc_do_save_buffer(dev, pos, save_state, false);
+       }
+}
+
+/**
+ * pci_allocate_vc_save_buffers - Allocate save buffers for VC caps
+ * @dev: device
+ *
+ * For each type of VC capability, VC/VC9/MFVC, find the capability, size
+ * it, and allocate a buffer for save/restore.
+ */
+
+void pci_allocate_vc_save_buffers(struct pci_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(vc_caps); i++) {
+               int len, pos = pci_find_ext_capability(dev, vc_caps[i].id);
+
+               if (!pos)
+                       continue;
+
+               len = pci_vc_do_save_buffer(dev, pos, NULL, false);
+               if (pci_add_ext_cap_save_buffer(dev, vc_caps[i].id, len))
+                       dev_err(&dev->dev,
+                               "unable to preallocate %s save buffer\n",
+                               vc_caps[i].name);
+       }
+}
index ffd0632c3cbcbf78e1eac6d241eefae57021319f..83cd1574c810d9f62bf141c70b7c2f55a16b5e56 100644 (file)
@@ -975,20 +975,20 @@ static int vfio_vc_cap_len(struct vfio_pci_device *vdev, u16 pos)
        int ret, evcc, phases, vc_arb;
        int len = PCI_CAP_VC_BASE_SIZEOF;
 
-       ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_REG1, &tmp);
+       ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_CAP1, &tmp);
        if (ret)
                return pcibios_err_to_errno(ret);
 
-       evcc = tmp & PCI_VC_REG1_EVCC; /* extended vc count */
-       ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_REG2, &tmp);
+       evcc = tmp & PCI_VC_CAP1_EVCC; /* extended vc count */
+       ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_CAP2, &tmp);
        if (ret)
                return pcibios_err_to_errno(ret);
 
-       if (tmp & PCI_VC_REG2_128_PHASE)
+       if (tmp & PCI_VC_CAP2_128_PHASE)
                phases = 128;
-       else if (tmp & PCI_VC_REG2_64_PHASE)
+       else if (tmp & PCI_VC_CAP2_64_PHASE)
                phases = 64;
-       else if (tmp & PCI_VC_REG2_32_PHASE)
+       else if (tmp & PCI_VC_CAP2_32_PHASE)
                phases = 32;
        else
                phases = 0;
index d78d28a733b15afdc25a620ca5925f6619f82a2c..5fd33dc1fe3ad265d352ed48f3a8cdeec0ca646e 100644 (file)
@@ -198,6 +198,9 @@ extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 extern size_t vmcoreinfo_size;
 extern size_t vmcoreinfo_max_size;
 
+/* flag to track if kexec reboot is in progress */
+extern bool kexec_in_progress;
+
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
                unsigned long long *crash_size, unsigned long long *crash_base);
 int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
index 009b02481436ff34ab9d3cfd93ea75070720b354..92a2f991262affb5b0ff4ecdbb57442ac7ae2733 100644 (file)
@@ -60,10 +60,10 @@ void arch_teardown_msi_irq(unsigned int irq);
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void arch_teardown_msi_irqs(struct pci_dev *dev);
 int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
-void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
+void arch_restore_msi_irqs(struct pci_dev *dev);
 
 void default_teardown_msi_irqs(struct pci_dev *dev);
-void default_restore_msi_irqs(struct pci_dev *dev, int irq);
+void default_restore_msi_irqs(struct pci_dev *dev);
 u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
 u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag);
 
index 1084a15175e04ff0bc715e3e429aab7027d279f8..f16fb1f01317953f54a35fabc2fd8f47cfd051f3 100644 (file)
@@ -224,7 +224,8 @@ enum pci_bus_speed {
 };
 
 struct pci_cap_saved_data {
-       char cap_nr;
+       u16 cap_nr;
+       bool cap_extended;
        unsigned int size;
        u32 data[0];
 };
@@ -938,6 +939,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev);
 void pci_msi_off(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);
 int pcix_get_mmrbc(struct pci_dev *dev);
@@ -976,6 +978,12 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev);
 int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state);
 int pci_load_and_free_saved_state(struct pci_dev *dev,
                                  struct pci_saved_state **state);
+struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap);
+struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
+                                                  u16 cap);
+int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size);
+int pci_add_ext_cap_save_buffer(struct pci_dev *dev,
+                               u16 cap, unsigned int size);
 int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
 int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
 pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
@@ -997,6 +1005,11 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
        return __pci_enable_wake(dev, state, false, enable);
 }
 
+/* PCI Virtual Channel */
+int pci_save_vc_state(struct pci_dev *dev);
+void pci_restore_vc_state(struct pci_dev *dev);
+void pci_allocate_vc_save_buffers(struct pci_dev *dev);
+
 #define PCI_EXP_IDO_REQUEST    (1<<0)
 #define PCI_EXP_IDO_COMPLETION (1<<1)
 void pci_enable_ido(struct pci_dev *dev, unsigned long type);
@@ -1567,65 +1580,65 @@ enum pci_fixup_pass {
 /* Anonymous variables would be nice... */
 #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,        \
                                  class_shift, hook)                    \
-       static const struct pci_fixup __pci_fixup_##name __used         \
+       static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used       \
        __attribute__((__section__(#section), aligned((sizeof(void *)))))    \
                = { vendor, device, class, class_shift, hook };
 
 #define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_HEADER(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_ENABLE(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device, class,    \
+               resume##hook, vendor, device, class,    \
                class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(vendor, device, class,    \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_SUSPEND(vendor, device, class,         \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device, class,   \
+               suspend##hook, vendor, device, class,   \
                class_shift, hook)
 
 #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device,           \
+               resume##hook, vendor, device,           \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME_EARLY(vendor, device, hook)           \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_SUSPEND(vendor, device, hook)                        \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device,          \
+               suspend##hook, vendor, device,          \
                PCI_ANY_ID, 0, hook)
 
 #ifdef CONFIG_PCI_QUIRKS
index 4a98e85438a7706c5288deda0626d17ed312aa17..ab6b4e7f66574a1edd7ca3f46ca8488bea43ae0f 100644 (file)
 #define  PCI_EXP_SLTCTL_CCIE   0x0010  /* Command Completed Interrupt Enable */
 #define  PCI_EXP_SLTCTL_HPIE   0x0020  /* Hot-Plug Interrupt Enable */
 #define  PCI_EXP_SLTCTL_AIC    0x00c0  /* Attention Indicator Control */
+#define  PCI_EXP_SLTCTL_ATTN_IND_ON    0x0040 /* Attention Indicator on */
+#define  PCI_EXP_SLTCTL_ATTN_IND_BLINK 0x0080 /* Attention Indicator blinking */
+#define  PCI_EXP_SLTCTL_ATTN_IND_OFF   0x00c0 /* Attention Indicator off */
 #define  PCI_EXP_SLTCTL_PIC    0x0300  /* Power Indicator Control */
+#define  PCI_EXP_SLTCTL_PWR_IND_ON     0x0100 /* Power Indicator on */
+#define  PCI_EXP_SLTCTL_PWR_IND_BLINK  0x0200 /* Power Indicator blinking */
+#define  PCI_EXP_SLTCTL_PWR_IND_OFF    0x0300 /* Power Indicator off */
 #define  PCI_EXP_SLTCTL_PCC    0x0400  /* Power Controller Control */
+#define  PCI_EXP_SLTCTL_PWR_ON         0x0000 /* Power On */
+#define  PCI_EXP_SLTCTL_PWR_OFF        0x0400 /* Power Off */
 #define  PCI_EXP_SLTCTL_EIC    0x0800  /* Electromechanical Interlock Control */
 #define  PCI_EXP_SLTCTL_DLLSCE 0x1000  /* Data Link Layer State Changed Enable */
 #define PCI_EXP_SLTSTA         26      /* Slot Status */
 #define PCI_ERR_ROOT_ERR_SRC   52      /* Error Source Identification */
 
 /* Virtual Channel */
-#define PCI_VC_PORT_REG1       4
-#define  PCI_VC_REG1_EVCC      0x7     /* extended VC count */
-#define PCI_VC_PORT_REG2       8
-#define  PCI_VC_REG2_32_PHASE  0x2
-#define  PCI_VC_REG2_64_PHASE  0x4
-#define  PCI_VC_REG2_128_PHASE 0x8
+#define PCI_VC_PORT_CAP1       4
+#define  PCI_VC_CAP1_EVCC      0x00000007      /* extended VC count */
+#define  PCI_VC_CAP1_LPEVCC    0x00000070      /* low prio extended VC count */
+#define  PCI_VC_CAP1_ARB_SIZE  0x00000c00
+#define PCI_VC_PORT_CAP2       8
+#define  PCI_VC_CAP2_32_PHASE          0x00000002
+#define  PCI_VC_CAP2_64_PHASE          0x00000004
+#define  PCI_VC_CAP2_128_PHASE         0x00000008
+#define  PCI_VC_CAP2_ARB_OFF           0xff000000
 #define PCI_VC_PORT_CTRL       12
+#define  PCI_VC_PORT_CTRL_LOAD_TABLE   0x00000001
 #define PCI_VC_PORT_STATUS     14
+#define  PCI_VC_PORT_STATUS_TABLE      0x00000001
 #define PCI_VC_RES_CAP         16
+#define  PCI_VC_RES_CAP_32_PHASE       0x00000002
+#define  PCI_VC_RES_CAP_64_PHASE       0x00000004
+#define  PCI_VC_RES_CAP_128_PHASE      0x00000008
+#define  PCI_VC_RES_CAP_128_PHASE_TB   0x00000010
+#define  PCI_VC_RES_CAP_256_PHASE      0x00000020
+#define  PCI_VC_RES_CAP_ARB_OFF                0xff000000
 #define PCI_VC_RES_CTRL                20
+#define  PCI_VC_RES_CTRL_LOAD_TABLE    0x00010000
+#define  PCI_VC_RES_CTRL_ARB_SELECT    0x000e0000
+#define  PCI_VC_RES_CTRL_ID            0x07000000
+#define  PCI_VC_RES_CTRL_ENABLE                0x80000000
 #define PCI_VC_RES_STATUS      26
+#define  PCI_VC_RES_STATUS_TABLE       0x00000001
+#define  PCI_VC_RES_STATUS_NEGO                0x00000002
 #define PCI_CAP_VC_BASE_SIZEOF         0x10
 #define PCI_CAP_VC_PER_VC_SIZEOF       0x0C
 
index 490afc03627e52e34e51d69e0a15693b7716b17a..d0d8fca54065d72a248b0f8b76346bb72c6e2441 100644 (file)
@@ -47,6 +47,9 @@ u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 size_t vmcoreinfo_size;
 size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
 
+/* Flag to indicate we are going to kexec a new kernel */
+bool kexec_in_progress = false;
+
 /* Location of the reserved area for the crash kernel */
 struct resource crashk_res = {
        .name  = "Crash kernel",
@@ -1675,6 +1678,7 @@ int kernel_kexec(void)
        } else
 #endif
        {
+               kexec_in_progress = true;
                kernel_restart_prepare(NULL);
                printk(KERN_EMERG "Starting new kernel\n");
                machine_shutdown();
index 987293d03ebcf0e6bf1c6b81e8a4e68c7965e903..5690b8eabfbc6316b17c36fe7003a67884928437 100644 (file)
@@ -2840,19 +2840,6 @@ already_gone:
        return false;
 }
 
-static bool __flush_work(struct work_struct *work)
-{
-       struct wq_barrier barr;
-
-       if (start_flush_work(work, &barr)) {
-               wait_for_completion(&barr.done);
-               destroy_work_on_stack(&barr.work);
-               return true;
-       } else {
-               return false;
-       }
-}
-
 /**
  * flush_work - wait for a work to finish executing the last queueing instance
  * @work: the work to flush
@@ -2866,10 +2853,18 @@ static bool __flush_work(struct work_struct *work)
  */
 bool flush_work(struct work_struct *work)
 {
+       struct wq_barrier barr;
+
        lock_map_acquire(&work->lockdep_map);
        lock_map_release(&work->lockdep_map);
 
-       return __flush_work(work);
+       if (start_flush_work(work, &barr)) {
+               wait_for_completion(&barr.done);
+               destroy_work_on_stack(&barr.work);
+               return true;
+       } else {
+               return false;
+       }
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
@@ -4814,14 +4809,7 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
 
        INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
        schedule_work_on(cpu, &wfc.work);
-
-       /*
-        * The work item is on-stack and can't lead to deadlock through
-        * flushing.  Use __flush_work() to avoid spurious lockdep warnings
-        * when work_on_cpu()s are nested.
-        */
-       __flush_work(&wfc.work);
-
+       flush_work(&wfc.work);
        return wfc.ret;
 }
 EXPORT_SYMBOL_GPL(work_on_cpu);