Re: [Bug 42002] Boot broken by "PCI : ability to relocate assigned pci-resources"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Sep 04, 2011 at 09:42:44PM +1200, Michal Ludvig wrote:
> Hi Bjorn,
> 
> On 09/02/2011 11:08 AM, Bjorn Helgaas wrote:
> >Thanks!  Can you reassign this to "Drivers/PCI" and set "Regression =
> >yes"?  I can't seem to do it myself.  Also, the logs look like console
> >logs, which don't include everything in the dmesg log unless you boot
> >with "ignore_loglevel".  Can you boot the failing one with
> >"ignore_loglevel"?  And maybe attach the "lspci -vv" output?
> 
> Attached in bugzilla as requested. Let me know if you need something more.
> https://bugzilla.kernel.org/show_bug.cgi?id=42002
> 
> Michal

Michal,

My patch assumed that the resource-range returned by __find_resource() will
always return a range that when allocated through request_resource() will not
lead to conflicts. However your platform somehow breaks that assumption.

I have rearranged the code to ensure that request_resource() returns
without conflicting overlaps; before returning success.


Please test the following new patch.
I have touch-tested on my machine and found it not to cause any problems.



diff --git a/kernel/resource.c b/kernel/resource.c
index 3ff4017..492d6f3 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -156,11 +156,7 @@ static struct resource * __request_resource(struct resource *root, struct resour
 	resource_size_t end = new->end;
 	struct resource *tmp, **p;
 
-	if (end < start)
-		return root;
-	if (start < root->start)
-		return root;
-	if (end > root->end)
+	if (end < start || start < root->start || end > root->end)
 		return root;
 	p = &root->child;
 	for (;;) {
@@ -172,9 +168,54 @@ static struct resource * __request_resource(struct resource *root, struct resour
 			return NULL;
 		}
 		p = &tmp->sibling;
-		if (tmp->end < start)
-			continue;
-		return tmp;
+		if (tmp->end >= start)
+			return tmp;
+	}
+}
+
+/*
+ * relocate the old resource, to the new position. Return error and do nothing
+ * if the new location conflicts with any other resource.
+ */
+static int  re_request_resource(struct resource *root,
+			struct resource *new, struct resource *old)
+{
+	resource_size_t start = new->start;
+	resource_size_t end = new->end;
+	struct resource *tmp, **p, **p_old  = NULL;
+
+	if (end < start || start < root->start || end > root->end)
+		return -EBUSY;
+	p = &root->child;
+	for (;;) {
+		if ( *p == old ) p_old = p;
+		tmp = *p;
+		if (!tmp || tmp->start > end) {
+
+			if (tmp == old) {
+				old->start = start;
+				old->end = end;
+				return 0;
+			}
+
+			if (!p_old) {
+				p_old = p;
+				while ( *p_old && old != (*p_old)->sibling )
+					p_old =  &(*p_old)->sibling;
+				BUG_ON(!*p_old);
+			}
+
+			/* relocate old */
+			*p_old = old->sibling;
+			old->start = start;
+			old->end   = end;
+			old->sibling = tmp;
+			*p = old;
+			return 0;
+		}
+		p = &tmp->sibling;
+		if (tmp->end >= start)
+			return -EBUSY;
 	}
 }
 
@@ -471,7 +512,6 @@ int reallocate_resource(struct resource *root, struct resource *old,
 {
 	int err=0;
 	struct resource new = *old;
-	struct resource *conflict;
 
 	write_lock(&resource_lock);
 
@@ -493,10 +533,7 @@ int reallocate_resource(struct resource *root, struct resource *old,
 		old->start = new.start;
 		old->end = new.end;
 	} else {
-		__release_resource(old);
-		*old = new;
-		conflict = __request_resource(root, old);
-		BUG_ON(conflict);
+	 	err = re_request_resource(root, &new, old);
 	}
 out:
 	write_unlock(&resource_lock);

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux