simple pnp bios io resources bug makes system unusable
cat /sys/devices/pnp0/00\:0c/name
Reserved Motherboard Resources
cat /sys/devices/pnp0/00\:0c/resources
state = active
io 0x4d0-0x4d1
io 0xcf8-0xcff
io 0x3f7-0x3f7
io 0x401-0x407
io 0x298-0x298
io 0x00000000-0xffffffff
mem 0xfffe0000-0xffffffff
mem 0x100000-0x7ffffff
fixup: check for null io base, other devices are now able to initialize.
static void current_ioresource(struct pnp_resource_table * res, int io, int len)
{
int i = 0;+ if (!io) return;
while ((res->port_resource[i].flags & IORESOURCE_IO) && i <
PNP_MAX_PORT) i++;
if (i < PNP_MAX_PORT) {
res->port_resource[i].start = (unsigned long) io;
res->port_resource[i].end = (unsigned long)(io + len - 1);
res->port_resource[i].flags = IORESOURCE_IO; // Also
clears _UNSET flag
}
}The pnpbios is reserving the complete range of every possible io port. This causes device activation to fail for every device that needs an io port because that resource will always appear busy.
Quoted 14 lines · CarlosRomero
cat /sys/devices/pnp0/00\:0c/name
Reserved Motherboard Resourcescat /sys/devices/pnp0/00\:0c/resources
state = active
io 0x4d0-0x4d1
io 0xcf8-0xcff
io 0x3f7-0x3f7
io 0x401-0x407
io 0x298-0x298
io 0x00000000-0xffffffff
mem 0xfffe0000-0xffffffff
mem 0x100000-0x7ffffff
Quoted 1 line
fixup: check for null io base, other devices are now able to initialize.
Unfortunatly it's not quite that simple.
Quoted 5 lines
static void
current_ioresource(struct pnp_resource_table * res, int io, int len){ int i = 0;
Quoted 10 lines
+ if (!io) return;
while ((res->port_resource[i].flags & IORESOURCE_IO) && i <
PNP_MAX_PORT) i++;
if (i < PNP_MAX_PORT) {
res->port_resource[i].start = (unsigned long) io;
res->port_resource[i].end = (unsigned long)(io + len - 1);
res->port_resource[i].flags = IORESOURCE_IO; // Also
clears _UNSET flag
}
}Below are two examples that both use a base of 0 in a valid way.
(one for mem)
# cat id PNP0c01 /* this is a system device */ # cat resources state = active mem 0x0-0x9ffff mem 0xe4000-0xfffff mem 0x100000-0x3ffffff mem 0xfff80000-0xfffbffff
(and one for io ports)
# cat id PNP0200 /* this is an AT DMA Controller */ # cat resources state = active io 0x0-0xf io 0x81-0x8f io 0xc0-0xdf dma 4
Therefore just eliminating base 0 addresses is not a proper solution.
Also if we just skip the culprit resource then the resource index number (a value that many drivers require to be consistent) will be offset by the number of skipped resources of the same type.
Currently I'm leaning toward this logic... if we have any of the following situations
- 0x00000000 for base and 0xffffffff for end
- 0x00000000 for base and 0x00000000 for end
- 0xffffffff for base and 0xffffffff for end then the resource range can be considered disabled.
Also a device can have a disabled resource but not be fully disabled, such as a parport with some features disabled (ECP etc). So the index number must be maintained, this will require some more complex changes.
I'll have a full fix out soon.
Thanks,
Adam
In article <[email protected]>,
Quoted 5 lines · Adam Belay
The pnpbios is reserving the complete range of every possible io port. This causes device activation to fail for every device that needs an io port because that resource will always appear busy.
No, I don't think that's what it is doing at all. Quite the reverse, in fact.
Look:
Quoted 4 lines · CarlosRomero
Quoted 3 lines
cat /sys/devices/pnp0/00\:0c/resources
io 0x00000000-0xffffffff
This means that "io" was zero, but more importantly, it means that "len" was zero too.
Quoted 3 lines
Quoted 1 line
fixup: check for null io base, other devices are now able to initialize.
Unfortunatly it's not quite that simple.
It _is_ that simple, but the code should check for "len" being zero, ie the fix looks like it should be just a simple
if (!len) return;
and that should fix it.
Quoted 1 line
Below are two examples that both use a base of 0 in a valid way.
Yes, and clearly they don't have "len == 0".
Quoted 6 lines
Currently I'm leaning toward this logic... if we have any of the following situations
-0x00000000for base and0xfffffffffor end
-0x00000000for base and0x00000000for end
-0xfffffffffor base and0xfffffffffor end then the resource range can be considered disabled.
I would suggest:
- "len == 0" => obviously disabled (both IO and memory)
- "end < base" => obviously disabled due to overflow crap
- "end >= 0x10003" => IO disabled (yeah, non-x86 can have IO above
that range in PCI, but I think it's undefined behaviour)
all three should be cases of "obviously we can't validly have such a resource", and the "len == 0" case should trivially fix the case that CarlosRomero saw.
Linus