Commit 2cf816a9 authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/pm' into next

* 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
parents 6a1c1d55 666ff6f8
...@@ -571,3 +571,18 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, pci_invalid_bar); ...@@ -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, 0x6f60, pci_invalid_bar);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, 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); 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);
...@@ -1152,16 +1152,12 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero ...@@ -1152,16 +1152,12 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
return; return;
if (state == VGA_SWITCHEROO_ON) { if (state == VGA_SWITCHEROO_ON) {
unsigned d3_delay = dev->pdev->d3_delay;
pr_info("amdgpu: switched on\n"); pr_info("amdgpu: switched on\n");
/* don't suspend or resume card normally */ /* don't suspend or resume card normally */
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
amdgpu_device_resume(dev, true, true); amdgpu_device_resume(dev, true, true);
dev->pdev->d3_delay = d3_delay;
dev->switch_power_state = DRM_SWITCH_POWER_ON; dev->switch_power_state = DRM_SWITCH_POWER_ON;
drm_kms_helper_poll_enable(dev); drm_kms_helper_poll_enable(dev);
} else { } else {
......
...@@ -113,7 +113,6 @@ static inline bool radeon_is_atpx_hybrid(void) { return false; } ...@@ -113,7 +113,6 @@ static inline bool radeon_is_atpx_hybrid(void) { return false; }
#endif #endif
#define RADEON_PX_QUIRK_DISABLE_PX (1 << 0) #define RADEON_PX_QUIRK_DISABLE_PX (1 << 0)
#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
struct radeon_px_quirk { struct radeon_px_quirk {
u32 chip_vendor; u32 chip_vendor;
...@@ -136,8 +135,6 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = { ...@@ -136,8 +135,6 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {
* https://bugzilla.kernel.org/show_bug.cgi?id=51381 * https://bugzilla.kernel.org/show_bug.cgi?id=51381
*/ */
{ PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, { 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 }, { 0, 0, 0, 0, 0 },
}; };
...@@ -1241,25 +1238,17 @@ static void radeon_check_arguments(struct radeon_device *rdev) ...@@ -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) static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
{ {
struct drm_device *dev = pci_get_drvdata(pdev); struct drm_device *dev = pci_get_drvdata(pdev);
struct radeon_device *rdev = dev->dev_private;
if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
return; return;
if (state == VGA_SWITCHEROO_ON) { if (state == VGA_SWITCHEROO_ON) {
unsigned d3_delay = dev->pdev->d3_delay;
pr_info("radeon: switched on\n"); pr_info("radeon: switched on\n");
/* don't suspend or resume card normally */ /* don't suspend or resume card normally */
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 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); radeon_resume_kms(dev, true, true);
dev->pdev->d3_delay = d3_delay;
dev->switch_power_state = DRM_SWITCH_POWER_ON; dev->switch_power_state = DRM_SWITCH_POWER_ON;
drm_kms_helper_poll_enable(dev); drm_kms_helper_poll_enable(dev);
} else { } else {
......
...@@ -252,7 +252,34 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie) ...@@ -252,7 +252,34 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
static int imx6q_pcie_abort_handler(unsigned long addr, static int imx6q_pcie_abort_handler(unsigned long addr,
unsigned int fsr, struct pt_regs *regs) unsigned int fsr, struct pt_regs *regs)
{ {
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; 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) static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
...@@ -819,8 +846,8 @@ static int __init imx6_pcie_init(void) ...@@ -819,8 +846,8 @@ static int __init imx6_pcie_init(void)
* we can install the handler here without risking it * we can install the handler here without risking it
* accessing some uninitialized driver state. * accessing some uninitialized driver state.
*/ */
hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0,
"imprecise external abort"); "external abort on non-linefetch");
return platform_driver_register(&imx6_pcie_driver); return platform_driver_register(&imx6_pcie_driver);
} }
......
...@@ -6,6 +6,7 @@ menu "PCI Endpoint" ...@@ -6,6 +6,7 @@ menu "PCI Endpoint"
config PCI_ENDPOINT config PCI_ENDPOINT
bool "PCI Endpoint Support" bool "PCI Endpoint Support"
depends on HAS_DMA
help help
Enable this configuration option to support configurable PCI Enable this configuration option to support configurable PCI
endpoint. This should be enabled if the platform has a PCI endpoint. This should be enabled if the platform has a PCI
......
...@@ -964,6 +964,7 @@ static int pci_pm_thaw_noirq(struct device *dev) ...@@ -964,6 +964,7 @@ static int pci_pm_thaw_noirq(struct device *dev)
return pci_legacy_resume_early(dev); return pci_legacy_resume_early(dev);
pci_update_current_state(pci_dev, PCI_D0); pci_update_current_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
if (drv && drv->pm && drv->pm->thaw_noirq) if (drv && drv->pm && drv->pm->thaw_noirq)
error = drv->pm->thaw_noirq(dev); error = drv->pm->thaw_noirq(dev);
......
...@@ -1960,12 +1960,13 @@ EXPORT_SYMBOL(pci_wake_from_d3); ...@@ -1960,12 +1960,13 @@ EXPORT_SYMBOL(pci_wake_from_d3);
/** /**
* pci_target_state - find an appropriate low power state for a given PCI dev * pci_target_state - find an appropriate low power state for a given PCI dev
* @dev: PCI device * @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. * 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 * If the platform can't manage @dev, return the deepest state from which it
* can generate wake events, based on any available PME info. * 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; pci_power_t target_state = PCI_D3hot;
...@@ -2002,7 +2003,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev) ...@@ -2002,7 +2003,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev)
if (dev->current_state == PCI_D3cold) if (dev->current_state == PCI_D3cold)
target_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 * Find the deepest state from which the device can generate
* wake-up events, make it the target state and enable device * 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) ...@@ -2028,13 +2029,14 @@ static pci_power_t pci_target_state(struct pci_dev *dev)
*/ */
int pci_prepare_to_sleep(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; int error;
if (target_state == PCI_POWER_ERROR) if (target_state == PCI_POWER_ERROR)
return -EIO; 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); error = pci_set_power_state(dev, target_state);
...@@ -2067,9 +2069,10 @@ EXPORT_SYMBOL(pci_back_from_sleep); ...@@ -2067,9 +2069,10 @@ EXPORT_SYMBOL(pci_back_from_sleep);
*/ */
int pci_finish_runtime_suspend(struct pci_dev *dev) 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; int error;
target_state = pci_target_state(dev, device_can_wakeup(&dev->dev));
if (target_state == PCI_POWER_ERROR) if (target_state == PCI_POWER_ERROR)
return -EIO; return -EIO;
...@@ -2105,8 +2108,8 @@ bool pci_dev_run_wake(struct pci_dev *dev) ...@@ -2105,8 +2108,8 @@ bool pci_dev_run_wake(struct pci_dev *dev)
if (!dev->pme_support) if (!dev->pme_support)
return false; return false;
/* PME-capable in principle, but not from the intended sleep state */ /* PME-capable in principle, but not from the target power state */
if (!pci_pme_capable(dev, pci_target_state(dev))) if (!pci_pme_capable(dev, pci_target_state(dev, false)))
return false; return false;
while (bus->parent) { while (bus->parent) {
...@@ -2141,10 +2144,12 @@ EXPORT_SYMBOL_GPL(pci_dev_run_wake); ...@@ -2141,10 +2144,12 @@ EXPORT_SYMBOL_GPL(pci_dev_run_wake);
bool pci_dev_keep_suspended(struct pci_dev *pci_dev) bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
{ {
struct device *dev = &pci_dev->dev; struct device *dev = &pci_dev->dev;
bool wakeup = device_may_wakeup(dev);
if (!pm_runtime_suspended(dev) if (!pm_runtime_suspended(dev)
|| pci_target_state(pci_dev) != pci_dev->current_state || pci_target_state(pci_dev, wakeup) != pci_dev->current_state
|| platform_pci_need_resume(pci_dev)) || platform_pci_need_resume(pci_dev)
|| (pci_dev->dev_flags & PCI_DEV_FLAGS_NEEDS_RESUME))
return false; return false;
/* /*
...@@ -2160,7 +2165,7 @@ bool pci_dev_keep_suspended(struct pci_dev *pci_dev) ...@@ -2160,7 +2165,7 @@ bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
spin_lock_irq(&dev->power.lock); spin_lock_irq(&dev->power.lock);
if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold && if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold &&
!device_may_wakeup(dev)) !wakeup)
__pci_pme_active(pci_dev, false); __pci_pme_active(pci_dev, false);
spin_unlock_irq(&dev->power.lock); spin_unlock_irq(&dev->power.lock);
......
...@@ -1684,6 +1684,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); ...@@ -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, 0x260a, quirk_intel_pcie_pm);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, 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 #ifdef CONFIG_X86_IO_APIC
static int dmi_disable_ioapicreroute(const struct dmi_system_id *d) static int dmi_disable_ioapicreroute(const struct dmi_system_id *d)
{ {
......
...@@ -1291,7 +1291,6 @@ static struct switchtec_dev *stdev_create(struct pci_dev *pdev) ...@@ -1291,7 +1291,6 @@ static struct switchtec_dev *stdev_create(struct pci_dev *pdev)
cdev = &stdev->cdev; cdev = &stdev->cdev;
cdev_init(cdev, &switchtec_fops); cdev_init(cdev, &switchtec_fops);
cdev->owner = THIS_MODULE; cdev->owner = THIS_MODULE;
cdev->kobj.parent = &dev->kobj;
return stdev; return stdev;
...@@ -1442,12 +1441,15 @@ static int switchtec_init_pci(struct switchtec_dev *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_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET; stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_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->partition_count = ioread8(&stdev->mmio_ntb->partition_count);
stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET; 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_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition];
stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET; stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET;
if (stdev->partition_count < 1)
stdev->partition_count = 1;
init_pff(stdev); init_pff(stdev);
pci_set_drvdata(pdev, stdev); pci_set_drvdata(pdev, stdev);
...@@ -1479,11 +1481,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev, ...@@ -1479,11 +1481,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
SWITCHTEC_EVENT_EN_IRQ, SWITCHTEC_EVENT_EN_IRQ,
&stdev->mmio_part_cfg->mrpc_comp_hdr); &stdev->mmio_part_cfg->mrpc_comp_hdr);
rc = cdev_add(&stdev->cdev, stdev->dev.devt, 1); rc = cdev_device_add(&stdev->cdev, &stdev->dev);
if (rc)
goto err_put;
rc = device_add(&stdev->dev);
if (rc) if (rc)
goto err_devadd; goto err_devadd;
...@@ -1492,7 +1490,6 @@ static int switchtec_pci_probe(struct pci_dev *pdev, ...@@ -1492,7 +1490,6 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
return 0; return 0;
err_devadd: err_devadd:
cdev_del(&stdev->cdev);
stdev_kill(stdev); stdev_kill(stdev);
err_put: err_put:
ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt)); ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
...@@ -1506,8 +1503,7 @@ static void switchtec_pci_remove(struct pci_dev *pdev) ...@@ -1506,8 +1503,7 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
device_del(&stdev->dev); cdev_device_del(&stdev->cdev, &stdev->dev);
cdev_del(&stdev->cdev);
ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt)); ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
dev_info(&stdev->dev, "unregistered.\n"); dev_info(&stdev->dev, "unregistered.\n");
......
...@@ -183,6 +183,11 @@ enum pci_dev_flags { ...@@ -183,6 +183,11 @@ enum pci_dev_flags {
PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9), PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9),
/* Do not use FLR even if device advertises PCI_AF_CAP */ /* Do not use FLR even if device advertises PCI_AF_CAP */
PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10), 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 { enum pci_irq_reroute_variant {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment