From patchwork Thu Oct 8 21:38:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yinghai Lu X-Patchwork-Id: 7356321 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 BD187BEEA4 for ; Thu, 8 Oct 2015 21:52:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A21B120790 for ; Thu, 8 Oct 2015 21:52:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 709B12054E for ; Thu, 8 Oct 2015 21:52:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757173AbbJHVvj (ORCPT ); Thu, 8 Oct 2015 17:51:39 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:25780 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756474AbbJHVpJ (ORCPT ); Thu, 8 Oct 2015 17:45:09 -0400 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id t98Lds58001586 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 8 Oct 2015 21:39:55 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id t98Ldscf027655 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 8 Oct 2015 21:39:54 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id t98Ldrea015074; Thu, 8 Oct 2015 21:39:53 GMT Received: from linux-siqj.site (/10.132.127.48) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 08 Oct 2015 14:39:53 -0700 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 Subject: [PATCH v7 27/60] PCI: Optimize bus align/size calculation for optional during sizing Date: Thu, 8 Oct 2015 14:38:46 -0700 Message-Id: <1444340359-8011-28-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1444340359-8011-1-git-send-email-yinghai@kernel.org> References: <1444340359-8011-1-git-send-email-yinghai@kernel.org> X-Source-IP: aserv0021.oracle.com [141.146.126.233] Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_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 Current add_align always use max align, that make required+optional to get allocated more than needed in some cases. Now we have new calculate_mem_align(), so we could use it for add_align calculation. Need to create separated list for required+optional align/size info. After that we can get smaller add_align/size, and we have more chance to make required+optional to get allocated sucessfully. The result for bridge that have Intel 4x10g card installed: pci 0000:20:03.2: bridge window [mem 0x00000000-0x000fffff 64bit pref] to [bus 2a-31] calculate_mem for required align/size: 00800000/00800000, 00800000/00800000, 00800000/00800000, 00800000/00800000, 00008000/00008000, 00008000/00008000, 00008000/00008000, 00008000/00008000 original min_align/min_size: 00400000/02400000 new min_align/min_size: 00400000/02400000 pci 0000:20:03.2: bridge window [mem 0x00000000-0x000fffff 64bit pref] to [bus 2a-31] calculate_mem for required+optional align/size: 00800000/00800000, 00800000/00800000, 00800000/00800000, 00800000/00800000, 00010000/00200000, 00010000/00200000, 00010000/00200000, 00010000/00200000, 00008000/00008000, 00008000/00008000, 00008000/00008000, 00008000/00008000, 00004000/00080000, 00004000/00080000, 00004000/00080000, 00004000/00080000 original code min_align/min_size: 00800000/03000000 new min_align/min_size: 00100000/02b00000 so required align/size: 0x400000/0x2400000, and new required+optional align/size: 0x100000/0x2b00000, and it is much better than original required+optional align/size: 0x800000/0x3000000 and even have smaller min_align than required. -v2: remove not used size1 in calculate_memsize Link: https://bugzilla.kernel.org/show_bug.cgi?id=81431 Reported-by: TJ Signed-off-by: Yinghai Lu drivers/pci/setup-bus.c | 82 +++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 31 deletions(-) --- drivers/pci/setup-bus.c | 82 ++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8f0ad46..0c6977c9 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -944,7 +944,6 @@ static resource_size_t calculate_iosize(resource_size_t size, static resource_size_t calculate_memsize(resource_size_t size, resource_size_t min_size, - resource_size_t size1, resource_size_t old_size, resource_size_t align) { @@ -954,7 +953,7 @@ static resource_size_t calculate_memsize(resource_size_t size, old_size = 0; if (size < old_size) size = old_size; - size = ALIGN(size + size1, align); + size = ALIGN(size, align); return size; } @@ -1217,45 +1216,46 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, struct list_head *realloc_head) { struct pci_dev *dev; - resource_size_t min_align, align, size, size0, size1; - resource_size_t max_align = 0; + resource_size_t min_align = 0, min_add_align = 0; + resource_size_t max_align = 0, max_add_align = 0; + resource_size_t size = 0, size0 = 0, size1 = 0, sum_add_size = 0; struct resource *b_res = find_free_bus_resource(bus, mask | IORESOURCE_PREFETCH, type); - resource_size_t children_add_size = 0; - resource_size_t children_add_align = 0; - resource_size_t add_align = 0; LIST_HEAD(align_test_list); + LIST_HEAD(align_test_add_list); if (!b_res) return -ENOSPC; - size = 0; - list_for_each_entry(dev, &bus->devices, bus_list) { int i; for (i = 0; i < PCI_NUM_RESOURCES; i++) { struct resource *r = &dev->resource[i]; - resource_size_t r_size; + resource_size_t r_size, align; int flags = pci_resource_pref_compatible(dev, r); if (r->parent || ((flags & mask) != type && (flags & mask) != type2 && (flags & mask) != type3)) continue; + r_size = resource_size(r); + align = pci_resource_alignment(dev, r); #ifdef CONFIG_PCI_IOV /* put SRIOV requested res to the optional list */ if (realloc_head && i >= PCI_IOV_RESOURCES && i <= PCI_IOV_RESOURCE_END) { - add_align = max(pci_resource_alignment(dev, r), add_align); + add_to_align_test_list(&align_test_add_list, + align, r_size); r->end = r->start - 1; add_to_list(realloc_head, dev, r, r_size, 0/* don't care */); - children_add_size += r_size; + sum_add_size += r_size; + if (align > max_add_align) + max_add_align = align; continue; } #endif - align = pci_resource_alignment(dev, r); if (align > (1ULL<<37)) { /*128 Gb*/ dev_warn(&dev->dev, "disabling BAR %d: %pR (bad alignment %#llx)\n", i, r, (unsigned long long) align); @@ -1263,33 +1263,52 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, continue; } - if (r_size > 1) + if (r_size > 1) { add_to_align_test_list(&align_test_list, align, r_size); - size += r_size; - if (align > max_align) - max_align = align; + size += r_size; + if (align > max_align) + max_align = align; + } if (realloc_head) { - children_add_size += get_res_add_size(realloc_head, r); - children_add_align = get_res_add_align(realloc_head, r); - add_align = max(add_align, children_add_align); + resource_size_t add_r_size, add_align; + + add_r_size = get_res_add_size(realloc_head, r); + add_align = get_res_add_align(realloc_head, r); + /* no add on ? */ + if (add_align < align) + add_align = align; + add_to_align_test_list(&align_test_add_list, + add_align, + r_size + add_r_size); + sum_add_size += r_size + add_r_size; + if (add_align > max_add_align) + max_add_align = add_align; } } } max_align = max(max_align, window_alignment(bus, b_res->flags)); - min_align = calculate_mem_align(&align_test_list, max_align, size, - window_alignment(bus, b_res->flags)); - size0 = calculate_memsize(size, min_size, 0, + if (size || min_size) { + min_align = calculate_mem_align(&align_test_list, max_align, + size, window_alignment(bus, b_res->flags)); + size0 = calculate_memsize(size, min_size, resource_size(b_res), min_align); + } free_align_test_list(&align_test_list); - add_align = max(min_align, add_align); - if (children_add_size > add_size) - add_size = children_add_size; - size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 : - calculate_memsize(size, min_size, add_size, - resource_size(b_res), add_align); + + if ((sum_add_size - size) < add_size) + sum_add_size = size + add_size; + if (sum_add_size > size && realloc_head) { + min_add_align = calculate_mem_align(&align_test_add_list, + max_add_align, sum_add_size, + window_alignment(bus, b_res->flags)); + size1 = calculate_memsize(sum_add_size, min_size, + resource_size(b_res), min_add_align); + } + free_align_test_list(&align_test_add_list); + if (!size0 && !size1) { if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n", @@ -1301,11 +1320,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, b_res->end = size0 + min_align - 1; b_res->flags |= IORESOURCE_STARTALIGN; if (size1 > size0 && realloc_head) { - add_to_list(realloc_head, bus->self, b_res, size1-size0, add_align); + add_to_list(realloc_head, bus->self, b_res, size1 - size0, + min_add_align); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window %pR to %pR add_size %llx add_align %llx\n", b_res, &bus->busn_res, (unsigned long long) (size1 - size0), - (unsigned long long) add_align); + (unsigned long long) min_add_align); } return 0; }