From patchwork Fri Aug 31 21:26:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 964716 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 422C7z1LsMz9s4V for ; Sat, 1 Sep 2018 07:25:35 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727442AbeIABeu (ORCPT ); Fri, 31 Aug 2018 21:34:50 -0400 Received: from mga12.intel.com ([192.55.52.136]:14103 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727416AbeIABeu (ORCPT ); Fri, 31 Aug 2018 21:34:50 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 31 Aug 2018 14:25:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,313,1531810800"; d="scan'208";a="86663852" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by orsmga001.jf.intel.com with ESMTP; 31 Aug 2018 14:25:30 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Benjamin Herrenschmidt , Sinan Kaya , Thomas Tai , poza@codeaurora.org, Lukas Wunner , Keith Busch Subject: [PATCH 14/16] pciehp: Ignore link events during DPC event Date: Fri, 31 Aug 2018 15:26:37 -0600 Message-Id: <20180831212639.10196-15-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180831212639.10196-1-keith.busch@intel.com> References: <20180831212639.10196-1-keith.busch@intel.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This patch adds a channel state to a subordinate bus. When a DPC event is triggered, the DPC driver will set the channel state to frozen, and the pciehp driver will ignore link events if the subordinate bus is being managed by DPC error handling. This is safe because the pciehp and DPC drivers share the same interrupt. The DPC driver sets the bus state in the top-half interrupt context, and the pciehp driver checks and masks off link events in its bottom-half error handler. Signed-off-by: Keith Busch --- drivers/pci/hotplug/pciehp_hpc.c | 9 +++++++++ drivers/pci/pcie/dpc.c | 8 ++++++-- include/linux/pci.h | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7c43336e08ba..a928dcccf78b 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -643,6 +643,15 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) synchronize_hardirq(irq); events = atomic_xchg(&ctrl->pending_events, 0); + + /* + * Ignore link events on the suborinate bus if error handling is + * active, as link down may be expected. We'll continue to handle + * presence detect changes. + */ + if (pdev->subordinate && pci_bus_offline(pdev->subordinate)) + events &= ~PCI_EXP_SLTSTA_DLLSC; + if (!events) { pci_config_pm_runtime_put(pdev); return IRQ_NONE; diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index eadfd835af13..93ce26191a2b 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -92,7 +92,8 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER); - + if (pdev->subordinate) + pdev->subordinate->error_state = pci_channel_io_normal; return PCI_ERS_RESULT_RECOVERED; } @@ -204,8 +205,11 @@ static irqreturn_t dpc_irq(int irq, void *context) pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_INTERRUPT); - if (status & PCI_EXP_DPC_STATUS_TRIGGER) + if (status & PCI_EXP_DPC_STATUS_TRIGGER) { + if (pdev->subordinate) + pdev->subordinate->error_state = pci_channel_io_frozen; return IRQ_WAKE_THREAD; + } return IRQ_HANDLED; } diff --git a/include/linux/pci.h b/include/linux/pci.h index e72ca8dd6241..a76e10049b08 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -573,9 +573,15 @@ struct pci_bus { struct device dev; struct bin_attribute *legacy_io; /* Legacy I/O for this bus */ struct bin_attribute *legacy_mem; /* Legacy mem */ + pci_channel_state_t error_state; /* Current connectivity state */ unsigned int is_added:1; }; +static inline int pci_bus_offline(struct pci_bus *bus) +{ + return (bus->error_state != pci_channel_io_normal); +} + #define to_pci_bus(n) container_of(n, struct pci_bus, dev) /*