linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Yinghai Lu <yinghai@kernel.org>
To: Bjorn Helgaas <bhelgaas@google.com>,
	David Miller <davem@davemloft.net>,
	David Ahern <david.ahern@oracle.com>,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>,
	Wei Yang <weiyang@linux.vnet.ibm.com>, TJ <linux@iam.tj>,
	Yijing Wang <wangyijing@huawei.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	Yinghai Lu <yinghai@kernel.org>
Subject: [PATCH 20/36] resources: Make allocate_resource return just fit resource
Date: Mon,  6 Jul 2015 16:39:10 -0700	[thread overview]
Message-ID: <1436225966-27247-21-git-send-email-yinghai@kernel.org> (raw)
In-Reply-To: <1436225966-27247-1-git-send-email-yinghai@kernel.org>

Find all suitable empty slots and pick one just fit, so we could save
the big slot for needed ones later when we have several pcie switches
and some bridges get assigned bios and we need to assign others in kernel.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 kernel/resource.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 68 insertions(+), 13 deletions(-)

diff --git a/kernel/resource.c b/kernel/resource.c
index 830cc11..c630ef1 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -48,6 +48,7 @@ struct resource_constraint {
 	resource_size_t (*alignf)(void *, const struct resource *,
 			resource_size_t, resource_size_t);
 	void *alignf_data;
+	bool fit;
 };
 
 static DEFINE_RWLOCK(resource_lock);
@@ -554,12 +555,15 @@ static void resource_clip(struct resource *res, resource_size_t min,
  * alignment constraints
  */
 static int __find_resource(struct resource *root, struct resource *old,
-			 struct resource *new,
+			 struct resource *new, struct resource *avail,
 			 resource_size_t  size,
 			 struct resource_constraint *constraint)
 {
 	struct resource *this = root->child;
-	struct resource tmp = *new, avail, alloc;
+	struct resource tmp = *new, availx, alloc;
+
+	if (!avail || avail == new)
+		avail = &availx;
 
 	tmp.start = root->start;
 	/*
@@ -583,15 +587,16 @@ static int __find_resource(struct resource *root, struct resource *old,
 		arch_remove_reservations(&tmp);
 
 		/* Check for overflow after ALIGN() */
-		avail.start = ALIGN(tmp.start, constraint->align);
-		avail.end = tmp.end;
-		avail.flags = new->flags & ~IORESOURCE_UNSET;
-		if (avail.start >= tmp.start) {
-			alloc.flags = avail.flags;
-			alloc.start = constraint->alignf(constraint->alignf_data, &avail,
+		avail->start = ALIGN(tmp.start, constraint->align);
+		avail->end = tmp.end;
+		avail->flags = new->flags & ~IORESOURCE_UNSET;
+		if (avail->start >= tmp.start) {
+			alloc.flags = avail->flags;
+			alloc.start = constraint->alignf(
+					constraint->alignf_data, avail,
 					size, constraint->align);
 			alloc.end = alloc.start + size - 1;
-			if (resource_contains(&avail, &alloc)) {
+			if (resource_contains(avail, &alloc)) {
 				new->start = alloc.start;
 				new->end = alloc.end;
 				return 0;
@@ -608,6 +613,11 @@ next:		if (!this || this->end == root->end)
 	return -EBUSY;
 }
 
+struct good_resource {
+	struct list_head list;
+	struct resource avail;
+	struct resource new;
+};
 /*
  * Find empty slot in the resource tree given range and alignment.
  */
@@ -615,7 +625,49 @@ static int find_resource(struct resource *root, struct resource *new,
 			resource_size_t size,
 			struct resource_constraint  *constraint)
 {
-	return  __find_resource(root, NULL, new, size, constraint);
+	int ret = -1;
+	LIST_HEAD(head);
+	struct good_resource *good, *tmp;
+	resource_size_t avail_size = (resource_size_t)-1ULL;
+
+	if (!constraint->fit)
+		return __find_resource(root, NULL, new, NULL, size,
+					constraint);
+
+	/* find all suitable ones and add to the list */
+	for (;;) {
+		good = kzalloc(sizeof(*good), GFP_KERNEL);
+		if (!good)
+			break;
+
+		good->new.start = new->start;
+		good->new.end = new->end;
+		good->new.flags = new->flags;
+		ret = __find_resource(root, NULL, &good->new, &good->avail,
+					size, constraint);
+		if (ret || __request_resource(root, &good->avail)) {
+			ret = -EBUSY;
+			kfree(good);
+			break;
+		}
+
+		list_add(&good->list, &head);
+	}
+
+	/* pick up the smallest one and delete the list */
+	list_for_each_entry_safe(good, tmp, &head, list) {
+		if (resource_size(&good->avail) < avail_size) {
+			avail_size = resource_size(&good->avail);
+			new->start = good->new.start;
+			new->end = good->new.end;
+			ret = 0;
+		}
+		list_del(&good->list);
+		__release_resource(&good->avail);
+		kfree(good);
+	}
+
+	return ret;
 }
 
 /**
@@ -636,7 +688,8 @@ static int __reallocate_resource(struct resource *root, struct resource *old,
 	struct resource new = *old;
 	struct resource *conflict;
 
-	if ((err = __find_resource(root, old, &new, newsize, constraint)))
+	err = __find_resource(root, old, &new, NULL, newsize, constraint);
+	if (err)
 		goto out;
 
 	if (resource_contains(&new, old)) {
@@ -675,6 +728,7 @@ out:
  * @align: alignment requested, in bytes
  * @alignf: alignment function, optional, called if not NULL
  * @alignf_data: arbitrary data to pass to the @alignf function
+ * @fit: only allocate fit range.
  *
  * Caller need to hold resource_lock if needed.
  */
@@ -685,7 +739,7 @@ static int __allocate_resource(struct resource *root, struct resource *new,
 						  const struct resource *,
 						  resource_size_t,
 						  resource_size_t),
-				void *alignf_data)
+				void *alignf_data, bool fit)
 {
 	int err;
 	struct resource_constraint constraint;
@@ -698,6 +752,7 @@ static int __allocate_resource(struct resource *root, struct resource *new,
 	constraint.align = align;
 	constraint.alignf = alignf;
 	constraint.alignf_data = alignf_data;
+	constraint.fit = fit;
 
 	if (new->parent) {
 		/* resource is already allocated, try reallocating with
@@ -738,7 +793,7 @@ int allocate_resource(struct resource *root, struct resource *new,
 
 	write_lock(&resource_lock);
 	ret = __allocate_resource(root, new, size, min, max, align,
-				   alignf, alignf_data);
+				   alignf, alignf_data, true);
 	write_unlock(&resource_lock);
 
 	return ret;
-- 
1.8.4.5


  parent reply	other threads:[~2015-07-06 23:39 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-06 23:38 [PATCH 00/36] PCI: Resource allocation cleanup for v4.3 Yinghai Lu
2015-07-06 23:38 ` [PATCH 01/36] PCI: Cleanup res_to_dev_res() printout for addon resources Yinghai Lu
2015-07-06 23:38 ` [PATCH 02/36] PCI: Reuse res_to_dev_res in reassign_resources_sorted Yinghai Lu
2015-07-06 23:38 ` [PATCH 03/36] PCI: Use correct align for optional only resources during sorting for resource allocation Yinghai Lu
2015-07-06 23:38 ` [PATCH 04/36] PCI: Optimize bus align/size calculation during sizing Yinghai Lu
2015-07-06 23:38 ` [PATCH 05/36] PCI: Optimize bus align/size calculation for optional " Yinghai Lu
2015-07-06 23:38 ` [PATCH 06/36] PCI: Reorder resources list for must/optional resources Yinghai Lu
2015-07-06 23:38 ` [PATCH 07/36] PCI: Remove duplicated code for resource sorting Yinghai Lu
2015-07-06 23:38 ` [PATCH 08/36] PCI: Rename pdev_sort_resources to pdev_check_resources Yinghai Lu
2015-07-06 23:38 ` [PATCH 09/36] PCI: Treat ROM resource as optional during realloc Yinghai Lu
2015-07-06 23:39 ` [PATCH 10/36] PCI: Add debug printout during releasing partial must/optinal assigned resources Yinghai Lu
2015-07-06 23:39 ` [PATCH 11/36] PCI: Simplify res reference using in __assign_resourcs_sorted Yinghai Lu
2015-07-06 23:39 ` [PATCH 12/36] PCI: Separate realloc list checking after allocation Yinghai Lu
2015-07-06 23:39 ` [PATCH 13/36] PCI: Add __add_to_list() Yinghai Lu
2015-07-06 23:39 ` [PATCH 14/36] PCI: Separate must_add assigning to another function Yinghai Lu
2015-07-06 23:39 ` [PATCH 15/36] PCI: Bail out early if there is no addon Yinghai Lu
2015-07-06 23:39 ` [PATCH 16/36] PCI: Add alt_size allocation support Yinghai Lu
2015-07-06 23:39 ` [PATCH 17/36] PCI: Add support for more than two alt_size under same bridge Yinghai Lu
2015-07-15  3:07   ` Yijing Wang
2015-07-15  5:08     ` Yinghai Lu
2015-07-15  5:16       ` Yijing Wang
2015-07-06 23:39 ` [PATCH 18/36] PCI: Better support for two alt_size Yinghai Lu
2015-07-06 23:39 ` [PATCH 19/36] resources: Split out __allocate_resource() Yinghai Lu
2015-07-06 23:39 ` Yinghai Lu [this message]
2015-07-06 23:39 ` [PATCH 21/36] PCI: Check pref compatible bit for mem64 resource of pcie device Yinghai Lu
2015-07-06 23:39 ` [PATCH 22/36] PCI: Only treat non-pef mmio64 as pref if all bridges has MEM_64 Yinghai Lu
2015-07-06 23:39 ` [PATCH 23/36] PCI: Add has_mem64 for host_bridge Yinghai Lu
2015-07-06 23:39 ` [PATCH 24/36] PCI: Only treat non-pef mmio64 as pref if host-bridge has_mem64 Yinghai Lu
2015-07-06 23:39 ` [PATCH 25/36] PCI: Restore pref mmio allocation logic for hostbridge without mmio64 Yinghai Lu
2015-07-06 23:39 ` [PATCH 26/36] sparc/PCI: Add mem64 resource parsing for root bus Yinghai Lu
2015-07-06 23:39 ` [PATCH 27/36] sparc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in of parsing Yinghai Lu
2015-07-06 23:39 ` [PATCH 28/36] powerpc/PCI: " Yinghai Lu
2015-07-06 23:39 ` [PATCH 29/36] of/PCI: Add IORESOURCE_MEM_64 for 64-bit resource Yinghai Lu
2015-07-10 20:21   ` Rob Herring
2015-07-06 23:39 ` [PATCH 30/36] PCI: Treat optional as must in first try for bridge rescan Yinghai Lu
2015-07-06 23:39 ` [PATCH 31/36] PCI: Get new realloc size for bridge for last try Yinghai Lu
2015-07-06 23:39 ` [PATCH 32/36] PCI: Don't release sibiling bridge resources during hotplug Yinghai Lu
2015-07-06 23:39 ` [PATCH 33/36] PCI: Don't release fixed resource for realloc Yinghai Lu
2015-07-06 23:39 ` [PATCH 34/36] PCI: Set resource to FIXED for lsi devices Yinghai Lu
2015-07-06 23:39 ` [PATCH 35/36] PCI, x86: Add pci=assign_pref_bars to re-allocate pref bars Yinghai Lu
2015-07-06 23:39 ` [PATCH 36/36] PCI: Don't set flags to 0 when assign resource fail Yinghai Lu
2015-07-09  3:30   ` Wei Yang
2015-07-09  5:01     ` Yinghai Lu
2015-07-09  6:04       ` Wei Yang
2015-07-09 16:20         ` Yinghai Lu
2015-07-10  2:30           ` Wei Yang
2015-07-10  2:48             ` Yinghai Lu
2015-07-10  5:49               ` Yinghai Lu
2015-07-11  0:03                 ` Wei Yang
2015-07-11  0:42                   ` Yinghai Lu
2015-07-11  1:37                     ` Wei Yang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1436225966-27247-21-git-send-email-yinghai@kernel.org \
    --to=yinghai@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=benh@kernel.crashing.org \
    --cc=bhelgaas@google.com \
    --cc=davem@davemloft.net \
    --cc=david.ahern@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux@iam.tj \
    --cc=wangyijing@huawei.com \
    --cc=weiyang@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).