From patchwork Sun Aug 11 02:48:14 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yinghai Lu X-Patchwork-Id: 2842600 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9CA409F271 for ; Sun, 11 Aug 2013 02:50:29 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A20CB20166 for ; Sun, 11 Aug 2013 02:50:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BBDEE2015A for ; Sun, 11 Aug 2013 02:50:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753817Ab3HKCtu (ORCPT ); Sat, 10 Aug 2013 22:49:50 -0400 Received: from userp1040.oracle.com ([156.151.31.81]:25907 "EHLO userp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753662Ab3HKCtp (ORCPT ); Sat, 10 Aug 2013 22:49:45 -0400 Received: from acsinet21.oracle.com (acsinet21.oracle.com [141.146.126.237]) by userp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with ESMTP id r7B2nOWW021873 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sun, 11 Aug 2013 02:49:25 GMT Received: from userz7021.oracle.com (userz7021.oracle.com [156.151.31.85]) by acsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r7B2nNPO002006 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 11 Aug 2013 02:49:24 GMT Received: from abhmt117.oracle.com (abhmt117.oracle.com [141.146.116.69]) by userz7021.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r7B2nMVu012562; Sun, 11 Aug 2013 02:49:22 GMT Received: from linux-siqj.site.site (/75.36.254.102) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sat, 10 Aug 2013 19:49:22 -0700 From: Yinghai Lu To: Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Tony Luck , Bjorn Helgaas , "Rafael J. Wysocki" Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, Yinghai Lu Subject: [PATCH v4 28/28] PCI, x86, ACPI: get ioapic address from acpi device Date: Sat, 10 Aug 2013 19:48:14 -0700 Message-Id: <1376189294-32022-29-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1376189294-32022-1-git-send-email-yinghai@kernel.org> References: <1376189294-32022-1-git-send-email-yinghai@kernel.org> X-Source-IP: acsinet21.oracle.com [141.146.126.237] Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some ioapic controllers do not show up on pci config space, or pci device is there but no bar is used and is set by firmware in other non standard registers. We can get ioapic address from ACPI0009's _CRS. Signed-off-by: Yinghai Lu --- drivers/pci/ioapic.c | 86 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c index 60351b2..41f7c69 100644 --- a/drivers/pci/ioapic.c +++ b/drivers/pci/ioapic.c @@ -32,6 +32,36 @@ struct acpi_pci_ioapic { static LIST_HEAD(ioapic_list); static DEFINE_MUTEX(ioapic_list_lock); +static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) +{ + struct resource *res; + struct acpi_resource_address64 addr; + acpi_status status; + unsigned long flags; + u64 start, end; + + status = acpi_resource_to_address64(acpi_res, &addr); + if (!ACPI_SUCCESS(status)) + return AE_OK; + + if (addr.resource_type == ACPI_MEMORY_RANGE) { + if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY) + return AE_OK; + flags = IORESOURCE_MEM; + } else + return AE_OK; + + start = addr.minimum + addr.translation_offset; + end = addr.maximum + addr.translation_offset; + + res = data; + res->flags = flags; + res->start = start; + res->end = end; + + return AE_OK; +} + static void handle_ioapic_add(acpi_handle handle, struct pci_dev **pdev, u32 *pgsi_base) { @@ -54,33 +84,56 @@ static void handle_ioapic_add(acpi_handle handle, struct pci_dev **pdev, return; dev = acpi_get_pci_dev(handle); - if (!dev) - return; + if (!dev || !pci_resource_len(dev, 0)) { + struct acpi_device_info *info; + char *hid = NULL; + + status = acpi_get_object_info(handle, &info); + if (ACPI_FAILURE(status)) + goto exit_put; + if (info->valid & ACPI_VALID_HID) + hid = info->hardware_id.string; + if (!hid || strcmp(hid, "ACPI0009")) { + kfree(info); + goto exit_put; + } + kfree(info); + memset(res, 0, sizeof(*res)); + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); + if (!res->flags) + goto exit_put; + } acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); gsi_base = gsb; type = "IOxAPIC"; + if (dev) { + ret = pci_enable_device(dev); + if (ret < 0) + goto exit_put; - ret = pci_enable_device(dev); - if (ret < 0) - goto exit_put; - - pci_set_master(dev); + pci_set_master(dev); - if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC) - type = "IOAPIC"; + if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC) + type = "IOAPIC"; - if (pci_request_region(dev, 0, type)) - goto exit_disable; + if (pci_resource_len(dev, 0)) { + if (pci_request_region(dev, 0, type)) + goto exit_disable; - res = &dev->resource[0]; + res = &dev->resource[0]; + } + } - if (acpi_register_ioapic(handle, res->start, gsi_base)) - goto exit_release; + if (acpi_register_ioapic(handle, res->start, gsi_base)) { + if (dev) + goto exit_release; + return; + } pr_info("%s %s %s at %pR, GSI %u\n", - dev_name(&dev->dev), objname, type, + dev ? dev_name(&dev->dev) : "", objname, type, res, gsi_base); *pdev = dev; @@ -100,6 +153,9 @@ static void handle_ioapic_remove(acpi_handle handle, struct pci_dev *dev, { acpi_unregister_ioapic(handle, gsi_base); + if (!dev) + return; + pci_release_region(dev, 0); pci_disable_device(dev); pci_dev_put(dev);