From patchwork Wed Mar 14 11:41:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 10281919 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A3A9D602BD for ; Wed, 14 Mar 2018 11:41:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 91A2228831 for ; Wed, 14 Mar 2018 11:41:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8688528848; Wed, 14 Mar 2018 11:41:33 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 3ABCC2884B for ; Wed, 14 Mar 2018 11:41:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750855AbeCNLla (ORCPT ); Wed, 14 Mar 2018 07:41:30 -0400 Received: from mga18.intel.com ([134.134.136.126]:55530 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750964AbeCNLl3 (ORCPT ); Wed, 14 Mar 2018 07:41:29 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Mar 2018 04:41:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,470,1515484800"; d="scan'208";a="182647489" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga004.jf.intel.com with ESMTP; 14 Mar 2018 04:41:27 -0700 Received: by black.fi.intel.com (Postfix, from userid 1001) id 31235190; Wed, 14 Mar 2018 13:41:25 +0200 (EET) From: Mika Westerberg To: Bjorn Helgaas , "Rafael J . Wysocki" Cc: Len Brown , Keith Busch , Mika Westerberg , linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH 1/2] PCI/DPC: Disable interrupt generation during suspend Date: Wed, 14 Mar 2018 14:41:24 +0300 Message-Id: <20180314114125.71132-1-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.16.1 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When system is resumed if the interrupt generation is enabled it may trigger immediately when interrupts are enabled depending on what is in the status register. This may generate spurious DPC conditions and unnecessary removal of devices. Make this work better with system suspend and disable interrupt generation when the system is suspended. Signed-off-by: Mika Westerberg --- drivers/pci/pcie/pcie-dpc.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pcie/pcie-dpc.c b/drivers/pci/pcie/pcie-dpc.c index 38e40c6c576f..14b96983dbbd 100644 --- a/drivers/pci/pcie/pcie-dpc.c +++ b/drivers/pci/pcie/pcie-dpc.c @@ -280,23 +280,44 @@ static int dpc_probe(struct pcie_device *dev) return status; } -static void dpc_remove(struct pcie_device *dev) +static void dpc_interrupt_enable(struct dpc_dev *dpc, bool enable) { - struct dpc_dev *dpc = get_service_data(dev); - struct pci_dev *pdev = dev->port; + struct pci_dev *pdev = dpc->dev->port; u16 ctl; pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, &ctl); - ctl &= ~(PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN); + if (enable) + ctl |= PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN; + else + ctl &= ~(PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN); pci_write_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, ctl); } +static void dpc_remove(struct pcie_device *dev) +{ + dpc_interrupt_enable(get_service_data(dev), false); +} + +static int dpc_suspend(struct pcie_device *dev) +{ + dpc_interrupt_enable(get_service_data(dev), false); + return 0; +} + +static int dpc_resume(struct pcie_device *dev) +{ + dpc_interrupt_enable(get_service_data(dev), true); + return 0; +} + static struct pcie_port_service_driver dpcdriver = { .name = "dpc", .port_type = PCIE_ANY_PORT, .service = PCIE_PORT_SERVICE_DPC, .probe = dpc_probe, .remove = dpc_remove, + .suspend = dpc_suspend, + .resume = dpc_resume, }; static int __init dpc_service_init(void)