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 11, 2011 at 12:49:59PM +1200, Michal Ludvig wrote:
> On 09/09/2011 11:34 PM, Ram Pai wrote:
> >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.
> 
> Hi Ram,
> 
> applied your patch on top of 3.1.0-rc5 and unfortunately it's not
> much better than it was. Log attached.
> 
> BTW Kernel bugzilla seems to be down, will update it later.
> 
> Michal

Hi Michal,

	Attaching yet another patch. Please revert the earlier patch
and apply this. I dont know if this will solve your problem.
if it does not, then I will have to send you a patch with lots
of printk to understand the root cause.  I suppose we can continue
our discussion on bugzilla. Thanks  for your help.


diff --git a/kernel/resource.c b/kernel/resource.c
index 3ff4017..4fcba8f 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,70 @@ 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;
+	}
+}
+
+static inline int check_overlap(struct resource *tmp,
+		resource_size_t start, resource_size_t end)
+{
+	return (tmp->start <= end && tmp->end >= start);
+}
+
+/*
+ * 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 = NULL, *prev, **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;
+		prev = tmp;
+		tmp = *p;
+
+		/* check for overlaps */
+		if (tmp && check_overlap(tmp, start, end)) {
+			if (tmp != old)
+				return -EBUSY;
+			if (tmp->sibling && check_overlap(tmp->sibling, start, end))
+				return -EBUSY;
+			old->start = start;
+			old->end = end;
+			return 0;
+		}
+
+		if (!tmp || tmp->start > end ) {
+			if (prev == old || 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 */
+			old->start = start;
+			old->end   = end;
+			*p_old = old->sibling;
+			old->sibling = tmp;
+			*p = old;
+			return 0;
+		}
+		p = &tmp->sibling;
 	}
 }
 
@@ -471,7 +528,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 +549,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