CFT/RFC: New cardbus resource allocation
The following is an experimental patch adjusts the way we allocate resouces for PCMCIA cards in cardbus devices.
When a PCMCIA driver wishes to claim resources for a card, the original code used to use an in-kernel structured list to find a free area of memory, mostly ignoring the Linux resource subsystem (although it did make use of the resource subsystem, it's racy.)
The following patch changes this. We instead use the PCI resource code to allocate a resource of the requested size, alignment, and offset from the parent bus of the cardbus bridge.
Why do we need the size, alignment and offset?
Some PCMCIA devices have specific requirements for IO addresses; some cards only decode 10 bits, and expect these 10 bits to be one of a selection of addresses. This means that the top 6 bits are ignored, and can be any value. However, the lower 10 bits must be one of a fixed set of values, eg 0x3f8, 0x3e8, 0x2f8, 0x2e8.
Hence, 0x3f8, 0x7f8, 0xbf8 etc are all possible values, which obviously gives you an alignment of (1 << 10) and an offset of 0x3f8.
(Appologies in advance if I've messed this patch up - it got dug it out of a pile of other patches in this area.)
drivers/pci/pci.c +1 -0
@@ -659,6 +659,7 @@EXPORT_SYMBOL (pci_clear_mwi);EXPORT_SYMBOL (pci_set_dma_mask);EXPORT_SYMBOL (pci_dac_set_dma_mask); +EXPORT_SYMBOL (pci_alloc_parent_resource);EXPORT_SYMBOL (pci_assign_resource);EXPORT_SYMBOL (pci_find_parent_resource);
drivers/pci/setup-res.c +47 -6
72 lines not on this page · raw message
drivers/pcmcia/cardbus.c +102 -0
105 lines not on this page · raw message
drivers/pcmcia/cs.c +1 -0
@@ -483,6 +483,7 @@cb_release_cis_mem (s);cb_free (s);#endif +release_cis_mem (s); s->functions =0 ;if (s->config) {kfree (s->config);
drivers/pcmcia/rsrc_mgr.c +41 -74
203 lines not on this page · raw message
Signature · 2 lines
Russell King ([email protected]) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html
Gah, sorry - should've mentioned - this patch is against plain 2.5.46.
Signature · 2 lines
Russell King ([email protected]) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html
Quoted 3 lines · Russell King
The following patch changes this. We instead use the PCI resource code to allocate a resource of the requested size, alignment, and offset from the parent bus of the cardbus bridge.
Looks quite reasonable.
Note that we don't need 2 similar functions in setup-res.c - pci_assign_resource() can be easily converted to use your pci_alloc_parent_resource(), and pci_assign_bus_resource() can be killed then.
Ivan.
Quoted 5 lines · Ivan Kokshaysky
Looks quite reasonable.
Note that we don't need 2 similar functions insetup-res.c-pci_assign_resource()can be easily converted to use yourpci_alloc_parent_resource(), andpci_assign_bus_resource()can be killed then.
I looked at that and decided it wasn't practical. pci_assign_resource() needs the parent resource to pass it down to the architecture specific layers. Unfortunately, trying to get that out of pci_alloc_parent_resource() makes the API rather disgusting IMHO.
Signature · 2 lines
Russell King ([email protected]) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html
Quoted 11 lines · Russell King
Quoted 5 lines · Ivan Kokshaysky
Looks quite reasonable.
Note that we don't need 2 similar functions insetup-res.c-pci_assign_resource()can be easily converted to use yourpci_alloc_parent_resource(), andpci_assign_bus_resource()can be killed then.I looked at that and decided it wasn't practical.
pci_assign_resource()needs the parent resource to pass it down to the architecture specific layers. Unfortunately, trying to get that out ofpci_alloc_parent_resource()makes the API rather disgusting IMHO.
Sigh. The API is already broken - passing parent resource to pcibios_update_resource() is not only pointless (since we have res->parent), but extremely misleading.
Almost all architectures declare
void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
^^^^ struct resource *res, int resource)
Obviously root != parent.
Vast majority of archs do not use `root' arg, but some do:
mips64/mips-boards/generic/pci.cmips64/sgi-ip27/ip27-pci.cmips/ite-boards/generic/it8172_pci.cmips/mips-boards/generic/pci.cia64/pci/pci.c
All of these use exactly the same code:
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
unsigned long where, size;
u32 reg;
where = PCI_BASE_ADDRESS_0 + (resource * 4);
size = res->end - res->start;
pci_read_config_dword(dev, where, ®);
reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
pci_write_config_dword(dev, where, reg);
}Which is wrong if the `root' is a pointer to the PCI or CardBus bridge resource.
The arg 2 to pcibios_update_resource() must be removed...
Ivan.