]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 20:40:23 +0000 (12:40 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 20:40:23 +0000 (12:40 -0800)
added patches:
pci-ability-to-relocate-assigned-pci-resources.patch
pci-calculate-right-add_size.patch

queue-3.0/pci-ability-to-relocate-assigned-pci-resources.patch [new file with mode: 0644]
queue-3.0/pci-calculate-right-add_size.patch [new file with mode: 0644]
queue-3.0/series

diff --git a/queue-3.0/pci-ability-to-relocate-assigned-pci-resources.patch b/queue-3.0/pci-ability-to-relocate-assigned-pci-resources.patch
new file mode 100644 (file)
index 0000000..3bc3a83
--- /dev/null
@@ -0,0 +1,325 @@
+From 2bbc6942273b5b3097bd265d82227bdd84b351b2 Mon Sep 17 00:00:00 2001
+From: Ram Pai <linuxram@us.ibm.com>
+Date: Mon, 25 Jul 2011 13:08:39 -0700
+Subject: PCI : ability to relocate assigned pci-resources
+
+From: Ram Pai <linuxram@us.ibm.com>
+
+commit 2bbc6942273b5b3097bd265d82227bdd84b351b2 upstream.
+
+Currently pci-bridges are allocated enough resources to satisfy their immediate
+requirements.  Any additional resource-requests fail if additional free space,
+contiguous to the one already allocated, is not available. This behavior is not
+reasonable since sufficient contiguous resources, that can satisfy the request,
+are available at a different location.
+
+This patch provides the ability to expand and relocate a allocated resource.
+
+       v2: Changelog: Fixed size calculation in pci_reassign_resource()
+       v3: Changelog : Split this patch. The resource.c changes are already
+                       upstream. All the pci driver changes are in here.
+
+Signed-off-by: Ram Pai <linuxram@us.ibm.com>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Cc: Andrew Worsley <amworsley@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/setup-bus.c |   27 +++++---
+ drivers/pci/setup-res.c |  150 ++++++++++++++++++++++++++++++------------------
+ include/linux/pci.h     |    1 
+ 3 files changed, 112 insertions(+), 66 deletions(-)
+
+--- a/drivers/pci/setup-bus.c
++++ b/drivers/pci/setup-bus.c
+@@ -34,6 +34,7 @@ struct resource_list_x {
+       resource_size_t start;
+       resource_size_t end;
+       resource_size_t add_size;
++      resource_size_t min_align;
+       unsigned long flags;
+ };
+@@ -65,7 +66,7 @@ void pci_realloc(void)
+  */
+ static void add_to_list(struct resource_list_x *head,
+                struct pci_dev *dev, struct resource *res,
+-               resource_size_t add_size)
++               resource_size_t add_size, resource_size_t min_align)
+ {
+       struct resource_list_x *list = head;
+       struct resource_list_x *ln = list->next;
+@@ -84,13 +85,16 @@ static void add_to_list(struct resource_
+       tmp->end = res->end;
+       tmp->flags = res->flags;
+       tmp->add_size = add_size;
++      tmp->min_align = min_align;
+       list->next = tmp;
+ }
+ static void add_to_failed_list(struct resource_list_x *head,
+                               struct pci_dev *dev, struct resource *res)
+ {
+-      add_to_list(head, dev, res, 0);
++      add_to_list(head, dev, res,
++                      0 /* dont care */,
++                      0 /* dont care */);
+ }
+ static void __dev_sort_resources(struct pci_dev *dev,
+@@ -159,13 +163,16 @@ static void adjust_resources_sorted(stru
+               idx = res - &list->dev->resource[0];
+               add_size=list->add_size;
+-              if (!resource_size(res) && add_size) {
+-                       res->end = res->start + add_size - 1;
+-                       if(pci_assign_resource(list->dev, idx))
++              if (!resource_size(res)) {
++                      res->end = res->start + add_size - 1;
++                      if(pci_assign_resource(list->dev, idx))
+                               reset_resource(res);
+-              } else if (add_size) {
+-                      adjust_resource(res, res->start,
+-                              resource_size(res) + add_size);
++              } else {
++                      resource_size_t align = list->min_align;
++                      res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
++                      if (pci_reassign_resource(list->dev, idx, add_size, align))
++                              dev_printk(KERN_DEBUG, &list->dev->dev, "failed to add optional resources res=%pR\n",
++                                                      res);
+               }
+ out:
+               tmp = list;
+@@ -622,7 +629,7 @@ static void pbus_size_io(struct pci_bus
+       b_res->end = b_res->start + size0 - 1;
+       b_res->flags |= IORESOURCE_STARTALIGN;
+       if (size1 > size0 && add_head)
+-              add_to_list(add_head, bus->self, b_res, size1-size0);
++              add_to_list(add_head, bus->self, b_res, size1-size0, 4096);
+ }
+ /**
+@@ -725,7 +732,7 @@ static int pbus_size_mem(struct pci_bus
+       b_res->end = size0 + min_align - 1;
+       b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
+       if (size1 > size0 && add_head)
+-              add_to_list(add_head, bus->self, b_res, size1-size0);
++              add_to_list(add_head, bus->self, b_res, size1-size0, min_align);
+       return 1;
+ }
+--- a/drivers/pci/setup-res.c
++++ b/drivers/pci/setup-res.c
+@@ -129,16 +129,16 @@ void pci_disable_bridge_window(struct pc
+ }
+ #endif        /* CONFIG_PCI_QUIRKS */
++
++
+ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
+-                               int resno)
++              int resno, resource_size_t size, resource_size_t align)
+ {
+       struct resource *res = dev->resource + resno;
+-      resource_size_t size, min, align;
++      resource_size_t min;
+       int ret;
+-      size = resource_size(res);
+       min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+-      align = pci_resource_alignment(dev, res);
+       /* First, try exact prefetching match.. */
+       ret = pci_bus_alloc_resource(bus, res, size, align, min,
+@@ -155,56 +155,101 @@ static int __pci_assign_resource(struct
+               ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
+                                            pcibios_align_resource, dev);
+       }
++      return ret;
++}
+-      if (ret < 0 && dev->fw_addr[resno]) {
+-              struct resource *root, *conflict;
+-              resource_size_t start, end;
++static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
++              int resno, resource_size_t size)
++{
++      struct resource *root, *conflict;
++      resource_size_t start, end;
++      int ret = 0;
++
++      if (res->flags & IORESOURCE_IO)
++              root = &ioport_resource;
++      else
++              root = &iomem_resource;
++
++      start = res->start;
++      end = res->end;
++      res->start = dev->fw_addr[resno];
++      res->end = res->start + size - 1;
++      dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
++               resno, res);
++      conflict = request_resource_conflict(root, res);
++      if (conflict) {
++              dev_info(&dev->dev,
++                       "BAR %d: %pR conflicts with %s %pR\n", resno,
++                       res, conflict->name, conflict);
++              res->start = start;
++              res->end = end;
++              ret = 1;
++      }
++      return ret;
++}
+-              /*
+-               * If we failed to assign anything, let's try the address
+-               * where firmware left it.  That at least has a chance of
+-               * working, which is better than just leaving it disabled.
+-               */
++static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align)
++{
++      struct resource *res = dev->resource + resno;
++      struct pci_bus *bus;
++      int ret;
++      char *type;
+-              if (res->flags & IORESOURCE_IO)
+-                      root = &ioport_resource;
++      bus = dev->bus;
++      while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
++              if (!bus->parent || !bus->self->transparent)
++                      break;
++              bus = bus->parent;
++      }
++
++      if (ret) {
++              if (res->flags & IORESOURCE_MEM)
++                      if (res->flags & IORESOURCE_PREFETCH)
++                              type = "mem pref";
++                      else
++                              type = "mem";
++              else if (res->flags & IORESOURCE_IO)
++                      type = "io";
+               else
+-                      root = &iomem_resource;
++                      type = "unknown";
++              dev_info(&dev->dev,
++                       "BAR %d: can't assign %s (size %#llx)\n",
++                       resno, type, (unsigned long long) resource_size(res));
++      }
+-              start = res->start;
+-              end = res->end;
+-              res->start = dev->fw_addr[resno];
+-              res->end = res->start + size - 1;
+-              dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
+-                       resno, res);
+-              conflict = request_resource_conflict(root, res);
+-              if (conflict) {
+-                      dev_info(&dev->dev,
+-                               "BAR %d: %pR conflicts with %s %pR\n", resno,
+-                               res, conflict->name, conflict);
+-                      res->start = start;
+-                      res->end = end;
+-              } else
+-                      ret = 0;
++      return ret;
++}
++
++int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
++                      resource_size_t min_align)
++{
++      struct resource *res = dev->resource + resno;
++      resource_size_t new_size;
++      int ret;
++
++      if (!res->parent) {
++              dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resouce %pR "
++                       "\n", resno, res);
++              return -EINVAL;
+       }
++      new_size = resource_size(res) + addsize + min_align;
++      ret = _pci_assign_resource(dev, resno, new_size, min_align);
+       if (!ret) {
+               res->flags &= ~IORESOURCE_STARTALIGN;
+               dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
+               if (resno < PCI_BRIDGE_RESOURCES)
+                       pci_update_resource(dev, resno);
+       }
+-
+       return ret;
+ }
+ int pci_assign_resource(struct pci_dev *dev, int resno)
+ {
+       struct resource *res = dev->resource + resno;
+-      resource_size_t align;
++      resource_size_t align, size;
+       struct pci_bus *bus;
+       int ret;
+-      char *type;
+       align = pci_resource_alignment(dev, res);
+       if (!align) {
+@@ -214,34 +259,27 @@ int pci_assign_resource(struct pci_dev *
+       }
+       bus = dev->bus;
+-      while ((ret = __pci_assign_resource(bus, dev, resno))) {
+-              if (bus->parent && bus->self->transparent)
+-                      bus = bus->parent;
+-              else
+-                      bus = NULL;
+-              if (bus)
+-                      continue;
+-              break;
+-      }
++      size = resource_size(res);
++      ret = _pci_assign_resource(dev, resno, size, align);
+-      if (ret) {
+-              if (res->flags & IORESOURCE_MEM)
+-                      if (res->flags & IORESOURCE_PREFETCH)
+-                              type = "mem pref";
+-                      else
+-                              type = "mem";
+-              else if (res->flags & IORESOURCE_IO)
+-                      type = "io";
+-              else
+-                      type = "unknown";
+-              dev_info(&dev->dev,
+-                       "BAR %d: can't assign %s (size %#llx)\n",
+-                       resno, type, (unsigned long long) resource_size(res));
+-      }
++      /*
++       * If we failed to assign anything, let's try the address
++       * where firmware left it.  That at least has a chance of
++       * working, which is better than just leaving it disabled.
++       */
++      if (ret < 0 && dev->fw_addr[resno])
++              ret = pci_revert_fw_address(res, dev, resno, size);
++      if (!ret) {
++              res->flags &= ~IORESOURCE_STARTALIGN;
++              dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
++              if (resno < PCI_BRIDGE_RESOURCES)
++                      pci_update_resource(dev, resno);
++      }
+       return ret;
+ }
++
+ /* Sort resources by alignment */
+ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+ {
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -800,6 +800,7 @@ int __pci_reset_function(struct pci_dev
+ int pci_reset_function(struct pci_dev *dev);
+ void pci_update_resource(struct pci_dev *dev, int resno);
+ int __must_check pci_assign_resource(struct pci_dev *dev, int i);
++int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
+ int pci_select_bars(struct pci_dev *dev, unsigned long flags);
+ /* ROM control related routines */
diff --git a/queue-3.0/pci-calculate-right-add_size.patch b/queue-3.0/pci-calculate-right-add_size.patch
new file mode 100644 (file)
index 0000000..287337d
--- /dev/null
@@ -0,0 +1,105 @@
+From a4ac9fea016fc5c09227eb479bd35e34978323a4 Mon Sep 17 00:00:00 2001
+From: Yinghai Lu <yinghai@kernel.org>
+Date: Sat, 21 Jan 2012 02:08:17 -0800
+Subject: PCI : Calculate right add_size
+
+From: Yinghai Lu <yinghai@kernel.org>
+
+commit a4ac9fea016fc5c09227eb479bd35e34978323a4 upstream.
+
+During debug of one SRIOV enabled hotplug device, we found found that
+add_size is not passed properly.
+
+The device has devices under two level bridges:
+
+ +-[0000:80]-+-00.0-[81-8f]--
+ |           +-01.0-[90-9f]--
+ |           +-02.0-[a0-af]----00.0-[a1-a3]--+-02.0-[a2]--+-00.0  Oracle Corporation Device
+ |           |                               \-03.0-[a3]--+-00.0  Oracle Corporation Device
+
+Which means later the parent bridge will not try to add a big enough range:
+
+[  557.455077] pci 0000:a0:00.0: BAR 14: assigned [mem 0xf9000000-0xf93fffff]
+[  557.461974] pci 0000:a0:00.0: BAR 15: assigned [mem 0xf6000000-0xf61fffff pref]
+[  557.469340] pci 0000:a1:02.0: BAR 14: assigned [mem 0xf9000000-0xf91fffff]
+[  557.476231] pci 0000:a1:02.0: BAR 15: assigned [mem 0xf6000000-0xf60fffff pref]
+[  557.483582] pci 0000:a1:03.0: BAR 14: assigned [mem 0xf9200000-0xf93fffff]
+[  557.490468] pci 0000:a1:03.0: BAR 15: assigned [mem 0xf6100000-0xf61fffff pref]
+[  557.497833] pci 0000:a1:03.0: BAR 14: can't assign mem (size 0x200000)
+[  557.504378] pci 0000:a1:03.0: failed to add optional resources res=[mem 0xf9200000-0xf93fffff]
+[  557.513026] pci 0000:a1:02.0: BAR 14: can't assign mem (size 0x200000)
+[  557.519578] pci 0000:a1:02.0: failed to add optional resources res=[mem 0xf9000000-0xf91fffff]
+
+It turns out we did not calculate size1 properly.
+
+static resource_size_t calculate_memsize(resource_size_t size,
+                resource_size_t min_size,
+                resource_size_t size1,
+                resource_size_t old_size,
+                resource_size_t align)
+{
+        if (size < min_size)
+                size = min_size;
+        if (old_size == 1 )
+                old_size = 0;
+        if (size < old_size)
+                size = old_size;
+        size = ALIGN(size + size1, align);
+        return size;
+}
+
+We should not pass add_size with min_size in calculate_memsize since
+that will make add_size not contribute final add_size.
+
+So just pass add_size with size1 to calculate_memsize().
+
+With this change, we should have chance to remove extra addon in
+pci_reassign_resource.
+
+Signed-off-by: Yinghai Lu <yinghai@kernel.org>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Cc: Andrew Worsley <amworsley@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/setup-bus.c |    4 ++--
+ drivers/pci/setup-res.c |    5 +++--
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/setup-bus.c
++++ b/drivers/pci/setup-bus.c
+@@ -614,7 +614,7 @@ static void pbus_size_io(struct pci_bus
+       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,
++              calculate_iosize(size, min_size, add_size + size1,
+                       resource_size(b_res), 4096);
+       if (!size0 && !size1) {
+               if (b_res->start || b_res->end)
+@@ -718,7 +718,7 @@ static int pbus_size_mem(struct pci_bus
+       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,
++              calculate_memsize(size, min_size, add_size,
+                               resource_size(b_res), min_align);
+       if (!size0 && !size1) {
+               if (b_res->start || b_res->end)
+--- a/drivers/pci/setup-res.c
++++ b/drivers/pci/setup-res.c
+@@ -233,11 +233,12 @@ int pci_reassign_resource(struct pci_dev
+               return -EINVAL;
+       }
+-      new_size = resource_size(res) + addsize + min_align;
++      /* already aligned with min_align */
++      new_size = resource_size(res) + addsize;
+       ret = _pci_assign_resource(dev, resno, new_size, min_align);
+       if (!ret) {
+               res->flags &= ~IORESOURCE_STARTALIGN;
+-              dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
++              dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
+               if (resno < PCI_BRIDGE_RESOURCES)
+                       pci_update_resource(dev, resno);
+       }
index f23eb477ebc78e00bf830f025e6163eb67fc3612..eb122b4bd0eeda060c338ae0ee89f0c6a2c6a978 100644 (file)
@@ -34,3 +34,5 @@ reiserfs-protect-reiserfs_quota_on-with-write-lock.patch
 reiserfs-move-quota-calls-out-of-write-lock.patch
 reiserfs-protect-reiserfs_quota_write-with-write-lock.patch
 selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch
+pci-ability-to-relocate-assigned-pci-resources.patch
+pci-calculate-right-add_size.patch