On Mon, 1 Oct 2001, Martin Diehl wrote: > On Mon, 1 Oct 2001, Alan Cox wrote: > > > Would a generic > > > > pci_fixup_device() > > > > type function not be more appropriate > > IIRC there was some discussion on l-k some time ago, whether such fixups > should stay close to were the issue appeared or better be placed at > generic pci quirk location. In this particular case I personally tend to > the latter one as well, particularly because there may be other BIOS' > doing similar things with non-cardbus memory bar's. Just to follow-up myself, seems the general pci-quirk approach is superior because there is no need to release-modify-reclaim the bad resource when fixing during pci header scan. Furthermore, there is already a cardbus specific fixup (disabling legacy registers) in drivers/pci/quirks.c. So I've just moved and adjusted the stuff to the same location. Improved patch vs. 2.4.10 below. Successfully tested on my OB-800 where the "featured" BIOS maps the cardbus bar at 0xe6000. Regards, Martin ------------------------- --- linux-2.4.10/drivers/pci/quirks.c Sun Sep 30 15:55:13 2001 +++ v2.4.10-md/drivers/pci/quirks.c Mon Oct 1 12:48:41 2001 @@ -412,6 +412,57 @@ } +/* BIOS might have mapped the cardbus memory resource to a bogus location + * in legacy memory area and the hostbridge somehow looses this window + * after pm-suspend (seen on OB800). + * We try to detect and fix this by re-assigning the resource if we + * find it mapped to legacy area <1M. But we don't try, if the obsolete + * MEM_TYPE_1M flag is set, just in case... + */ + +static void __init quirk_cardbus_bar(struct pci_dev *dev) +{ + unsigned long oldstart; + u32 temp, extend; + struct resource *res; + + if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class) + return; + + if (!(dev->resource[0].flags&IORESOURCE_MEM)) /* not cardbus memory BAR */ + return; + + oldstart = dev->resource[0].start; + if (oldstart >= 0x00100000UL) /* mapped above 1MB legacy area - fine! */ + return; + + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &temp); + if (temp & PCI_BASE_ADDRESS_MEM_TYPE_1M) { + printk(KERN_DEBUG "%s: cardbus memory has obsolete 1M flag set?\n", + __FUNCTION__); + return; + } + + /* re-read required size and flags from device */ + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffffffff); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &temp); + if (temp & PCI_BASE_ADDRESS_SPACE_IO) { /* paranoia */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, oldstart); + printk(KERN_WARNING "%s: cardbus memory mutated to io?\n", + __FUNCTION__); + return; + } + extend = ~(u32)(temp & PCI_BASE_ADDRESS_MEM_MASK); + + res = &dev->resource[0]; + res->start = 0; + res->end = res->start + extend; + res->flags = IORESOURCE_MEM; + if (temp & PCI_BASE_ADDRESS_MEM_PREFETCH) + res->flags |= IORESOURCE_PREFETCH; +} + /* * The main table of quirks. */ @@ -462,6 +513,7 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic }, + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_bar }, { 0 } }; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/