[PATCH - 2/2] Identify native drivers and ACPI subsystem accessingthe same resources - Main implementation
From: Thomas Renninger
Date: Fri Jul 13 2007 - 08:59:41 EST
Also request ACPI OperationRegion SystemIO to be reserved via /proc/ioports
This patch registers ACPI OperationRegions (only SystemIO, SystemMemory might
follow if this works out) in /proc/ioports. Only ACPI drivers are allowed to
request space beloning to these regions via acpi_request_region (e.g. also
pnpacpi makes use of it).
Also acpi_enforce_resources= param is introduces:
- no (default) same behaviour as without that patch
- lax print msg to syslog which driver might interfere with
which ACPI OperationRegion
- strict Like lax, but also returns -EBUSY on failed interfering
native drivers, to force them to not load (and potentially
interfere with ACPI)
Signed-off-by: Thomas Renninger <trenn@xxxxxxx>
---
drivers/acpi/osl.c | 283 +++++++++++++++++++++++++++++++++++++-----
drivers/acpi/processor_core.c | 2
drivers/pnp/isapnp/core.c | 9 -
drivers/pnp/pnpacpi/core.c | 9 -
drivers/pnp/pnpbios/core.c | 9 -
drivers/pnp/system.c | 43 ++++--
include/linux/acpi.h | 3
include/linux/ioport.h | 2
include/linux/pnp.h | 5
kernel/resource.c | 16 +-
10 files changed, 323 insertions(+), 58 deletions(-)
Index: linux-2.6.22.1/drivers/acpi/osl.c
===================================================================
--- linux-2.6.22.1.orig/drivers/acpi/osl.c
+++ linux-2.6.22.1/drivers/acpi/osl.c
@@ -44,6 +44,14 @@
#include <asm/uaccess.h>
#include <linux/efi.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+
+#if 1
+#define dprintk printk /* debug */
+#else
+#define dprintk(format,args...)
+#endif
#define _COMPONENT ACPI_OS_SERVICES
ACPI_MODULE_NAME("osl");
@@ -74,6 +82,15 @@ static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
+struct ioport_res_list{
+ struct resource res;
+ struct list_head res_list;
+};
+
+static LIST_HEAD(ioport_res_list);
+DEFINE_SPINLOCK(acpi_res_lock);
+
+
#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
static char osi_additional_string[OSI_STRING_LENGTH_MAX];
@@ -89,49 +106,133 @@ int osi_linux; /* disable _OSI(Linux) b
static struct __initdata dmi_system_id acpi_osl_dmi_table[];
#endif
-static void __init acpi_request_region (struct acpi_generic_address *addr,
- unsigned int length, char *desc)
-{
- struct resource *res;
+/*
+ type: We have three mappings:
+ ACPI_ADR_SPACE_SYSTEM_IO and friends in include/acpi/actypes.h
+ IORESOURCE_IO and friends in include/linux/ioport.h
+ and the one we go for (as we only support IO and MEM here anyway):
+ PORT (Y/N) -> IO for yes, MEM for no, also see:
+ drivers/pnp/system.c
+*/
+
+int acpi_request_region (resource_size_t addr, unsigned int length,
+ const char *desc, unsigned int port)
+{
+ struct resource *par_res = NULL;
+ struct resource *new_res;
+ struct ioport_res_list *io_res_list;
+
+ new_res = (struct resource*) kzalloc(sizeof (struct resource), GFP_KERNEL);
+
+ new_res->start = addr;
+ new_res->end = addr + length - 1;
+ new_res->name = desc;
- if (!addr->address || !length)
- return;
+ if (port)
+ new_res->flags |= IORESOURCE_IO;
+ else
+ new_res->flags |= IORESOURCE_MEM;
- if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
- res = request_region(addr->address, length, desc);
- else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
- res = request_mem_region(addr->address, length, desc);
+ if (!addr || !length){
+ kfree(new_res);
+ return -1;
+ }
+
+ spin_lock(&acpi_res_lock);
+ list_for_each_entry(io_res_list, &ioport_res_list, res_list){
+ if (new_res->start < io_res_list->res.start){
+ if (new_res->end >= io_res_list->res.start)
+ goto err_out;
+ else
+ continue;
+ }
+ else if (new_res->end > io_res_list->res.end){
+ if (new_res->start <= io_res_list->res.end)
+ goto err_out;
+ else
+ continue;
+ }
+ par_res = &io_res_list->res;
+ break;
+ }
+
+ if (port){
+ if (par_res){
+ new_res->flags |= IORESOURCE_BUSY;
+ if (insert_resource(par_res, new_res))
+ goto err_out;
+ else
+ dprintk (KERN_ERR "Insert ACPI resource success:"
+ " %s->%s\n", io_res_list->res.name,
+ new_res->name);
+ }
+ else{
+ if (request_region(addr, length, desc))
+ dprintk ("Added io reg: start: %lX, end: %lX, name: %s\n",
+ (long unsigned int)new_res->start,
+ (long unsigned int)new_res->end, new_res->name);
+ else
+ goto err_out;
+ }
+ }
+ else{
+ if (request_mem_region(addr, length, desc))
+ dprintk ("Added mem reg: start: %lX, end: %lX, name: %s\n",
+ (long unsigned int)new_res->start,
+ (long unsigned int)new_res->end, new_res->name);
+ else
+ if (request_region(addr, length, desc))
+ goto err_out;
+ }
+ spin_unlock(&acpi_res_lock);
+ return 0;
+
+ err_out:
+ spin_unlock(&acpi_res_lock);
+
+ /* Partial overlap? Bad, and unfixable */
+ printk (KERN_ERR "Could not add %s reg: start: %lX, end: %lX, name: "
+ "%s\n", port ? "IO" : "mem", (long unsigned int)new_res->start,
+ (long unsigned int)new_res->end, new_res->name);
+ if (par_res)
+ printk (KERN_ERR "Could not add %s reg to parent: start: %lX,"
+ " end: %lX, name: %s\n", port ? "IO" : "mem",
+ (long unsigned int)par_res->start,
+ (long unsigned int)par_res->end, par_res->name);
+ kfree(new_res);
+ return -EBUSY;
}
+EXPORT_SYMBOL(acpi_request_region);
static int __init acpi_reserve_resources(void)
{
- acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
- "ACPI PM1a_EVT_BLK");
+ acpi_request_region(acpi_gbl_FADT.xpm1a_event_block.address, acpi_gbl_FADT.pm1_event_length,
+ "ACPI PM1a_EVT_BLK", 1);
- acpi_request_region(&acpi_gbl_FADT.xpm1b_event_block, acpi_gbl_FADT.pm1_event_length,
- "ACPI PM1b_EVT_BLK");
+ acpi_request_region(acpi_gbl_FADT.xpm1b_event_block.address, acpi_gbl_FADT.pm1_event_length,
+ "ACPI PM1b_EVT_BLK", 1);
- acpi_request_region(&acpi_gbl_FADT.xpm1a_control_block, acpi_gbl_FADT.pm1_control_length,
- "ACPI PM1a_CNT_BLK");
+ acpi_request_region(acpi_gbl_FADT.xpm1a_control_block.address, acpi_gbl_FADT.pm1_control_length,
+ "ACPI PM1a_CNT_BLK", 1);
- acpi_request_region(&acpi_gbl_FADT.xpm1b_control_block, acpi_gbl_FADT.pm1_control_length,
- "ACPI PM1b_CNT_BLK");
+ acpi_request_region(acpi_gbl_FADT.xpm1b_control_block.address, acpi_gbl_FADT.pm1_control_length,
+ "ACPI PM1b_CNT_BLK", 1);
if (acpi_gbl_FADT.pm_timer_length == 4)
- acpi_request_region(&acpi_gbl_FADT.xpm_timer_block, 4, "ACPI PM_TMR");
+ acpi_request_region(acpi_gbl_FADT.xpm_timer_block.address, 4, "ACPI PM_TMR", 1);
- acpi_request_region(&acpi_gbl_FADT.xpm2_control_block, acpi_gbl_FADT.pm2_control_length,
- "ACPI PM2_CNT_BLK");
+ acpi_request_region(acpi_gbl_FADT.xpm2_control_block.address, acpi_gbl_FADT.pm2_control_length,
+ "ACPI PM2_CNT_BLK", 1);
/* Length of GPE blocks must be a non-negative multiple of 2 */
if (!(acpi_gbl_FADT.gpe0_block_length & 0x1))
- acpi_request_region(&acpi_gbl_FADT.xgpe0_block,
- acpi_gbl_FADT.gpe0_block_length, "ACPI GPE0_BLK");
+ acpi_request_region(acpi_gbl_FADT.xgpe0_block.address,
+ acpi_gbl_FADT.gpe0_block_length, "ACPI GPE0_BLK", 1);
if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
- acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
- acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
+ acpi_request_region(acpi_gbl_FADT.xgpe1_block.address,
+ acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK", 1);
return 0;
}
@@ -1049,6 +1150,57 @@ static int __init acpi_wake_gpes_always_
__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
/*
+ * Enforce declarations of ACPI OperationRegion
+ * (SystemIO and SystemMemory only) to be used as exclusive IO resources.
+ * IO ports and memory declared in ACPI might be used by the ACPI subsystem
+ * and can interfere with legacy drivers.
+ * acpi_enforce_resources= can be set to:
+ *
+ * - strict (2)
+ * -> further driver trying to access the resources will not load
+ * - lax (1)
+ * -> further driver trying to access the resources will load, but you
+ * get a system message that something might go wrong...
+ *
+ * - no (default) (0)
+ * -> ACPI Operation Region resources will not be registered
+ *
+ */
+
+#define ENFORCE_RESOURCES_STRICT 2
+#define ENFORCE_RESOURCES_LAX 1
+#define ENFORCE_RESOURCES_NO 0
+
+static unsigned int acpi_enforce_resources;
+
+static int __init acpi_enforce_resources_setup(char *str)
+{
+
+ char msg[64] = "Setting acpi_enforce_resources=";
+
+ if (str == NULL || *str == '\0')
+ return 0;
+
+ if (!strcmp("strict", str)){
+ acpi_enforce_resources = ENFORCE_RESOURCES_STRICT;
+ strcat(msg, "strict");
+ }
+ else if (!strcmp("lax", str)){
+ acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
+ strcat(msg, "lax");
+ }
+ else if (!strcmp("no", str)){
+ acpi_enforce_resources = ENFORCE_RESOURCES_NO;
+ strcat(msg, "no");
+ }
+
+ printk(KERN_INFO "%s\n", msg);
+ return 1;
+}
+
+__setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
+
+/*
* max_cstate is defined in the base kernel so modules can
* change it w/o depending on the state of the processor module.
*/
@@ -1220,15 +1372,90 @@ acpi_status
acpi_os_validate_address (
u8 space_id,
acpi_physical_address address,
- acpi_size length)
+ acpi_size length,
+ char *name)
{
+ char *buf;
+ struct ioport_res_list *res;
+
+ if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
+ return AE_OK;
+
+ /*
+ This will never ever get freed again...
+ This could get a problem for dynamic table allocation/removal
+ with SSDTs, needs to be handled at later time.
+ */
+ res = (struct ioport_res_list*) kzalloc(sizeof(struct ioport_res_list), GFP_KERNEL);
+ buf = (char*)kzalloc(strlen(name) + 6, GFP_KERNEL);
- return AE_OK;
+ if(!buf || !res)
+ return AE_OK;
+
+ res->res.name = buf;
+ res->res.start = address;
+ res->res.end = address + length - 1;
+
+ sprintf (buf, "ACPI %s", name);
+ switch (space_id){
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ res->res.flags |= IORESOURCE_IO;
+ list_add(&res->res_list, &ioport_res_list);
+ if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT)
+ res->res.flags |= IORESOURCE_BUSY;
+ else if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
+ res->res.flags |= IORESOURCE_SHARED;
+ if (insert_resource(&ioport_resource, &res->res))
+ printk(KERN_ERR "Could not insert resource: %s\n",
+ res->res.name);
+ else
+ dprintk ("Added %s %s: IO reg: start: %lX, end: %lX, "
+ "name: %s\n",
+ (res->res.flags & IORESOURCE_SHARED)
+ ? "sharable" : "",
+ (res->res.flags & IORESOURCE_BUSY)
+ ? "busy" : "",
+ (long unsigned int)res->res.start,
+ (long unsigned int)res->res.end,
+ res->res.name);
+ break;
+
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ res->res.flags |= IORESOURCE_MEM;
+ printk ("%s - %s\n", __FUNCTION__, buf);
+ if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT)
+ res->res.flags |= IORESOURCE_BUSY;
+ else if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
+ res->res.flags |= IORESOURCE_SHARED;
+ if (insert_resource(&iomem_resource, &res->res))
+ printk(KERN_ERR "Could not insert resource: %s\n",
+ res->res.name);
+ else
+ dprintk ("Added %s %s: mem reg: start: %lX, end: %lX, "
+ "name: %s\n",
+ (res->res.flags & IORESOURCE_SHARED)
+ ? "sharable" : "",
+ (res->res.flags & IORESOURCE_BUSY)
+ ? "busy" : "",
+ (long unsigned int)res->res.start,
+ (long unsigned int)res->res.end,
+ res->res.name);
+ break;
+ case ACPI_ADR_SPACE_PCI_CONFIG:
+ case ACPI_ADR_SPACE_EC:
+ case ACPI_ADR_SPACE_SMBUS:
+ case ACPI_ADR_SPACE_CMOS:
+ case ACPI_ADR_SPACE_PCI_BAR_TARGET:
+ case ACPI_ADR_SPACE_DATA_TABLE:
+ case ACPI_ADR_SPACE_FIXED_HARDWARE:
+ break;
+ }
+ return AE_OK;
}
#ifdef CONFIG_DMI
#ifdef OSI_LINUX_ENABLED
-static int dmi_osi_not_linux(struct dmi_system_id *d)
+ static int dmi_osi_not_linux(struct dmi_system_id *d)
{
printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident);
enable_osi_linux(0);
Index: linux-2.6.22.1/include/linux/ioport.h
===================================================================
--- linux-2.6.22.1.orig/include/linux/ioport.h
+++ linux-2.6.22.1/include/linux/ioport.h
@@ -45,6 +45,8 @@ struct resource_list {
#define IORESOURCE_SHADOWABLE 0x00010000
#define IORESOURCE_BUS_HAS_VGA 0x00080000
+#define IORESOURCE_SHARED 0x00100000 /* This IO address appears in ACPI namespace */
+
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_AUTO 0x40000000
Index: linux-2.6.22.1/kernel/resource.c
===================================================================
--- linux-2.6.22.1.orig/kernel/resource.c
+++ linux-2.6.22.1/kernel/resource.c
@@ -80,11 +80,12 @@ static int r_show(struct seq_file *m, vo
for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent)
if (p->parent == root)
break;
- seq_printf(m, "%*s%0*llx-%0*llx : %s\n",
+ seq_printf(m, "%*s%0*llx-%0*llx : %s%s - %p\n",
depth * 2, "",
width, (unsigned long long) r->start,
width, (unsigned long long) r->end,
- r->name ? r->name : "<BAD>");
+ r->name ? r->name : "<BAD>", r->flags &
+ IORESOURCE_SHARED ? "*" : "",r);
return 0;
}
@@ -382,8 +383,10 @@ int insert_resource(struct resource *par
for (next = first; ; next = next->sibling) {
/* Partial overlap? Bad, and unfixable */
- if (next->start < new->start || next->end > new->end)
+ if (next->start < new->start || next->end > new->end){
+ result = -EFAULT;
goto out;
+ }
if (!next->sibling)
break;
if (next->sibling->start > new->end)
@@ -503,6 +506,13 @@ struct resource * __request_region(struc
if (!conflict)
break;
if (conflict != parent) {
+ if (conflict->flags & IORESOURCE_SHARED){
+ printk(KERN_ERR "IO region [%s]"
+ " conflicts with [%s]. "
+ " Ignoring.., system might run"
+ " unstable.\n",
+ res->name, conflict->name);
+ }
parent = conflict;
if (!(conflict->flags & IORESOURCE_BUSY))
continue;
Index: linux-2.6.22.1/drivers/pnp/system.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/system.c
+++ linux-2.6.22.1/drivers/pnp/system.c
@@ -22,21 +22,18 @@ static const struct pnp_device_id pnp_de
{ "", 0 }
};
-static void reserve_range(const char *pnpid, resource_size_t start, resource_size_t end, int port)
+int pnp_reserve_range(resource_size_t start, unsigned int length,
+ const char *pnpid, int port)
{
struct resource *res;
- char *regionid;
- regionid = kmalloc(16, GFP_KERNEL);
- if (regionid == NULL)
- return;
- snprintf(regionid, 16, "pnp %s", pnpid);
if (port)
- res = request_region(start, end-start+1, regionid);
+ res = request_region(start, length, pnpid);
else
- res = request_mem_region(start, end-start+1, regionid);
+ res = request_region(start, length, pnpid);
+
if (res == NULL)
- kfree(regionid);
+ return -EBUSY;
else
res->flags &= ~IORESOURCE_BUSY;
/*
@@ -47,13 +44,15 @@ static void reserve_range(const char *pn
printk(KERN_INFO
"pnp: %s: %s range 0x%llx-0x%llx %s reserved\n",
pnpid, port ? "ioport" : "iomem",
- (unsigned long long)start, (unsigned long long)end,
+ (unsigned long long)start, (unsigned long long)start+length,
NULL != res ? "has been" : "could not be");
+ return 0;
}
static void reserve_resources_of_dev(const struct pnp_dev *dev)
{
int i;
+ char *regionid;
for (i = 0; i < PNP_MAX_PORT; i++) {
if (!pnp_port_valid(dev, i))
@@ -73,16 +72,32 @@ static void reserve_resources_of_dev(con
if (pnp_port_end(dev, i) < pnp_port_start(dev, i))
continue; /* invalid */
- reserve_range(dev->dev.bus_id, pnp_port_start(dev, i),
- pnp_port_end(dev, i), 1);
+ regionid = kmalloc(16, GFP_KERNEL);
+ if (regionid == NULL)
+ return;
+ snprintf(regionid, 16, "pnp %s", dev->dev.bus_id);
+
+ if (dev->protocol->request_sys_resource(pnp_port_start(dev, i),
+ pnp_port_end(dev, i)
+ - pnp_port_start(dev, i) + 1,
+ regionid, 1))
+ kfree(regionid);
}
for (i = 0; i < PNP_MAX_MEM; i++) {
if (!pnp_mem_valid(dev, i))
continue;
- reserve_range(dev->dev.bus_id, pnp_mem_start(dev, i),
- pnp_mem_end(dev, i), 0);
+ regionid = kmalloc(16, GFP_KERNEL);
+ if (regionid == NULL)
+ return;
+ snprintf(regionid, 16, "pnp %s", dev->dev.bus_id);
+
+ if (dev->protocol->request_sys_resource(pnp_port_start(dev, i),
+ pnp_port_end(dev, i)
+ - pnp_port_start(dev, i) + 1,
+ regionid, 1))
+ kfree(regionid);
}
return;
Index: linux-2.6.22.1/drivers/acpi/processor_core.c
===================================================================
--- linux-2.6.22.1.orig/drivers/acpi/processor_core.c
+++ linux-2.6.22.1/drivers/acpi/processor_core.c
@@ -606,7 +606,7 @@ static int acpi_processor_get_info(struc
*
* (In particular, allocating the IO range for Cardbus)
*/
- request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+ acpi_request_region(pr->throttling.address, 6, "ACPI CPU throttle", 1);
}
#ifdef CONFIG_CPU_FREQ
Index: linux-2.6.22.1/include/linux/pnp.h
===================================================================
--- linux-2.6.22.1.orig/include/linux/pnp.h
+++ linux-2.6.22.1/include/linux/pnp.h
@@ -326,6 +326,9 @@ struct pnp_card_driver {
* Protocol Management
*/
+int pnp_reserve_range(resource_size_t start, unsigned int length,
+ const char *pnpid, int port);
+
struct pnp_protocol {
struct list_head protocol_list;
char * name;
@@ -334,6 +337,8 @@ struct pnp_protocol {
int (*get)(struct pnp_dev *dev, struct pnp_resource_table *res);
int (*set)(struct pnp_dev *dev, struct pnp_resource_table *res);
int (*disable)(struct pnp_dev *dev);
+ int (*request_sys_resource)(resource_size_t addr, unsigned int length,
+ const char *desc, unsigned int port);
/* used by pnp layer only (look but don't touch) */
unsigned char number; /* protocol number*/
Index: linux-2.6.22.1/drivers/pnp/isapnp/core.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/isapnp/core.c
+++ linux-2.6.22.1/drivers/pnp/isapnp/core.c
@@ -1032,10 +1032,11 @@ static int isapnp_disable_resources(stru
}
struct pnp_protocol isapnp_protocol = {
- .name = "ISA Plug and Play",
- .get = isapnp_get_resources,
- .set = isapnp_set_resources,
- .disable = isapnp_disable_resources,
+ .name = "ISA Plug and Play",
+ .get = isapnp_get_resources,
+ .set = isapnp_set_resources,
+ .disable = isapnp_disable_resources,
+ .request_sys_resource = pnp_reserve_range,
};
static int __init isapnp_init(void)
Index: linux-2.6.22.1/drivers/pnp/pnpacpi/core.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/pnpacpi/core.c
+++ linux-2.6.22.1/drivers/pnp/pnpacpi/core.c
@@ -120,10 +120,11 @@ static int pnpacpi_disable_resources(str
}
static struct pnp_protocol pnpacpi_protocol = {
- .name = "Plug and Play ACPI",
- .get = pnpacpi_get_resources,
- .set = pnpacpi_set_resources,
- .disable = pnpacpi_disable_resources,
+ .name = "Plug and Play ACPI",
+ .get = pnpacpi_get_resources,
+ .set = pnpacpi_set_resources,
+ .disable = pnpacpi_disable_resources,
+ .request_sys_resource = acpi_request_region,
};
static int __init pnpacpi_add_device(struct acpi_device *device)
Index: linux-2.6.22.1/drivers/pnp/pnpbios/core.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/pnpbios/core.c
+++ linux-2.6.22.1/drivers/pnp/pnpbios/core.c
@@ -310,10 +310,11 @@ static int pnpbios_disable_resources(str
/* PnP Layer support */
struct pnp_protocol pnpbios_protocol = {
- .name = "Plug and Play BIOS",
- .get = pnpbios_get_resources,
- .set = pnpbios_set_resources,
- .disable = pnpbios_disable_resources,
+ .name = "Plug and Play BIOS",
+ .get = pnpbios_get_resources,
+ .set = pnpbios_set_resources,
+ .disable = pnpbios_disable_resources,
+ .request_sys_resource = pnp_reserve_range,
};
static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
Index: linux-2.6.22.1/include/linux/acpi.h
===================================================================
--- linux-2.6.22.1.orig/include/linux/acpi.h
+++ linux-2.6.22.1/include/linux/acpi.h
@@ -174,6 +174,9 @@ struct acpi_pci_driver {
int acpi_pci_register_driver(struct acpi_pci_driver *driver);
void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
+int acpi_request_region (resource_size_t addr, unsigned int length,
+ const char *desc, unsigned int port);
+
#endif /* CONFIG_ACPI */
#ifdef CONFIG_ACPI_EC
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/