From patchwork Tue Jan 8 16:52:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 1946871 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 3A9B33FED4 for ; Tue, 8 Jan 2013 16:53:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756827Ab3AHQxJ (ORCPT ); Tue, 8 Jan 2013 11:53:09 -0500 Received: from mail-da0-f50.google.com ([209.85.210.50]:36697 "EHLO mail-da0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756808Ab3AHQwy (ORCPT ); Tue, 8 Jan 2013 11:52:54 -0500 Received: by mail-da0-f50.google.com with SMTP id h15so276857dan.37 for ; Tue, 08 Jan 2013 08:52:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:in-reply-to:references; bh=8GxKla6oP8+Kr8cLvHmN5ni/84YqVMwjCiPDBTn4yEk=; b=l9BFBUjK39kEbJ+B7+1D73gObFbsS6KzTIsGM6wrtV+nGnuKALqRSZqMiDX22YYKgm xIjiq+Yx3CCvaDwFqUCu26Yy563w5QjMi3rkfurZzNz7lC0jUcuzNH91dOsHYX3pstwd WktrUv9O1bTLtj72hCn9CElRX0HJP/mz7NzHa7sWDoKK1c9OQLWR6GIbAGPQGtP9aH5u ijgJHBzFhZVG+tEbt/7cfBlgs9d/1u0Fb3k5tADym5Iv9K5hCNao5Qsbx0esBijne0xX FJMFzaEl1Uxe3thr1673GRjYWp3uEsuEfrGtkDkOPXkM1Sl48uW/wtjN5vi/oiJY/Idi BBsg== X-Received: by 10.68.235.2 with SMTP id ui2mr200013663pbc.163.1357663974101; Tue, 08 Jan 2013 08:52:54 -0800 (PST) Received: from localhost.localdomain ([120.196.98.117]) by mx.google.com with ESMTPS id f5sm41038922pav.22.2013.01.08.08.52.51 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 08 Jan 2013 08:52:53 -0800 (PST) From: Jiang Liu To: Bjorn Helgaas Cc: Yijing Wang , "Rafael J . Wysocki" , linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, Jiang Liu Subject: [PATCH v3 6/6] PCI/AER: update AER configuration when PCI hotplug event happens Date: Wed, 9 Jan 2013 00:52:25 +0800 Message-Id: <1357663945-16054-7-git-send-email-jiang.liu@huawei.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1357663945-16054-1-git-send-email-jiang.liu@huawei.com> References: <1357663945-16054-1-git-send-email-jiang.liu@huawei.com> In-Reply-To: References: 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 76ef634..d825c46 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); }