From patchwork Wed Aug 10 06:56:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Yan X-Patchwork-Id: 596434 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:b345:0:0:0:0 with SMTP id w5csp5013495maz; Wed, 10 Aug 2022 05:58:10 -0700 (PDT) X-Google-Smtp-Source: AA6agR6xyczTksRWP9sUx8vE6t1e8aUW1KDl4JBCU3L9/Z+fz+eVE+V5EdC0dByL7+PbYc9X9FYZ X-Received: by 2002:a05:6602:2ac4:b0:684:672c:3729 with SMTP id m4-20020a0566022ac400b00684672c3729mr7546472iov.186.1660136290714; Wed, 10 Aug 2022 05:58:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1660136290; cv=none; d=google.com; s=arc-20160816; b=i34uCawWnOc5wm+wjymP+UOXz+dhUw93gdUTgn2IoFKPaOyGDyBwTY6/UvxsSnI8cZ 7wUMubA9Cm3NVV25Y1O9jW5xBnL6fzRaXaXFX01KNADKulsYvlj1MnxWa69GY71I8k4c qgE3ERuVAYIDG3ggTzB79V45bzx3UHQI+wZEgmiNkwVZkmM/JIx4O2Tcpz6ZiqrgoU7q FuGLCuEfTyGpWeO9xcWSi6RpD88vMArbNtagX3sNJk6UNncw1ybVdEzlznBZAl7PltSl O+i6UXlmajumX4AFLBOphTEySBtWP26Qcj2m1dUMIEWnkR7CGZ5YGVAiCOlgWqGhuxp5 MKyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature; bh=U3oZ44fiZ0dE0vRm1r7dsnRggj5xY6kl0Z4926yuogc=; b=wfSrWRzz5nzLLUPzjhmN7R2eTshsumrCz2c3VqMHhNBmA6hem0wraqh2osd5v6cTm+ BxnzFvoZgahSsA+qCjK77MQ5d1S1s0z7kJJpXI6paNAJPAHWbUVNMigYmO3TUE6uaBL2 D1DfqvYpEhd6jcLGXsC5j6DiEy4tkPX6c/74ixUjTgsLTJal/YO35wCCqY/SNV0vzEvT 2IzeCor+6NfU+dg65Dr29TzJblXQG3EPB+vgTj35ThpXDWZhNdr86cDYzd4IlDHU+NjU 82XovgoxnO0h44ibtTv5mTl8ixgIXORBCPCqmsRpT2DlRpnuWwTi2PLdduyLU4imRdbc LBfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ucqwHO5b; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id k11-20020a056638140b00b00342834cbdd8si12534630jad.12.2022.08.10.05.58.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Aug 2022 05:58:10 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ucqwHO5b; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 172178415B; Wed, 10 Aug 2022 14:58:06 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ucqwHO5b"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id ED7738485B; Wed, 10 Aug 2022 08:56:44 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6A121845C9 for ; Wed, 10 Aug 2022 08:56:41 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=leo.yan@linaro.org Received: by mail-pj1-x102f.google.com with SMTP id d65-20020a17090a6f4700b001f303a97b14so1213456pjk.1 for ; Tue, 09 Aug 2022 23:56:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=U3oZ44fiZ0dE0vRm1r7dsnRggj5xY6kl0Z4926yuogc=; b=ucqwHO5bwPJ3XDF18VTSxMxudzBsAV7ZWwWVjzUVNaEkWJ/BnnlN946DgP+0RVaH5J gfr4N6NOSSznTfBW/3w3njzC8WwLPn/VqkD2mloNIlft904aaU1Tg36Ugvd2DDihtXyG 2VZwzDR43aOG2eN+5NsmUD0WT1+6kNTPJOIpkchp3NN/1g73L13zOYDH/KNFmuOvmVcK 2JFrFItFfPyVcUFNSBa8HZwcfYY2siFJEdT0MTddK9PuPmOYIX6yM+Jl/q1d6chjqcNv 5w5QbxHJoXC6gUvIgpZcJjpcXn3o2q+LiHIVds69P/S5WkJfrtVI8NLh2M9BOJHzkF9v +deQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=U3oZ44fiZ0dE0vRm1r7dsnRggj5xY6kl0Z4926yuogc=; b=lZFaV3q74UGXvkXsttwfxm673eCIPT2UvkHg8IW9nMYmAkzA1g8kSfv8PknlQn2MB/ CmcD7N91XgLznNYy/wyZ4ARwoRGrjk9h7JpTfHemr3IhrOUe030gL+0rN9AOtMUR0I/p aCu9HsEpeRz2ko6hV6+jh6loYjJzMTiRBpq/z8KwFU4Ztw71vBQ8EC8zJzFctNwCvl2/ xCldoCbvoezi6NvbajmqpzStTtgcxar4lmKXI7AujfxIF7IwHsrILF0u/imyDppCb4Jm kp0klWY6VUGDmr3zuhljOh0KCPmecWmOIwH/aAJMS2RrVGe3Gq/7RCaSQibI4CR15amQ VYhg== X-Gm-Message-State: ACgBeo1xUhj93dMrNH//6MpnvrM/n6uI1Rd4ITG85fCBEan40wVX6Lks qpvjRREz0/zoAdmPlTxpwXXXmg== X-Received: by 2002:a17:902:f646:b0:168:e2da:8931 with SMTP id m6-20020a170902f64600b00168e2da8931mr26503539plg.84.1660114599311; Tue, 09 Aug 2022 23:56:39 -0700 (PDT) Received: from localhost (n058152077182.netvigator.com. [58.152.77.182]) by smtp.gmail.com with ESMTPSA id h3-20020a170902f54300b0016bedcced2fsm12267622plf.35.2022.08.09.23.56.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Aug 2022 23:56:38 -0700 (PDT) From: Leo Yan To: Stefan Roese , =?utf-8?q?Pali_Roh=C3=A1r?= , "Maciej W. Rozycki" , Bin Meng , Vladimir Oltean , u-boot@lists.denx.de, Matsumoto Misako Cc: Leo Yan Subject: [PATCH] pci: Sort resources before assignment Date: Wed, 10 Aug 2022 14:56:33 +0800 Message-Id: <20220810065633.156864-1-leo.yan@linaro.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Mailman-Approved-At: Wed, 10 Aug 2022 14:58:04 +0200 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean A PCI device can request resource for multiple memory regions, e.g. a PCI device tries to allocate prefetchable memory for two regions, one region size is 0x1000_0000 and another is 0x1_0000_0000. And the PCIe controller provides prefetchable memory window size is 0x1_8000_0000, thus in theory the PCIe controller can meet the memory requirement for the PCI device: 0x1_8000_0000 > 0x1_1000_0000 (0x1000_0000 + 0x1_0000_0000) When allocate the memory region, pciauto_region_allocate() applies the alignment for the start address, we can see the memory regions are allocated as: => pci bar 1.0.0 ID Base Size Width Type ---------------------------------------------------------- 0 0x0000000088000000 0x0000000004000000 32 MEM 1 0x000000008c000000 0x0000000000100000 32 MEM 2 0x0000001000000000 0x0000000010000000 64 MEM Prefetchable 3 0x0000001100000000 0x0000000100000000 64 MEM Prefetchable The problem is for the last memory region, we can see its start address is 0x11_0000_0000 and the size is 0x1_0000_0000, therefore, these two memory regions occupy memory size is: 0x11_0000_0000 + 0x1_0000_0000 - 0x10_0000_0000 = 0x2_0000_0000 The allocated memory region (0x2_0000_0000) is out of the range, because the maximum space provided by PCI controller is only 0x1_8000_0000. To fix this issue, this patch sorts resources with descending, this can give the priority for big chunk memory region, the big memory region is allocated ahead before a small region, so that its start address does not necessarily introduce big hole caused by the alignment, which is finished by function pdev_sort_resources(). And we use another function pdev_assign_resources() to set BARs based on the sorted list. As result, we can see the updated memory regions are altered as below; the end address is: 0x11_0000_0000 + 0x1000_0000, which falls into the permitted memory window. => pci bar 1.0.0 ID Base Size Width Type ---------------------------------------------------------- 0 0x0000000088000000 0x0000000004000000 32 MEM 1 0x000000008c000000 0x0000000000100000 32 MEM 2 0x0000001100000000 0x0000000010000000 64 MEM Prefetchable 3 0x0000001000000000 0x0000000100000000 64 MEM Prefetchable Reported-by: Matsumoto Misako Signed-off-by: Leo Yan --- drivers/pci/pci_auto.c | 104 +++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 25 deletions(-) diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index c7968926a1..69c801fc62 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "pci_internal.h" /* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */ @@ -21,6 +23,69 @@ #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8 #endif +struct pci_dev_resource { + struct list_head list; + int bar; + pci_size_t bar_size; + int found_mem64; + struct pci_region *bar_res; +}; + +/* Sort resources by bar size */ +static void pdev_sort_resources(struct pci_dev_resource *new, + struct list_head *head) +{ + struct pci_dev_resource *dev_res; + struct list_head *n; + + /* Fallback is smallest one or list is empty */ + n = head; + list_for_each_entry(dev_res, head, list) { + if (new->bar_size > dev_res->bar_size) { + n = &dev_res->list; + break; + } + } + + /* Insert it just before n */ + list_add_tail(&new->list, n); +} + +static void pdev_assign_resources(struct udevice *dev, struct list_head *head) +{ + struct pci_dev_resource *dev_res; + int bar; + pci_addr_t bar_value; + int ret = 0; + + list_for_each_entry(dev_res, head, list) { + ret = pciauto_region_allocate(dev_res->bar_res, dev_res->bar_size, + &bar_value, dev_res->found_mem64); + if (ret) + printf("PCI: Failed autoconfig bar %x\n", dev_res->bar); + + bar = dev_res->bar; + if (!ret) { + /* Write it out and update our limit */ + dm_pci_write_config32(dev, bar, (u32)bar_value); + + if (dev_res->found_mem64) { + bar += 4; + if (IS_ENABLED(CONFIG_SYS_PCI_64BIT)) + dm_pci_write_config32(dev, bar, + (u32)(bar_value >> 32)); + else + /* + * If we are a 64-bit decoder then increment to + * the upper 32 bits of the bar and force it to + * locate in the lower 4GB of memory. + */ + dm_pci_write_config32(dev, bar, 0x00000000); + } + } + } +} + static void dm_pciauto_setup_device(struct udevice *dev, struct pci_region *mem, struct pci_region *prefetch, @@ -37,6 +102,10 @@ static void dm_pciauto_setup_device(struct udevice *dev, struct pci_region *bar_res = NULL; int found_mem64 = 0; u16 class; + LIST_HEAD(head); + struct pci_dev_resource pdev_resource[6]; + + memset(pdev_resource, 0x0, sizeof(pdev_resource)); dm_pci_read_config16(dev, PCI_COMMAND, &cmdstat); cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | @@ -64,8 +133,6 @@ static void dm_pciauto_setup_device(struct udevice *dev, for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) { - int ret = 0; - /* Tickle the BAR and get the response */ dm_pci_write_config32(dev, bar, 0xffffffff); dm_pci_read_config32(dev, bar, &bar_response); @@ -118,30 +185,15 @@ static void dm_pciauto_setup_device(struct udevice *dev, (unsigned long long)bar_size); } - ret = pciauto_region_allocate(bar_res, bar_size, - &bar_value, found_mem64); - if (ret) - printf("PCI: Failed autoconfig bar %x\n", bar); - - if (!ret) { - /* Write it out and update our limit */ - dm_pci_write_config32(dev, bar, (u32)bar_value); + INIT_LIST_HEAD(&pdev_resource[bar_nr].list); + pdev_resource[bar_nr].bar = bar; + pdev_resource[bar_nr].bar_size = bar_size; + pdev_resource[bar_nr].bar_res = bar_res; + pdev_resource[bar_nr].found_mem64 = found_mem64; + pdev_sort_resources(&pdev_resource[bar_nr], &head); - if (found_mem64) { - bar += 4; -#ifdef CONFIG_SYS_PCI_64BIT - dm_pci_write_config32(dev, bar, - (u32)(bar_value >> 32)); -#else - /* - * If we are a 64-bit decoder then increment to - * the upper 32 bits of the bar and force it to - * locate in the lower 4GB of memory. - */ - dm_pci_write_config32(dev, bar, 0x00000000); -#endif - } - } + if (found_mem64) + bar += 4; cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY; @@ -151,6 +203,8 @@ static void dm_pciauto_setup_device(struct udevice *dev, bar_nr++; } + pdev_assign_resources(dev, &head); + /* Configure the expansion ROM address */ if (header_type == PCI_HEADER_TYPE_NORMAL || header_type == PCI_HEADER_TYPE_BRIDGE) {