From patchwork Thu Sep 6 15:50:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 10590771 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2F6E1112B for ; Thu, 6 Sep 2018 15:50:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1EDBC2AE7A for ; Thu, 6 Sep 2018 15:50:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1C4832AE9E; Thu, 6 Sep 2018 15:50:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8D4A82AEB8 for ; Thu, 6 Sep 2018 15:50:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730388AbeIFU0z (ORCPT ); Thu, 6 Sep 2018 16:26:55 -0400 Received: from mga01.intel.com ([192.55.52.88]:22811 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730272AbeIFU0z (ORCPT ); Thu, 6 Sep 2018 16:26:55 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Sep 2018 08:50:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,338,1531810800"; d="scan'208";a="86569756" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga004.fm.intel.com with ESMTP; 06 Sep 2018 08:50:25 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 01E1248F; Thu, 6 Sep 2018 18:50:20 +0300 (EEST) From: Mika Westerberg To: Bjorn Helgaas , "Rafael J. Wysocki" Cc: Len Brown , Lukas Wunner , Keith Busch , Ashok Raj , Mario.Limonciello@dell.com, Anthony Wong , "D . J . Bernstein" , Linus Walleij , Mika Westerberg , linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH 05/10] PCI: portdrv: Resume upon exit from system suspend if left runtime suspended Date: Thu, 6 Sep 2018 18:50:15 +0300 Message-Id: <20180906155020.51700-6-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180906155020.51700-1-mika.westerberg@linux.intel.com> References: <20180906155020.51700-1-mika.westerberg@linux.intel.com> Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently we try to keep PCIe ports runtime suspended over system suspend if possible. This mostly happens when entering suspend-to-idle because there is no need to re-configure wake settings. This causes problems if the parent port goes into D3cold and it gets resumed upon exit from system suspend. This may happen for example if the port is part of PCIe switch and the same switch is connected to a PCIe endpoint that needs to be resumed. The way exit from D3cold works according PCIe 4.0 spec 5.3.1.4.2 is that power is restored and cold reset is signaled. After this the device is in D0unitialized state keeping PME context if it supports wake from D3cold. The problem occurs when a PCIe hotplug port is left suspended and the parent port goes into D3cold and back to D0, the port keeps its PME context but since everything else is reset back to defaults (D0unitialized) it is not set to detect hotplug events anymore. For this reason change the PCIe portdrv power management logic so that it is fine to keep the port runtime suspended over system suspend but it needs to be resumed upon exit to make sure it gets properly re-initialized. The custom ->prepare() hook with DPM_FLAG_SMART_PREPARE is needed because otherwise pci_pm_prepare() instructs the PM core to go directly to pci_pm_complete() on resume and this skips resuming the port. Signed-off-by: Mika Westerberg --- drivers/pci/pcie/portdrv_pci.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index eef22dc29140..74761f660a30 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -43,6 +43,21 @@ __setup("pcie_ports=", pcie_port_setup); /* global data */ #ifdef CONFIG_PM +int pcie_port_prepare(struct device *dev) +{ + /* + * Return 0 here to indicate PCI core that: + * - Direct complete path should be avoided + * - It is OK to leave the port runtime suspended over system + * suspend + * + * However, the port needs to be resumed afterwards because it may + * have been in D3cold in which case we need to re-initialize the + * hardware as it is in D0uninitialized in that case. + */ + return 0; +} + static int pcie_port_runtime_suspend(struct device *dev) { return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY; @@ -64,6 +79,7 @@ static int pcie_port_runtime_idle(struct device *dev) } static const struct dev_pm_ops pcie_portdrv_pm_ops = { + .prepare = pcie_port_prepare, .suspend = pcie_port_device_suspend, .resume_noirq = pcie_port_device_resume_noirq, .resume = pcie_port_device_resume, @@ -109,8 +125,8 @@ static int pcie_portdrv_probe(struct pci_dev *dev, pci_save_state(dev); - dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_SMART_SUSPEND | - DPM_FLAG_LEAVE_SUSPENDED); + dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_SMART_PREPARE | + DPM_FLAG_SMART_SUSPEND); if (pci_bridge_d3_possible(dev)) { /*