From patchwork Fri Nov 5 02:36:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Helgaas X-Patchwork-Id: 303052 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 oA52ajsl007997 for ; Fri, 5 Nov 2010 02:36:45 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753311Ab0KECgU (ORCPT ); Thu, 4 Nov 2010 22:36:20 -0400 Received: from g4t0017.houston.hp.com ([15.201.24.20]:6834 "EHLO g4t0017.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753305Ab0KECgP (ORCPT ); Thu, 4 Nov 2010 22:36:15 -0400 Received: from g4t0018.houston.hp.com (g4t0018.houston.hp.com [16.234.32.27]) by g4t0017.houston.hp.com (Postfix) with ESMTP id AD36E3877A; Fri, 5 Nov 2010 02:36:11 +0000 (UTC) Received: from ldl (ldl.usa.hp.com [16.125.112.222]) by g4t0018.houston.hp.com (Postfix) with ESMTP id 253761008D; Fri, 5 Nov 2010 02:36:10 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl (Postfix) with ESMTP id EF346CF0031; Thu, 4 Nov 2010 20:36:09 -0600 (MDT) Received: from ldl ([127.0.0.1]) by localhost (ldl.fc.hp.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KdE1ap+byCMv; Thu, 4 Nov 2010 20:36:09 -0600 (MDT) Received: from eh.fc.hp.com (bob.lnx.usa.hp.com [16.125.112.218]) by ldl (Postfix) with ESMTP id C805FCF002B; Thu, 4 Nov 2010 20:36:09 -0600 (MDT) Received: from bob.kio (localhost [127.0.0.1]) by eh.fc.hp.com (Postfix) with ESMTP id 9347E260C8; Thu, 4 Nov 2010 20:36:09 -0600 (MDT) Subject: [PATCH] PCI: fix pci_bus_alloc_resource() hang To: Jesse Barnes From: Bjorn Helgaas Cc: Bob Picco , Brian Bloniarz , Charles Butterfield , Denys Vlasenko , Ingo Molnar , linux-pci@vger.kernel.org, "Horst H. von Brand" , "H. Peter Anvin" , Borislav Petkov , Borislav Petkov , Stefan Becker , Chuck Ebbert , Fabrice Bellet , Yinghai Lu , Leann Ogasawara , Linus Torvalds , Thomas Gleixner Date: Thu, 04 Nov 2010 20:36:09 -0600 Message-ID: <20101105023609.27340.3879.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]); Fri, 05 Nov 2010 02:36:45 +0000 (UTC) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 5624db8..794c890 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -64,6 +64,24 @@ void pci_bus_remove_resources(struct pci_bus *bus) } } +static int resource_compare(struct resource *res1, struct resource *res2) +{ + if (res1->end < res2->end) + return -1; + + if (res1->end > res2->end) + return 1; + + if (res1->start < res2->start) + return -1; + + if (res1->start > res2->start) + return 1; + + /* If start/end are identical, order them to avoid loops */ + return res1 - res2; +} + /* * Find the highest-address bus resource below the cursor "res". If the * cursor is NULL, return the highest resource. @@ -82,26 +100,12 @@ static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, if ((r->flags & IORESOURCE_TYPE_BITS) != type) continue; - /* If this resource is at or past the cursor, skip it */ - if (res) { - if (r == res) - continue; - if (r->end > res->end) - continue; - if (r->end == res->end && r->start > res->start) - continue; + /* Only look at resources before the cursor */ + if (!res || resource_compare(r, res) < 0) { + /* Keep the highest one we find */ + if (!prev || resource_compare(r, prev) > 0) + prev = r; } - - if (!prev) - prev = r; - - /* - * A small resource is higher than a large one that ends at - * the same address. - */ - if (r->end > prev->end || - (r->end == prev->end && r->start > prev->start)) - prev = r; } return prev;