From patchwork Wed Dec 8 21:36:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Helgaas X-Patchwork-Id: 392222 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oB8LbXKV022691 for ; Wed, 8 Dec 2010 21:37:34 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755596Ab0LHVhM (ORCPT ); Wed, 8 Dec 2010 16:37:12 -0500 Received: from g4t0014.houston.hp.com ([15.201.24.17]:2990 "EHLO g4t0014.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755452Ab0LHVgT (ORCPT ); Wed, 8 Dec 2010 16:36:19 -0500 Received: from g4t0018.houston.hp.com (g4t0018.houston.hp.com [16.234.32.27]) by g4t0014.houston.hp.com (Postfix) with ESMTP id 68CBA2475E; Wed, 8 Dec 2010 21:36:18 +0000 (UTC) Received: from ldl (ldl.usa.hp.com [16.125.112.222]) by g4t0018.houston.hp.com (Postfix) with ESMTP id 7366A1011B; Wed, 8 Dec 2010 21:36:17 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl (Postfix) with ESMTP id 2D16BCF002A; Wed, 8 Dec 2010 14:36:17 -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 RFRpETFYBotD; Wed, 8 Dec 2010 14:36:17 -0700 (MST) Received: from eh.fc.hp.com (bob.lnx.usa.hp.com [16.125.112.218]) by ldl (Postfix) with ESMTP id 09191CF0029; Wed, 8 Dec 2010 14:36:17 -0700 (MST) Received: from bob.kio (localhost [127.0.0.1]) by eh.fc.hp.com (Postfix) with ESMTP id E328526200; Wed, 8 Dec 2010 14:36:16 -0700 (MST) Subject: [PATCH 3/5] x86: avoid PNP resources when allocating address space To: Jesse Barnes , Len Brown From: Bjorn Helgaas Cc: Jiri Slaby , Dan Williams , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, "H. Peter Anvin" , Thomas Gleixner , Linus Torvalds , Ingo Molnar , Adam Belay , Matthew Garrett Date: Wed, 08 Dec 2010 14:36:16 -0700 Message-ID: <20101208213616.13026.77390.stgit@bob.kio> In-Reply-To: <20101208213606.13026.47657.stgit@bob.kio> References: <20101208213606.13026.47657.stgit@bob.kio> User-Agent: StGit/0.15 MIME-Version: 1.0 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 (demeter1.kernel.org [140.211.167.41]); Wed, 08 Dec 2010 21:37:35 +0000 (UTC) diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c index 5dd6473..1daee92 100644 --- a/arch/x86/kernel/resource.c +++ b/arch/x86/kernel/resource.c @@ -1,6 +1,80 @@ #include +#include #include +#ifdef CONFIG_PNP +static bool resource_conflict(struct resource *res, resource_size_t start, + resource_size_t end) +{ + /* + * Return true if and only if "res" conflicts with the [start-end] + * range. + */ + return res->start <= end && res->end >= start; +} + +static void resource_split(struct resource *res, resource_size_t start, + resource_size_t end, struct resource *low, + struct resource *high) +{ + /* + * If "res" conflicts with [start-end], split "res" into the + * part below "start" (low) and the part above "end" (high), + * either (or both) of which may be empty. + * + * If there's no conflict, return the entire "res" as "low". + */ + *low = *res; + low->start = res->start; + low->end = res->start - 1; /* default to empty (size 0) */ + + *high = *res; + high->end = res->end; + high->start = res->end + 1; /* default to empty (size 0) */ + + if (!resource_conflict(res, start, end)) { + low->end = res->end; + return; + } + + if (res->start < start) + low->end = start - 1; + + if (res->end > end) + high->start = end + 1; +} + +static void pnp_remove_reservations(struct resource *avail) +{ + unsigned long type = resource_type(avail); + struct pnp_dev *dev; + int i; + struct resource *res, low, high; + + /* + * Clip the available region to avoid PNP devices. The PNP + * resources really should be in the resource map to begin with, + * but there are still some issues preventing that. + */ + pnp_for_each_dev(dev) { + i = 0; + res = pnp_get_resource(dev, type, i++); + while (res) { + if (!(res->flags & IORESOURCE_WINDOW)) { + resource_split(avail, res->start, res->end, + &low, &high); + if (resource_size(&low) > resource_size(&high)) + *avail = low; + else + *avail = high; + } + + res = pnp_get_resource(dev, type, i++); + } + } +} +#endif + void arch_remove_reservations(struct resource *avail) { /* @@ -11,4 +85,8 @@ void arch_remove_reservations(struct resource *avail) if (avail->start < BIOS_END) avail->start = BIOS_END; } + +#ifdef CONFIG_PNP + pnp_remove_reservations(avail); +#endif }