]> git.hungrycats.org Git - linux/commitdiff
[PATCH] 2.5.14: New PCI allocation code (alpha, arm, parisc) [1/2]
authorIvan Kokshaysky <ink@jurassic.park.msu.ru>
Tue, 7 May 2002 03:27:32 +0000 (20:27 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 7 May 2002 03:27:32 +0000 (20:27 -0700)
This changes PCI resource allocation algorithm to 3 passes vs.
current 2 passes. Extra pass is used for calculation of required
size and alignment of PCI buses behind PCI-PCI bridges. After
that, in the pass #3, these buses get allocated like regular
PCI devices. This gives tighter PCI IO and memory packing -
for instance, this fixes allocation problems on certain alphas
with very small (112Mb) PCI memory range. Also, the new code
- will allow mixed approach to resource allocation:
  architecture can keep BIOS settings for some devices,
  and re-allocate resources for others, including improperly
  initialized bridges;
- makes prefetchable ranges support much simpler;
- allows sizing of IO and memory ranges for the host
  bridges, which might be very useful in some situations.

It was tested on various alphas; I haven't heard any complaints
from rmk and rth, so probably all of this is ok. :-)

Part 1:
- for all archs, 4th argument (align) added to
  pcibios_align_resource (and its callers).
  It's necessary because this function will be called for
  bus resources as well, and in this case size != alignment.
- for several archs, dead/bogus code removed from
  pcibios_fixup_pbus_ranges().

27 files changed:
arch/alpha/kernel/pci.c
arch/arm/kernel/bios32.c
arch/i386/kernel/pci/i386.c
arch/ia64/kernel/pci.c
arch/mips/ddb5074/pci.c
arch/mips/ddb5476/pci.c
arch/mips/ddb5xxx/common/pci.c
arch/mips/gt64120/common/pci.c
arch/mips/ite-boards/generic/it8172_pci.c
arch/mips/kernel/pci.c
arch/mips/mips-boards/generic/pci.c
arch/mips/sni/pci.c
arch/mips64/mips-boards/generic/pci.c
arch/mips64/sgi-ip27/ip27-pci.c
arch/mips64/sgi-ip32/ip32-pci.c
arch/parisc/kernel/pci.c
arch/ppc/kernel/pci.c
arch/ppc64/kernel/pci.c
arch/sh/kernel/pci_st40.c
arch/sh/kernel/pcibios.c
arch/sparc/kernel/pcic.c
arch/sparc64/kernel/pci.c
arch/x86_64/kernel/pci-x86_64.c
drivers/pci/setup-res.c
include/linux/ioport.h
include/linux/pci.h
kernel/resource.c

index f7bb7c60b4a8096518fe9ce9c33621f1a1c743c0..90ce900f87a43a5c20dc1f477322c22a0e6abf40 100644 (file)
@@ -128,7 +128,8 @@ struct pci_fixup pcibios_fixups[] __initdata = {
 #define GB                     (1024*MB)
 
 void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
        struct pci_dev *dev = data;
        struct pci_controller *hose = dev->sysdata;
@@ -168,7 +169,7 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size)
                 */
 
                /* Align to multiple of size of minimum base.  */
-               alignto = MAX(0x1000, size);
+               alignto = MAX(0x1000, align);
                start = ALIGN(start, alignto);
                if (hose->sparse_mem_base && size <= 7 * 16*MB) {
                        if (((start / (16*MB)) & 0x7) == 0) {
index 55231f66c56a84e7e1f86f550ce5ccd9973c90b8..5a10bf3956abb87544299f48e1596188e19eb55e 100644 (file)
@@ -662,7 +662,8 @@ char * __init pcibios_setup(char *str)
  * but we want to try to avoid allocating at 0x2900-0x2bff
  * which might be mirrored at 0x0100-0x03ff..
  */
-void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+void pcibios_align_resource(void *data, struct resource *res,
+                           unsigned long size, unsigned long align)
 {
        if (res->flags & IORESOURCE_IO) {
                unsigned long start = res->start;
index 27a14f0b317a1a06e9ef6027611bdb2444db23b0..830ea58c32c65f55f1246a212e1754b1b9675476 100644 (file)
@@ -75,7 +75,8 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
  * which might have be mirrored at 0x0100-0x03ff..
  */
 void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
        if (res->flags & IORESOURCE_IO) {
                unsigned long start = res->start;
index 3a4725bace0b3afb4354971d421b9ae8f72f4df1..271230162e2aad8bd5a3ab7c8a25cc7e0847040d 100644 (file)
@@ -259,10 +259,6 @@ pcibios_update_irq (struct pci_dev *dev, int irq)
 void __init
 pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
 {
-       ranges->io_start -= bus->resource[0]->start;
-       ranges->io_end -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end -= bus->resource[1]->start;
 }
 
 int
@@ -278,7 +274,8 @@ pcibios_enable_device (struct pci_dev *dev)
 }
 
 void
-pcibios_align_resource (void *data, struct resource *res, unsigned long size)
+pcibios_align_resource (void *data, struct resource *res,
+                       unsigned long size, unsigned long align)
 {
 }
 
index 919fbb1cee9cf96531914a6f998849a3116e6d3f..7453785b7db8534cddc2ef48559dc422c2a40d72 100644 (file)
@@ -319,10 +319,6 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus,
                                      struct pbus_set_ranges_data *ranges)
 {
-       ranges->io_start -= bus->resource[0]->start;
-       ranges->io_end -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end -= bus->resource[1]->start;
 }
 
 int pcibios_enable_resources(struct pci_dev *dev)
@@ -396,7 +392,7 @@ void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
 }
 
 void pcibios_align_resource(void *data, struct resource *res,
-                           unsigned long size)
+                           unsigned long size, unsigned long align)
 {
        struct pci_dev *dev = data;
 
index 264e95af6deb3fa984714c62538e206a10017f86..59e984d9a924e2b51091145621032a501429b928 100644 (file)
@@ -470,7 +470,7 @@ void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
 }
 
 void pcibios_align_resource(void *data, struct resource *res,
-                           unsigned long size)
+                           unsigned long size, unsigned long align)
 {
        struct pci_dev *dev = data;
 
index 33cc327d8d1c3cedb5a6390d81494a89dda83f12..23082d5544e42a0832a013f1ac650f73b4c27829 100644 (file)
@@ -164,7 +164,8 @@ char *pcibios_setup(char *str)
 }
 
 void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
        /* this should not be called */
        MIPS_ASSERT(1 == 0);
index 5f9a05e45246e799ba0cf23b83a427a18016296c..93283099ccccd6e0e06904b0dd2530a8b2db2931 100644 (file)
@@ -886,7 +886,7 @@ void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
 }
 
 void pcibios_align_resource(void *data, struct resource *res,
-                           unsigned long size)
+                           unsigned long size, unsigned long align)
 {
        struct pci_dev *dev = data;
 
index 713ae41283ce2d801df0ac505377e5a558818205..b20807a702b6e9dbc9a8716ca821373416d8b990 100644 (file)
@@ -241,7 +241,8 @@ pcibios_enable_device(struct pci_dev *dev)
 
 
 void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
     printk("pcibios_align_resource\n");
 }
index 0cc855fb32374ea2776a0c247d4f3c94e84eb727..0437fc375d0cb4f1ca65a8cd60c9054cef9817d8 100644 (file)
@@ -161,7 +161,8 @@ char *pcibios_setup(char *str)
 }
 
 void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
        /* this should not be called */
 }
index 900e2af1611ef678aa355a97b68b59f4c9403c11..d8e9f73192691833725dc2ebf24e0a697c1ea494 100644 (file)
@@ -286,7 +286,8 @@ pcibios_enable_device(struct pci_dev *dev)
 }
 
 void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
 }
 
index 080324211391ea46edf86a5d3a6b59e314b3d0ae..3499b222b813c8faa8dd3a9f168683e17197af36 100644 (file)
@@ -199,7 +199,8 @@ int __init pcibios_enable_device(struct pci_dev *dev)
 }
 
 void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
 }
 
index 073f4e8cf25038fb7a3cd4f06e06deef99808793..513042d8bbf62aa4000b2e371f6a3e0cf4f73c32 100644 (file)
@@ -290,7 +290,8 @@ pcibios_enable_device(struct pci_dev *dev)
 }
 
 void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
 }
 
index da315783a68cf1fdb0d07f4748059dc4eaef69ce..1560f6c6537263b92071cc170f2fdbb658acda7c 100644 (file)
@@ -238,10 +238,6 @@ void __init
 pcibios_fixup_pbus_ranges(struct pci_bus * bus,
                           struct pbus_set_ranges_data * ranges)
 {
-       ranges->io_start  -= bus->resource[0]->start;
-       ranges->io_end    -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end   -= bus->resource[1]->start;
 }
 
 int __init
@@ -252,7 +248,8 @@ pcibios_enable_device(struct pci_dev *dev)
 }
 
 void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
 }
 
index 99a102b0c7aba7315cb69c35ade66652b6fa1fc2..5cc9cd86d6729c7cd9728cd25b92e39f664521e0 100644 (file)
@@ -329,7 +329,7 @@ char * __init pcibios_setup (char *str)
 }
 
 void __init pcibios_align_resource (void *data, struct resource *res,
-                                   unsigned long size)
+                                   unsigned long size, unsigned long align)
 {
 }
 
@@ -352,10 +352,6 @@ void __init pcibios_fixup_bus (struct pci_bus *b)
 void __init pcibios_fixup_pbus_ranges(struct pci_bus * bus,
                                      struct pbus_set_ranges_data * ranges)
 {
-       ranges->io_start -= bus->resource[0]->start;
-       ranges->io_end -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end -= bus->resource[1]->start;
 }
 
 /*
index a46f69832b60b9a7735ee7f86a6ceccb72725071..20d3311631a6868adcc1e33f7814da4f09a9c076 100644 (file)
@@ -337,13 +337,15 @@ void pcibios_fixup_pbus_ranges(
 ** than res->start.
 */
 void __devinit
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long alignment)
 {
        unsigned long mask, align;
 
-       DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx)\n",
+       DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n",
                ((struct pci_dev *) data)->slot_name,
-               res->parent, res->start, res->end, (int) res->flags, size);
+               res->parent, res->start, res->end,
+               (int) res->flags, size, alignment);
 
        /* has resource already been aligned/assigned? */
        if (res->parent)
@@ -400,11 +402,11 @@ pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
 
                        if (res.flags & IORESOURCE_IO) {
                                res.start = inner.io_end;
-                               pcibios_align_resource(dev, &res, size);
+                               pcibios_align_resource(dev, &res, size, 0);
                                inner.io_end += res.start + size;
                        } else if (res.flags & IORESOURCE_MEM) {
                                res.start = inner.mem_end;
-                               pcibios_align_resource(dev, &res, size);
+                               pcibios_align_resource(dev, &res, size, 0);
                                inner.mem_end = res.start + size;
                        }
 
index 77e1de956a6b289282f5965fd94486e78dd149e2..13ed868b0f0c76ab3d00fc052ea8d1f5cc3c028b 100644 (file)
@@ -1083,10 +1083,6 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp)
 void __init
 pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
 {
-       ranges->io_start -= bus->resource[0]->start;
-       ranges->io_end -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end -= bus->resource[1]->start;
 }
 
 unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
index c1a69658d87a7e00b95e3228f9a7ff3917d367fa..4ce2729d8524d825f32ae942b60be28f3fb07456 100644 (file)
@@ -180,7 +180,8 @@ pcibios_fixup_resources(struct pci_dev* dev)
  * which might have be mirrored at 0x0100-0x03ff..
  */
 void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
        struct pci_dev *dev = data;
 
index 0754b0387e59980bdbcf65da9c50c7057918d859..7f47cb6e512c042a2002e31db1fd754cbba44701 100644 (file)
@@ -414,10 +414,6 @@ void __init
 pcibios_fixup_pbus_ranges(struct pci_bus *bus,
                          struct pbus_set_ranges_data *ranges)
 {
-       ranges->io_start -= bus->resource[0]->start;
-       ranges->io_end -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end -= bus->resource[1]->start;
 }
 
 void __init pcibios_init(void)
index 19a5a29905fff6a8a6a4b2477a22d53322c49622..cfd0adb401fb8b49135cf0fb2c792aec879ba6d6 100644 (file)
@@ -60,7 +60,8 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
  * addresses to be allocated in the 0x000-0x0ff region
  * modulo 0x400.
  */
-void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+void pcibios_align_resource(void *data, struct resource *res,
+                           unsigned long size, unsigned long align)
 {
        if (res->flags & IORESOURCE_IO) {
                unsigned long start = res->start;
index 5bc6a12f1b43faf0e7ff83d503d42edeee970c11..0bc967629b66a4915ce1dbe75d2d1dddc82b0b3a 100644 (file)
@@ -865,7 +865,8 @@ void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,
 {
 }
 
-void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+void pcibios_align_resource(void *data, struct resource *res,
+                           unsigned long size, unsigned long align)
 {
 }
 
index bca907b6e1861ce3661fb51f5d24c03f2d9e284e..f1f8492cd01fb51d8e4d396fbc81cafcc10e761c 100644 (file)
@@ -311,7 +311,8 @@ void pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
 {
 }
 
-void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+void pcibios_align_resource(void *data, struct resource *res,
+                           unsigned long size, unsigned long align)
 {
 }
 
index 781e1c021e075870bc09162c25d374f839df5019..c8737eb46cb262e6162f62c762c178ab935be220 100644 (file)
@@ -136,7 +136,8 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
  * which might have be mirrored at 0x0100-0x03ff..
  */
 void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+pcibios_align_resource(void *data, struct resource *res,
+                      unsigned long size, unsigned long align)
 {
        if (res->flags & IORESOURCE_IO) {
                unsigned long start = res->start;
index fafbf4c18b24c68fd401cc9987423a2e0d04a119..c19dceb2bdb50539eceba3d1341a7601beb6b252 100644 (file)
@@ -69,6 +69,7 @@ static int pci_assign_bus_resource(const struct pci_bus *bus,
        unsigned int type_mask,
        int resno)
 {
+       unsigned long align;
        int i;
 
        type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
@@ -81,12 +82,20 @@ static int pci_assign_bus_resource(const struct pci_bus *bus,
                if ((res->flags ^ r->flags) & type_mask)
                        continue;
 
-               /* We cannot allocate a non-prefetching resource from a pre-fetching area */
-               if ((r->flags & IORESOURCE_PREFETCH) && !(res->flags & IORESOURCE_PREFETCH))
+               /* We cannot allocate a non-prefetching resource
+                  from a pre-fetching area */
+               if ((r->flags & IORESOURCE_PREFETCH) &&
+                   !(res->flags & IORESOURCE_PREFETCH))
                        continue;
 
+               /* The bridge resources are special, as their
+                  size != alignment. Sizing routines return
+                  required alignment in the "start" field. */
+               align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
+
                /* Ok, try it out.. */
-               if (allocate_resource(r, res, size, min, -1, size, pcibios_align_resource, dev) < 0)
+               if (allocate_resource(r, res, size, min, -1, align,
+                                     pcibios_align_resource, dev) < 0)
                        continue;
 
                /* Update PCI config space.  */
index 819c0000052bf4ceac4a8ad126fdaf85a870aeba..7f50af85568737da88e0e5a18be94c2133e6768f 100644 (file)
@@ -92,7 +92,8 @@ extern int allocate_resource(struct resource *root, struct resource *new,
                             unsigned long size,
                             unsigned long min, unsigned long max,
                             unsigned long align,
-                            void (*alignf)(void *, struct resource *, unsigned long),
+                            void (*alignf)(void *, struct resource *,
+                                           unsigned long, unsigned long),
                             void *alignf_data);
 
 /* Convenience shorthand with allocation */
index 44007acbf3ed313408041caeeab908c634297cea..65a5a3bcfcdb70e762da31877058f5b87138e858 100644 (file)
@@ -500,7 +500,8 @@ int pcibios_enable_device(struct pci_dev *);
 char *pcibios_setup (char *str);
 
 /* Used only when drivers/pci/setup.c is used */
-void pcibios_align_resource(void *, struct resource *, unsigned long);
+void pcibios_align_resource(void *, struct resource *,
+                           unsigned long, unsigned long);
 void pcibios_update_resource(struct pci_dev *, struct resource *,
                             struct resource *, int);
 void pcibios_update_irq(struct pci_dev *, int irq);
index 7804ab3230d1be8908971ab395ed5f3bde2f70fc..bf331c1092ed389d3d3f483b8eea99b5cd69bd0f 100644 (file)
@@ -152,7 +152,8 @@ static int find_resource(struct resource *root, struct resource *new,
                         unsigned long size,
                         unsigned long min, unsigned long max,
                         unsigned long align,
-                        void (*alignf)(void *, struct resource *, unsigned long),
+                        void (*alignf)(void *, struct resource *,
+                                       unsigned long, unsigned long),
                         void *alignf_data)
 {
        struct resource *this = root->child;
@@ -169,7 +170,7 @@ static int find_resource(struct resource *root, struct resource *new,
                        new->end = max;
                new->start = (new->start + align - 1) & ~(align - 1);
                if (alignf)
-                       alignf(alignf_data, new, size);
+                       alignf(alignf_data, new, size, align);
                if (new->start < new->end && new->end - new->start + 1 >= size) {
                        new->end = new->start + size - 1;
                        return 0;
@@ -189,7 +190,8 @@ int allocate_resource(struct resource *root, struct resource *new,
                      unsigned long size,
                      unsigned long min, unsigned long max,
                      unsigned long align,
-                     void (*alignf)(void *, struct resource *, unsigned long),
+                     void (*alignf)(void *, struct resource *,
+                                    unsigned long, unsigned long),
                      void *alignf_data)
 {
        int err;