[PATCH 2/2] PCI: make SRIOV BAR's nice to have resources.

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

 



Yinghai's patch that makes SRIOV BAR's nice-to-have resources.
This patch is ported to apply on top of the previous patch.

---
 drivers/pci/setup-bus.c |   55 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 146200c..2ff48dd 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -122,13 +122,16 @@ static inline void reset_resource(struct resource *res)
  *             resources
  * @head     : head of the list tracking requests with allocated
  *             resources
+ * @fail_head : head of the list tracking requests failed to allocate
+ *             resources
  *
  * Walk through each element of the add_head and try to procure
  * additional resources for the element, provided the element
  * is in the head list.
  */
 static void adjust_resources_sorted(struct resource_list_x *add_head,
-		struct resource_list *head)
+		struct resource_list *head,
+		struct resource_list_x *fail_head)
 {
 	struct resource *res;
 	struct resource_list_x *list, *tmp, *prev;
@@ -155,9 +158,16 @@ static void adjust_resources_sorted(struct resource_list_x *add_head,
 		idx = res - &list->dev->resource[0];
 		add_size=list->add_size;
 		if (!resource_size(res)) {
-			 res->end = res->start + add_size - 1;
-			 if(pci_assign_resource(list->dev, idx))
-				reset_resource(res);
+			res->end = res->start + add_size - 1;
+			if(pci_assign_resource(list->dev, idx)) {
+#ifdef CONFIG_PCI_IOV
+				/* add to failed list for next loop */
+				if (fail_head && idx >= PCI_IOV_RESOURCES &&
+						idx <= PCI_IOV_RESOURCE_END)
+					add_to_failed_list(fail_head, list->dev,
+						 res);
+#endif
+			}
 		} else {
 			resource_size_t align = list->min_align;
 			res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
@@ -217,7 +227,7 @@ static void __assign_resources_sorted(struct resource_list *head,
 	/* Try to satisfy any additional nice-to-have resource
 		requests */
 	if (add_head)
-		adjust_resources_sorted(add_head, head);
+		adjust_resources_sorted(add_head, head, fail_head);
 	free_list(resource_list, head);
 }
 
@@ -541,6 +551,20 @@ static resource_size_t calculate_memsize(resource_size_t size,
 	return size;
 }
 
+static resource_size_t get_res_add_size(struct resource_list_x *add_head,
+					struct resource *res)
+{
+	struct resource_list_x *list;
+
+	/* check if it is in add_head list */
+	for (list = add_head->next; list && list->res != res;
+			list = list->next);
+	if (list)
+		return list->add_size;
+
+	return 0;
+}
+
 /**
  * pbus_size_io() - size the io window of a given bus
  *
@@ -560,6 +584,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 	struct pci_dev *dev;
 	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
 	unsigned long size = 0, size0 = 0, size1 = 0;
+	resource_size_t children_add_size = 0;
 
 	if (!b_res)
  		return;
@@ -580,10 +605,15 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 				size += r_size;
 			else
 				size1 += r_size;
+
+			if (add_head)
+				children_add_size += get_res_add_size(add_head, r);
 		}
 	}
 	size0 = calculate_iosize(size, min_size, size1,
 			resource_size(b_res), 4096);
+	if (children_add_size > add_size)
+		add_size = children_add_size;
 	size1 = (!add_head || (add_head && !add_size)) ? size0 :
 		calculate_iosize(size, min_size+add_size, size1,
 			resource_size(b_res), 4096);
@@ -625,6 +655,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus, type);
 	unsigned int mem64_mask = 0;
+	resource_size_t children_add_size = 0;
 
 	if (!b_res)
 		return 0;
@@ -646,6 +677,15 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			if (r->parent || (r->flags & mask) != type)
 				continue;
 			r_size = resource_size(r);
+#ifdef CONFIG_PCI_IOV
+			/* put SRIOV requested res to good to have list */
+			if (add_head && i >= PCI_IOV_RESOURCES &&
+					i <= PCI_IOV_RESOURCE_END) {
+				r->end = r->start - 1;
+				add_to_list(add_head, dev, r, r_size, 0);
+				r_size = 0;
+			}
+#endif
 			/* For bridges size != alignment */
 			align = pci_resource_alignment(dev, r);
 			order = __ffs(align) - 20;
@@ -666,6 +706,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			if (order > max_order)
 				max_order = order;
 			mem64_mask &= r->flags & IORESOURCE_MEM_64;
+
+			if (add_head)
+				children_add_size += get_res_add_size(add_head, r);
 		}
 	}
 	align = 0;
@@ -682,6 +725,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 		align += aligns[order];
 	}
 	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
+	if (children_add_size > add_size)
+		add_size = children_add_size;
 	size1 = (!add_head || (add_head && !add_size)) ? size0 :
 		calculate_memsize(size, min_size+add_size, 0,
 				resource_size(b_res), min_align);
-- 
1.7.1

--
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