From ec3c9fdf4812f674e26e9592b25fd7ac8ebbd5ea Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 12 Jul 2005 13:58:17 -0700 Subject: [PATCH] --- yaml --- r: 4671 b: refs/heads/master c: eb0a90b4970d667e9ae9df538710f12b8e78e442 h: refs/heads/master i: 4669: 5294f5f8b7e33231c2dc97f6a40027138127f133 4667: 96b0d3c68c509754e45acdd058c247fc2673634d 4663: c1dbd6e6bb3f7030994e6c7e27c0bb2ccaab5f0a 4655: c3c127ed13e546b371ae09f2b0922961120f7321 4639: a7c5c4b30d45e00528dab8832fbb25a735146b68 4607: c5f1070f819c72aad2a902b7b9a141824c11c9e4 v: v3 --- [refs] | 2 +- trunk/drivers/pcmcia/yenta_socket.c | 126 +++++++++++++++++++--------- 2 files changed, 89 insertions(+), 39 deletions(-) diff --git a/[refs] b/[refs] index 5f8cffe87344..dfcabde2c645 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 278798357d4a8658067dc9ac399d8ffba8389f03 +refs/heads/master: eb0a90b4970d667e9ae9df538710f12b8e78e442 diff --git a/trunk/drivers/pcmcia/yenta_socket.c b/trunk/drivers/pcmcia/yenta_socket.c index d3807e22fe04..f9d2367b6bdf 100644 --- a/trunk/drivers/pcmcia/yenta_socket.c +++ b/trunk/drivers/pcmcia/yenta_socket.c @@ -527,24 +527,87 @@ static int yenta_sock_suspend(struct pcmcia_socket *sock) * 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_MAX 512 +#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 int yenta_search_one_res(struct resource *root, struct resource *res, + u32 min) +{ + u32 align, size, start, end; + + if (res->flags & IORESOURCE_IO) { + align = 1024; + size = BRIDGE_IO_MAX; + start = PCIBIOS_MIN_CARDBUS_IO; + end = ~0U; + } else { + unsigned long avail = root->end - root->start; + int i; + size = BRIDGE_MEM_MAX; + if (size > avail/8) { + size=(avail+1)/8; + /* round size down to next power of 2 */ + i = 0; + while ((size /= 2) != 0) + i++; + size = 1 << i; + } + if (size < min) + size = min; + align = size; + start = PCIBIOS_MIN_MEM; + end = ~0U; + } + + do { + if (allocate_resource(root, res, size, start, end, align, + NULL, NULL)==0) { + return 1; + } + size = size/2; + align = size; + } while (size >= min); + + return 0; +} + + +static int yenta_search_res(struct yenta_socket *socket, struct resource *res, + u32 min) +{ + int i; + for (i=0; idev->bus->resource[i]; + if (!root) + continue; + + if ((res->flags ^ root->flags) & + (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) + continue; /* Wrong type */ + + if (yenta_search_one_res(root, res, min)) + return 1; + } + return 0; +} + static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) { struct pci_bus *bus; struct resource *root, *res; u32 start, end; - u32 align, size, min; unsigned mask; res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; @@ -573,48 +636,35 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ pci_name(socket->dev), nr); } - res->start = 0; - res->end = 0; - root = pci_find_parent_resource(socket->dev, res); - if (type & IORESOURCE_IO) { - align = 1024; - size = BRIDGE_IO_MAX; - min = BRIDGE_IO_MIN; - start = PCIBIOS_MIN_CARDBUS_IO; - end = ~0U; + if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || + (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || + (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { + config_writel(socket, addr_start, res->start); + config_writel(socket, addr_end, res->end); + } } else { - unsigned long avail = root->end - root->start; - int i; - size = BRIDGE_MEM_MAX; - if (size > avail/8) { - size=(avail+1)/8; - /* round size down to next power of 2 */ - i = 0; - while ((size /= 2) != 0) - i++; - size = 1 << i; + if (type & IORESOURCE_PREFETCH) { + if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || + (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || + (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { + config_writel(socket, addr_start, res->start); + config_writel(socket, addr_end, res->end); + } + /* Approximating prefetchable by non-prefetchable */ + res->flags = IORESOURCE_MEM; } - if (size < BRIDGE_MEM_MIN) - size = BRIDGE_MEM_MIN; - 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) { + if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || + (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || + (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); - return; } - size = size/2; - align = size; - } while (size >= min); + } + 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; + pci_name(socket->dev), type); + res->start = res->end = res->flags = 0; } /*