reduce size of bridge regions for yenta.c
PATCH 1/1 reduce size of bridge regions for yenta.c
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
drivers/pcmcia/yenta.c +55 -5
@@ -2,6 +2,11 @@* Regular lowlevel cardbus driver ("yenta") * * (C) Copyright 1999, 2000 Linus Torvalds +* +* Changelog: +* Aug 2002: Manfred Spraul <[email protected]> +* 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"
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