From patchwork Fri Apr 8 00:15:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yinghai Lu X-Patchwork-Id: 8778841 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C5C23C0553 for ; Fri, 8 Apr 2016 00:27:37 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C479B20222 for ; Fri, 8 Apr 2016 00:27:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D11CD20204 for ; Fri, 8 Apr 2016 00:27:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932306AbcDHA1A (ORCPT ); Thu, 7 Apr 2016 20:27:00 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:43413 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932600AbcDHAWT (ORCPT ); Thu, 7 Apr 2016 20:22:19 -0400 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u380H0Fb009789 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 8 Apr 2016 00:17:01 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u380GxYq026119 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 8 Apr 2016 00:17:00 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u380Gxr9019403; Fri, 8 Apr 2016 00:16:59 GMT Received: from aserv0022.oracle.com (/10.132.126.127) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 07 Apr 2016 17:16:59 -0700 From: Yinghai Lu To: Bjorn Helgaas , David Miller , Benjamin Herrenschmidt , Linus Torvalds Cc: Wei Yang , TJ , Yijing Wang , Khalid Aziz , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, Yinghai Lu Subject: [PATCH v11 45/60] PCI: Add support for more than two alt_size entries under same bridge Date: Thu, 7 Apr 2016 17:15:58 -0700 Message-Id: <1460074573-7481-46-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1460074573-7481-1-git-send-email-yinghai@kernel.org> References: <1460074573-7481-1-git-send-email-yinghai@kernel.org> X-Source-IP: userv0021.oracle.com [156.151.31.71] Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When we have two bridges under parent bridge, and each child bridge has alt_size, we need to increase parent alt_size to make sure it could fit all alt entries. In the patch, we first select one big size, and then keep reducing the size and retrying to get the minimum value for alt_size. For example, two bridges: one have 8M/8M, and 1M/1M children res. one have 4M/4M, and 1M/1M children res. Then we have child pridges alt_align/alt_size: 8M/9M, 4M/5M. Before this patch, parent bridge alt_align/alt_size is 8M/14M that is wrong, as it can not fit two alt entries at all. With this patch parent bridge alt_align/alt_size: 8M/17M. 8M 16M 20M 24M |------------|-------------|-----|-----| 8M 25M |---------------------------| 17M |---9M----------| |-5M----| At same time, child bridges required align/size: 4M/12M, 2M/6M. and prarent bridge required align/size: 4M/20M. So at last, we use 8M/17M as parent bridge alt_align/alt_size. Link: https://bugzilla.kernel.org/show_bug.cgi?id=100451 Reported-by: Yijing Wang Tested-by: Yijing Wang Signed-off-by: Yinghai Lu --- drivers/pci/setup-bus.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index f3e9873..88557b9 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1372,6 +1372,47 @@ out: return good_align; } +static resource_size_t calculate_mem_alt_size(struct list_head *head, + resource_size_t max_align, resource_size_t size, + resource_size_t align_low) +{ + struct align_test_res *p; + resource_size_t tmp; + resource_size_t good_size, bad_size; + int count = 0, order; + + good_size = ALIGN(size, align_low); + + list_for_each_entry(p, head, list) + count++; + + if (count <= 1) + goto out; + + sort_align_test(head); + + tmp = max(size, max_align); + order = __fls(count); + if ((1ULL << order) < count) + order++; + good_size = ALIGN((tmp << order), align_low); + bad_size = ALIGN(size, align_low) - align_low; + size = good_size; + while (size > bad_size) { + /* check if align/size fit all entries */ + if (is_align_size_good(head, max_align, size, 0)) + good_size = size; + else + bad_size = size; + + size = bad_size + ((good_size - bad_size) >> 1); + size = round_down(size, align_low); + } + +out: + return good_size; +} + static inline bool is_optional(int i) { @@ -1418,6 +1459,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, mask | IORESOURCE_PREFETCH, type); LIST_HEAD(align_test_list); LIST_HEAD(align_test_add_list); + LIST_HEAD(align_test_alt_list); resource_size_t alt_size = 0, alt_align = 0; resource_size_t window_align; @@ -1493,10 +1535,17 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, dev_res = res_to_dev_res(realloc_head, r); if (dev_res && dev_res->alt_size) { + add_to_align_test_list( + &align_test_alt_list, + dev_res->alt_align, + dev_res->alt_size); alt_size += dev_res->alt_size; if (alt_align < dev_res->alt_align) alt_align = dev_res->alt_align; } else if (r_size > 1) { + add_to_align_test_list( + &align_test_alt_list, + align, r_size); alt_size += r_size; if (alt_align < align) alt_align = align; @@ -1516,14 +1565,17 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, if (size0 && realloc_head) { alt_align = max(alt_align, window_align); - alt_size = calculate_memsize(alt_size, min_size, - 0, window_align); + /* need to increase size to fit more alt */ + alt_size = calculate_mem_alt_size(&align_test_alt_list, + alt_align, alt_size, + window_align); /* required is better ? */ if (alt_size >= size0) { alt_align = 0; alt_size = 0; } } + free_align_test_list(&align_test_alt_list); if (sum_add_size < min_sum_size) sum_add_size = min_sum_size;