Merge branch 'pci/pm' into next
authorBjorn Helgaas <bhelgaas@google.com>
Sun, 2 Jul 2017 23:48:49 +0000 (18:48 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Sun, 2 Jul 2017 23:48:49 +0000 (18:48 -0500)
* pci/pm:
  PCI/PM: Avoid using device_may_wakeup() for runtime PM
  x86/PCI: Avoid AMD SB7xx EHCI USB wakeup defect
  PCI/PM: Restore the status of PCI devices across hibernation
  drm/radeon: make MacBook Pro d3_delay quirk more generic
  drm/amdgpu: remove unnecessary save/restore of pdev->d3_delay
  PCI/PM: Add needs_resume flag to avoid suspend complete optimization
  PCI: imx6: Fix config read timeout handling
  switchtec: Fix minor bug with partition ID register
  switchtec: Use new cdev_device_add() helper function
  PCI: endpoint: Make PCI_ENDPOINT depend on HAS_DMA

arch/x86/pci/fixup.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/pci/dwc/pci-imx6.c
drivers/pci/endpoint/Kconfig
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/pci/switch/switchtec.c
include/linux/pci.h

index 6d52b94..2259acd 100644 (file)
@@ -571,3 +571,18 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, pci_invalid_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar);
+
+/*
+ * Device [1022:7808]
+ * 23. USB Wake on Connect/Disconnect with Low Speed Devices
+ * https://support.amd.com/TechDocs/46837.pdf
+ * Appendix A2
+ * https://support.amd.com/TechDocs/42413.pdf
+ */
+static void pci_fixup_amd_ehci_pme(struct pci_dev *dev)
+{
+       dev_info(&dev->dev, "PME# does not work under D3, disabling it\n");
+       dev->pme_support &= ~((PCI_PM_CAP_PME_D3 | PCI_PM_CAP_PME_D3cold)
+               >> PCI_PM_CAP_PME_SHIFT);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x7808, pci_fixup_amd_ehci_pme);
index 43ca16b..bbac5d5 100644 (file)
@@ -1152,16 +1152,12 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
                return;
 
        if (state == VGA_SWITCHEROO_ON) {
-               unsigned d3_delay = dev->pdev->d3_delay;
-
                pr_info("amdgpu: switched on\n");
                /* don't suspend or resume card normally */
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 
                amdgpu_device_resume(dev, true, true);
 
-               dev->pdev->d3_delay = d3_delay;
-
                dev->switch_power_state = DRM_SWITCH_POWER_ON;
                drm_kms_helper_poll_enable(dev);
        } else {
index 6ecf427..aecaafb 100644 (file)
@@ -113,7 +113,6 @@ static inline bool radeon_is_atpx_hybrid(void) { return false; }
 #endif
 
 #define RADEON_PX_QUIRK_DISABLE_PX  (1 << 0)
-#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
 
 struct radeon_px_quirk {
        u32 chip_vendor;
@@ -136,8 +135,6 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {
         * https://bugzilla.kernel.org/show_bug.cgi?id=51381
         */
        { PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
-       /* macbook pro 8.2 */
-       { PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
        { 0, 0, 0, 0, 0 },
 };
 
@@ -1241,25 +1238,17 @@ static void radeon_check_arguments(struct radeon_device *rdev)
 static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
 {
        struct drm_device *dev = pci_get_drvdata(pdev);
-       struct radeon_device *rdev = dev->dev_private;
 
        if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
                return;
 
        if (state == VGA_SWITCHEROO_ON) {
-               unsigned d3_delay = dev->pdev->d3_delay;
-
                pr_info("radeon: switched on\n");
                /* don't suspend or resume card normally */
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 
-               if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP))
-                       dev->pdev->d3_delay = 20;
-
                radeon_resume_kms(dev, true, true);
 
-               dev->pdev->d3_delay = d3_delay;
-
                dev->switch_power_state = DRM_SWITCH_POWER_ON;
                drm_kms_helper_poll_enable(dev);
        } else {
index a98cba5..19a289b 100644 (file)
@@ -252,7 +252,34 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
 static int imx6q_pcie_abort_handler(unsigned long addr,
                unsigned int fsr, struct pt_regs *regs)
 {
-       return 0;
+       unsigned long pc = instruction_pointer(regs);
+       unsigned long instr = *(unsigned long *)pc;
+       int reg = (instr >> 12) & 15;
+
+       /*
+        * If the instruction being executed was a read,
+        * make it look like it read all-ones.
+        */
+       if ((instr & 0x0c100000) == 0x04100000) {
+               unsigned long val;
+
+               if (instr & 0x00400000)
+                       val = 255;
+               else
+                       val = -1;
+
+               regs->uregs[reg] = val;
+               regs->ARM_pc += 4;
+               return 0;
+       }
+
+       if ((instr & 0x0e100090) == 0x00100090) {
+               regs->uregs[reg] = -1;
+               regs->ARM_pc += 4;
+               return 0;
+       }
+
+       return 1;
 }
 
 static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
@@ -819,8 +846,8 @@ static int __init imx6_pcie_init(void)
         * we can install the handler here without risking it
         * accessing some uninitialized driver state.
         */
-       hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
-                       "imprecise external abort");
+       hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0,
+                       "external abort on non-linefetch");
 
        return platform_driver_register(&imx6_pcie_driver);
 }
index c23f146..c09623c 100644 (file)
@@ -6,6 +6,7 @@ menu "PCI Endpoint"
 
 config PCI_ENDPOINT
        bool "PCI Endpoint Support"
+       depends on HAS_DMA
        help
           Enable this configuration option to support configurable PCI
           endpoint. This should be enabled if the platform has a PCI
index 192e7b6..b399fa3 100644 (file)
@@ -964,6 +964,7 @@ static int pci_pm_thaw_noirq(struct device *dev)
                return pci_legacy_resume_early(dev);
 
        pci_update_current_state(pci_dev, PCI_D0);
+       pci_restore_state(pci_dev);
 
        if (drv && drv->pm && drv->pm->thaw_noirq)
                error = drv->pm->thaw_noirq(dev);
index 7c4e1aa..59f29e3 100644 (file)
@@ -1960,12 +1960,13 @@ EXPORT_SYMBOL(pci_wake_from_d3);
 /**
  * pci_target_state - find an appropriate low power state for a given PCI dev
  * @dev: PCI device
+ * @wakeup: Whether or not wakeup functionality will be enabled for the device.
  *
  * Use underlying platform code to find a supported low power state for @dev.
  * If the platform can't manage @dev, return the deepest state from which it
  * can generate wake events, based on any available PME info.
  */
-static pci_power_t pci_target_state(struct pci_dev *dev)
+static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
 {
        pci_power_t target_state = PCI_D3hot;
 
@@ -2002,7 +2003,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev)
        if (dev->current_state == PCI_D3cold)
                target_state = PCI_D3cold;
 
-       if (device_may_wakeup(&dev->dev)) {
+       if (wakeup) {
                /*
                 * Find the deepest state from which the device can generate
                 * wake-up events, make it the target state and enable device
@@ -2028,13 +2029,14 @@ static pci_power_t pci_target_state(struct pci_dev *dev)
  */
 int pci_prepare_to_sleep(struct pci_dev *dev)
 {
-       pci_power_t target_state = pci_target_state(dev);
+       bool wakeup = device_may_wakeup(&dev->dev);
+       pci_power_t target_state = pci_target_state(dev, wakeup);
        int error;
 
        if (target_state == PCI_POWER_ERROR)
                return -EIO;
 
-       pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
+       pci_enable_wake(dev, target_state, wakeup);
 
        error = pci_set_power_state(dev, target_state);
 
@@ -2067,9 +2069,10 @@ EXPORT_SYMBOL(pci_back_from_sleep);
  */
 int pci_finish_runtime_suspend(struct pci_dev *dev)
 {
-       pci_power_t target_state = pci_target_state(dev);
+       pci_power_t target_state;
        int error;
 
+       target_state = pci_target_state(dev, device_can_wakeup(&dev->dev));
        if (target_state == PCI_POWER_ERROR)
                return -EIO;
 
@@ -2105,8 +2108,8 @@ bool pci_dev_run_wake(struct pci_dev *dev)
        if (!dev->pme_support)
                return false;
 
-       /* PME-capable in principle, but not from the intended sleep state */
-       if (!pci_pme_capable(dev, pci_target_state(dev)))
+       /* PME-capable in principle, but not from the target power state */
+       if (!pci_pme_capable(dev, pci_target_state(dev, false)))
                return false;
 
        while (bus->parent) {
@@ -2141,10 +2144,12 @@ EXPORT_SYMBOL_GPL(pci_dev_run_wake);
 bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
 {
        struct device *dev = &pci_dev->dev;
+       bool wakeup = device_may_wakeup(dev);
 
        if (!pm_runtime_suspended(dev)
-           || pci_target_state(pci_dev) != pci_dev->current_state
-           || platform_pci_need_resume(pci_dev))
+           || pci_target_state(pci_dev, wakeup) != pci_dev->current_state
+           || platform_pci_need_resume(pci_dev)
+           || (pci_dev->dev_flags & PCI_DEV_FLAGS_NEEDS_RESUME))
                return false;
 
        /*
@@ -2160,7 +2165,7 @@ bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
        spin_lock_irq(&dev->power.lock);
 
        if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold &&
-           !device_may_wakeup(dev))
+           !wakeup)
                __pci_pme_active(pci_dev, false);
 
        spin_unlock_irq(&dev->power.lock);
index 16e6cd8..e1deb79 100644 (file)
@@ -1684,6 +1684,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,     0x2609, quirk_intel_pcie_pm);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   0x260a, quirk_intel_pcie_pm);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   0x260b, quirk_intel_pcie_pm);
 
+static void quirk_radeon_pm(struct pci_dev *dev)
+{
+       if (dev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+           dev->subsystem_device == 0x00e2) {
+               if (dev->d3_delay < 20) {
+                       dev->d3_delay = 20;
+                       dev_info(&dev->dev, "extending delay after power-on from D3 to %d msec\n",
+                                dev->d3_delay);
+               }
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6741, quirk_radeon_pm);
+
 #ifdef CONFIG_X86_IO_APIC
 static int dmi_disable_ioapicreroute(const struct dmi_system_id *d)
 {
index cc6e085..f6a6340 100644 (file)
@@ -1291,7 +1291,6 @@ static struct switchtec_dev *stdev_create(struct pci_dev *pdev)
        cdev = &stdev->cdev;
        cdev_init(cdev, &switchtec_fops);
        cdev->owner = THIS_MODULE;
-       cdev->kobj.parent = &dev->kobj;
 
        return stdev;
 
@@ -1442,12 +1441,15 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,
        stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
        stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
        stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_OFFSET;
-       stdev->partition = ioread8(&stdev->mmio_ntb->partition_id);
+       stdev->partition = ioread8(&stdev->mmio_sys_info->partition_id);
        stdev->partition_count = ioread8(&stdev->mmio_ntb->partition_count);
        stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET;
        stdev->mmio_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition];
        stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET;
 
+       if (stdev->partition_count < 1)
+               stdev->partition_count = 1;
+
        init_pff(stdev);
 
        pci_set_drvdata(pdev, stdev);
@@ -1479,11 +1481,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
                  SWITCHTEC_EVENT_EN_IRQ,
                  &stdev->mmio_part_cfg->mrpc_comp_hdr);
 
-       rc = cdev_add(&stdev->cdev, stdev->dev.devt, 1);
-       if (rc)
-               goto err_put;
-
-       rc = device_add(&stdev->dev);
+       rc = cdev_device_add(&stdev->cdev, &stdev->dev);
        if (rc)
                goto err_devadd;
 
@@ -1492,7 +1490,6 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
        return 0;
 
 err_devadd:
-       cdev_del(&stdev->cdev);
        stdev_kill(stdev);
 err_put:
        ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
@@ -1506,8 +1503,7 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
 
        pci_set_drvdata(pdev, NULL);
 
-       device_del(&stdev->dev);
-       cdev_del(&stdev->cdev);
+       cdev_device_del(&stdev->cdev, &stdev->dev);
        ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
        dev_info(&stdev->dev, "unregistered.\n");
 
index 4f0613d..a8acc5e 100644 (file)
@@ -183,6 +183,11 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9),
        /* Do not use FLR even if device advertises PCI_AF_CAP */
        PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10),
+       /*
+        * Resume before calling the driver's system suspend hooks, disabling
+        * the direct_complete optimization.
+        */
+       PCI_DEV_FLAGS_NEEDS_RESUME = (__force pci_dev_flags_t) (1 << 11),
 };
 
 enum pci_irq_reroute_variant {