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 Index: 2.6.12-rc2/drivers/pcmcia/yenta_socket.c =================================================================== --- 2.6.12-rc2.orig/drivers/pcmcia/yenta_socket.c 2005-04-10 01:02:36.000000000 +0200 +++ 2.6.12-rc2/drivers/pcmcia/yenta_socket.c 2005-04-10 01:02:53.000000000 +0200 @@ -516,19 +516,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; @@ -548,11 +552,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; @@ -560,7 +564,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; @@ -569,12 +574,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; @@ -584,26 +589,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; } /* @@ -614,7 +629,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.12-rc2/include/asm-i386/pci.h =================================================================== --- 2.6.12-rc2.orig/include/asm-i386/pci.h 2005-04-10 01:02:36.000000000 +0200 +++ 2.6.12-rc2/include/asm-i386/pci.h 2005-04-10 01:02:53.000000000 +0200 @@ -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);