[PATCH] IPMI: reserve I/O ports separately

From: Corey Minyard <minyard@acm.org>

This patch is pretty important to get in for IPMI, new systems have been
changing the way ACPI and IPMI interact, and this works around the problems
for now.  This is a temporary fix until we get proper ACPI handling in
IPMI.

Fixed releasing already-allocated regions when a later request fails, and
forward-ported it to HEAD.

Some BIOSes reserve disjoint I/O regions in their ACPI tables for the IPMI
controller.  This causes problems when trying to register the entire I/O
region.  Therefore we must register each I/O port separately.

Signed-off-by: Jordan Hargrave <Jordan_Hargrave@dell.com>
Signed-off-by: Matt Domsch <Matt_Domsch@dell.com>
Signed-off-by: Corey Minyard <minyard@acm.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Corey Minyard 2006-05-30 21:25:57 -07:00 committed by Linus Torvalds
parent 44d7aff035
commit d61a3ead26

View File

@ -1184,20 +1184,20 @@ static void port_outl(struct si_sm_io *io, unsigned int offset,
static void port_cleanup(struct smi_info *info) static void port_cleanup(struct smi_info *info)
{ {
unsigned int addr = info->io.addr_data; unsigned int addr = info->io.addr_data;
int mapsize; int idx;
if (addr) { if (addr) {
mapsize = ((info->io_size * info->io.regspacing) for (idx = 0; idx < info->io_size; idx++) {
- (info->io.regspacing - info->io.regsize)); release_region(addr + idx * info->io.regspacing,
info->io.regsize);
release_region (addr, mapsize); }
} }
} }
static int port_setup(struct smi_info *info) static int port_setup(struct smi_info *info)
{ {
unsigned int addr = info->io.addr_data; unsigned int addr = info->io.addr_data;
int mapsize; int idx;
if (!addr) if (!addr)
return -ENODEV; return -ENODEV;
@ -1225,16 +1225,22 @@ static int port_setup(struct smi_info *info)
return -EINVAL; return -EINVAL;
} }
/* Calculate the total amount of memory to claim. This is an /* Some BIOSes reserve disjoint I/O regions in their ACPI
* unusual looking calculation, but it avoids claiming any * tables. This causes problems when trying to register the
* more memory than it has to. It will claim everything * entire I/O region. Therefore we must register each I/O
* between the first address to the end of the last full * port separately.
* register. */ */
mapsize = ((info->io_size * info->io.regspacing) for (idx = 0; idx < info->io_size; idx++) {
- (info->io.regspacing - info->io.regsize)); if (request_region(addr + idx * info->io.regspacing,
info->io.regsize, DEVICE_NAME) == NULL) {
if (request_region(addr, mapsize, DEVICE_NAME) == NULL) /* Undo allocations */
return -EIO; while (idx--) {
release_region(addr + idx * info->io.regspacing,
info->io.regsize);
}
return -EIO;
}
}
return 0; return 0;
} }