As a follow-up, we can make yenta_socket try harder to limit itself to the
parent bridge windows. This is done by lowering the
PCIBIOS_MIN_CARDBUS_IO and by updating yenta_allocate_res(). It now tries at
first to get resources within the bridge windows, and if they are large
enough (>=BRIDGE_{IO,MEM}_ACC), these are used. If no or only too small
resources were found, it falls back to the resources behind the parent PCI
bridge if this is "transparent". Using this patch may result in such "funny"
/proc/ioports as:

2800-28ff : PCI CardBus #07
3000-3fff : PCI Bus #02
  3000-303f : 0000:02:08.0
    3000-303f : e100
  3400-34ff : PCI CardBus #03
  3800-38ff : PCI CardBus #03
  3c00-3cff : PCI CardBus #07

There weren't enough properly aligned ports available inside PCI Bus #02 to
stuff all four (2x2) IO windows into it, so one was taken outside the
transparent PCI bridge ioport window.

Signed-off-by: Dominik Brodowski <[EMAIL PROTECTED]>

Index: 2.6.11++/drivers/pcmcia/yenta_socket.c
===================================================================
--- 2.6.11++.orig/drivers/pcmcia/yenta_socket.c 2005-03-17 23:13:58.000000000 
+0100
+++ 2.6.11++/drivers/pcmcia/yenta_socket.c      2005-03-17 23:40:38.000000000 
+0100
@@ -518,19 +518,23 @@
  * Use an adaptive allocation for the memory resource,
  * sometimes the memory behind pci bridges is limited:
  * 1/8 of the size of the io window of the parent.
- * max 4 MB, min 16 kB.
+ * max 4 MB, min 16 kB. We try very hard to not get
+ * below the "ACC" values, though.
  */
 #define BRIDGE_MEM_MAX 4*1024*1024
+#define BRIDGE_MEM_ACC 128*1024
 #define BRIDGE_MEM_MIN 16*1024
 
 #define BRIDGE_IO_MAX 256
+#define BRIDGE_IO_ACC 256
 #define BRIDGE_IO_MIN 32
 
 #ifndef PCIBIOS_MIN_CARDBUS_IO
 #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO
 #endif
 
-static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned 
type)
+static int yenta_try_allocate_res(struct yenta_socket *socket, int nr,
+                                 unsigned int type, unsigned int run)
 {
        struct pci_bus *bus;
        struct resource *root, *res;
@@ -550,11 +554,11 @@
        res->name = bus->name;
        res->flags = type;
        res->start = 0;
-       res->end = 0;
+       res->end = run;
        root = pci_find_parent_resource(socket->dev, res);
 
        if (!root)
-               return;
+               return -ENODEV;
 
        start = config_readl(socket, offset) & mask;
        end = config_readl(socket, offset+4) | ~mask;
@@ -562,7 +566,8 @@
                res->start = start;
                res->end = end;
                if (request_resource(root, res) == 0)
-                       return;
+                       return 0;
+
                printk(KERN_INFO "yenta %s: Preassigned resource %d busy, 
reconfiguring...\n",
                                pci_name(socket->dev), nr);
                res->start = res->end = 0;
@@ -571,12 +576,12 @@
        if (type & IORESOURCE_IO) {
                align = 1024;
                size = BRIDGE_IO_MAX;
-               min = BRIDGE_IO_MIN;
+               min = run ? BRIDGE_IO_ACC : BRIDGE_IO_MIN;
                start = PCIBIOS_MIN_CARDBUS_IO;
                end = ~0U;
        } else {
                unsigned long avail = root->end - root->start;
-               int i;
+               u32 i;
                size = BRIDGE_MEM_MAX;
                if (size > avail/8) {
                        size=(avail+1)/8;
@@ -586,26 +591,36 @@
                                i++;
                        size = 1 << i;
                }
-               if (size < BRIDGE_MEM_MIN)
-                       size = BRIDGE_MEM_MIN;
+               i = run ? BRIDGE_MEM_ACC : BRIDGE_MEM_MIN;
+               if (size < i)
+                       size = i;
                min = BRIDGE_MEM_MIN;
                align = size;
                start = PCIBIOS_MIN_MEM;
                end = ~0U;
        }
-       
+
        do {
                if (allocate_resource(root, res, size, start, end, align, NULL, 
NULL)==0) {
                        config_writel(socket, offset, res->start);
                        config_writel(socket, offset+4, res->end);
-                       return;
+                       return 0;
                }
                size = size/2;
                align = size;
        } while (size >= min);
+
+       return -ENODEV;
+}
+
+static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned 
type)
+{
+       if (!(yenta_try_allocate_res(socket, nr, type, 1)) ||
+           !(yenta_try_allocate_res(socket, nr, type, 0)))
+               return;
+
        printk(KERN_INFO "yenta %s: no resource of type %x available, trying to 
continue...\n",
                        pci_name(socket->dev), type);
-       res->start = res->end = 0;
 }
 
 /*
@@ -616,7 +631,7 @@
        yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH);
        yenta_allocate_res(socket, 1, IORESOURCE_MEM);
        yenta_allocate_res(socket, 2, IORESOURCE_IO);
-       yenta_allocate_res(socket, 3, IORESOURCE_IO);   /* PCI isn't clever 
enough to use this one yet */
+       yenta_allocate_res(socket, 3, IORESOURCE_IO);
 }
 
 
Index: 2.6.11++/include/asm-i386/pci.h
===================================================================
--- 2.6.11++.orig/include/asm-i386/pci.h        2005-03-17 23:13:58.000000000 
+0100
+++ 2.6.11++/include/asm-i386/pci.h     2005-03-17 23:31:08.000000000 +0100
@@ -21,7 +21,7 @@
 #define PCIBIOS_MIN_IO         0x1000
 #define PCIBIOS_MIN_MEM                (pci_mem_start)
 
-#define PCIBIOS_MIN_CARDBUS_IO 0x4000
+#define PCIBIOS_MIN_CARDBUS_IO 0x2000
 
 void pcibios_config_init(void);
 struct pci_bus * pcibios_scan_root(int bus);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to