From patchwork Wed Mar 10 20:50:30 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Helgaas X-Patchwork-Id: 84680 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o2AKoZKS022962 for ; Wed, 10 Mar 2010 20:50:35 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757122Ab0CJUue (ORCPT ); Wed, 10 Mar 2010 15:50:34 -0500 Received: from g4t0016.houston.hp.com ([15.201.24.19]:26511 "EHLO g4t0016.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757115Ab0CJUue (ORCPT ); Wed, 10 Mar 2010 15:50:34 -0500 Received: from g4t0018.houston.hp.com (g4t0018.houston.hp.com [16.234.32.27]) by g4t0016.houston.hp.com (Postfix) with ESMTP id 48AB4149B3; Wed, 10 Mar 2010 20:50:33 +0000 (UTC) Received: from ldl (ldl.fc.hp.com [15.11.146.30]) by g4t0018.houston.hp.com (Postfix) with ESMTP id C56BD10143; Wed, 10 Mar 2010 20:50:32 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl (Postfix) with ESMTP id 80624CF0037; Wed, 10 Mar 2010 13:50:32 -0700 (MST) Received: from ldl ([127.0.0.1]) by localhost (ldl.fc.hp.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OaDedTIt2npJ; Wed, 10 Mar 2010 13:50:32 -0700 (MST) Received: from tigger.helgaas (lart.fc.hp.com [15.11.146.31]) by ldl (Postfix) with ESMTP id 6356CCF0010; Wed, 10 Mar 2010 13:50:32 -0700 (MST) From: Bjorn Helgaas To: Yanko Kaneti Subject: Re: [Bug 15480] [regression] Gigabyte GA-MA78GM-S2H boot fails without pci=nocrs Date: Wed, 10 Mar 2010 13:50:30 -0700 User-Agent: KMail/1.9.10 Cc: linux-pci@vger.kernel.org, "Rafael J. Wysocki" , bugzilla-daemon@bugzilla.kernel.org, Thomas Renninger , Linus Torvalds References: <201003091356.03597.bjorn.helgaas@hp.com> In-Reply-To: <201003091356.03597.bjorn.helgaas@hp.com> MIME-Version: 1.0 Content-Disposition: inline Message-Id: <201003101350.31554.bjorn.helgaas@hp.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 10 Mar 2010 20:50:35 +0000 (UTC) diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 6e22454..42d8f01 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -118,7 +118,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) { struct pci_root_info *info = data; - struct resource *res; + struct resource *res, *conflict; struct acpi_resource_address64 addr; acpi_status status; unsigned long flags; @@ -157,21 +157,39 @@ setup_resource(struct acpi_resource *acpi_res, void *data) return AE_OK; } - if (insert_resource(root, res)) { + for (;;) { + conflict = insert_resource_conflict(root, res); + if (!conflict) + break; + dev_err(&info->bridge->dev, - "can't allocate host bridge window %pR\n", res); - } else { - pci_bus_add_resource(info->bus, res, 0); - info->res_num++; - if (addr.translation_offset) - dev_info(&info->bridge->dev, "host bridge window %pR " - "(PCI address [%#llx-%#llx])\n", - res, res->start - addr.translation_offset, - res->end - addr.translation_offset); - else - dev_info(&info->bridge->dev, - "host bridge window %pR\n", res); + "host bridge window %pR conflicts with %pR\n", + res, conflict); + if (res->start < conflict->end && conflict->end < res->end) + res->start = conflict->end + 1; + if (res->start < conflict->start && conflict->start < res->end) + res->end = conflict->start - 1; + + if (res->start >= res->end) { + dev_err(&info->bridge->dev, + "can't allocate host bridge window\n"); + return AE_OK; + } + + dev_info(&info->bridge->dev, + "host bridge window trimmed to %pR\n", res); } + + pci_bus_add_resource(info->bus, res, 0); + info->res_num++; + if (addr.translation_offset) + dev_info(&info->bridge->dev, "host bridge window %pR " + "(PCI address [%#llx-%#llx])\n", + res, res->start - addr.translation_offset, + res->end - addr.translation_offset); + else + dev_info(&info->bridge->dev, + "host bridge window %pR\n", res); return AE_OK; } diff --git a/include/linux/ioport.h b/include/linux/ioport.h index dda9841..9f88526 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -117,6 +117,7 @@ extern void reserve_region_with_split(struct resource *root, resource_size_t start, resource_size_t end, const char *name); extern int insert_resource(struct resource *parent, struct resource *new); +extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new); extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); extern int allocate_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..8ec71a2 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -496,6 +496,16 @@ int insert_resource(struct resource *parent, struct resource *new) return conflict ? -EBUSY : 0; } +struct resource *insert_resource_conflict(struct resource *parent, struct resource *new) +{ + struct resource *conflict; + + write_lock(&resource_lock); + conflict = __insert_resource(parent, new); + write_unlock(&resource_lock); + return conflict; +} + /** * insert_resource_expand_to_fit - Insert a resource into the resource tree * @root: root resource descriptor