Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755321AbbG0XeI (ORCPT ); Mon, 27 Jul 2015 19:34:08 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:37717 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932084AbbG0XeC (ORCPT ); Mon, 27 Jul 2015 19:34:02 -0400 From: Yinghai Lu To: Bjorn Helgaas , David Miller , Benjamin Herrenschmidt , Wei Yang , TJ , Yijing Wang Cc: Andrew Morton , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, Yinghai Lu , stable@vger.kernel.org Subject: [PATCH v3 46/51] PCI: Don't release fixed resource for realloc Date: Mon, 27 Jul 2015 16:30:04 -0700 Message-Id: <1438039809-24957-47-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1438039809-24957-1-git-send-email-yinghai@kernel.org> References: <1438039809-24957-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 63a5d4cf..dcbbe04 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -2070,14 +2070,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 388e3ae..27dbb18 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -141,7 +141,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 697b8ca..4e43f9b 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -276,11 +276,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/