Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754453AbbLKFKu (ORCPT ); Fri, 11 Dec 2015 00:10:50 -0500 Received: from aserp1040.oracle.com ([141.146.126.69]:47539 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750940AbbLKFKn (ORCPT ); Fri, 11 Dec 2015 00:10:43 -0500 From: Yinghai Lu To: Bjorn Helgaas , David Miller , Benjamin Herrenschmidt , Wei Yang , TJ , Yijing Wang , Khalid Aziz Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, Yinghai Lu , stable@vger.kernel.org Subject: [PATCH v9 16/60] PCI: Don't release fixed resource for realloc Date: Thu, 10 Dec 2015 21:06:12 -0800 Message-Id: <1449810416-2950-17-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1449810416-2950-1-git-send-email-yinghai@kernel.org> References: <1449810416-2950-1-git-send-email-yinghai@kernel.org> X-Source-IP: aserv0022.oracle.com [141.146.126.234] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2961 Lines: 100 We should not release bridge resource if there is fixed resources under it, otherwise the children firmware would stop working. Reported-by: Paul Johnson Suggested-by: Bjorn Helgaas Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=92351 Signed-off-by: Yinghai Lu Cc: stable@vger.kernel.org --- drivers/pci/setup-bus.c | 6 ++++-- include/linux/ioport.h | 2 +- kernel/resource.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 86c51ef..dd92c5ea 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1541,14 +1541,16 @@ static void pci_bridge_release_resources(struct pci_bus *bus, r = &b_res[idx]; - if (!r->parent) + if (!r->parent || r->flags & IORESOURCE_PCI_FIXED) return; /* * if there are children under that, we should release them * all */ - release_child_resources(r); + if (!release_child_resources(r)) + return; + if (!release_resource(r)) { type = old_flags = r->flags & type_mask; dev_printk(KERN_DEBUG, &dev->dev, "resource %d %pR released\n", diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 24bea08..26b0a08 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -142,7 +142,7 @@ extern struct resource iomem_resource; extern struct resource *request_resource_conflict(struct resource *root, struct resource *new); extern int request_resource(struct resource *root, struct resource *new); extern int release_resource(struct resource *new); -void release_child_resources(struct resource *new); +bool release_child_resources(struct resource *new); extern void reserve_region_with_split(struct resource *root, resource_size_t start, resource_size_t end, const char *name); diff --git a/kernel/resource.c b/kernel/resource.c index f150dbb..6927298 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -275,11 +275,35 @@ static void __release_child_resources(struct resource *r) } } -void release_child_resources(struct resource *r) +static bool __has_fixed_child_resources(struct resource *r) { + struct resource *p; + + p = r->child; + while (p) { + if (p->flags & IORESOURCE_PCI_FIXED) + return true; + + if (__has_fixed_child_resources(p)) + return true; + + p = p->sibling; + } + + return false; +} + +bool release_child_resources(struct resource *r) +{ + bool fixed; + write_lock(&resource_lock); - __release_child_resources(r); + fixed = __has_fixed_child_resources(r); + if (!fixed) + __release_child_resources(r); write_unlock(&resource_lock); + + return !fixed; } /** -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/