From patchwork Wed Jun 20 21:38:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 932401 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 419ymY2XXLz9s3C for ; Thu, 21 Jun 2018 07:35:25 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933370AbeFTVfX (ORCPT ); Wed, 20 Jun 2018 17:35:23 -0400 Received: from mga03.intel.com ([134.134.136.65]:20584 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933285AbeFTVfW (ORCPT ); Wed, 20 Jun 2018 17:35:22 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2018 14:35:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,249,1526367600"; d="scan'208";a="238905907" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2018 14:35:21 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Sinan Kaya , Oza Pawandeep , Keith Busch Subject: [PATCH 1/7] PCI/DPC: Leave interrupts enabled while handling event Date: Wed, 20 Jun 2018 15:38:27 -0600 Message-Id: <20180620213833.25072-1-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Now that the DPC driver clears the interrupt status before exiting the irq handler, we don't need to abuse the DPC control register to know if a shared interrupt is for a new DPC event: a DPC port can not trigger a second interrupt until the host clears the trigger status later in the work queue handler. Signed-off-by: Keith Busch Reviewed-by: Sinan Kaya Reviewed-by: Oza Pawandeep --- drivers/pci/pcie/dpc.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 921ed979109d..972aac892846 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -77,7 +77,7 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) struct dpc_dev *dpc; struct pcie_device *pciedev; struct device *devdpc; - u16 cap, ctl; + u16 cap; /* * DPC disables the Link automatically in hardware, so it has @@ -105,10 +105,6 @@ 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); - pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl); - pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL, - ctl | PCI_EXP_DPC_CTL_INT_EN); - return PCI_ERS_RESULT_RECOVERED; } @@ -183,16 +179,11 @@ static irqreturn_t dpc_irq(int irq, void *context) struct dpc_dev *dpc = (struct dpc_dev *)context; struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; - u16 cap = dpc->cap_pos, ctl, status, source, reason, ext_reason; - - pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl); - - if (!(ctl & PCI_EXP_DPC_CTL_INT_EN) || ctl == (u16)(~0)) - return IRQ_NONE; + u16 cap = dpc->cap_pos, status, source, reason, ext_reason; pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); - if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT)) + if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0)) return IRQ_NONE; if (!(status & PCI_EXP_DPC_STATUS_TRIGGER)) { @@ -201,9 +192,6 @@ static irqreturn_t dpc_irq(int irq, void *context) return IRQ_HANDLED; } - pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL, - ctl & ~PCI_EXP_DPC_CTL_INT_EN); - pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, &source); @@ -226,9 +214,8 @@ static irqreturn_t dpc_irq(int irq, void *context) pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_INTERRUPT); - - schedule_work(&dpc->work); - + if (status & PCI_EXP_DPC_STATUS_TRIGGER) + schedule_work(&dpc->work); return IRQ_HANDLED; } From patchwork Wed Jun 20 21:38:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 932402 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 419ymZ0jzMz9s3R for ; Thu, 21 Jun 2018 07:35:26 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933437AbeFTVfX (ORCPT ); Wed, 20 Jun 2018 17:35:23 -0400 Received: from mga03.intel.com ([134.134.136.65]:20584 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933326AbeFTVfX (ORCPT ); Wed, 20 Jun 2018 17:35:23 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2018 14:35:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,249,1526367600"; d="scan'208";a="238905910" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2018 14:35:21 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Sinan Kaya , Oza Pawandeep , Keith Busch Subject: [PATCH 2/7] PCI/DPC: Defer event handling to work queue Date: Wed, 20 Jun 2018 15:38:28 -0600 Message-Id: <20180620213833.25072-2-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180620213833.25072-1-keith.busch@intel.com> References: <20180620213833.25072-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 moves all event handling to the existing work queue, which will make passing event information simpler to the handler. Signed-off-by: Keith Busch --- drivers/pci/pcie/dpc.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 972aac892846..5f5fac279c75 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -108,14 +108,6 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) return PCI_ERS_RESULT_RECOVERED; } -static void dpc_work(struct work_struct *work) -{ - struct dpc_dev *dpc = container_of(work, struct dpc_dev, work); - struct pci_dev *pdev = dpc->dev->port; - - /* We configure DPC so it only triggers on ERR_FATAL */ - pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC); -} static void dpc_process_rp_pio_error(struct dpc_dev *dpc) { @@ -174,33 +166,21 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) } } -static irqreturn_t dpc_irq(int irq, void *context) +static void dpc_work(struct work_struct *work) { - struct dpc_dev *dpc = (struct dpc_dev *)context; + struct dpc_dev *dpc = container_of(work, struct dpc_dev, work); struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; u16 cap = dpc->cap_pos, status, source, reason, ext_reason; pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); - - if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0)) - return IRQ_NONE; - - if (!(status & PCI_EXP_DPC_STATUS_TRIGGER)) { - pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, - PCI_EXP_DPC_STATUS_INTERRUPT); - return IRQ_HANDLED; - } - - pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, - &source); + pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, &source); dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n", - status, source); + status, source); reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1; ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5; - dev_warn(dev, "DPC %s detected, remove downstream devices\n", (reason == 0) ? "unmasked uncorrectable error" : (reason == 1) ? "ERR_NONFATAL" : @@ -208,10 +188,26 @@ static irqreturn_t dpc_irq(int irq, void *context) (ext_reason == 0) ? "RP PIO error" : (ext_reason == 1) ? "software trigger" : "reserved error"); + /* show RP PIO error detail information */ if (dpc->rp_extensions && reason == 3 && ext_reason == 0) dpc_process_rp_pio_error(dpc); + /* We configure DPC so it only triggers on ERR_FATAL */ + pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC); +} + +static irqreturn_t dpc_irq(int irq, void *context) +{ + struct dpc_dev *dpc = (struct dpc_dev *)context; + struct pci_dev *pdev = dpc->dev->port; + u16 cap = dpc->cap_pos, status; + + pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); + + if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0)) + return IRQ_NONE; + pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_INTERRUPT); if (status & PCI_EXP_DPC_STATUS_TRIGGER) From patchwork Wed Jun 20 21:38:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 932406 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 419yms0nG2z9s3R for ; Thu, 21 Jun 2018 07:35:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933433AbeFTVfi (ORCPT ); Wed, 20 Jun 2018 17:35:38 -0400 Received: from mga03.intel.com ([134.134.136.65]:20584 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933422AbeFTVfX (ORCPT ); Wed, 20 Jun 2018 17:35:23 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2018 14:35:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,249,1526367600"; d="scan'208";a="238905913" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2018 14:35:22 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Sinan Kaya , Oza Pawandeep , Keith Busch Subject: [PATCH 3/7] PCI/DPC: Remove rp_pio_status from dpc struct Date: Wed, 20 Jun 2018 15:38:29 -0600 Message-Id: <20180620213833.25072-3-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180620213833.25072-1-keith.busch@intel.com> References: <20180620213833.25072-1-keith.busch@intel.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org We don't need to save the rp pio status across multiple contexts as all DPC event handling occurs in a single work queue context. Signed-off-by: Keith Busch --- drivers/pci/pcie/dpc.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 5f5fac279c75..1b0b25ba947c 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -19,7 +19,6 @@ struct dpc_dev { struct work_struct work; u16 cap_pos; bool rp_extensions; - u32 rp_pio_status; u8 rp_log_size; }; @@ -96,11 +95,6 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) if (dpc->rp_extensions && dpc_wait_rp_inactive(dpc)) return PCI_ERS_RESULT_DISCONNECT; - if (dpc->rp_extensions && dpc->rp_pio_status) { - pci_write_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, - dpc->rp_pio_status); - dpc->rp_pio_status = 0; - } pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER); @@ -122,8 +116,6 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) dev_err(dev, "rp_pio_status: %#010x, rp_pio_mask: %#010x\n", status, mask); - dpc->rp_pio_status = status; - pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_SEVERITY, &sev); pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_SYSERROR, &syserr); pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_EXCEPTION, &exc); @@ -134,15 +126,14 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &dpc_status); first_error = (dpc_status & 0x1f00) >> 8; - status &= ~mask; for (i = 0; i < ARRAY_SIZE(rp_pio_error_string); i++) { - if (status & (1 << i)) + if ((status & ~mask) & (1 << i)) dev_err(dev, "[%2d] %s%s\n", i, rp_pio_error_string[i], first_error == i ? " (First)" : ""); } if (dpc->rp_log_size < 4) - return; + goto clear_status; pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG, &dw0); pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 4, @@ -155,7 +146,7 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) dw0, dw1, dw2, dw3); if (dpc->rp_log_size < 5) - return; + goto clear_status; pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_IMPSPEC_LOG, &log); dev_err(dev, "RP PIO ImpSpec Log %#010x\n", log); @@ -164,6 +155,8 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG, &prefix); dev_err(dev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix); } + clear_status: + pci_write_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, status); } static void dpc_work(struct work_struct *work) From patchwork Wed Jun 20 21:38:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 932407 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 419yms641Wz9s3C for ; Thu, 21 Jun 2018 07:35:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933326AbeFTVfi (ORCPT ); Wed, 20 Jun 2018 17:35:38 -0400 Received: from mga03.intel.com ([134.134.136.65]:20585 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933433AbeFTVfX (ORCPT ); Wed, 20 Jun 2018 17:35:23 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2018 14:35:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,249,1526367600"; d="scan'208";a="238905916" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2018 14:35:22 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Sinan Kaya , Oza Pawandeep , Keith Busch Subject: [PATCH 4/7] PCI/AER: API for obtaining AER information Date: Wed, 20 Jun 2018 15:38:30 -0600 Message-Id: <20180620213833.25072-4-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180620213833.25072-1-keith.busch@intel.com> References: <20180620213833.25072-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 exports some commone AER functions and structures for other drivers to use. Since this is making the function externally visible, appending "aer_" prefix to the function name. Signed-off-by: Keith Busch --- drivers/pci/pcie/aer.c | 30 +++++------------------------- include/linux/aer.h | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index a2e88386af28..0a60275f0582 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -31,26 +31,6 @@ #include "portdrv.h" #define AER_ERROR_SOURCES_MAX 100 -#define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */ - -struct aer_err_info { - struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES]; - int error_dev_num; - - unsigned int id:16; - - unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */ - unsigned int __pad1:5; - unsigned int multi_error_valid:1; - - unsigned int first_error:5; - unsigned int __pad2:2; - unsigned int tlp_header_valid:1; - - unsigned int status; /* COR/UNCOR Error Status */ - unsigned int mask; /* COR/UNCOR Error Mask */ - struct aer_header_log_regs tlp; /* TLP Header */ -}; struct aer_err_source { unsigned int status; @@ -547,7 +527,7 @@ static void __aer_print_error(struct pci_dev *dev, } } -static void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) +void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) { int layer, agent; int id = ((dev->bus->number << 8) | dev->devfn); @@ -876,7 +856,7 @@ EXPORT_SYMBOL_GPL(aer_recover_queue); #endif /** - * get_device_error_info - read error status from dev and store it to info + * aer_get_device_error_info - read error status from dev and store it to info * @dev: pointer to the device expected to have a error record * @info: pointer to structure to store the error record * @@ -884,7 +864,7 @@ EXPORT_SYMBOL_GPL(aer_recover_queue); * * Note that @info is reused among all error devices. Clear fields properly. */ -static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) +int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) { int pos, temp; @@ -942,11 +922,11 @@ static inline void aer_process_err_devices(struct aer_err_info *e_info) /* Report all before handle them, not to lost records by reset etc. */ for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { - if (get_device_error_info(e_info->dev[i], e_info)) + if (aer_get_device_error_info(e_info->dev[i], e_info)) aer_print_error(e_info->dev[i], e_info); } for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { - if (get_device_error_info(e_info->dev[i], e_info)) + if (aer_get_device_error_info(e_info->dev[i], e_info)) handle_error_source(e_info->dev[i], e_info); } } diff --git a/include/linux/aer.h b/include/linux/aer.h index 514bffa11dbb..58fa04cc7407 100644 --- a/include/linux/aer.h +++ b/include/linux/aer.h @@ -40,6 +40,27 @@ struct aer_capability_regs { u16 uncor_err_source; }; +#define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */ + +struct aer_err_info { + struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES]; + int error_dev_num; + + unsigned int id:16; + + unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */ + unsigned int __pad1:5; + unsigned int multi_error_valid:1; + + unsigned int first_error:5; + unsigned int __pad2:2; + unsigned int tlp_header_valid:1; + + unsigned int status; /* COR/UNCOR Error Status */ + unsigned int mask; /* COR/UNCOR Error Mask */ + struct aer_header_log_regs tlp; /* TLP Header */ +}; + #if defined(CONFIG_PCIEAER) /* PCIe port driver needs this function to enable AER */ int pci_enable_pcie_error_reporting(struct pci_dev *dev); @@ -65,6 +86,9 @@ static inline int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) } #endif +int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info); +void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); + void cper_print_aer(struct pci_dev *dev, int aer_severity, struct aer_capability_regs *aer); int cper_severity_to_aer(int cper_severity); From patchwork Wed Jun 20 21:38:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 932405 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 419ymr2m6wz9s3C for ; Thu, 21 Jun 2018 07:35:40 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933451AbeFTVfi (ORCPT ); Wed, 20 Jun 2018 17:35:38 -0400 Received: from mga03.intel.com ([134.134.136.65]:20584 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933326AbeFTVfY (ORCPT ); Wed, 20 Jun 2018 17:35:24 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2018 14:35:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,249,1526367600"; d="scan'208";a="238905921" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2018 14:35:22 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Sinan Kaya , Oza Pawandeep , Keith Busch Subject: [PATCH 5/7] PCI/DPC: Print AER status in DPC event handling Date: Wed, 20 Jun 2018 15:38:31 -0600 Message-Id: <20180620213833.25072-5-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180620213833.25072-1-keith.busch@intel.com> References: <20180620213833.25072-1-keith.busch@intel.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org A DPC enabled device suppresses ERR_(NON)FATAL messages, preventing the AER handler from reporting error details. If the DPC trigger reason says the downstream port detected the error, this patch has the DPC driver collect the AER uncorrectable status for logging, then clears the status. Signed-off-by: Keith Busch --- drivers/pci/pcie/dpc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 1b0b25ba947c..f6098dd171f3 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -6,6 +6,7 @@ * Copyright (C) 2016 Intel Corp. */ +#include #include #include #include @@ -161,6 +162,7 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) static void dpc_work(struct work_struct *work) { + struct aer_err_info info; struct dpc_dev *dpc = container_of(work, struct dpc_dev, work); struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; @@ -185,6 +187,10 @@ static void dpc_work(struct work_struct *work) /* show RP PIO error detail information */ if (dpc->rp_extensions && reason == 3 && ext_reason == 0) dpc_process_rp_pio_error(dpc); + else if (reason == 0 && aer_get_device_error_info(pdev, &info)) { + aer_print_error(pdev, &info); + pci_cleanup_aer_uncorrect_error_status(pdev); + } /* We configure DPC so it only triggers on ERR_FATAL */ pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC); From patchwork Wed Jun 20 21:38:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 932404 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 419ymn5RJ2z9s3R for ; Thu, 21 Jun 2018 07:35:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933402AbeFTVff (ORCPT ); Wed, 20 Jun 2018 17:35:35 -0400 Received: from mga03.intel.com ([134.134.136.65]:20585 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933451AbeFTVfY (ORCPT ); Wed, 20 Jun 2018 17:35:24 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2018 14:35:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,249,1526367600"; d="scan'208";a="238905927" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2018 14:35:23 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Sinan Kaya , Oza Pawandeep , Keith Busch Subject: [PATCH 6/7] PCI/DPC: Use threaded IRQ for bottom half handling Date: Wed, 20 Jun 2018 15:38:32 -0600 Message-Id: <20180620213833.25072-6-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180620213833.25072-1-keith.busch@intel.com> References: <20180620213833.25072-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 removes the work struct that was being used to handle a DPC event and uses a threaded IRQ instead for the purpose. Signed-off-by: Keith Busch --- drivers/pci/pcie/dpc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index f6098dd171f3..348b59954961 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -17,7 +17,6 @@ struct dpc_dev { struct pcie_device *dev; - struct work_struct work; u16 cap_pos; bool rp_extensions; u8 rp_log_size; @@ -160,10 +159,10 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) pci_write_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, status); } -static void dpc_work(struct work_struct *work) +static irqreturn_t dpc_handler(int irq, void *context) { struct aer_err_info info; - struct dpc_dev *dpc = container_of(work, struct dpc_dev, work); + struct dpc_dev *dpc = (struct dpc_dev *)context; struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; u16 cap = dpc->cap_pos, status, source, reason, ext_reason; @@ -194,6 +193,8 @@ static void dpc_work(struct work_struct *work) /* We configure DPC so it only triggers on ERR_FATAL */ pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC); + + return IRQ_HANDLED; } static irqreturn_t dpc_irq(int irq, void *context) @@ -210,7 +211,7 @@ 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) - schedule_work(&dpc->work); + return IRQ_WAKE_THREAD; return IRQ_HANDLED; } @@ -232,11 +233,11 @@ static int dpc_probe(struct pcie_device *dev) dpc->cap_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DPC); dpc->dev = dev; - INIT_WORK(&dpc->work, dpc_work); set_service_data(dev, dpc); - status = devm_request_irq(device, dev->irq, dpc_irq, IRQF_SHARED, - "pcie-dpc", dpc); + status = devm_request_threaded_irq(device, dev->irq, dpc_irq, + dpc_handler, IRQF_SHARED, + "pcie-dpc", dpc); if (status) { dev_warn(device, "request IRQ%d failed: %d\n", dev->irq, status); From patchwork Wed Jun 20 21:38:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 932403 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 419ymm5K57z9s3C for ; Thu, 21 Jun 2018 07:35:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933285AbeFTVfd (ORCPT ); Wed, 20 Jun 2018 17:35:33 -0400 Received: from mga03.intel.com ([134.134.136.65]:20584 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933459AbeFTVfY (ORCPT ); Wed, 20 Jun 2018 17:35:24 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2018 14:35:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,249,1526367600"; d="scan'208";a="238905932" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.44]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2018 14:35:23 -0700 From: Keith Busch To: Linux PCI , Bjorn Helgaas Cc: Sinan Kaya , Oza Pawandeep , Keith Busch Subject: [PATCH 7/7] PCI/DPC: Remove indirection waiting for inactive link Date: Wed, 20 Jun 2018 15:38:33 -0600 Message-Id: <20180620213833.25072-7-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180620213833.25072-1-keith.busch@intel.com> References: <20180620213833.25072-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 just simplifies waiting for the contained link to become inactive, removing the indirection to a unnecessary DPC specific handler. Signed-off-by: Keith Busch --- drivers/pci/pcie/dpc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 348b59954961..921e68c461bd 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -64,18 +64,12 @@ static int dpc_wait_rp_inactive(struct dpc_dev *dpc) return 0; } -static void dpc_wait_link_inactive(struct dpc_dev *dpc) -{ - struct pci_dev *pdev = dpc->dev->port; - - pcie_wait_for_link(pdev, false); -} - static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) { struct dpc_dev *dpc; struct pcie_device *pciedev; struct device *devdpc; + u16 cap; /* @@ -91,7 +85,7 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) * Wait until the Link is inactive, then clear DPC Trigger Status * to allow the Port to leave DPC. */ - dpc_wait_link_inactive(dpc); + pcie_wait_for_link(pdev, false); if (dpc->rp_extensions && dpc_wait_rp_inactive(dpc)) return PCI_ERS_RESULT_DISCONNECT;