diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/asus_acpi.c | 55 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 5 | ||||
-rw-r--r-- | drivers/acpi/bay.c | 6 | ||||
-rw-r--r-- | drivers/acpi/blacklist.c | 58 | ||||
-rw-r--r-- | drivers/acpi/debug.c | 57 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 6 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 19 | ||||
-rw-r--r-- | drivers/acpi/events/evgpe.c | 25 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsxfeval.c | 10 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 69 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 17 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 47 | ||||
-rw-r--r-- | drivers/acpi/processor_perflib.c | 16 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 100 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 15 | ||||
-rw-r--r-- | drivers/acpi/sleep/proc.c | 46 | ||||
-rw-r--r-- | drivers/acpi/tables/Makefile | 2 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxfroot.c | 4 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 17 | ||||
-rw-r--r-- | drivers/acpi/video.c | 49 |
20 files changed, 447 insertions, 176 deletions
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index d915fec9bf6..d25ef961415 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -142,6 +142,7 @@ struct asus_hotk { xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N A4S, //Z81sp //(Centrino) + F3Sa, END_MODEL } model; //Models currently supported u16 event_count[128]; //count for each event TODO make this better @@ -405,7 +406,20 @@ static struct model_data model_conf[END_MODEL] = { .brightness_get = "GPLV", .mt_bt_switch = "BLED", .mt_wled = "WLED" - } + }, + + { + .name = "F3Sa", + .mt_bt_switch = "BLED", + .mt_wled = "WLED", + .mt_mled = "MLED", + .brightness_get = "GPLV", + .brightness_set = "SPLV", + .mt_lcd_switch = "\\_SB.PCI0.SBRG.EC0._Q10", + .lcd_status = "\\_SB.PCI0.SBRG.EC0.RPIN", + .display_get = "\\ADVG", + .display_set = "SDSP", + }, }; @@ -710,15 +724,8 @@ static int get_lcd_state(void) { int lcd = 0; - if (hotk->model != L3H) { - /* We don't have to check anything if we are here */ - if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) - printk(KERN_WARNING - "Asus ACPI: Error reading LCD status\n"); - - if (hotk->model == L2D) - lcd = ~lcd; - } else { /* L3H and the like have to be handled differently */ + if (hotk->model == L3H) { + /* L3H and the like have to be handled differently */ acpi_status status = 0; struct acpi_object_list input; union acpi_object mt_params[2]; @@ -745,6 +752,32 @@ static int get_lcd_state(void) if (out_obj.type == ACPI_TYPE_INTEGER) /* That's what the AML code does */ lcd = out_obj.integer.value >> 8; + } else if (hotk->model == F3Sa) { + unsigned long tmp; + union acpi_object param; + struct acpi_object_list input; + acpi_status status; + + /* Read pin 11 */ + param.type = ACPI_TYPE_INTEGER; + param.integer.value = 0x11; + input.count = 1; + input.pointer = ¶m; + + status = acpi_evaluate_integer(NULL, hotk->methods->lcd_status, + &input, &tmp); + if (status != AE_OK) + return -1; + + lcd = tmp; + } else { + /* We don't have to check anything if we are here */ + if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) + printk(KERN_WARNING + "Asus ACPI: Error reading LCD status\n"); + + if (hotk->model == L2D) + lcd = ~lcd; } return (lcd & 1); @@ -1134,6 +1167,8 @@ static int asus_model_match(char *model) return W5A; else if (strncmp(model, "A4S", 3) == 0) return A4S; + else if (strncmp(model, "F3Sa", 4) == 0) + return F3Sa; else return END_MODEL; } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index c4a769d1ba8..f6215e80980 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -194,6 +194,9 @@ static int acpi_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_MANUFACTURER: val->strval = battery->oem_info; break; + case POWER_SUPPLY_PROP_SERIAL_NUMBER: + val->strval = battery->serial_number; + break; default: return -EINVAL; } @@ -212,6 +215,7 @@ static enum power_supply_property charge_battery_props[] = { POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_SERIAL_NUMBER, }; static enum power_supply_property energy_battery_props[] = { @@ -226,6 +230,7 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_ENERGY_NOW, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_SERIAL_NUMBER, }; #endif diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 6daf6088ac8..477711435b2 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -46,6 +46,12 @@ MODULE_LICENSE("GPL"); printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } static void bay_notify(acpi_handle handle, u32 event, void *data); +static const struct acpi_device_id bay_device_ids[] = { + {"LNXIOBAY", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, bay_device_ids); + struct bay { acpi_handle handle; char *name; diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 8809654d6cc..6dbaa2d15fe 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -70,8 +70,6 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = { /* IBM 600E - _ADR should return 7, but it returns 1 */ {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, - {"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions, - "Bogus PCI routing", 1}, {""} }; @@ -208,33 +206,35 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * Disable OSI(Linux) warnings on all "Acer, inc." * * _OSI(Linux) disables the latest Windows BIOS code: + * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"), + * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"), * _OSI(Linux) effect unknown: * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"), */ - { - .callback = dmi_disable_osi_linux, - .ident = "Acer, inc.", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."), - }, - }, + /* + * note that dmi_check_system() uses strstr() + * to match sub-strings rather than !strcmp(), + * so "Acer" below matches "Acer, inc." above. + */ /* * Disable OSI(Linux) warnings on all "Acer" * * _OSI(Linux) effect unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"), * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), + * + * _OSI(Linux) is a NOP: + * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), */ { - .callback = dmi_unknown_osi_linux, + .callback = dmi_disable_osi_linux, .ident = "Acer", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -242,21 +242,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, /* * Disable OSI(Linux) warnings on all "Apple Computer, Inc." + * Disable OSI(Linux) warnings on all "Apple Inc." * * _OSI(Linux) confirmed to be a NOP: * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), + * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), * _OSI(Linux) effect unknown: * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"), * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), */ { .callback = dmi_disable_osi_linux, .ident = "Apple", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + DMI_MATCH(DMI_SYS_VENDOR, "Apple"), }, }, /* @@ -294,13 +295,13 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * DMI_MATCH(DMI_BOARD_NAME, "IFL91"), */ { - .callback = dmi_unknown_osi_linux, + .callback = dmi_disable_osi_linux, .ident = "Compal", .matches = { DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), }, }, - { /* OSI(Linux) touches USB, breaks suspend to disk */ + { /* OSI(Linux) touches USB, unknown side-effect */ .callback = dmi_disable_osi_linux, .ident = "Dell Dimension 5150", .matches = { @@ -310,7 +311,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) is a NOP */ .callback = dmi_disable_osi_linux, - .ident = "Dell", + .ident = "Dell i1501", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"), @@ -318,7 +319,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell", + .ident = "Dell Latitude D830", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"), @@ -326,7 +327,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell", + .ident = "Dell OP GX620", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"), @@ -334,15 +335,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell", + .ident = "Dell PE 1900", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"), }, }, + { /* OSI(Linux) is a NOP */ + .callback = dmi_disable_osi_linux, + .ident = "Dell PE R200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"), + }, + }, { /* OSI(Linux) touches USB */ .callback = dmi_disable_osi_linux, - .ident = "Dell", + .ident = "Dell PR 390", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"), @@ -358,7 +367,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell", + .ident = "Dell PE SC440", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"), @@ -474,6 +483,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * * _OSI(Linux) confirmed to be a NOP: * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"), + * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), + * + * unknown: + * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"), + * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), */ { .callback = dmi_disable_osi_linux, @@ -516,7 +530,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"), */ { - .callback = dmi_unknown_osi_linux, + .callback = dmi_disable_osi_linux, .ident = "Sony", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index bf513e07b77..6df564f4ca6 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -130,6 +130,63 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) { module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); +static char trace_method_name[6]; +module_param_string(trace_method_name, trace_method_name, 6, 0644); +static unsigned int trace_debug_layer; +module_param(trace_debug_layer, uint, 0644); +static unsigned int trace_debug_level; +module_param(trace_debug_level, uint, 0644); + +static int param_set_trace_state(const char *val, struct kernel_param *kp) +{ + int result = 0; + + if (!strncmp(val, "enable", strlen("enable") - 1)) { + result = acpi_debug_trace(trace_method_name, trace_debug_level, + trace_debug_layer, 0); + if (result) + result = -EBUSY; + goto exit; + } + + if (!strncmp(val, "disable", strlen("disable") - 1)) { + int name = 0; + result = acpi_debug_trace((char *)&name, trace_debug_level, + trace_debug_layer, 0); + if (result) + result = -EBUSY; + goto exit; + } + + if (!strncmp(val, "1", 1)) { + result = acpi_debug_trace(trace_method_name, trace_debug_level, + trace_debug_layer, 1); + if (result) + result = -EBUSY; + goto exit; + } + + result = -EINVAL; +exit: + return result; +} + +static int param_get_trace_state(char *buffer, struct kernel_param *kp) +{ + if (!acpi_gbl_trace_method_name) + return sprintf(buffer, "disable"); + else { + if (acpi_gbl_trace_flags & 1) + return sprintf(buffer, "1"); + else + return sprintf(buffer, "enable"); + } + return 0; +} + +module_param_call(trace_state, param_set_trace_state, param_get_trace_state, + NULL, 0644); + /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 1dabdf4c07b..b3dec2101e2 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -51,6 +51,12 @@ static struct atomic_notifier_head dock_notifier_list; static struct platform_device *dock_device; static char dock_device_name[] = "dock"; +static const struct acpi_device_id dock_device_ids[] = { + {"LNXDOCK", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, dock_device_ids); + struct dock_station { acpi_handle handle; unsigned long last_dock_time; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 987b967c746..7222a18a031 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -573,7 +573,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, void *handler_context, void *region_context) { struct acpi_ec *ec = handler_context; - int result = 0, i = 0; + int result = 0, i; u8 temp = 0; if ((address > 0xFF) || !value || !handler_context) @@ -585,7 +585,18 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, if (bits != 8 && acpi_strict) return AE_BAD_PARAMETER; - while (bits - i > 0) { + acpi_ec_burst_enable(ec); + + if (function == ACPI_READ) { + result = acpi_ec_read(ec, address, &temp); + *value = temp; + } else { + temp = 0xff & (*value); + result = acpi_ec_write(ec, address, temp); + } + + for (i = 8; unlikely(bits - i > 0); i += 8) { + ++address; if (function == ACPI_READ) { result = acpi_ec_read(ec, address, &temp); (*value) |= ((acpi_integer)temp) << i; @@ -593,10 +604,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, temp = 0xff & ((*value) >> i); result = acpi_ec_write(ec, address, temp); } - i += 8; - ++address; } + acpi_ec_burst_disable(ec); + switch (result) { case -EINVAL: return AE_BAD_PARAMETER; diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index e22f4a973c0..31cb8cd8cab 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -270,18 +270,18 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) case ACPI_GPE_TYPE_WAKE_RUN: ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); - /*lint -fallthrough */ + /* fallthrough */ case ACPI_GPE_TYPE_RUNTIME: /* Disable the requested runtime GPE */ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); - status = acpi_hw_write_gpe_enable_reg(gpe_event_info); - break; + + /* fallthrough */ default: - return_ACPI_STATUS(AE_BAD_PARAMETER); + acpi_hw_write_gpe_enable_reg(gpe_event_info); } return_ACPI_STATUS(AE_OK); @@ -501,6 +501,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) * an interrupt handler. * ******************************************************************************/ +static void acpi_ev_asynch_enable_gpe(void *context); static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) { @@ -576,22 +577,30 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) method_node))); } } + /* Defer enabling of GPE until all notify handlers are done */ + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe, + gpe_event_info); + return_VOID; +} - if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == +static void acpi_ev_asynch_enable_gpe(void *context) +{ + struct acpi_gpe_event_info *gpe_event_info = context; + acpi_status status; + if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) { /* * GPE is level-triggered, we clear the GPE status bit after * handling the event. */ - status = acpi_hw_clear_gpe(&local_gpe_event_info); + status = acpi_hw_clear_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { return_VOID; } } /* Enable this GPE */ - - (void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info); + (void)acpi_hw_write_gpe_enable_reg(gpe_event_info); return_VOID; } diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index f39fbc6b923..b92133faf5b 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -443,6 +443,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, struct acpica_device_id hid; struct acpi_compatible_id_list *cid; acpi_native_uint i; + int found; status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -496,16 +497,19 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, /* Walk the CID list */ + found = 0; for (i = 0; i < cid->count; i++) { if (ACPI_STRNCMP(cid->id[i].value, info->hid, sizeof(struct - acpi_compatible_id)) != + acpi_compatible_id)) == 0) { - ACPI_FREE(cid); - return (AE_OK); + found = 1; + break; } } ACPI_FREE(cid); + if (!found) + return (AE_OK); } } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e53fb516f9d..0c41db3075a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -120,7 +120,7 @@ static char osi_additional_string[OSI_STRING_LENGTH_MAX]; */ #define OSI_LINUX_ENABLE 0 -struct osi_linux { +static struct osi_linux { unsigned int enable:1; unsigned int dmi:1; unsigned int cmdline:1; @@ -250,11 +250,16 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) "System description tables not found\n"); return 0; } - } else - return acpi_find_rsdp(); + } else { + acpi_physical_address pa = 0; + + acpi_find_root_pointer(&pa); + return pa; + } } -void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) +void __iomem *__init_refok +acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { if (phys > ULONG_MAX) { printk(KERN_ERR PREFIX "Cannot map memory that high\n"); @@ -661,25 +666,6 @@ static void acpi_os_execute_deferred(struct work_struct *work) dpc->function(dpc->context); kfree(dpc); - /* Yield cpu to notify thread */ - cond_resched(); - - return; -} - -static void acpi_os_execute_notify(struct work_struct *work) -{ - struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); - - if (!dpc) { - printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); - return; - } - - dpc->function(dpc->context); - - kfree(dpc); - return; } @@ -703,7 +689,7 @@ acpi_status acpi_os_execute(acpi_execute_type type, { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; - + struct workqueue_struct *queue; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); @@ -727,20 +713,13 @@ acpi_status acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - if (type == OSL_NOTIFY_HANDLER) { - INIT_WORK(&dpc->work, acpi_os_execute_notify); - if (!queue_work(kacpi_notify_wq, &dpc->work)) { - status = AE_ERROR; - kfree(dpc); - } - } else { - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - if (!queue_work(kacpid_wq, &dpc->work)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Call to queue_work() failed.\n")); - status = AE_ERROR; - kfree(dpc); - } + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; + if (!queue_work(queue, &dpc->work)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Call to queue_work() failed.\n")); + status = AE_ERROR; + kfree(dpc); } return_ACPI_STATUS(status); } @@ -1213,24 +1192,24 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) * * Returns 0 on success */ -int acpi_dmi_dump(void) +static int acpi_dmi_dump(void) { if (!dmi_available) return -1; printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", - dmi_get_slot(DMI_SYS_VENDOR)); + dmi_get_system_info(DMI_SYS_VENDOR)); printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", - dmi_get_slot(DMI_PRODUCT_NAME)); + dmi_get_system_info(DMI_PRODUCT_NAME)); printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", - dmi_get_slot(DMI_PRODUCT_VERSION)); + dmi_get_system_info(DMI_PRODUCT_VERSION)); printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", - dmi_get_slot(DMI_BOARD_NAME)); + dmi_get_system_info(DMI_BOARD_NAME)); printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", - dmi_get_slot(DMI_BIOS_VENDOR)); + dmi_get_system_info(DMI_BIOS_VENDOR)); printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", - dmi_get_slot(DMI_BIOS_DATE)); + dmi_get_system_info(DMI_BIOS_DATE)); return 0; } diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e48ee4f8749..c53113e1800 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -812,11 +812,18 @@ static int is_processor_present(acpi_handle handle) status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) { - ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); - return 0; - } - return 1; + /* + * if a processor object does not have an _STA object, + * OSPM assumes that the processor is present. + */ + if (status == AE_NOT_FOUND) + return 1; + + if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) + return 1; + + ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); + return 0; } static diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 199ea214615..32003fdc91e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -98,6 +98,9 @@ module_param(bm_history, uint, 0644); static int acpi_processor_set_power_policy(struct acpi_processor *pr); +#else /* CONFIG_CPU_IDLE */ +static unsigned int latency_factor __read_mostly = 2; +module_param(latency_factor, uint, 0644); #endif /* @@ -201,6 +204,10 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); } +/* + * Callers should disable interrupts before the call and enable + * interrupts after return. + */ static void acpi_safe_halt(void) { current_thread_info()->status &= ~TS_POLLING; @@ -261,7 +268,7 @@ static atomic_t c3_cpu_count; /* Common C-state entry for C2, C3, .. */ static void acpi_cstate_enter(struct acpi_processor_cx *cstate) { - if (cstate->space_id == ACPI_CSTATE_FFH) { + if (cstate->entry_method == ACPI_CSTATE_FFH) { /* Call into architectural FFH based C-state */ acpi_processor_ffh_cstate_enter(cstate); } else { @@ -413,6 +420,8 @@ static void acpi_processor_idle(void) pm_idle_save(); else acpi_safe_halt(); + + local_irq_enable(); return; } @@ -521,6 +530,7 @@ static void acpi_processor_idle(void) * skew otherwise. */ sleep_ticks = 0xFFFFFFFF; + local_irq_enable(); break; case ACPI_STATE_C2: @@ -922,20 +932,20 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.address = reg->address; cx.index = current_count + 1; - cx.space_id = ACPI_CSTATE_SYSTEMIO; + cx.entry_method = ACPI_CSTATE_SYSTEMIO; if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { if (acpi_processor_ffh_cstate_probe (pr->id, &cx, reg) == 0) { - cx.space_id = ACPI_CSTATE_FFH; - } else if (cx.type != ACPI_STATE_C1) { + cx.entry_method = ACPI_CSTATE_FFH; + } else if (cx.type == ACPI_STATE_C1) { /* * C1 is a special case where FIXED_HARDWARE * can be handled in non-MWAIT way as well. * In that case, save this _CST entry info. - * That is, we retain space_id of SYSTEM_IO for - * halt based C1. * Otherwise, ignore this info and continue. */ + cx.entry_method = ACPI_CSTATE_HALT; + } else { continue; } } @@ -1369,12 +1379,16 @@ static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr, /** * acpi_idle_do_entry - a helper function that does C2 and C3 type entry * @cx: cstate data + * + * Caller disables interrupt before call and enables interrupt after return. */ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) { - if (cx->space_id == ACPI_CSTATE_FFH) { + if (cx->entry_method == ACPI_CSTATE_FFH) { /* Call into architectural FFH based C-state */ acpi_processor_ffh_cstate_enter(cx); + } else if (cx->entry_method == ACPI_CSTATE_HALT) { + acpi_safe_halt(); } else { int unused; /* IO port based C-state */ @@ -1396,21 +1410,27 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct cpuidle_state *state) { + u32 t1, t2; struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); + pr = processors[smp_processor_id()]; if (unlikely(!pr)) return 0; + local_irq_disable(); if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); - acpi_safe_halt(); + t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + acpi_idle_do_entry(cx); + t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + local_irq_enable(); cx->usage++; - return 0; + return ticks_elapsed_in_us(t1, t2); } /** @@ -1517,7 +1537,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (dev->safe_state) { return dev->safe_state->enter(dev, dev->safe_state); } else { + local_irq_disable(); acpi_safe_halt(); + local_irq_enable(); return 0; } } @@ -1609,7 +1631,7 @@ struct cpuidle_driver acpi_idle_driver = { */ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) { - int i, count = 0; + int i, count = CPUIDLE_DRIVER_STATE_START; struct acpi_processor_cx *cx; struct cpuidle_state *state; struct cpuidle_device *dev = &pr->power.dev; @@ -1638,13 +1660,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); state->exit_latency = cx->latency; - state->target_residency = cx->latency * 6; + state->target_residency = cx->latency * latency_factor; state->power_usage = cx->power; state->flags = 0; switch (cx->type) { case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; + state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_c1; dev->safe_state = state; break; @@ -1667,6 +1690,8 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) } count++; + if (count == CPUIDLE_STATE_MAX) + break; } dev->state_count = count; diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 463b0247cbc..f32010bee4d 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -60,6 +60,11 @@ static DEFINE_MUTEX(performance_mutex); * policy is adjusted accordingly. */ +static unsigned int ignore_ppc = 0; +module_param(ignore_ppc, uint, 0644); +MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ + "limited by BIOS, this should help"); + #define PPC_REGISTERED 1 #define PPC_IN_USE 2 @@ -72,6 +77,9 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, struct acpi_processor *pr; unsigned int ppc = 0; + if (ignore_ppc) + return 0; + mutex_lock(&performance_mutex); if (event != CPUFREQ_INCOMPATIBLE) @@ -130,7 +138,13 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) int acpi_processor_ppc_has_changed(struct acpi_processor *pr) { - int ret = acpi_processor_get_platform_limit(pr); + int ret; + + if (ignore_ppc) + return 0; + + ret = acpi_processor_get_platform_limit(pr); + if (ret < 0) return (ret); else diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d9d531cce27..c7b0aa52dd2 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -941,6 +941,15 @@ static int acpi_bay_match(struct acpi_device *device){ return -ENODEV; } +/* + * acpi_dock_match - see if a device has a _DCK method + */ +static int acpi_dock_match(struct acpi_device *device) +{ + acpi_handle tmp; + return acpi_get_handle(device->handle, "_DCK", &tmp); +} + static void acpi_device_set_id(struct acpi_device *device, struct acpi_device *parent, acpi_handle handle, int type) @@ -950,6 +959,7 @@ static void acpi_device_set_id(struct acpi_device *device, char *hid = NULL; char *uid = NULL; struct acpi_compatible_id_list *cid_list = NULL; + const char *cid_add = NULL; acpi_status status; switch (type) { @@ -972,15 +982,18 @@ static void acpi_device_set_id(struct acpi_device *device, device->flags.bus_address = 1; } - if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){ - status = acpi_video_bus_match(device); - if(ACPI_SUCCESS(status)) - hid = ACPI_VIDEO_HID; + /* If we have a video/bay/dock device, add our selfdefined + HID to the CID list. Like that the video/bay/dock drivers + will get autoloaded and the device might still match + against another driver. + */ + if (ACPI_SUCCESS(acpi_video_bus_match(device))) + cid_add = ACPI_VIDEO_HID; + else if (ACPI_SUCCESS(acpi_bay_match(device))) + cid_add = ACPI_BAY_HID; + else if (ACPI_SUCCESS(acpi_dock_match(device))) + cid_add = ACPI_DOCK_HID; - status = acpi_bay_match(device); - if (ACPI_SUCCESS(status)) - hid = ACPI_BAY_HID; - } break; case ACPI_BUS_TYPE_POWER: hid = ACPI_POWER_HID; @@ -1021,11 +1034,44 @@ static void acpi_device_set_id(struct acpi_device *device, strcpy(device->pnp.unique_id, uid); device->flags.unique_id = 1; } - if (cid_list) { - device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL); - if (device->pnp.cid_list) - memcpy(device->pnp.cid_list, cid_list, cid_list->size); - else + if (cid_list || cid_add) { + struct acpi_compatible_id_list *list; + int size = 0; + int count = 0; + + if (cid_list) { + size = cid_list->size; + } else if (cid_add) { + size = sizeof(struct acpi_compatible_id_list); + cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); + if (!cid_list) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(buffer.pointer); + return; + } else { + cid_list->count = 0; + cid_list->size = size; + } + } + if (cid_add) + size += sizeof(struct acpi_compatible_id); + list = kmalloc(size, GFP_KERNEL); + + if (list) { + if (cid_list) { + memcpy(list, cid_list, cid_list->size); + count = cid_list->count; + } + if (cid_add) { + strncpy(list->id[count].value, cid_add, + ACPI_MAX_CID_LENGTH); + count++; + device->flags.compatible_ids = 1; + } + list->size = size; + list->count = count; + device->pnp.cid_list = list; + } else printk(KERN_ERR "Memory allocation error\n"); } @@ -1081,6 +1127,20 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) } static int +acpi_is_child_device(struct acpi_device *device, + int (*matcher)(struct acpi_device *)) +{ + int result = -ENODEV; + + do { + if (ACPI_SUCCESS(matcher(device))) + return AE_OK; + } while ((device = device->parent)); + + return result; +} + +static int acpi_add_single_object(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type, struct acpi_bus_ops *ops) @@ -1131,10 +1191,20 @@ acpi_add_single_object(struct acpi_device **child, case ACPI_BUS_TYPE_PROCESSOR: case ACPI_BUS_TYPE_DEVICE: result = acpi_bus_get_status(device); - if (ACPI_FAILURE(result) || !device->status.present) { - result = -ENOENT; + if (ACPI_FAILURE(result)) { + result = -ENODEV; goto end; } + if (!device->status.present) { + /* Bay and dock should be handled even if absent */ + if (!ACPI_SUCCESS( + acpi_is_child_device(device, acpi_bay_match)) && + !ACPI_SUCCESS( + acpi_is_child_device(device, acpi_dock_match))) { + result = -ENODEV; + goto end; + } + } break; default: STRUCT_TO_INT(device->status) = diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index c9a733f36bd..293a1cbb47c 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -472,11 +472,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) if (acpi_target_sleep_state == ACPI_STATE_S0 || (wake && adev->wakeup.state.enabled && adev->wakeup.sleep_state <= acpi_target_sleep_state)) { + acpi_status status; + acpi_method[3] = 'W'; - acpi_evaluate_integer(handle, acpi_method, NULL, &d_max); - /* Sanity check */ - if (d_max < d_min) + status = acpi_evaluate_integer(handle, acpi_method, NULL, + &d_max); + if (ACPI_FAILURE(status)) { + d_max = d_min; + } else if (d_max < d_min) { + /* Warn the user of the broken DSDT */ + printk(KERN_WARNING "ACPI: Wrong value from %s\n", + acpi_method); + /* Sanitize it */ d_min = d_max; + } } if (d_min_p) diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 1538355c266..f8df5217d47 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -178,6 +178,9 @@ static int get_date_field(char **p, u32 * value) * Try to find delimeter, only to insert null. The end of the * string won't have one, but is still valid. */ + if (*p == NULL) + return result; + next = strpbrk(*p, "- :"); if (next) *next++ = '\0'; @@ -190,6 +193,8 @@ static int get_date_field(char **p, u32 * value) if (next) *p = next; + else + *p = NULL; return result; } @@ -251,27 +256,6 @@ acpi_system_write_alarm(struct file *file, if ((result = get_date_field(&p, &sec))) goto end; - if (sec > 59) { - min += 1; - sec -= 60; - } - if (min > 59) { - hr += 1; - min -= 60; - } - if (hr > 23) { - day += 1; - hr -= 24; - } - if (day > 31) { - mo += 1; - day -= 31; - } - if (mo > 12) { - yr += 1; - mo -= 12; - } - spin_lock_irq(&rtc_lock); rtc_control = CMOS_READ(RTC_CONTROL); @@ -288,24 +272,24 @@ acpi_system_write_alarm(struct file *file, spin_unlock_irq(&rtc_lock); if (sec > 59) { - min++; - sec -= 60; + min += sec/60; + sec = sec%60; } if (min > 59) { - hr++; - min -= 60; + hr += min/60; + min = min%60; } if (hr > 23) { - day++; - hr -= 24; + day += hr/24; + hr = hr%24; } if (day > 31) { - mo++; - day -= 31; + mo += day/32; + day = day%32; } if (mo > 12) { - yr++; - mo -= 12; + yr += mo/13; + mo = mo%13; } spin_lock_irq(&rtc_lock); diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile index 0a7d7afac25..7385efa6162 100644 --- a/drivers/acpi/tables/Makefile +++ b/drivers/acpi/tables/Makefile @@ -2,6 +2,6 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o +obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index cf8fa514189..9ecb4b6c1e7 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -100,7 +100,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) /******************************************************************************* * - * FUNCTION: acpi_tb_find_rsdp + * FUNCTION: acpi_find_root_pointer * * PARAMETERS: table_address - Where the table pointer is returned * @@ -219,8 +219,6 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) return_ACPI_STATUS(AE_NOT_FOUND); } -ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) - /******************************************************************************* * * FUNCTION: acpi_tb_scan_memory_for_rsdp diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 5f79b445121..3a0af9a8cd2 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -492,7 +492,7 @@ static int acpi_thermal_get_devices(struct acpi_thermal *tz) static int acpi_thermal_critical(struct acpi_thermal *tz) { - if (!tz || !tz->trips.critical.flags.valid || nocrt) + if (!tz || !tz->trips.critical.flags.valid) return -EINVAL; if (tz->temperature >= tz->trips.critical.temperature) { @@ -501,9 +501,6 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) } else if (tz->trips.critical.flags.enabled) tz->trips.critical.flags.enabled = 0; - printk(KERN_EMERG - "Critical temperature reached (%ld C), shutting down.\n", - KELVIN_TO_CELSIUS(tz->temperature)); acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, @@ -511,14 +508,20 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); - orderly_poweroff(true); + /* take no action if nocrt is set */ + if(!nocrt) { + printk(KERN_EMERG + "Critical temperature reached (%ld C), shutting down.\n", + KELVIN_TO_CELSIUS(tz->temperature)); + orderly_poweroff(true); + } return 0; } static int acpi_thermal_hot(struct acpi_thermal *tz) { - if (!tz || !tz->trips.hot.flags.valid || nocrt) + if (!tz || !tz->trips.hot.flags.valid) return -EINVAL; if (tz->temperature >= tz->trips.hot.temperature) { @@ -534,7 +537,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); - /* TBD: Call user-mode "sleep(S4)" function */ + /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */ return 0; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bd77e81e81c..a54ff6bce8f 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -292,18 +292,26 @@ static int acpi_video_device_set_state(struct acpi_video_device *device, int sta static int acpi_video_get_brightness(struct backlight_device *bd) { unsigned long cur_level; + int i; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); acpi_video_device_lcd_get_level_current(vd, &cur_level); - return (int) cur_level; + for (i = 2; i < vd->brightness->count; i++) { + if (vd->brightness->levels[i] == cur_level) + /* The first two entries are special - see page 575 + of the ACPI spec 3.0 */ + return i-2; + } + return 0; } static int acpi_video_set_brightness(struct backlight_device *bd) { - int request_level = bd->props.brightness; + int request_level = bd->props.brightness+2; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); - acpi_video_device_lcd_set_level(vd, request_level); + acpi_video_device_lcd_set_level(vd, + vd->brightness->levels[request_level]); return 0; } @@ -652,7 +660,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) kfree(obj); if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ - unsigned long tmp; static int count = 0; char *name; name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); @@ -660,11 +667,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) return; sprintf(name, "acpi_video%d", count++); - acpi_video_device_lcd_get_level_current(device, &tmp); device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); - device->backlight->props.max_brightness = max_level; - device->backlight->props.brightness = (int)tmp; + device->backlight->props.max_brightness = device->brightness->count-3; + device->backlight->props.brightness = acpi_video_get_brightness(device->backlight); backlight_update_status(device->backlight); kfree(name); @@ -1256,8 +1262,37 @@ acpi_video_bus_write_DOS(struct file *file, static int acpi_video_bus_add_fs(struct acpi_device *device) { + long device_id; + int status; struct proc_dir_entry *entry = NULL; struct acpi_video_bus *video; + struct device *dev; + + status = + acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); + + if (!ACPI_SUCCESS(status)) + return -ENODEV; + + /* We need to attempt to determine whether the _ADR refers to a + PCI device or not. There's no terribly good way to do this, + so the best we can hope for is to assume that there'll never + be a video device in the host bridge */ + if (device_id >= 0x10000) { + /* It looks like a PCI device. Does it exist? */ + dev = acpi_get_physical_device(device->handle); + } else { + /* It doesn't look like a PCI device. Does its parent + exist? */ + acpi_handle phandle; + if (acpi_get_parent(device->handle, &phandle)) + return -ENODEV; + dev = acpi_get_physical_device(phandle); + } + if (!dev) + return -ENODEV; + put_device(dev); + video = acpi_driver_data(device); |