public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] reduce size of bridge regions for yenta.c
@ 2002-08-24 15:03 Manfred Spraul
  2002-08-24 17:18 ` Manfred Spraul
  0 siblings, 1 reply; 2+ messages in thread
From: Manfred Spraul @ 2002-08-24 15:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: torvalds, dhinds

[-- Attachment #1: Type: text/plain, Size: 529 bytes --]

yenta.c tries to allocate 2 bridge regions, each 4 MB: one for 
prefetchable memory, one for non-prefetchable memory.

The size of the regions must be adaptive: in my laptop, the cardbus 
bridge sits behind a pci bridge with a 1 MB bridge region :-(

The attached patch:
- limits the memory window to 1/8 of the window of the parent bridge 
(max 4 MB, min 16 kB)
- frees the resources during module unload
- adds error checking+printk

Please test it - my laptop now works.
Patch vs. 2.4.19, applies to 2.5.30, too.

--
	Manfred

[-- Attachment #2: patch-yenta --]
[-- Type: text/plain, Size: 2732 bytes --]

--- 2.4/drivers/pcmcia/yenta.c	Sat Aug  3 02:39:44 2002
+++ build-2.4/drivers/pcmcia/yenta.c	Sat Aug 24 16:59:34 2002
@@ -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"

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] reduce size of bridge regions for yenta.c
  2002-08-24 15:03 [PATCH] reduce size of bridge regions for yenta.c Manfred Spraul
@ 2002-08-24 17:18 ` Manfred Spraul
  0 siblings, 0 replies; 2+ messages in thread
From: Manfred Spraul @ 2002-08-24 17:18 UTC (permalink / raw)
  To: Manfred Spraul; +Cc: linux-kernel, torvalds, dhinds

dhinds pointed me to a recent thread with another possible workaround:

The ICH-3M bridge is actually a transparent bridge that forwards all 
memory IO:

<<<< ich-3M datasheet (29071601.pdf)

MEMBASE Memory Base Register (HUB-PCI D30:F0)
Offset Address: 20 21h Attribute: R/W
Default Value: FFF0h Size: 16 bits
This register defines the base of the hub interface to PCI 
non-prefetchable memory range. Since the ICH3 will forward all hub 
interface memory accesses to PCI, the ICH3 will only use this 
information for determining when not to accept cycles as a target. This 
register must be initialized by the configuration software. For the 
purpose of address decode, address bits A[19:0] are assumed to be 0. 
Thus, the bottom of the defined memory address range will be aligned to 
a 1-MB boundary.
<<<<

Perhaps a pci-quirk should set

	bus->resource[1] = bus->parent->resource[1];

for the ICH-3M.

No patch, I don't understand the pci layer good enough to write such a 
quirk.

But IMHO the changes to yenta.c should be applied anyway: allocating 8 
MB, without any fallback, without reasonable error output is gross.

--
	Manfred


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-08-24 17:11 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-08-24 15:03 [PATCH] reduce size of bridge regions for yenta.c Manfred Spraul
2002-08-24 17:18 ` Manfred Spraul

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox