patch-2.4.21 linux-2.4.21/drivers/pcmcia/yenta.c
Next file: linux-2.4.21/drivers/s390/Config.in
Previous file: linux-2.4.21/drivers/pcmcia/sa1100_generic.c
Back to the patch index
Back to the overall index
- Lines: 105
- Date:
2003-06-13 07:51:35.000000000 -0700
- Orig file:
linux-2.4.20/drivers/pcmcia/yenta.c
- Orig date:
2002-08-02 17:39:44.000000000 -0700
diff -urN linux-2.4.20/drivers/pcmcia/yenta.c linux-2.4.21/drivers/pcmcia/yenta.c
@@ -2,6 +2,11 @@
* Regular lowlevel cardbus driver ("yenta")
*
* (C) Copyright 1999, 2000 Linus Torvalds
+ *
+ * Changelog:
+ * Aug 2002: Manfred Spraul <manfred@colorfullife.com>
+ * Dynamically adjust the size of the bridge resource
+ *
*/
#include <linux/init.h>
#include <linux/pci.h>
@@ -704,6 +709,15 @@
return 0;
}
+/*
+ * Use an adaptive allocation for the memory resource,
+ * sometimes the size behind pci bridges is limited:
+ * 1/8 of the size of the io window of the parent.
+ * max 4 MB, min 16 kB.
+ */
+#define BRIDGE_SIZE_MAX 4*1024*1024
+#define BRIDGE_SIZE_MIN 16*1024
+
static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
{
struct pci_bus *bus;
@@ -735,21 +749,42 @@
if (start && end > start) {
res->start = start;
res->end = end;
- request_resource(root, res);
- return;
+ if (request_resource(root, res) == 0)
+ return;
+ printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n",
+ socket->dev->slot_name, nr);
+ res->start = res->end = 0;
}
- align = size = 4*1024*1024;
- min = PCIBIOS_MIN_MEM; max = ~0U;
if (type & IORESOURCE_IO) {
align = 1024;
size = 256;
min = 0x4000;
max = 0xffff;
+ } else {
+ unsigned long avail = root->end - root->start;
+ int i;
+ align = size = BRIDGE_SIZE_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 < BRIDGE_SIZE_MIN)
+ size = BRIDGE_SIZE_MIN;
+ align = size;
+ min = PCIBIOS_MIN_MEM; max = ~0U;
}
- if (allocate_resource(root, res, size, min, max, align, NULL, NULL) < 0)
+ if (allocate_resource(root, res, size, min, max, align, NULL, NULL) < 0) {
+ printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
+ socket->dev->slot_name, type);
+ res->start = res->end = 0;
return;
+ }
config_writel(socket, offset, res->start);
config_writel(socket, offset+4, res->end);
@@ -767,6 +802,20 @@
}
/*
+ * Free the bridge mappings for the device..
+ */
+static void yenta_free_resources(pci_socket_t *socket)
+{
+ int i;
+ for (i=0;i<4;i++) {
+ struct resource *res;
+ res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
+ if (res->start != 0 && res->end != 0)
+ release_resource(res);
+ res->start = res->end = 0;
+ }
+}
+/*
* Close it down - release our resources and go home..
*/
static void yenta_close(pci_socket_t *sock)
@@ -782,6 +831,7 @@
if (sock->base)
iounmap(sock->base);
+ yenta_free_resources(sock);
}
#include "ti113x.h"
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)