[patch 3/19] pcmcia: try to use parent bridge window at first

Dominik Brodowski linux at dominikbrodowski.net
Sun Mar 20 05:38:11 EST 2005


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 <linux at dominikbrodowski.net>

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);



More information about the linux-pcmcia mailing list