From patchwork Sat Sep 15 03:05:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 1461301 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 009BE40220 for ; Sat, 15 Sep 2012 03:14:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756832Ab2IODN5 (ORCPT ); Fri, 14 Sep 2012 23:13:57 -0400 Received: from mail-pb0-f46.google.com ([209.85.160.46]:33180 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751424Ab2IODNz (ORCPT ); Fri, 14 Sep 2012 23:13:55 -0400 Received: by mail-pb0-f46.google.com with SMTP id rr13so6509443pbb.19 for ; Fri, 14 Sep 2012 20:13:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=2hw+3/rgpVKJaSwmGElSqRdRshsrtXaEiphCx3Omamk=; b=xYXLLriz/8c1U8iWCcTWX9ZuUIhfKK/HD4c/V7pbvY612ZRjbG5JKgkM4si6GhH0uj /6us70WqnJqq7faUw9iGrUSom9JQiNxC1A180neLRSRKa2ut4V6W3tPdu828HXbtsaK8 nKzC9RxLSss5ME2URMp9Cfy6mRZ0TUAsgcXgLQHA2mtFjmRet2XGJpjq+CYnJljPSZtf Brs1OGuC3UVlRc3U6SGYHoyWaipbAZheIsSzAOdn8X1ON4yHEidN+BOD2VkQvlw8btbJ xvYkZmnG9SLjynJsa2MUWKN5k1jFltpQeE9xQU/YDEY0/oVgHS3aONbySFbWJathFWuL X2XA== Received: by 10.68.138.169 with SMTP id qr9mr8203270pbb.27.1347678834849; Fri, 14 Sep 2012 20:13:54 -0700 (PDT) Received: from localhost.localdomain ([221.221.18.122]) by mx.google.com with ESMTPS id jz10sm2092777pbc.8.2012.09.14.20.13.47 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 14 Sep 2012 20:13:54 -0700 (PDT) From: Jiang Liu To: Bjorn Helgaas Cc: Tony Luck , Yijing Wang , Yinghai Lu , Kenji Kaneshige , Jiang Liu , linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, Jiang Liu Subject: [PATCH v2 9/9] PCI/AER: update AER configuration when PCI hotplug event happens Date: Sat, 15 Sep 2012 11:05:12 +0800 Message-Id: <1347678312-11124-10-git-send-email-jiang.liu@huawei.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1347678312-11124-1-git-send-email-jiang.liu@huawei.com> References: <1347678312-11124-1-git-send-email-jiang.liu@huawei.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Yijing Wang The AER driver only configures downstream PCIe devices at driver binding time and all hot-added PCIe devices won't be managed by the AER driver. So hook PCIe device hotplug events to setup AER configuration for hot-added PCIe devices. Signed-off-by: Yijing Wang Signed-off-by: Jiang Liu --- drivers/pci/pcie/aer/aerdrv.c | 63 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 030cf12..b70ec84 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -408,6 +408,55 @@ static void aer_error_resume(struct pci_dev *dev) pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); } +static void acpi_pcie_aer_notify_dev(struct pcie_device *dev, bool enable) +{ + int rc, pos; + u32 val = 0; + struct pci_dev *pdev = dev->port; + + if (dev->service != PCIE_PORT_SERVICE_AER) + return; + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) + return; + while (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) { + pdev = pdev->bus->self; + if (!pdev) + return; + } + + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); + if (!pos) + return; + rc = pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &val); + if (rc || val == 0xFFFFFFFF || !(val & ROOT_PORT_INTR_ON_MESG_MASK)) + return; + + set_device_error_reporting(dev->port, &enable); +} + +static int acpi_pcie_aer_notify(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct device *dev = data; + + switch (event) { + case BUS_NOTIFY_ADD_DEVICE: + acpi_pcie_aer_notify_dev(to_pcie_device(dev), true); + break; + case BUS_NOTIFY_DEL_DEVICE: + acpi_pcie_aer_notify_dev(to_pcie_device(dev), false); + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static struct notifier_block acpi_pcie_aer_notifier = { + .notifier_call = &acpi_pcie_aer_notify, +}; + /** * aer_service_init - register AER root service driver * @@ -415,9 +464,20 @@ static void aer_error_resume(struct pci_dev *dev) */ static int __init aer_service_init(void) { + int ret; + if (!pci_aer_available() || aer_acpi_firmware_first()) return -ENXIO; - return pcie_port_service_register(&aerdriver); + + ret = pcie_port_service_register(&aerdriver); + if (!ret) { + ret = bus_register_notifier(&pcie_port_bus_type, + &acpi_pcie_aer_notifier); + if (ret) + pcie_port_service_unregister(&aerdriver); + } + + return ret; } /** @@ -427,6 +487,7 @@ static int __init aer_service_init(void) */ static void __exit aer_service_exit(void) { + bus_unregister_notifier(&pcie_port_bus_type, &acpi_pcie_aer_notifier); pcie_port_service_unregister(&aerdriver); }