]> Git Repo - linux.git/commitdiff
Merge tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
authorLinus Torvalds <[email protected]>
Thu, 22 Oct 2020 19:41:00 +0000 (12:41 -0700)
committerLinus Torvalds <[email protected]>
Thu, 22 Oct 2020 19:41:00 +0000 (12:41 -0700)
Pull PCI updates from Bjorn Helgaas:
 "Enumeration:
   - Print IRQ number used by PCIe Link Bandwidth Notification (Dongdong
     Liu)
   - Add schedule point in pci_read_config() to reduce max latency
     (Jiang Biao)
   - Add Kconfig options for MPS/MRRS strategy (Jim Quinlan)

  Resource management:
   - Fix pci_iounmap() memory leak when !CONFIG_GENERIC_IOMAP (Lorenzo
     Pieralisi)

  PCIe native device hotplug:
   - Reduce noisiness on hot removal (Lukas Wunner)

  Power management:
   - Revert "PCI/PM: Apply D2 delay as milliseconds, not microseconds"
     that was done on the basis of spec typo (Bjorn Helgaas)
   - Rename pci_dev.d3_delay to d3hot_delay to remove D3hot/D3cold
     ambiguity (Krzysztof Wilczyński)
   - Remove unused pcibios_pm_ops (Vaibhav Gupta)

  IOMMU:
   - Enable Translation Blocking for external devices to harden against
     DMA attacks (Rajat Jain)

  Error handling:
   - Add an ACPI APEI notifier chain for vendor CPER records to enable
     device-specific error handling (Shiju Jose)

  ASPM:
   - Remove struct aspm_register_info to simplify code (Saheed O.
     Bolarinwa)

  Amlogic Meson PCIe controller driver:
   - Build as module by default (Kevin Hilman)

  Ampere Altra PCIe controller driver:
   - Add MCFG quirk to work around non-standard ECAM implementation
     (Tuan Phan)

  Broadcom iProc PCIe controller driver:
   - Set affinity mask on MSI interrupts (Mark Tomlinson)

  Broadcom STB PCIe controller driver:
   - Make PCIE_BRCMSTB depend on ARCH_BRCMSTB (Jim Quinlan)
   - Add DT bindings for more Brcmstb chips (Jim Quinlan)
   - Add bcm7278 register info (Jim Quinlan)
   - Add bcm7278 PERST# support (Jim Quinlan)
   - Add suspend and resume pm_ops (Jim Quinlan)
   - Add control of rescal reset (Jim Quinlan)
   - Set additional internal memory DMA viewport sizes (Jim Quinlan)
   - Accommodate MSI for older chips (Jim Quinlan)
   - Set bus max burst size by chip type (Jim Quinlan)
   - Add support for bcm7211, bcm7216, bcm7445, bcm7278 (Jim Quinlan)

  Freescale i.MX6 PCIe controller driver:
   - Use dev_err_probe() to reduce redundant messages (Anson Huang)

  Freescale Layerscape PCIe controller driver:
   - Enforce 4K DMA buffer alignment in endpoint test (Hou Zhiqiang)
   - Add DT compatible strings for ls1088a, ls2088a (Xiaowei Bao)
   - Add endpoint support for ls1088a, ls2088a (Xiaowei Bao)
   - Add endpoint test support for lS1088a (Xiaowei Bao)
   - Add MSI-X support for ls1088a (Xiaowei Bao)

  HiSilicon HIP PCIe controller driver:
   - Handle HIP-specific errors via ACPI APEI (Yicong Yang)

  HiSilicon Kirin PCIe controller driver:
   - Return -EPROBE_DEFER if the GPIO isn't ready (Bean Huo)

  Intel VMD host bridge driver:
   - Factor out physical offset, bus offset, IRQ domain, IRQ allocation
     (Jon Derrick)
   - Use generic PCI PM correctly (Jon Derrick)

  Marvell Aardvark PCIe controller driver:
   - Fix compilation on s390 (Pali Rohár)
   - Implement driver 'remove' function and allow to build it as module
     (Pali Rohár)
   - Move PCIe reset card code to advk_pcie_train_link() (Pali Rohár)
   - Convert mvebu a3700 internal SMCC firmware return codes to errno
     (Pali Rohár)
   - Fix initialization with old Marvell's Arm Trusted Firmware (Pali
     Rohár)

  Microsoft Hyper-V host bridge driver:
   - Fix hibernation in case interrupts are not re-created (Dexuan Cui)

  NVIDIA Tegra PCIe controller driver:
   - Stop checking return value of debugfs_create() functions (Greg
     Kroah-Hartman)
   - Convert to use DEFINE_SEQ_ATTRIBUTE macro (Liu Shixin)

  Qualcomm PCIe controller driver:
   - Reset PCIe to work around Qsdk U-Boot issue (Ansuel Smith)

  Renesas R-Car PCIe controller driver:
   - Add DT documentation for r8a774a1, r8a774b1, r8a774e1 endpoints
     (Lad Prabhakar)
   - Add RZ/G2M, RZ/G2N, RZ/G2H IDs to endpoint test (Lad Prabhakar)
   - Add DT support for r8a7742 (Lad Prabhakar)

  Socionext UniPhier Pro5 controller driver:
   - Add DT descriptions of iATU register (host and endpoint) (Kunihiko
     Hayashi)

  Synopsys DesignWare PCIe controller driver:
   - Add link up check in dw_child_pcie_ops.map_bus() (racy, but seems
     unavoidable) (Hou Zhiqiang)
   - Fix endpoint Header Type check so multi-function devices work (Hou
     Zhiqiang)
   - Skip PCIE_MSI_INTR0* programming if MSI is disabled (Jisheng Zhang)
   - Stop leaking MSI page in suspend/resume (Jisheng Zhang)
   - Add common iATU register support instead of keystone-specific code
     (Kunihiko Hayashi)
   - Major config space access and other cleanups in dwc core and
     drivers that use it (al, exynos, histb, imx6, intel-gw, keystone,
     kirin, meson, qcom, tegra) (Rob Herring)
   - Add multiple PFs support for endpoint (Xiaowei Bao)
   - Add MSI-X doorbell mode in endpoint mode (Xiaowei Bao)

  Miscellaneous:
   - Use fallthrough pseudo-keyword (Gustavo A. R. Silva)
   - Fix "0 used as NULL pointer" warnings (Gustavo Pimentel)
   - Fix "cast truncates bits from constant value" warnings (Gustavo
     Pimentel)
   - Remove redundant zeroing for sg_init_table() (Julia Lawall)
   - Use scnprintf(), not snprintf(), in sysfs "show" functions
     (Krzysztof Wilczyński)
   - Remove unused assignments (Krzysztof Wilczyński)
   - Fix "0 used as NULL pointer" warning (Krzysztof Wilczyński)
   - Simplify bool comparisons (Krzysztof Wilczyński)
   - Use for_each_child_of_node() and for_each_node_by_name() (Qinglang
     Miao)
   - Simplify return expressions (Qinglang Miao)"

* tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (147 commits)
  PCI: vmd: Update VMD PM to correctly use generic PCI PM
  PCI: vmd: Create IRQ allocation helper
  PCI: vmd: Create IRQ Domain configuration helper
  PCI: vmd: Create bus offset configuration helper
  PCI: vmd: Create physical offset helper
  PCI: v3-semi: Remove unneeded break
  PCI: dwc: Add link up check in dw_child_pcie_ops.map_bus()
  PCI/ASPM: Remove struct pcie_link_state.l1ss
  PCI/ASPM: Remove struct aspm_register_info.l1ss_cap
  PCI/ASPM: Pass L1SS Capabilities value, not struct aspm_register_info
  PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl1
  PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl2 (unused)
  PCI/ASPM: Remove struct aspm_register_info.l1ss_cap_ptr
  PCI/ASPM: Remove struct aspm_register_info.latency_encoding
  PCI/ASPM: Remove struct aspm_register_info.enabled
  PCI/ASPM: Remove struct aspm_register_info.support
  PCI/ASPM: Use 'parent' and 'child' for readability
  PCI/ASPM: Move LTR path check to where it's used
  PCI/ASPM: Move pci_clear_and_set_dword() earlier
  PCI: dwc: Fix MSI page leakage in suspend/resume
  ...

15 files changed:
1  2 
Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
drivers/net/ethernet/marvell/sky2.c
drivers/pci/Kconfig
drivers/pci/controller/Kconfig
drivers/pci/controller/pci-hyperv.c
drivers/pci/controller/pcie-brcmstb.c
drivers/pci/controller/vmd.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/p2pdma.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/staging/media/atomisp/pci/atomisp_v4l2.c

index 53d5952b7e57fc8064a6bb0b720781245ab8bd35,a059c96c294b178e4d80bc2ecc0f776f6051fabe..84eeb7fe6e0141fc64cf121a0f7a1e481cf784b7
@@@ -14,8 -14,12 +14,12 @@@ maintainers
  properties:
    compatible:
      items:
-       - const: renesas,r8a774c0-pcie-ep
-       - const: renesas,rcar-gen3-pcie-ep
+       - enum:
+           - renesas,r8a774a1-pcie-ep     # RZ/G2M
+           - renesas,r8a774b1-pcie-ep     # RZ/G2N
+           - renesas,r8a774c0-pcie-ep     # RZ/G2E
+           - renesas,r8a774e1-pcie-ep     # RZ/G2H
+       - const: renesas,rcar-gen3-pcie-ep # R-Car Gen3 and RZ/G2
  
    reg:
      maxItems: 5
@@@ -55,8 -59,6 +59,8 @@@ required
    - clock-names
    - max-functions
  
 +additionalProperties: false
 +
  examples:
    - |
      #include <dt-bindings/clock/r8a774c0-cpg-mssr.h>
index 344864275ed56a6a323a19645f8a13d62b39db02,dd11c06ca7f93f9c61408f6b3e61d720473a2896..25981a7a43b5d3508688ffe369624a0de15977b3
@@@ -1376,7 -1376,7 +1376,7 @@@ static int sky2_ioctl(struct net_devic
        case SIOCGMIIPHY:
                data->phy_id = PHY_ADDR_MARV;
  
 -              /* fallthru */
 +              fallthrough;
        case SIOCGMIIREG: {
                u16 val = 0;
  
@@@ -2764,7 -2764,7 +2764,7 @@@ static int sky2_status_intr(struct sky2
  
                case OP_RXCHKSVLAN:
                        sky2_rx_tag(sky2, length);
 -                      /* fall through */
 +                      fallthrough;
                case OP_RXCHKS:
                        if (likely(dev->features & NETIF_F_RXCSUM))
                                sky2_rx_checksum(sky2, status);
@@@ -5105,7 -5105,7 +5105,7 @@@ static int sky2_probe(struct pci_dev *p
        INIT_WORK(&hw->restart_work, sky2_restart);
  
        pci_set_drvdata(pdev, hw);
-       pdev->d3_delay = 300;
+       pdev->d3hot_delay = 300;
  
        return 0;
  
diff --combined drivers/pci/Kconfig
index 438a792d2cf7715fcb992871e322768d328d8521,d323b25ae27e4bc6d0bea410e84b11e2b34c59f7..0c473d75e625c5bdd187d19f984b841803a6a656
@@@ -56,9 -56,6 +56,9 @@@ config PCI_MSI_IRQ_DOMAI
        depends on PCI_MSI
        select GENERIC_MSI_IRQ_DOMAIN
  
 +config PCI_MSI_ARCH_FALLBACKS
 +      bool
 +
  config PCI_QUIRKS
        default y
        bool "Enable PCI quirk workarounds" if EXPERT
@@@ -190,6 -187,68 +190,68 @@@ config PCI_HYPER
          The PCI device frontend driver allows the kernel to import arbitrary
          PCI devices from a PCI backend to support PCI driver domains.
  
+ choice
+       prompt "PCI Express hierarchy optimization setting"
+       default PCIE_BUS_DEFAULT
+       depends on PCI && EXPERT
+       help
+         MPS (Max Payload Size) and MRRS (Max Read Request Size) are PCIe
+         device parameters that affect performance and the ability to
+         support hotplug and peer-to-peer DMA.
+         The following choices set the MPS and MRRS optimization strategy
+         at compile-time.  The choices are the same as those offered for
+         the kernel command-line parameter 'pci', i.e.,
+         'pci=pcie_bus_tune_off', 'pci=pcie_bus_safe',
+         'pci=pcie_bus_perf', and 'pci=pcie_bus_peer2peer'.
+         This is a compile-time setting and can be overridden by the above
+         command-line parameters.  If unsure, choose PCIE_BUS_DEFAULT.
+ config PCIE_BUS_TUNE_OFF
+       bool "Tune Off"
+       depends on PCI
+       help
+         Use the BIOS defaults; don't touch MPS at all.  This is the same
+         as booting with 'pci=pcie_bus_tune_off'.
+ config PCIE_BUS_DEFAULT
+       bool "Default"
+       depends on PCI
+       help
+         Default choice; ensure that the MPS matches upstream bridge.
+ config PCIE_BUS_SAFE
+       bool "Safe"
+       depends on PCI
+       help
+         Use largest MPS that boot-time devices support.  If you have a
+         closed system with no possibility of adding new devices, this
+         will use the largest MPS that's supported by all devices.  This
+         is the same as booting with 'pci=pcie_bus_safe'.
+ config PCIE_BUS_PERFORMANCE
+       bool "Performance"
+       depends on PCI
+       help
+         Use MPS and MRRS for best performance.  Ensure that a given
+         device's MPS is no larger than its parent MPS, which allows us to
+         keep all switches/bridges to the max MPS supported by their
+         parent.  This is the same as booting with 'pci=pcie_bus_perf'.
+ config PCIE_BUS_PEER2PEER
+       bool "Peer2peer"
+       depends on PCI
+       help
+         Set MPS = 128 for all devices.  MPS configuration effected by the
+         other options could cause the MPS on one root port to be
+         different than that of the MPS on another, which may cause
+         hot-added devices or peer-to-peer DMA to fail.  Set MPS to the
+         smallest possible value (128B) system-wide to avoid these issues.
+         This is the same as booting with 'pci=pcie_bus_peer2peer'.
+ endchoice
  source "drivers/pci/hotplug/Kconfig"
  source "drivers/pci/controller/Kconfig"
  source "drivers/pci/endpoint/Kconfig"
index 4a7afbe189f8c9f87798d419d659f9e7f1a38ef0,6ebe69dd12291247ef70c3d72165db609c7a8769..64e2f5e379aa390229e2557ac15d09dc6b4fc402
@@@ -12,7 -12,7 +12,7 @@@ config PCI_MVEB
        select PCI_BRIDGE_EMUL
  
  config PCI_AARDVARK
-       bool "Aardvark PCIe controller"
+       tristate "Aardvark PCIe controller"
        depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST
        depends on OF
        depends on PCI_MSI_IRQ_DOMAIN
@@@ -41,7 -41,6 +41,7 @@@ config PCI_TEGR
        bool "NVIDIA Tegra PCIe controller"
        depends on ARCH_TEGRA || COMPILE_TEST
        depends on PCI_MSI_IRQ_DOMAIN
 +      select PCI_MSI_ARCH_FALLBACKS
        help
          Say Y here if you want support for the PCIe host controller found
          on NVIDIA Tegra SoCs.
@@@ -68,7 -67,6 +68,7 @@@ config PCIE_RCAR_HOS
        bool "Renesas R-Car PCIe host controller"
        depends on ARCH_RENESAS || COMPILE_TEST
        depends on PCI_MSI_IRQ_DOMAIN
 +      select PCI_MSI_ARCH_FALLBACKS
        help
          Say Y here if you want PCIe controller support on R-Car SoCs in host
          mode.
@@@ -97,7 -95,6 +97,7 @@@ config PCI_HOST_GENERI
  config PCIE_XILINX
        bool "Xilinx AXI PCIe host bridge support"
        depends on OF || COMPILE_TEST
 +      select PCI_MSI_ARCH_FALLBACKS
        help
          Say 'Y' here if you want kernel to support the Xilinx AXI PCIe
          Host Bridge driver.
@@@ -273,9 -270,10 +273,10 @@@ config VM
  
  config PCIE_BRCMSTB
        tristate "Broadcom Brcmstb PCIe host controller"
-       depends on ARCH_BCM2835 || COMPILE_TEST
+       depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
        depends on OF
        depends on PCI_MSI_IRQ_DOMAIN
+       default ARCH_BRCMSTB
        help
          Say Y here to enable PCIe host controller support for
          Broadcom STB based SoCs, like the Raspberry Pi 4.
@@@ -297,6 -295,13 +298,13 @@@ config PCI_LOONGSO
          Say Y here if you want to enable PCI controller support on
          Loongson systems.
  
+ config PCIE_HISI_ERR
+       depends on ACPI_APEI_GHES && (ARM64 || COMPILE_TEST)
+       bool "HiSilicon HIP PCIe controller error handling driver"
+       help
+         Say Y here if you want error handling support
+         for the PCIe controller's errors on HiSilicon HIP SoCs
  source "drivers/pci/controller/dwc/Kconfig"
  source "drivers/pci/controller/mobiveil/Kconfig"
  source "drivers/pci/controller/cadence/Kconfig"
index 4e992403fffedf2e39d88b9b99ae28a6c9de2b54,a9df492fbffa26a9dd61205fd9a55aa9e86e2bb6..03ed5cb1c4b25224b7175fe7fca4dbe1745e1527
@@@ -1276,11 -1276,25 +1276,25 @@@ static void hv_irq_unmask(struct irq_da
  exit_unlock:
        spin_unlock_irqrestore(&hbus->retarget_msi_interrupt_lock, flags);
  
-       if (res) {
+       /*
+        * During hibernation, when a CPU is offlined, the kernel tries
+        * to move the interrupt to the remaining CPUs that haven't
+        * been offlined yet. In this case, the below hv_do_hypercall()
+        * always fails since the vmbus channel has been closed:
+        * refer to cpu_disable_common() -> fixup_irqs() ->
+        * irq_migrate_all_off_this_cpu() -> migrate_one_irq().
+        *
+        * Suppress the error message for hibernation because the failure
+        * during hibernation does not matter (at this time all the devices
+        * have been frozen). Note: the correct affinity info is still updated
+        * into the irqdata data structure in migrate_one_irq() ->
+        * irq_do_set_affinity() -> hv_set_affinity(), so later when the VM
+        * resumes, hv_pci_restore_msi_state() is able to correctly restore
+        * the interrupt with the correct affinity.
+        */
+       if (res && hbus->state != hv_pcibus_removing)
                dev_err(&hbus->hdev->device,
                        "%s() failed: %#llx", __func__, res);
-               return;
-       }
  
        pci_msi_unmask_irq(data);
  }
@@@ -1531,8 -1545,16 +1545,8 @@@ static struct irq_chip hv_msi_irq_chip 
        .irq_unmask             = hv_irq_unmask,
  };
  
 -static irq_hw_number_t hv_msi_domain_ops_get_hwirq(struct msi_domain_info *info,
 -                                                 msi_alloc_info_t *arg)
 -{
 -      return arg->msi_hwirq;
 -}
 -
  static struct msi_domain_ops hv_msi_ops = {
 -      .get_hwirq      = hv_msi_domain_ops_get_hwirq,
        .msi_prepare    = pci_msi_prepare,
 -      .set_desc       = pci_msi_set_desc,
        .msi_free       = hv_msi_free,
  };
  
@@@ -2507,10 -2529,7 +2521,10 @@@ static void hv_pci_onchannelcallback(vo
  
  /**
   * hv_pci_protocol_negotiation() - Set up protocol
 - * @hdev:     VMBus's tracking struct for this root PCI bus
 + * @hdev:             VMBus's tracking struct for this root PCI bus.
 + * @version:          Array of supported channel protocol versions in
 + *                    the order of probing - highest go first.
 + * @num_version:      Number of elements in the version array.
   *
   * This driver is intended to support running on Windows 10
   * (server) and later versions. It will not run on earlier
@@@ -3367,6 -3386,34 +3381,34 @@@ static int hv_pci_suspend(struct hv_dev
        return 0;
  }
  
+ static int hv_pci_restore_msi_msg(struct pci_dev *pdev, void *arg)
+ {
+       struct msi_desc *entry;
+       struct irq_data *irq_data;
+       for_each_pci_msi_entry(entry, pdev) {
+               irq_data = irq_get_irq_data(entry->irq);
+               if (WARN_ON_ONCE(!irq_data))
+                       return -EINVAL;
+               hv_compose_msi_msg(irq_data, &entry->msg);
+       }
+       return 0;
+ }
+ /*
+  * Upon resume, pci_restore_msi_state() -> ... ->  __pci_write_msi_msg()
+  * directly writes the MSI/MSI-X registers via MMIO, but since Hyper-V
+  * doesn't trap and emulate the MMIO accesses, here hv_compose_msi_msg()
+  * must be used to ask Hyper-V to re-create the IOMMU Interrupt Remapping
+  * Table entries.
+  */
+ static void hv_pci_restore_msi_state(struct hv_pcibus_device *hbus)
+ {
+       pci_walk_bus(hbus->pci_bus, hv_pci_restore_msi_msg, NULL);
+ }
  static int hv_pci_resume(struct hv_device *hdev)
  {
        struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
  
        prepopulate_bars(hbus);
  
+       hv_pci_restore_msi_state(hbus);
        hbus->state = hv_pcibus_installed;
        return 0;
  out:
index bac63d04297f0740ae4a1ab6889bed1da0d148ef,afa7ba1d9a3883fc9f426707f8aefd7724ab87e8..bea86899bd5df1c4371eb6c7c3834d9d3654ba9a
  #include <linux/of_platform.h>
  #include <linux/pci.h>
  #include <linux/printk.h>
+ #include <linux/reset.h>
  #include <linux/sizes.h>
  #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/types.h>
  
 -#include <soc/bcm2835/raspberrypi-firmware.h>
 -
  #include "../pci.h"
  
  /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
  #define  PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK               0x1000
  #define  PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK    0x2000
  #define  PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK      0x300000
- #define  PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_128               0x0
  #define  PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK           0xf8000000
+ #define  PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK           0x07c00000
+ #define  PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK           0x0000001f
+ #define  SCB_SIZE_MASK(x) PCIE_MISC_MISC_CTRL_SCB ## x ## _SIZE_MASK
  
  #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO              0x400c
  #define PCIE_MEM_WIN0_LO(win) \
  #define PCIE_MISC_MSI_BAR_CONFIG_HI                   0x4048
  
  #define PCIE_MISC_MSI_DATA_CONFIG                     0x404c
- #define  PCIE_MISC_MSI_DATA_CONFIG_VAL                        0xffe06540
+ #define  PCIE_MISC_MSI_DATA_CONFIG_VAL_32             0xffe06540
+ #define  PCIE_MISC_MSI_DATA_CONFIG_VAL_8              0xfff86540
  
  #define PCIE_MISC_PCIE_CTRL                           0x4064
  #define  PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK    0x1
+ #define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK          0x4
  
  #define PCIE_MISC_PCIE_STATUS                         0x4068
  #define  PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK         0x80
@@@ -88,6 -96,9 +94,9 @@@
  #define  PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK    0x10
  #define  PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK  0x40
  
+ #define PCIE_MISC_REVISION                            0x406c
+ #define  BRCM_PCIE_HW_REV_33                          0x0303
  #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT              0x4070
  #define  PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK  0xfff00000
  #define  PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK   0xfff0
  #define  PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK      0x2
  #define  PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK              0x08000000
  
- #define PCIE_MSI_INTR2_STATUS                         0x4500
- #define PCIE_MSI_INTR2_CLR                            0x4508
- #define PCIE_MSI_INTR2_MASK_SET                               0x4510
- #define PCIE_MSI_INTR2_MASK_CLR                               0x4514
+ #define PCIE_INTR2_CPU_BASE           0x4300
+ #define PCIE_MSI_INTR2_BASE           0x4500
+ /* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */
+ #define  MSI_INT_STATUS                       0x0
+ #define  MSI_INT_CLR                  0x8
+ #define  MSI_INT_MASK_SET             0x10
+ #define  MSI_INT_MASK_CLR             0x14
  
  #define PCIE_EXT_CFG_DATA                             0x8000
  
  #define  PCIE_EXT_SLOT_SHIFT                          15
  #define  PCIE_EXT_FUNC_SHIFT                          12
  
- #define PCIE_RGR1_SW_INIT_1                           0x9210
  #define  PCIE_RGR1_SW_INIT_1_PERST_MASK                       0x1
- #define  PCIE_RGR1_SW_INIT_1_INIT_MASK                        0x2
+ #define  PCIE_RGR1_SW_INIT_1_PERST_SHIFT              0x0
+ #define RGR1_SW_INIT_1_INIT_GENERIC_MASK              0x2
+ #define RGR1_SW_INIT_1_INIT_GENERIC_SHIFT             0x1
+ #define RGR1_SW_INIT_1_INIT_7278_MASK                 0x1
+ #define RGR1_SW_INIT_1_INIT_7278_SHIFT                        0x0
  
  /* PCIe parameters */
  #define BRCM_NUM_PCIE_OUT_WINS                0x4
  #define BRCM_INT_PCI_MSI_NR           32
+ #define BRCM_INT_PCI_MSI_LEGACY_NR    8
+ #define BRCM_INT_PCI_MSI_SHIFT                0
  
  /* MSI target adresses */
  #define BRCM_MSI_TARGET_ADDR_LT_4GB   0x0fffffffcULL
  #define SSC_STATUS_OFFSET             0x1
  #define SSC_STATUS_SSC_MASK           0x400
  #define SSC_STATUS_PLL_LOCK_MASK      0x800
+ #define PCIE_BRCM_MAX_MEMC            3
+ #define IDX_ADDR(pcie)                        (pcie->reg_offsets[EXT_CFG_INDEX])
+ #define DATA_ADDR(pcie)                       (pcie->reg_offsets[EXT_CFG_DATA])
+ #define PCIE_RGR1_SW_INIT_1(pcie)     (pcie->reg_offsets[RGR1_SW_INIT_1])
+ /* Rescal registers */
+ #define PCIE_DVT_PMU_PCIE_PHY_CTRL                            0xc700
+ #define  PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_NFLDS                        0x3
+ #define  PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_DIG_RESET_MASK               0x4
+ #define  PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_DIG_RESET_SHIFT      0x2
+ #define  PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_RESET_MASK           0x2
+ #define  PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_RESET_SHIFT          0x1
+ #define  PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_MASK           0x1
+ #define  PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_SHIFT          0x0
+ /* Forward declarations */
+ struct brcm_pcie;
+ static inline void brcm_pcie_bridge_sw_init_set_7278(struct brcm_pcie *pcie, u32 val);
+ static inline void brcm_pcie_bridge_sw_init_set_generic(struct brcm_pcie *pcie, u32 val);
+ static inline void brcm_pcie_perst_set_7278(struct brcm_pcie *pcie, u32 val);
+ static inline void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val);
+ enum {
+       RGR1_SW_INIT_1,
+       EXT_CFG_INDEX,
+       EXT_CFG_DATA,
+ };
+ enum {
+       RGR1_SW_INIT_1_INIT_MASK,
+       RGR1_SW_INIT_1_INIT_SHIFT,
+ };
+ enum pcie_type {
+       GENERIC,
+       BCM7278,
+       BCM2711,
+ };
+ struct pcie_cfg_data {
+       const int *offsets;
+       const enum pcie_type type;
+       void (*perst_set)(struct brcm_pcie *pcie, u32 val);
+       void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
+ };
+ static const int pcie_offsets[] = {
+       [RGR1_SW_INIT_1] = 0x9210,
+       [EXT_CFG_INDEX]  = 0x9000,
+       [EXT_CFG_DATA]   = 0x9004,
+ };
+ static const struct pcie_cfg_data generic_cfg = {
+       .offsets        = pcie_offsets,
+       .type           = GENERIC,
+       .perst_set      = brcm_pcie_perst_set_generic,
+       .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ };
+ static const int pcie_offset_bcm7278[] = {
+       [RGR1_SW_INIT_1] = 0xc010,
+       [EXT_CFG_INDEX] = 0x9000,
+       [EXT_CFG_DATA] = 0x9004,
+ };
+ static const struct pcie_cfg_data bcm7278_cfg = {
+       .offsets        = pcie_offset_bcm7278,
+       .type           = BCM7278,
+       .perst_set      = brcm_pcie_perst_set_7278,
+       .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_7278,
+ };
+ static const struct pcie_cfg_data bcm2711_cfg = {
+       .offsets        = pcie_offsets,
+       .type           = BCM2711,
+       .perst_set      = brcm_pcie_perst_set_generic,
+       .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ };
  
  struct brcm_msi {
        struct device           *dev;
        int                     irq;
        /* used indicates which MSI interrupts have been alloc'd */
        unsigned long           used;
+       bool                    legacy;
+       /* Some chips have MSIs in bits [31..24] of a shared register. */
+       int                     legacy_shift;
+       int                     nr; /* No. of MSI available, depends on chip */
+       /* This is the base pointer for interrupt status/set/clr regs */
+       void __iomem            *intr_base;
  };
  
  /* Internal PCIe Host Controller Information.*/
@@@ -175,6 -281,14 +279,14 @@@ struct brcm_pcie 
        int                     gen;
        u64                     msi_target_addr;
        struct brcm_msi         *msi;
+       const int               *reg_offsets;
+       enum pcie_type          type;
+       struct reset_control    *rescal;
+       int                     num_memc;
+       u64                     memc_size[PCIE_BRCM_MAX_MEMC];
+       u32                     hw_rev;
+       void                    (*perst_set)(struct brcm_pcie *pcie, u32 val);
+       void                    (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
  };
  
  /*
@@@ -365,8 -479,10 +477,10 @@@ static void brcm_pcie_msi_isr(struct ir
        msi = irq_desc_get_handler_data(desc);
        dev = msi->dev;
  
-       status = readl(msi->base + PCIE_MSI_INTR2_STATUS);
-       for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
+       status = readl(msi->intr_base + MSI_INT_STATUS);
+       status >>= msi->legacy_shift;
+       for_each_set_bit(bit, &status, msi->nr) {
                virq = irq_find_mapping(msi->inner_domain, bit);
                if (virq)
                        generic_handle_irq(virq);
@@@ -383,7 -499,7 +497,7 @@@ static void brcm_msi_compose_msi_msg(st
  
        msg->address_lo = lower_32_bits(msi->target_addr);
        msg->address_hi = upper_32_bits(msi->target_addr);
-       msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL) | data->hwirq;
+       msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | data->hwirq;
  }
  
  static int brcm_msi_set_affinity(struct irq_data *irq_data,
  static void brcm_msi_ack_irq(struct irq_data *data)
  {
        struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
+       const int shift_amt = data->hwirq + msi->legacy_shift;
  
-       writel(1 << data->hwirq, msi->base + PCIE_MSI_INTR2_CLR);
+       writel(1 << shift_amt, msi->intr_base + MSI_INT_CLR);
  }
  
  
@@@ -412,7 -529,7 +527,7 @@@ static int brcm_msi_alloc(struct brcm_m
        int hwirq;
  
        mutex_lock(&msi->lock);
-       hwirq = bitmap_find_free_region(&msi->used, BRCM_INT_PCI_MSI_NR, 0);
+       hwirq = bitmap_find_free_region(&msi->used, msi->nr, 0);
        mutex_unlock(&msi->lock);
  
        return hwirq;
@@@ -461,8 -578,7 +576,7 @@@ static int brcm_allocate_domains(struc
        struct fwnode_handle *fwnode = of_node_to_fwnode(msi->np);
        struct device *dev = msi->dev;
  
-       msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
-                                                 &msi_domain_ops, msi);
+       msi->inner_domain = irq_domain_add_linear(NULL, msi->nr, &msi_domain_ops, msi);
        if (!msi->inner_domain) {
                dev_err(dev, "failed to create IRQ domain\n");
                return -ENOMEM;
@@@ -499,7 -615,10 +613,10 @@@ static void brcm_msi_remove(struct brcm
  
  static void brcm_msi_set_regs(struct brcm_msi *msi)
  {
-       writel(0xffffffff, msi->base + PCIE_MSI_INTR2_MASK_CLR);
+       u32 val = __GENMASK(31, msi->legacy_shift);
+       writel(val, msi->intr_base + MSI_INT_MASK_CLR);
+       writel(val, msi->intr_base + MSI_INT_CLR);
  
        /*
         * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
        writel(upper_32_bits(msi->target_addr),
               msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
  
-       writel(PCIE_MISC_MSI_DATA_CONFIG_VAL,
-              msi->base + PCIE_MISC_MSI_DATA_CONFIG);
+       val = msi->legacy ? PCIE_MISC_MSI_DATA_CONFIG_VAL_8 : PCIE_MISC_MSI_DATA_CONFIG_VAL_32;
+       writel(val, msi->base + PCIE_MISC_MSI_DATA_CONFIG);
  }
  
  static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
        msi->np = pcie->np;
        msi->target_addr = pcie->msi_target_addr;
        msi->irq = irq;
+       msi->legacy = pcie->hw_rev < BRCM_PCIE_HW_REV_33;
+       if (msi->legacy) {
+               msi->intr_base = msi->base + PCIE_INTR2_CPU_BASE;
+               msi->nr = BRCM_INT_PCI_MSI_LEGACY_NR;
+               msi->legacy_shift = 24;
+       } else {
+               msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE;
+               msi->nr = BRCM_INT_PCI_MSI_NR;
+               msi->legacy_shift = 0;
+       }
  
        ret = brcm_allocate_domains(msi);
        if (ret)
@@@ -599,22 -729,43 +727,43 @@@ static struct pci_ops brcm_pcie_ops = 
        .write = pci_generic_config_write,
  };
  
- static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
+ static inline void brcm_pcie_bridge_sw_init_set_generic(struct brcm_pcie *pcie, u32 val)
+ {
+       u32 tmp, mask =  RGR1_SW_INIT_1_INIT_GENERIC_MASK;
+       u32 shift = RGR1_SW_INIT_1_INIT_GENERIC_SHIFT;
+       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+       tmp = (tmp & ~mask) | ((val << shift) & mask);
+       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+ }
+ static inline void brcm_pcie_bridge_sw_init_set_7278(struct brcm_pcie *pcie, u32 val)
+ {
+       u32 tmp, mask =  RGR1_SW_INIT_1_INIT_7278_MASK;
+       u32 shift = RGR1_SW_INIT_1_INIT_7278_SHIFT;
+       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+       tmp = (tmp & ~mask) | ((val << shift) & mask);
+       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+ }
+ static inline void brcm_pcie_perst_set_7278(struct brcm_pcie *pcie, u32 val)
  {
        u32 tmp;
  
-       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
-       u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_INIT_MASK);
-       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
+       /* Perst bit has moved and assert value is 0 */
+       tmp = readl(pcie->base + PCIE_MISC_PCIE_CTRL);
+       u32p_replace_bits(&tmp, !val, PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK);
+       writel(tmp, pcie->base +  PCIE_MISC_PCIE_CTRL);
  }
  
- static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie, u32 val)
+ static inline void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val)
  {
        u32 tmp;
  
-       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
+       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
        u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_PERST_MASK);
-       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
+       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
  }
  
  static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
                                                        u64 *rc_bar2_offset)
  {
        struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
-       struct device *dev = pcie->dev;
        struct resource_entry *entry;
+       struct device *dev = pcie->dev;
+       u64 lowest_pcie_addr = ~(u64)0;
+       int ret, i = 0;
+       u64 size = 0;
  
-       entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM);
-       if (!entry)
-               return -ENODEV;
+       resource_list_for_each_entry(entry, &bridge->dma_ranges) {
+               u64 pcie_beg = entry->res->start - entry->offset;
  
+               size += entry->res->end - entry->res->start + 1;
+               if (pcie_beg < lowest_pcie_addr)
+                       lowest_pcie_addr = pcie_beg;
+       }
  
-       /*
-        * The controller expects the inbound window offset to be calculated as
-        * the difference between PCIe's address space and CPU's. The offset
-        * provided by the firmware is calculated the opposite way, so we
-        * negate it.
-        */
-       *rc_bar2_offset = -entry->offset;
-       *rc_bar2_size = 1ULL << fls64(entry->res->end - entry->res->start);
+       if (lowest_pcie_addr == ~(u64)0) {
+               dev_err(dev, "DT node has no dma-ranges\n");
+               return -EINVAL;
+       }
+       ret = of_property_read_variable_u64_array(pcie->np, "brcm,scb-sizes", pcie->memc_size, 1,
+                                                 PCIE_BRCM_MAX_MEMC);
+       if (ret <= 0) {
+               /* Make an educated guess */
+               pcie->num_memc = 1;
+               pcie->memc_size[0] = 1ULL << fls64(size - 1);
+       } else {
+               pcie->num_memc = ret;
+       }
+       /* Each memc is viewed through a "port" that is a power of 2 */
+       for (i = 0, size = 0; i < pcie->num_memc; i++)
+               size += pcie->memc_size[i];
+       /* System memory starts at this address in PCIe-space */
+       *rc_bar2_offset = lowest_pcie_addr;
+       /* The sum of all memc views must also be a power of 2 */
+       *rc_bar2_size = 1ULL << fls64(size - 1);
  
        /*
         * We validate the inbound memory view even though we should trust
@@@ -689,22 -862,19 +860,19 @@@ static int brcm_pcie_setup(struct brcm_
        void __iomem *base = pcie->base;
        struct device *dev = pcie->dev;
        struct resource_entry *entry;
-       unsigned int scb_size_val;
        bool ssc_good = false;
        struct resource *res;
        int num_out_wins = 0;
        u16 nlw, cls, lnksta;
-       int i, ret;
-       u32 tmp, aspm_support;
+       int i, ret, memc;
+       u32 tmp, burst, aspm_support;
  
        /* Reset the bridge */
-       brcm_pcie_bridge_sw_init_set(pcie, 1);
-       brcm_pcie_perst_set(pcie, 1);
+       pcie->bridge_sw_init_set(pcie, 1);
        usleep_range(100, 200);
  
        /* Take the bridge out of reset */
-       brcm_pcie_bridge_sw_init_set(pcie, 0);
+       pcie->bridge_sw_init_set(pcie, 0);
  
        tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
        tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK;
        /* Wait for SerDes to be stable */
        usleep_range(100, 200);
  
+       /*
+        * SCB_MAX_BURST_SIZE is a two bit field.  For GENERIC chips it
+        * is encoded as 0=128, 1=256, 2=512, 3=Rsvd, for BCM7278 it
+        * is encoded as 0=Rsvd, 1=128, 2=256, 3=512.
+        */
+       if (pcie->type == BCM2711)
+               burst = 0x0; /* 128B */
+       else if (pcie->type == BCM7278)
+               burst = 0x3; /* 512 bytes */
+       else
+               burst = 0x2; /* 512 bytes */
        /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
        u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK);
        u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK);
-       u32p_replace_bits(&tmp, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_128,
-                         PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK);
+       u32p_replace_bits(&tmp, burst, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK);
        writel(tmp, base + PCIE_MISC_MISC_CTRL);
  
        ret = brcm_pcie_get_rc_bar2_size_and_offset(pcie, &rc_bar2_size,
        writel(upper_32_bits(rc_bar2_offset),
               base + PCIE_MISC_RC_BAR2_CONFIG_HI);
  
-       scb_size_val = rc_bar2_size ?
-                      ilog2(rc_bar2_size) - 15 : 0xf; /* 0xf is 1GB */
        tmp = readl(base + PCIE_MISC_MISC_CTRL);
-       u32p_replace_bits(&tmp, scb_size_val,
-                         PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK);
+       for (memc = 0; memc < pcie->num_memc; memc++) {
+               u32 scb_size_val = ilog2(pcie->memc_size[memc]) - 15;
+               if (memc == 0)
+                       u32p_replace_bits(&tmp, scb_size_val, SCB_SIZE_MASK(0));
+               else if (memc == 1)
+                       u32p_replace_bits(&tmp, scb_size_val, SCB_SIZE_MASK(1));
+               else if (memc == 2)
+                       u32p_replace_bits(&tmp, scb_size_val, SCB_SIZE_MASK(2));
+       }
        writel(tmp, base + PCIE_MISC_MISC_CTRL);
  
        /*
        tmp &= ~PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK;
        writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
  
-       /* Mask all interrupts since we are not handling any yet */
-       writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_MASK_SET);
-       /* clear any interrupts we find on boot */
-       writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_CLR);
        if (pcie->gen)
                brcm_pcie_set_gen(pcie, pcie->gen);
  
        /* Unassert the fundamental reset */
-       brcm_pcie_perst_set(pcie, 0);
+       pcie->perst_set(pcie, 0);
  
        /*
         * Give the RC/EP time to wake up, before trying to configure RC.
@@@ -882,6 -1063,52 +1061,52 @@@ static void brcm_pcie_enter_l23(struct 
                dev_err(pcie->dev, "failed to enter low-power link state\n");
  }
  
+ static int brcm_phy_cntl(struct brcm_pcie *pcie, const int start)
+ {
+       static const u32 shifts[PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_NFLDS] = {
+               PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_SHIFT,
+               PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_RESET_SHIFT,
+               PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_DIG_RESET_SHIFT,};
+       static const u32 masks[PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_NFLDS] = {
+               PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_MASK,
+               PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_RESET_MASK,
+               PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_DIG_RESET_MASK,};
+       const int beg = start ? 0 : PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_NFLDS - 1;
+       const int end = start ? PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_NFLDS : -1;
+       u32 tmp, combined_mask = 0;
+       u32 val;
+       void __iomem *base = pcie->base;
+       int i, ret;
+       for (i = beg; i != end; start ? i++ : i--) {
+               val = start ? BIT_MASK(shifts[i]) : 0;
+               tmp = readl(base + PCIE_DVT_PMU_PCIE_PHY_CTRL);
+               tmp = (tmp & ~masks[i]) | (val & masks[i]);
+               writel(tmp, base + PCIE_DVT_PMU_PCIE_PHY_CTRL);
+               usleep_range(50, 200);
+               combined_mask |= masks[i];
+       }
+       tmp = readl(base + PCIE_DVT_PMU_PCIE_PHY_CTRL);
+       val = start ? combined_mask : 0;
+       ret = (tmp & combined_mask) == val ? 0 : -EIO;
+       if (ret)
+               dev_err(pcie->dev, "failed to %s phy\n", (start ? "start" : "stop"));
+       return ret;
+ }
+ static inline int brcm_phy_start(struct brcm_pcie *pcie)
+ {
+       return pcie->rescal ? brcm_phy_cntl(pcie, 1) : 0;
+ }
+ static inline int brcm_phy_stop(struct brcm_pcie *pcie)
+ {
+       return pcie->rescal ? brcm_phy_cntl(pcie, 0) : 0;
+ }
  static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
  {
        void __iomem *base = pcie->base;
        if (brcm_pcie_link_up(pcie))
                brcm_pcie_enter_l23(pcie);
        /* Assert fundamental reset */
-       brcm_pcie_perst_set(pcie, 1);
+       pcie->perst_set(pcie, 1);
  
        /* Deassert request for L23 in case it was asserted */
        tmp = readl(base + PCIE_MISC_PCIE_CTRL);
        writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
  
        /* Shutdown PCIe bridge */
-       brcm_pcie_bridge_sw_init_set(pcie, 1);
+       pcie->bridge_sw_init_set(pcie, 1);
+ }
+ static int brcm_pcie_suspend(struct device *dev)
+ {
+       struct brcm_pcie *pcie = dev_get_drvdata(dev);
+       int ret;
+       brcm_pcie_turn_off(pcie);
+       ret = brcm_phy_stop(pcie);
+       clk_disable_unprepare(pcie->clk);
+       return ret;
+ }
+ static int brcm_pcie_resume(struct device *dev)
+ {
+       struct brcm_pcie *pcie = dev_get_drvdata(dev);
+       void __iomem *base;
+       u32 tmp;
+       int ret;
+       base = pcie->base;
+       clk_prepare_enable(pcie->clk);
+       ret = brcm_phy_start(pcie);
+       if (ret)
+               goto err;
+       /* Take bridge out of reset so we can access the SERDES reg */
+       pcie->bridge_sw_init_set(pcie, 0);
+       /* SERDES_IDDQ = 0 */
+       tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
+       u32p_replace_bits(&tmp, 0, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
+       writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
+       /* wait for serdes to be stable */
+       udelay(100);
+       ret = brcm_pcie_setup(pcie);
+       if (ret)
+               goto err;
+       if (pcie->msi)
+               brcm_msi_set_regs(pcie->msi);
+       return 0;
+ err:
+       clk_disable_unprepare(pcie->clk);
+       return ret;
  }
  
  static void __brcm_pcie_remove(struct brcm_pcie *pcie)
  {
        brcm_msi_remove(pcie);
        brcm_pcie_turn_off(pcie);
+       brcm_phy_stop(pcie);
+       reset_control_assert(pcie->rescal);
        clk_disable_unprepare(pcie->clk);
  }
  
@@@ -925,20 -1205,55 +1203,40 @@@ static int brcm_pcie_remove(struct plat
        return 0;
  }
  
+ static const struct of_device_id brcm_pcie_match[] = {
+       { .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg },
+       { .compatible = "brcm,bcm7211-pcie", .data = &generic_cfg },
+       { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
+       { .compatible = "brcm,bcm7216-pcie", .data = &bcm7278_cfg },
+       { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
+       {},
+ };
  static int brcm_pcie_probe(struct platform_device *pdev)
  {
        struct device_node *np = pdev->dev.of_node, *msi_np;
        struct pci_host_bridge *bridge;
 -      struct device_node *fw_np;
+       const struct pcie_cfg_data *data;
        struct brcm_pcie *pcie;
        int ret;
  
 -      /*
 -       * We have to wait for Raspberry Pi's firmware interface to be up as a
 -       * PCI fixup, rpi_firmware_init_vl805(), depends on it. This driver's
 -       * probe can race with the firmware interface's (see
 -       * drivers/firmware/raspberrypi.c) and potentially break the PCI fixup.
 -       */
 -      fw_np = of_find_compatible_node(NULL, NULL,
 -                                      "raspberrypi,bcm2835-firmware");
 -      if (fw_np && !rpi_firmware_get(fw_np)) {
 -              of_node_put(fw_np);
 -              return -EPROBE_DEFER;
 -      }
 -      of_node_put(fw_np);
 -
        bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
        if (!bridge)
                return -ENOMEM;
  
+       data = of_device_get_match_data(&pdev->dev);
+       if (!data) {
+               pr_err("failed to look up compatible string\n");
+               return -EINVAL;
+       }
        pcie = pci_host_bridge_priv(bridge);
        pcie->dev = &pdev->dev;
        pcie->np = np;
+       pcie->reg_offsets = data->offsets;
+       pcie->type = data->type;
+       pcie->perst_set = data->perst_set;
+       pcie->bridge_sw_init_set = data->bridge_sw_init_set;
  
        pcie->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(pcie->base))
                dev_err(&pdev->dev, "could not enable clock\n");
                return ret;
        }
+       pcie->rescal = devm_reset_control_get_optional_shared(&pdev->dev, "rescal");
+       if (IS_ERR(pcie->rescal)) {
+               clk_disable_unprepare(pcie->clk);
+               return PTR_ERR(pcie->rescal);
+       }
+       ret = reset_control_deassert(pcie->rescal);
+       if (ret)
+               dev_err(&pdev->dev, "failed to deassert 'rescal'\n");
+       ret = brcm_phy_start(pcie);
+       if (ret) {
+               reset_control_assert(pcie->rescal);
+               clk_disable_unprepare(pcie->clk);
+               return ret;
+       }
  
        ret = brcm_pcie_setup(pcie);
        if (ret)
                goto fail;
  
+       pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION);
        msi_np = of_parse_phandle(pcie->np, "msi-parent", 0);
        if (pci_msi_enabled() && msi_np == pcie->np) {
                ret = brcm_pcie_enable_msi(pcie);
@@@ -983,18 -1316,20 +1299,20 @@@ fail
        return ret;
  }
  
- static const struct of_device_id brcm_pcie_match[] = {
-       { .compatible = "brcm,bcm2711-pcie" },
-       {},
- };
  MODULE_DEVICE_TABLE(of, brcm_pcie_match);
  
+ static const struct dev_pm_ops brcm_pcie_pm_ops = {
+       .suspend = brcm_pcie_suspend,
+       .resume = brcm_pcie_resume,
+ };
  static struct platform_driver brcm_pcie_driver = {
        .probe = brcm_pcie_probe,
        .remove = brcm_pcie_remove,
        .driver = {
                .name = "brcm-pcie",
                .of_match_table = brcm_pcie_match,
+               .pm = &brcm_pcie_pm_ops,
        },
  };
  module_platform_driver(brcm_pcie_driver);
index aa1b12bac9a1567a8ccc48d7cf273c46788e0542,c8d46bd01e87452dd714778752cce95abfea2e81..f375c21ceeb16308285df97788ec5a8b6c085f8b
@@@ -298,6 -298,34 +298,33 @@@ static struct msi_domain_info vmd_msi_d
        .chip           = &vmd_msi_controller,
  };
  
 -      vmd->irq_domain = pci_msi_create_irq_domain(fn, &vmd_msi_domain_info,
 -                                                  x86_vector_domain);
+ static int vmd_create_irq_domain(struct vmd_dev *vmd)
+ {
+       struct fwnode_handle *fn;
+       fn = irq_domain_alloc_named_id_fwnode("VMD-MSI", vmd->sysdata.domain);
+       if (!fn)
+               return -ENODEV;
++      vmd->irq_domain = pci_msi_create_irq_domain(fn, &vmd_msi_domain_info, NULL);
+       if (!vmd->irq_domain) {
+               irq_domain_free_fwnode(fn);
+               return -ENODEV;
+       }
+       return 0;
+ }
+ static void vmd_remove_irq_domain(struct vmd_dev *vmd)
+ {
+       if (vmd->irq_domain) {
+               struct fwnode_handle *fn = vmd->irq_domain->fwnode;
+               irq_domain_remove(vmd->irq_domain);
+               irq_domain_free_fwnode(fn);
+       }
+ }
  static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus,
                                  unsigned int devfn, int reg, int len)
  {
@@@ -417,97 -445,175 +444,175 @@@ static int vmd_find_free_domain(void
        return domain + 1;
  }
  
- static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
+ static int vmd_get_phys_offsets(struct vmd_dev *vmd, bool native_hint,
+                               resource_size_t *offset1,
+                               resource_size_t *offset2)
  {
-       struct pci_sysdata *sd = &vmd->sysdata;
-       struct fwnode_handle *fn;
-       struct resource *res;
-       u32 upper_bits;
-       unsigned long flags;
-       LIST_HEAD(resources);
-       resource_size_t offset[2] = {0};
-       resource_size_t membar2_offset = 0x2000;
-       struct pci_bus *child;
+       struct pci_dev *dev = vmd->dev;
+       u64 phys1, phys2;
  
-       /*
-        * Shadow registers may exist in certain VMD device ids which allow
-        * guests to correctly assign host physical addresses to the root ports
-        * and child devices. These registers will either return the host value
-        * or 0, depending on an enable bit in the VMD device.
-        */
-       if (features & VMD_FEAT_HAS_MEMBAR_SHADOW) {
+       if (native_hint) {
                u32 vmlock;
                int ret;
  
-               membar2_offset = MB2_SHADOW_OFFSET + MB2_SHADOW_SIZE;
-               ret = pci_read_config_dword(vmd->dev, PCI_REG_VMLOCK, &vmlock);
+               ret = pci_read_config_dword(dev, PCI_REG_VMLOCK, &vmlock);
                if (ret || vmlock == ~0)
                        return -ENODEV;
  
                if (MB2_SHADOW_EN(vmlock)) {
                        void __iomem *membar2;
  
-                       membar2 = pci_iomap(vmd->dev, VMD_MEMBAR2, 0);
+                       membar2 = pci_iomap(dev, VMD_MEMBAR2, 0);
                        if (!membar2)
                                return -ENOMEM;
-                       offset[0] = vmd->dev->resource[VMD_MEMBAR1].start -
-                                       (readq(membar2 + MB2_SHADOW_OFFSET) &
-                                        PCI_BASE_ADDRESS_MEM_MASK);
-                       offset[1] = vmd->dev->resource[VMD_MEMBAR2].start -
-                                       (readq(membar2 + MB2_SHADOW_OFFSET + 8) &
-                                        PCI_BASE_ADDRESS_MEM_MASK);
-                       pci_iounmap(vmd->dev, membar2);
-               }
-       }
-       if (features & VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP) {
-               int pos = pci_find_capability(vmd->dev, PCI_CAP_ID_VNDR);
+                       phys1 = readq(membar2 + MB2_SHADOW_OFFSET);
+                       phys2 = readq(membar2 + MB2_SHADOW_OFFSET + 8);
+                       pci_iounmap(dev, membar2);
+               } else
+                       return 0;
+       } else {
+               /* Hypervisor-Emulated Vendor-Specific Capability */
+               int pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
                u32 reg, regu;
  
-               pci_read_config_dword(vmd->dev, pos + 4, &reg);
+               pci_read_config_dword(dev, pos + 4, &reg);
  
                /* "SHDW" */
                if (pos && reg == 0x53484457) {
-                       pci_read_config_dword(vmd->dev, pos + 8, &reg);
-                       pci_read_config_dword(vmd->dev, pos + 12, &regu);
-                       offset[0] = vmd->dev->resource[VMD_MEMBAR1].start -
-                                       (((u64) regu << 32 | reg) &
-                                        PCI_BASE_ADDRESS_MEM_MASK);
-                       pci_read_config_dword(vmd->dev, pos + 16, &reg);
-                       pci_read_config_dword(vmd->dev, pos + 20, &regu);
-                       offset[1] = vmd->dev->resource[VMD_MEMBAR2].start -
-                                       (((u64) regu << 32 | reg) &
-                                        PCI_BASE_ADDRESS_MEM_MASK);
+                       pci_read_config_dword(dev, pos + 8, &reg);
+                       pci_read_config_dword(dev, pos + 12, &regu);
+                       phys1 = (u64) regu << 32 | reg;
+                       pci_read_config_dword(dev, pos + 16, &reg);
+                       pci_read_config_dword(dev, pos + 20, &regu);
+                       phys2 = (u64) regu << 32 | reg;
+               } else
+                       return 0;
+       }
+       *offset1 = dev->resource[VMD_MEMBAR1].start -
+                       (phys1 & PCI_BASE_ADDRESS_MEM_MASK);
+       *offset2 = dev->resource[VMD_MEMBAR2].start -
+                       (phys2 & PCI_BASE_ADDRESS_MEM_MASK);
+       return 0;
+ }
+ static int vmd_get_bus_number_start(struct vmd_dev *vmd)
+ {
+       struct pci_dev *dev = vmd->dev;
+       u16 reg;
+       pci_read_config_word(dev, PCI_REG_VMCAP, &reg);
+       if (BUS_RESTRICT_CAP(reg)) {
+               pci_read_config_word(dev, PCI_REG_VMCONFIG, &reg);
+               switch (BUS_RESTRICT_CFG(reg)) {
+               case 0:
+                       vmd->busn_start = 0;
+                       break;
+               case 1:
+                       vmd->busn_start = 128;
+                       break;
+               case 2:
+                       vmd->busn_start = 224;
+                       break;
+               default:
+                       pci_err(dev, "Unknown Bus Offset Setting (%d)\n",
+                               BUS_RESTRICT_CFG(reg));
+                       return -ENODEV;
                }
        }
  
+       return 0;
+ }
+ static irqreturn_t vmd_irq(int irq, void *data)
+ {
+       struct vmd_irq_list *irqs = data;
+       struct vmd_irq *vmdirq;
+       int idx;
+       idx = srcu_read_lock(&irqs->srcu);
+       list_for_each_entry_rcu(vmdirq, &irqs->irq_list, node)
+               generic_handle_irq(vmdirq->virq);
+       srcu_read_unlock(&irqs->srcu, idx);
+       return IRQ_HANDLED;
+ }
+ static int vmd_alloc_irqs(struct vmd_dev *vmd)
+ {
+       struct pci_dev *dev = vmd->dev;
+       int i, err;
+       vmd->msix_count = pci_msix_vec_count(dev);
+       if (vmd->msix_count < 0)
+               return -ENODEV;
+       vmd->msix_count = pci_alloc_irq_vectors(dev, 1, vmd->msix_count,
+                                               PCI_IRQ_MSIX);
+       if (vmd->msix_count < 0)
+               return vmd->msix_count;
+       vmd->irqs = devm_kcalloc(&dev->dev, vmd->msix_count, sizeof(*vmd->irqs),
+                                GFP_KERNEL);
+       if (!vmd->irqs)
+               return -ENOMEM;
+       for (i = 0; i < vmd->msix_count; i++) {
+               err = init_srcu_struct(&vmd->irqs[i].srcu);
+               if (err)
+                       return err;
+               INIT_LIST_HEAD(&vmd->irqs[i].irq_list);
+               err = devm_request_irq(&dev->dev, pci_irq_vector(dev, i),
+                                      vmd_irq, IRQF_NO_THREAD,
+                                      "vmd", &vmd->irqs[i]);
+               if (err)
+                       return err;
+       }
+       return 0;
+ }
+ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
+ {
+       struct pci_sysdata *sd = &vmd->sysdata;
+       struct resource *res;
+       u32 upper_bits;
+       unsigned long flags;
+       LIST_HEAD(resources);
+       resource_size_t offset[2] = {0};
+       resource_size_t membar2_offset = 0x2000;
+       struct pci_bus *child;
+       int ret;
+       /*
+        * Shadow registers may exist in certain VMD device ids which allow
+        * guests to correctly assign host physical addresses to the root ports
+        * and child devices. These registers will either return the host value
+        * or 0, depending on an enable bit in the VMD device.
+        */
+       if (features & VMD_FEAT_HAS_MEMBAR_SHADOW) {
+               membar2_offset = MB2_SHADOW_OFFSET + MB2_SHADOW_SIZE;
+               ret = vmd_get_phys_offsets(vmd, true, &offset[0], &offset[1]);
+               if (ret)
+                       return ret;
+       } else if (features & VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP) {
+               ret = vmd_get_phys_offsets(vmd, false, &offset[0], &offset[1]);
+               if (ret)
+                       return ret;
+       }
        /*
         * Certain VMD devices may have a root port configuration option which
         * limits the bus range to between 0-127, 128-255, or 224-255
         */
        if (features & VMD_FEAT_HAS_BUS_RESTRICTIONS) {
-               u16 reg16;
-               pci_read_config_word(vmd->dev, PCI_REG_VMCAP, &reg16);
-               if (BUS_RESTRICT_CAP(reg16)) {
-                       pci_read_config_word(vmd->dev, PCI_REG_VMCONFIG,
-                                            &reg16);
-                       switch (BUS_RESTRICT_CFG(reg16)) {
-                       case 1:
-                               vmd->busn_start = 128;
-                               break;
-                       case 2:
-                               vmd->busn_start = 224;
-                               break;
-                       case 3:
-                               pci_err(vmd->dev, "Unknown Bus Offset Setting\n");
-                               return -ENODEV;
-                       default:
-                               break;
-                       }
-               }
+               ret = vmd_get_bus_number_start(vmd);
+               if (ret)
+                       return ret;
        }
  
        res = &vmd->dev->resource[VMD_CFGBAR];
  
        sd->node = pcibus_to_node(vmd->dev->bus);
  
-       fn = irq_domain_alloc_named_id_fwnode("VMD-MSI", vmd->sysdata.domain);
-       if (!fn)
-               return -ENODEV;
-       vmd->irq_domain = pci_msi_create_irq_domain(fn, &vmd_msi_domain_info,
-                                                   NULL);
-       if (!vmd->irq_domain) {
-               irq_domain_free_fwnode(fn);
-               return -ENODEV;
-       }
+       ret = vmd_create_irq_domain(vmd);
+       if (ret)
+               return ret;
  
 +      /*
 +       * Override the irq domain bus token so the domain can be distinguished
 +       * from a regular PCI/MSI domain.
 +       */
 +      irq_domain_update_bus_token(vmd->irq_domain, DOMAIN_BUS_VMD_MSI);
 +
        pci_add_resource(&resources, &vmd->resources[0]);
        pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
        pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
                                       &vmd_ops, sd, &resources);
        if (!vmd->bus) {
                pci_free_resource_list(&resources);
-               irq_domain_remove(vmd->irq_domain);
-               irq_domain_free_fwnode(fn);
+               vmd_remove_irq_domain(vmd);
                return -ENODEV;
        }
  
        vmd_attach_resources(vmd);
-       dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
+       if (vmd->irq_domain)
+               dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
  
        pci_scan_child_bus(vmd->bus);
        pci_assign_unassigned_bus_resources(vmd->bus);
        return 0;
  }
  
- static irqreturn_t vmd_irq(int irq, void *data)
- {
-       struct vmd_irq_list *irqs = data;
-       struct vmd_irq *vmdirq;
-       int idx;
-       idx = srcu_read_lock(&irqs->srcu);
-       list_for_each_entry_rcu(vmdirq, &irqs->irq_list, node)
-               generic_handle_irq(vmdirq->virq);
-       srcu_read_unlock(&irqs->srcu, idx);
-       return IRQ_HANDLED;
- }
  static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
  {
        struct vmd_dev *vmd;
-       int i, err;
+       int err;
  
        if (resource_size(&dev->resource[VMD_CFGBAR]) < (1 << 20))
                return -ENOMEM;
            dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)))
                return -ENODEV;
  
-       vmd->msix_count = pci_msix_vec_count(dev);
-       if (vmd->msix_count < 0)
-               return -ENODEV;
-       vmd->msix_count = pci_alloc_irq_vectors(dev, 1, vmd->msix_count,
-                                       PCI_IRQ_MSIX);
-       if (vmd->msix_count < 0)
-               return vmd->msix_count;
-       vmd->irqs = devm_kcalloc(&dev->dev, vmd->msix_count, sizeof(*vmd->irqs),
-                                GFP_KERNEL);
-       if (!vmd->irqs)
-               return -ENOMEM;
-       for (i = 0; i < vmd->msix_count; i++) {
-               err = init_srcu_struct(&vmd->irqs[i].srcu);
-               if (err)
-                       return err;
-               INIT_LIST_HEAD(&vmd->irqs[i].irq_list);
-               err = devm_request_irq(&dev->dev, pci_irq_vector(dev, i),
-                                      vmd_irq, IRQF_NO_THREAD,
-                                      "vmd", &vmd->irqs[i]);
-               if (err)
-                       return err;
-       }
+       err = vmd_alloc_irqs(vmd);
+       if (err)
+               return err;
  
        spin_lock_init(&vmd->cfg_lock);
        pci_set_drvdata(dev, vmd);
@@@ -709,15 -764,13 +769,13 @@@ static void vmd_cleanup_srcu(struct vmd
  static void vmd_remove(struct pci_dev *dev)
  {
        struct vmd_dev *vmd = pci_get_drvdata(dev);
-       struct fwnode_handle *fn = vmd->irq_domain->fwnode;
  
        sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
        pci_stop_root_bus(vmd->bus);
        pci_remove_root_bus(vmd->bus);
        vmd_cleanup_srcu(vmd);
        vmd_detach_resources(vmd);
-       irq_domain_remove(vmd->irq_domain);
-       irq_domain_free_fwnode(fn);
+       vmd_remove_irq_domain(vmd);
  }
  
  #ifdef CONFIG_PM_SLEEP
@@@ -730,7 -783,6 +788,6 @@@ static int vmd_suspend(struct device *d
        for (i = 0; i < vmd->msix_count; i++)
                devm_free_irq(dev, pci_irq_vector(pdev, i), &vmd->irqs[i]);
  
-       pci_save_state(pdev);
        return 0;
  }
  
@@@ -748,7 -800,6 +805,6 @@@ static int vmd_resume(struct device *de
                        return err;
        }
  
-       pci_restore_state(pdev);
        return 0;
  }
  #endif
index 9f85815b4f53403dd7f5dd3a0d23384232c25e0c,2f5f4bb42dcc6f4019995191d897e42f0814e76a..529c348084401462090b7667394d0ce0cd4bce96
@@@ -73,10 -73,8 +73,8 @@@ static int board_added(struct controlle
  
        /* Check link training status */
        retval = pciehp_check_link_status(ctrl);
-       if (retval) {
-               ctrl_err(ctrl, "Failed to check link status\n");
+       if (retval)
                goto err_exit;
-       }
  
        /* Check for a power fault */
        if (ctrl->power_fault_detected || pciehp_query_power_fault(ctrl)) {
@@@ -236,7 -234,7 +234,7 @@@ void pciehp_handle_presence_or_link_cha
        switch (ctrl->state) {
        case BLINKINGOFF_STATE:
                cancel_delayed_work(&ctrl->button_work);
 -              /* fall through */
 +              fallthrough;
        case ON_STATE:
                ctrl->state = POWEROFF_STATE;
                mutex_unlock(&ctrl->state_lock);
        switch (ctrl->state) {
        case BLINKINGON_STATE:
                cancel_delayed_work(&ctrl->button_work);
 -              /* fall through */
 +              fallthrough;
        case OFF_STATE:
                ctrl->state = POWERON_STATE;
                mutex_unlock(&ctrl->state_lock);
index 65502e3f7b4fb68aa43491d4fa94b2bffba61dd7,aedd9dfd2a16a8ba740bc03274e2a84fb1ee9ed4..6a6705e0cf17851cffb68bca54d2dd17b4be3368
@@@ -299,7 -299,6 +299,6 @@@ static int board_added(struct slot *p_s
        if (p_slot->status == 0xFF) {
                /* power fault occurred, but it was benign */
                ctrl_dbg(ctrl, "%s: Power fault\n", __func__);
-               rc = POWER_FAILURE;
                p_slot->status = 0;
                goto err_exit;
        }
@@@ -642,7 -641,7 +641,7 @@@ int shpchp_sysfs_enable_slot(struct slo
        switch (p_slot->state) {
        case BLINKINGON_STATE:
                cancel_delayed_work(&p_slot->work);
 -              /* fall through */
 +              fallthrough;
        case STATIC_STATE:
                p_slot->state = POWERON_STATE;
                mutex_unlock(&p_slot->lock);
@@@ -678,7 -677,7 +677,7 @@@ int shpchp_sysfs_disable_slot(struct sl
        switch (p_slot->state) {
        case BLINKINGOFF_STATE:
                cancel_delayed_work(&p_slot->work);
 -              /* fall through */
 +              fallthrough;
        case STATIC_STATE:
                p_slot->state = POWEROFF_STATE;
                mutex_unlock(&p_slot->lock);
diff --combined drivers/pci/p2pdma.c
index 9d53c16b73295e7dd140b71e505dd00479cd8921,85fc9936fa9eeb41656e417989897680416da5d7..de1c331dbed43fdbfb743380a9af9439a2b2638a
@@@ -53,7 -53,7 +53,7 @@@ static ssize_t size_show(struct device 
        if (pdev->p2pdma->pool)
                size = gen_pool_size(pdev->p2pdma->pool);
  
-       return snprintf(buf, PAGE_SIZE, "%zd\n", size);
+       return scnprintf(buf, PAGE_SIZE, "%zd\n", size);
  }
  static DEVICE_ATTR_RO(size);
  
@@@ -66,7 -66,7 +66,7 @@@ static ssize_t available_show(struct de
        if (pdev->p2pdma->pool)
                avail = gen_pool_avail(pdev->p2pdma->pool);
  
-       return snprintf(buf, PAGE_SIZE, "%zd\n", avail);
+       return scnprintf(buf, PAGE_SIZE, "%zd\n", avail);
  }
  static DEVICE_ATTR_RO(available);
  
@@@ -75,8 -75,8 +75,8 @@@ static ssize_t published_show(struct de
  {
        struct pci_dev *pdev = to_pci_dev(dev);
  
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       pdev->p2pdma->p2pmem_published);
+       return scnprintf(buf, PAGE_SIZE, "%d\n",
+                        pdev->p2pdma->p2pmem_published);
  }
  static DEVICE_ATTR_RO(published);
  
@@@ -185,9 -185,9 +185,9 @@@ int pci_p2pdma_add_resource(struct pci_
                return -ENOMEM;
  
        pgmap = &p2p_pgmap->pgmap;
 -      pgmap->res.start = pci_resource_start(pdev, bar) + offset;
 -      pgmap->res.end = pgmap->res.start + size - 1;
 -      pgmap->res.flags = pci_resource_flags(pdev, bar);
 +      pgmap->range.start = pci_resource_start(pdev, bar) + offset;
 +      pgmap->range.end = pgmap->range.start + size - 1;
 +      pgmap->nr_range = 1;
        pgmap->type = MEMORY_DEVICE_PCI_P2PDMA;
  
        p2p_pgmap->provider = pdev;
  
        error = gen_pool_add_owner(pdev->p2pdma->pool, (unsigned long)addr,
                        pci_bus_address(pdev, bar) + offset,
 -                      resource_size(&pgmap->res), dev_to_node(&pdev->dev),
 +                      range_len(&pgmap->range), dev_to_node(&pdev->dev),
                        pgmap->ref);
        if (error)
                goto pages_free;
  
 -      pci_info(pdev, "added peer-to-peer DMA memory %pR\n",
 -               &pgmap->res);
 +      pci_info(pdev, "added peer-to-peer DMA memory %#llx-%#llx\n",
 +               pgmap->range.start, pgmap->range.end);
  
        return 0;
  
@@@ -556,14 -556,13 +556,14 @@@ int pci_p2pdma_distance_many(struct pci
                return -1;
  
        for (i = 0; i < num_clients; i++) {
 -              if (IS_ENABLED(CONFIG_DMA_VIRT_OPS) &&
 -                  clients[i]->dma_ops == &dma_virt_ops) {
 +#ifdef CONFIG_DMA_VIRT_OPS
 +              if (clients[i]->dma_ops == &dma_virt_ops) {
                        if (verbose)
                                dev_warn(clients[i],
                                         "cannot be used for peer-to-peer DMA because the driver makes use of dma_virt_ops\n");
                        return -1;
                }
 +#endif
  
                pci_client = find_parent_pci_dev(clients[i]);
                if (!pci_client) {
@@@ -762,7 -761,7 +762,7 @@@ struct scatterlist *pci_p2pmem_alloc_sg
        struct scatterlist *sg;
        void *addr;
  
-       sg = kzalloc(sizeof(*sg), GFP_KERNEL);
+       sg = kmalloc(sizeof(*sg), GFP_KERNEL);
        if (!sg)
                return NULL;
  
@@@ -843,10 -842,9 +843,10 @@@ static int __pci_p2pdma_map_sg(struct p
         * this should never happen because it will be prevented
         * by the check in pci_p2pdma_distance_many()
         */
 -      if (WARN_ON_ONCE(IS_ENABLED(CONFIG_DMA_VIRT_OPS) &&
 -                       dev->dma_ops == &dma_virt_ops))
 +#ifdef CONFIG_DMA_VIRT_OPS
 +      if (WARN_ON_ONCE(dev->dma_ops == &dma_virt_ops))
                return 0;
 +#endif
  
        for_each_sg(sg, s, nents, i) {
                paddr = sg_phys(s);
diff --combined drivers/pci/pci-acpi.c
index d9aa551f8423634ffb803c4b730e87325daf6563,154db9a47511948a2f703c0be696699fa1482bab..bf03648c2072319d2c2e401d794de263bd38cd75
@@@ -944,16 -944,6 +944,16 @@@ static bool acpi_pci_bridge_d3(struct p
        if (!dev->is_hotplug_bridge)
                return false;
  
 +      /* Assume D3 support if the bridge is power-manageable by ACPI. */
 +      adev = ACPI_COMPANION(&dev->dev);
 +      if (!adev && !pci_dev_is_added(dev)) {
 +              adev = acpi_pci_find_companion(&dev->dev);
 +              ACPI_COMPANION_SET(&dev->dev, adev);
 +      }
 +
 +      if (adev && acpi_device_power_manageable(adev))
 +              return true;
 +
        /*
         * Look for a special _DSD property for the root port and if it
         * is set we know the hierarchy behind it supports D3 just fine.
@@@ -1177,7 -1167,7 +1177,7 @@@ static struct acpi_device *acpi_pci_fin
   * @pdev: the PCI device whose delay is to be updated
   * @handle: ACPI handle of this device
   *
-  * Update the d3_delay and d3cold_delay of a PCI device from the ACPI _DSM
+  * Update the d3hot_delay and d3cold_delay of a PCI device from the ACPI _DSM
   * control method of either the device itself or the PCI host bridge.
   *
   * Function 8, "Reset Delay," applies to the entire hierarchy below a PCI
@@@ -1216,8 -1206,8 +1216,8 @@@ static void pci_acpi_optimize_delay(str
                }
                if (elements[3].type == ACPI_TYPE_INTEGER) {
                        value = (int)elements[3].integer.value / 1000;
-                       if (value < PCI_PM_D3_WAIT)
-                               pdev->d3_delay = value;
+                       if (value < PCI_PM_D3HOT_WAIT)
+                               pdev->d3hot_delay = value;
                }
        }
        ACPI_FREE(obj);
diff --combined drivers/pci/pci-driver.c
index d1b7169c0684036af73e46af2989caed9700dab6,40be221e69cf4fecc221bf927004dbb0a3ead9ea..8b587fc97f7bc90787a1e90ff821b001da9cdb48
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/kexec.h>
  #include <linux/of_device.h>
  #include <linux/acpi.h>
 +#include <linux/dma-map-ops.h>
  #include "pci.h"
  #include "pcie/portdrv.h"
  
@@@ -970,12 -969,6 +970,6 @@@ static int pci_pm_resume(struct device 
  
  #ifdef CONFIG_HIBERNATE_CALLBACKS
  
- /*
-  * pcibios_pm_ops - provide arch-specific hooks when a PCI device is doing
-  * a hibernate transition
-  */
- struct dev_pm_ops __weak pcibios_pm_ops;
  static int pci_pm_freeze(struct device *dev)
  {
        struct pci_dev *pci_dev = to_pci_dev(dev);
@@@ -1034,9 -1027,6 +1028,6 @@@ static int pci_pm_freeze_noirq(struct d
  
        pci_pm_set_unknown_state(pci_dev);
  
-       if (pcibios_pm_ops.freeze_noirq)
-               return pcibios_pm_ops.freeze_noirq(dev);
        return 0;
  }
  
@@@ -1044,13 -1034,6 +1035,6 @@@ static int pci_pm_thaw_noirq(struct dev
  {
        struct pci_dev *pci_dev = to_pci_dev(dev);
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-       int error;
-       if (pcibios_pm_ops.thaw_noirq) {
-               error = pcibios_pm_ops.thaw_noirq(dev);
-               if (error)
-                       return error;
-       }
  
        /*
         * The pm->thaw_noirq() callback assumes the device has been
@@@ -1175,9 -1158,6 +1159,6 @@@ static int pci_pm_poweroff_noirq(struc
  
        pci_fixup_device(pci_fixup_suspend_late, pci_dev);
  
-       if (pcibios_pm_ops.poweroff_noirq)
-               return pcibios_pm_ops.poweroff_noirq(dev);
        return 0;
  }
  
@@@ -1185,13 -1165,6 +1166,6 @@@ static int pci_pm_restore_noirq(struct 
  {
        struct pci_dev *pci_dev = to_pci_dev(dev);
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-       int error;
-       if (pcibios_pm_ops.restore_noirq) {
-               error = pcibios_pm_ops.restore_noirq(dev);
-               if (error)
-                       return error;
-       }
  
        pci_pm_default_resume_early(pci_dev);
        pci_fixup_device(pci_fixup_resume_early, pci_dev);
diff --combined drivers/pci/pci.c
index e39c5499770ff4377766a72ccbb165e2bdbb917e,0e63e0e777088f86d8d75231b012d58e3d024acd..6d4d5a2f923d9ef291eb7f09d5af3b452fe487df
@@@ -15,7 -15,6 +15,6 @@@
  #include <linux/init.h>
  #include <linux/msi.h>
  #include <linux/of.h>
- #include <linux/of_pci.h>
  #include <linux/pci.h>
  #include <linux/pm.h>
  #include <linux/slab.h>
@@@ -30,8 -29,6 +29,6 @@@
  #include <linux/pm_runtime.h>
  #include <linux/pci_hotplug.h>
  #include <linux/vmalloc.h>
- #include <linux/pci-ats.h>
- #include <asm/setup.h>
  #include <asm/dma.h>
  #include <linux/aer.h>
  #include "pci.h"
@@@ -49,7 -46,7 +46,7 @@@ EXPORT_SYMBOL(isa_dma_bridge_buggy)
  int pci_pci_problems;
  EXPORT_SYMBOL(pci_pci_problems);
  
- unsigned int pci_pm_d3_delay;
+ unsigned int pci_pm_d3hot_delay;
  
  static void pci_pme_list_scan(struct work_struct *work);
  
@@@ -66,10 -63,10 +63,10 @@@ struct pci_pme_device 
  
  static void pci_dev_d3_sleep(struct pci_dev *dev)
  {
-       unsigned int delay = dev->d3_delay;
+       unsigned int delay = dev->d3hot_delay;
  
-       if (delay < pci_pm_d3_delay)
-               delay = pci_pm_d3_delay;
+       if (delay < pci_pm_d3hot_delay)
+               delay = pci_pm_d3hot_delay;
  
        if (delay)
                msleep(delay);
@@@ -101,7 -98,19 +98,19 @@@ unsigned long pci_hotplug_mmio_pref_siz
  #define DEFAULT_HOTPLUG_BUS_SIZE      1
  unsigned long pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE;
  
+ /* PCIe MPS/MRRS strategy; can be overridden by kernel command-line param */
+ #ifdef CONFIG_PCIE_BUS_TUNE_OFF
+ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
+ #elif defined CONFIG_PCIE_BUS_SAFE
+ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE;
+ #elif defined CONFIG_PCIE_BUS_PERFORMANCE
+ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE;
+ #elif defined CONFIG_PCIE_BUS_PEER2PEER
+ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PEER2PEER;
+ #else
  enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
+ #endif
  
  /*
   * The default CLS is used if arch didn't set CLS explicitly and not
@@@ -876,6 -885,10 +885,10 @@@ static void pci_std_enable_acs(struct p
        /* Upstream Forwarding */
        ctrl |= (cap & PCI_ACS_UF);
  
+       /* Enable Translation Blocking for external devices */
+       if (dev->external_facing || dev->untrusted)
+               ctrl |= (cap & PCI_ACS_TB);
        pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
  }
  
@@@ -1049,7 -1062,7 +1062,7 @@@ static int pci_raw_set_power_state(stru
                if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
                 && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
                        need_restore = true;
 -              /* Fall-through - force to D0 */
 +              fallthrough;    /* force to D0 */
        default:
                pmcsr = 0;
                break;
        if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
                pci_dev_d3_sleep(dev);
        else if (state == PCI_D2 || dev->current_state == PCI_D2)
-               msleep(PCI_PM_D2_DELAY);
+               udelay(PCI_PM_D2_DELAY);
  
        pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
        dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
@@@ -2541,7 -2554,7 +2554,7 @@@ static pci_power_t pci_target_state(str
                case PCI_D2:
                        if (pci_no_d1d2(dev))
                                break;
 -                      /* else, fall through */
 +                      fallthrough;
                default:
                        target_state = state;
                }
@@@ -3013,7 -3026,7 +3026,7 @@@ void pci_pm_init(struct pci_dev *dev
        }
  
        dev->pm_cap = pm;
-       dev->d3_delay = PCI_PM_D3_WAIT;
+       dev->d3hot_delay = PCI_PM_D3HOT_WAIT;
        dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
        dev->bridge_d3 = pci_bridge_d3_possible(dev);
        dev->d3cold_allowed = true;
                         (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
                         (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
                         (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
-                        (pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
+                        (pmc & PCI_PM_CAP_PME_D3hot) ? " D3hot" : "",
                         (pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
                dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT;
                dev->pme_poll = true;
@@@ -4621,7 -4634,7 +4634,7 @@@ static int pci_af_flr(struct pci_dev *d
   *
   * NOTE: This causes the caller to sleep for twice the device power transition
   * cooldown period, which for the D0->D3hot and D3hot->D0 transitions is 10 ms
-  * by default (i.e. unless the @dev's d3_delay field has a different value).
+  * by default (i.e. unless the @dev's d3hot_delay field has a different value).
   * Moreover, only devices in D0 can be reset by this function.
   */
  static int pci_pm_reset(struct pci_dev *dev, int probe)
@@@ -4701,9 -4714,7 +4714,7 @@@ static bool pcie_wait_for_link_delay(st
        }
        if (active && ret)
                msleep(delay);
-       else if (ret != active)
-               pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
-                       active ? "set" : "cleared");
        return ret == active;
  }
  
@@@ -4828,6 -4839,7 +4839,7 @@@ void pci_bridge_wait_for_secondary_bus(
                        delay);
                if (!pcie_wait_for_link_delay(dev, true, delay)) {
                        /* Did not train, no need to wait any further */
+                       pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n");
                        return;
                }
        }
@@@ -4920,16 -4932,10 +4932,10 @@@ static int pci_reset_hotplug_slot(struc
  
  static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
  {
-       struct pci_dev *pdev;
-       if (dev->subordinate || !dev->slot ||
+       if (dev->multifunction || dev->subordinate || !dev->slot ||
            dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
                return -ENOTTY;
  
-       list_for_each_entry(pdev, &dev->bus->devices, bus_list)
-               if (pdev != dev && pdev->slot == dev->slot)
-                       return -ENOTTY;
        return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
  }
  
@@@ -6005,7 -6011,7 +6011,7 @@@ int pci_set_vga_state(struct pci_dev *d
  
        if (flags & PCI_VGA_STATE_CHANGE_DECODES) {
                pci_read_config_word(dev, PCI_COMMAND, &cmd);
-               if (decode == true)
+               if (decode)
                        cmd |= command_bits;
                else
                        cmd &= ~command_bits;
                if (bridge) {
                        pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
                                             &cmd);
-                       if (decode == true)
+                       if (decode)
                                cmd |= PCI_BRIDGE_CTL_VGA;
                        else
                                cmd &= ~PCI_BRIDGE_CTL_VGA;
@@@ -6350,7 -6356,7 +6356,7 @@@ static ssize_t resource_alignment_show(
  
        spin_lock(&resource_alignment_lock);
        if (resource_alignment_param)
-               count = snprintf(buf, PAGE_SIZE, "%s", resource_alignment_param);
+               count = scnprintf(buf, PAGE_SIZE, "%s", resource_alignment_param);
        spin_unlock(&resource_alignment_lock);
  
        /*
diff --combined drivers/pci/quirks.c
index 01f23e30bd8f4a0c57e9454fbc71c2fc5710d7aa,eefed9d269453cc1b6b29d2bd623b5f315ee0189..f70692ac79c565f517209db63b6e614bd4ff3928
@@@ -1730,7 -1730,7 +1730,7 @@@ static void quirk_jmicron_ata(struct pc
        case PCI_DEVICE_ID_JMICRON_JMB366:
                /* Redirect IDE second PATA port to the right spot */
                conf5 |= (1 << 24);
 -              /* Fall through */
 +              fallthrough;
        case PCI_DEVICE_ID_JMICRON_JMB361:
        case PCI_DEVICE_ID_JMICRON_JMB363:
        case PCI_DEVICE_ID_JMICRON_JMB369:
@@@ -1846,7 -1846,7 +1846,7 @@@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_I
   */
  static void quirk_intel_pcie_pm(struct pci_dev *dev)
  {
-       pci_pm_d3_delay = 120;
+       pci_pm_d3hot_delay = 120;
        dev->no_d1d2 = 1;
  }
  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,  0x25e2, quirk_intel_pcie_pm);
@@@ -1873,12 -1873,12 +1873,12 @@@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_I
  
  static void quirk_d3hot_delay(struct pci_dev *dev, unsigned int delay)
  {
-       if (dev->d3_delay >= delay)
+       if (dev->d3hot_delay >= delay)
                return;
  
-       dev->d3_delay = delay;
+       dev->d3hot_delay = delay;
        pci_info(dev, "extending delay after power-on from D3hot to %d msec\n",
-                dev->d3_delay);
+                dev->d3hot_delay);
  }
  
  static void quirk_radeon_pm(struct pci_dev *dev)
@@@ -2224,7 -2224,7 +2224,7 @@@ static void quirk_netmos(struct pci_de
                if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
                                dev->subsystem_device == 0x0299)
                        return;
 -              /* else, fall through */
 +              fallthrough;
        case PCI_DEVICE_ID_NETMOS_9735:
        case PCI_DEVICE_ID_NETMOS_9745:
        case PCI_DEVICE_ID_NETMOS_9845:
@@@ -3387,36 -3387,36 +3387,36 @@@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_I
   * PCI devices which are on Intel chips can skip the 10ms delay
   * before entering D3 mode.
   */
- static void quirk_remove_d3_delay(struct pci_dev *dev)
- {
-       dev->d3_delay = 0;
- }
- /* C600 Series devices do not need 10ms d3_delay */
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0412, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c00, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c0c, quirk_remove_d3_delay);
- /* Lynxpoint-H PCH devices do not need 10ms d3_delay */
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c18, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c1c, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c20, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c2d, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c31, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3a, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3d, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay);
- /* Intel Cherrytrail devices do not need 10ms d3_delay */
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2280, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b0, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b8, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22d8, quirk_remove_d3_delay);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22dc, quirk_remove_d3_delay);
+ static void quirk_remove_d3hot_delay(struct pci_dev *dev)
+ {
+       dev->d3hot_delay = 0;
+ }
+ /* C600 Series devices do not need 10ms d3hot_delay */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0412, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c00, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c0c, quirk_remove_d3hot_delay);
+ /* Lynxpoint-H PCH devices do not need 10ms d3hot_delay */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c18, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c1c, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c20, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c2d, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c31, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3a, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3d, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3hot_delay);
+ /* Intel Cherrytrail devices do not need 10ms d3hot_delay */
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2280, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b0, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b8, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22d8, quirk_remove_d3hot_delay);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22dc, quirk_remove_d3hot_delay);
  
  /*
   * Some devices may pass our check in pci_intx_mask_supported() if
@@@ -3673,6 -3673,63 +3673,6 @@@ static void quirk_apple_poweroff_thunde
  DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
                               PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
                               quirk_apple_poweroff_thunderbolt);
 -
 -/*
 - * Apple: Wait for the Thunderbolt controller to reestablish PCI tunnels
 - *
 - * During suspend the Thunderbolt controller is reset and all PCI
 - * tunnels are lost. The NHI driver will try to reestablish all tunnels
 - * during resume. We have to manually wait for the NHI since there is
 - * no parent child relationship between the NHI and the tunneled
 - * bridges.
 - */
 -static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
 -{
 -      struct pci_dev *sibling = NULL;
 -      struct pci_dev *nhi = NULL;
 -
 -      if (!x86_apple_machine)
 -              return;
 -      if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
 -              return;
 -
 -      /*
 -       * Find the NHI and confirm that we are a bridge on the Thunderbolt
 -       * host controller and not on a Thunderbolt endpoint.
 -       */
 -      sibling = pci_get_slot(dev->bus, 0x0);
 -      if (sibling == dev)
 -              goto out; /* we are the downstream bridge to the NHI */
 -      if (!sibling || !sibling->subordinate)
 -              goto out;
 -      nhi = pci_get_slot(sibling->subordinate, 0x0);
 -      if (!nhi)
 -              goto out;
 -      if (nhi->vendor != PCI_VENDOR_ID_INTEL
 -                  || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
 -                      nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
 -                      nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI &&
 -                      nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
 -                  || nhi->class != PCI_CLASS_SYSTEM_OTHER << 8)
 -              goto out;
 -      pci_info(dev, "quirk: waiting for Thunderbolt to reestablish PCI tunnels...\n");
 -      device_pm_wait_for_dev(&dev->dev, &nhi->dev);
 -out:
 -      pci_dev_put(nhi);
 -      pci_dev_put(sibling);
 -}
 -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
 -                             PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
 -                             quirk_apple_wait_for_thunderbolt);
 -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
 -                             PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
 -                             quirk_apple_wait_for_thunderbolt);
 -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
 -                             PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE,
 -                             quirk_apple_wait_for_thunderbolt);
 -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
 -                             PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
 -                             quirk_apple_wait_for_thunderbolt);
  #endif
  
  /*
@@@ -4892,6 -4949,13 +4892,13 @@@ static void pci_quirk_enable_intel_rp_m
        }
  }
  
+ /*
+  * Currently this quirk does the equivalent of
+  * PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF
+  *
+  * TODO: This quirk also needs to do equivalent of PCI_ACS_TB,
+  * if dev->external_facing || dev->untrusted
+  */
  static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev)
  {
        if (!pci_quirk_intel_pch_acs_match(dev))
@@@ -4931,6 -4995,9 +4938,9 @@@ static int pci_quirk_enable_intel_spt_p
        ctrl |= (cap & PCI_ACS_CR);
        ctrl |= (cap & PCI_ACS_UF);
  
+       if (dev->external_facing || dev->untrusted)
+               ctrl |= (cap & PCI_ACS_TB);
        pci_write_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, ctrl);
  
        pci_info(dev, "Intel SPT PCH root port ACS workaround enabled\n");
index 376205e97a8911f7858429f4f184808f335e5071,beba430a197e19c7ad6e59342be33bde65f5a1b2..0295e2e32d7973d7750615e482df8fd183096d87
@@@ -1086,7 -1086,7 +1086,7 @@@ static int atomisp_subdev_probe(struct 
                case RAW_CAMERA:
                        dev_dbg(isp->dev, "raw_index: %d\n", raw_index);
                        raw_index = isp->input_cnt;
 -                      /* fall through */
 +                      fallthrough;
                case SOC_CAMERA:
                        dev_dbg(isp->dev, "SOC_INDEX: %d\n", isp->input_cnt);
                        if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) {
@@@ -1429,6 -1429,7 +1429,6 @@@ atomisp_load_firmware(struct atomisp_de
   */
  static bool is_valid_device(struct pci_dev *pdev, const struct pci_device_id *id)
  {
 -      unsigned int a0_max_id = 0;
        const char *name;
        const char *product;
  
  
        switch (id->device & ATOMISP_PCI_DEVICE_SOC_MASK) {
        case ATOMISP_PCI_DEVICE_SOC_MRFLD:
 -              a0_max_id = ATOMISP_PCI_REV_MRFLD_A0_MAX;
                name = "Merrifield";
                break;
        case ATOMISP_PCI_DEVICE_SOC_BYT:
 -              a0_max_id = ATOMISP_PCI_REV_BYT_A0_MAX;
                name = "Baytrail";
                break;
        case ATOMISP_PCI_DEVICE_SOC_ANN:
@@@ -1570,7 -1573,7 +1570,7 @@@ static int atomisp_pci_probe(struct pci
        spin_lock_init(&isp->lock);
  
        /* This is not a true PCI device on SoC, so the delay is not needed. */
-       pdev->d3_delay = 0;
+       pdev->d3hot_delay = 0;
  
        pci_set_drvdata(pdev, isp);
  
  
        pci_set_master(pdev);
  
 -      err = pci_enable_msi(pdev);
 -      if (err) {
 +      err = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
 +      if (err < 0) {
                dev_err(&pdev->dev, "Failed to enable msi (%d)\n", err);
                goto enable_msi_fail;
        }
@@@ -1824,7 -1827,7 +1824,7 @@@ register_entities_fail
  initialize_modules_fail:
        cpu_latency_qos_remove_request(&isp->pm_qos);
        atomisp_msi_irq_uninit(isp);
 -      pci_disable_msi(pdev);
 +      pci_free_irq_vectors(pdev);
  enable_msi_fail:
  fw_validation_fail:
        release_firmware(isp->firmware);
This page took 0.347873 seconds and 4 git commands to generate.