Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (23 commits) ACPICA: fix stray va_end() caused by mis-merge ACPI: Reject below-freezing temperatures as invalid critical temperatures ACPICA: Fix for access to deleted object <regression> ACPICA: Fix to make _SST method optional ACPICA: Fix for Load operator, load table at the namespace root ACPICA: Ignore ACPI table signature for Load() operator ACPICA: Fix to allow zero-length ASL field declarations ACPI: use memory_read_from_buffer() bay: exit if notify handler cannot be installed dock.c remove trailing printk whitespace proper prototype for acpi_processor_tstate_has_changed() ACPI: handle invalid ACPI SLIT table PNPACPI: use _CRS IRQ descriptor length for _SRS pnpacpi: fix shareable IRQ encode/decode pnpacpi: fix IRQ flag decoding MAINTAINERS: update ACPI homepage ACPI 2.6.26-rc2: Add missing newline to DSDT/SSDT warning message ACPI: EC: Use msleep instead of udelay while waiting for event. thinkpad-acpi: fix LED handling on older ThinkPads thinkpad-acpi: fix initialization error paths ...
This commit is contained in:
commit
da50ccc6a0
@ -503,7 +503,7 @@ generate input device EV_KEY events.
|
||||
In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW
|
||||
events for switches:
|
||||
|
||||
SW_RADIO T60 and later hardare rfkill rocker switch
|
||||
SW_RFKILL_ALL T60 and later hardare rfkill rocker switch
|
||||
SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A
|
||||
|
||||
Non hot-key ACPI HKEY event map:
|
||||
|
10
MAINTAINERS
10
MAINTAINERS
@ -228,21 +228,21 @@ ACPI BATTERY DRIVERS
|
||||
P: Alexey Starikovskiy
|
||||
M: astarikovskiy@suse.de
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://acpi.sourceforge.net/
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
|
||||
ACPI EC DRIVER
|
||||
P: Alexey Starikovskiy
|
||||
M: astarikovskiy@suse.de
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://acpi.sourceforge.net/
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
|
||||
ACPI FAN DRIVER
|
||||
P: Len Brown
|
||||
M: len.brown@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://acpi.sourceforge.net/
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
|
||||
ACPI PCI HOTPLUG DRIVER
|
||||
@ -255,14 +255,14 @@ ACPI THERMAL DRIVER
|
||||
P: Len Brown
|
||||
M: len.brown@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://acpi.sourceforge.net/
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
|
||||
ACPI VIDEO DRIVER
|
||||
P: Rui Zhang
|
||||
M: rui.zhang@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://acpi.sourceforge.net/
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
|
||||
ACPI WMI DRIVER
|
||||
|
@ -465,7 +465,6 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
|
||||
printk(KERN_ERR
|
||||
"ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
|
||||
len, slit->header.length);
|
||||
memset(numa_slit, 10, sizeof(numa_slit));
|
||||
return;
|
||||
}
|
||||
slit_table = slit;
|
||||
@ -574,8 +573,14 @@ void __init acpi_numa_arch_fixup(void)
|
||||
printk(KERN_INFO "Number of memory chunks in system = %d\n",
|
||||
num_node_memblks);
|
||||
|
||||
if (!slit_table)
|
||||
if (!slit_table) {
|
||||
for (i = 0; i < MAX_NUMNODES; i++)
|
||||
for (j = 0; j < MAX_NUMNODES; j++)
|
||||
node_distance(i, j) = i == j ? LOCAL_DISTANCE :
|
||||
REMOTE_DISTANCE;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(numa_slit, -1, sizeof(numa_slit));
|
||||
for (i = 0; i < slit_table->locality_count; i++) {
|
||||
if (!pxm_bit_test(i))
|
||||
|
@ -97,36 +97,9 @@ static __init inline int srat_disabled(void)
|
||||
return numa_off || acpi_numa < 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A lot of BIOS fill in 10 (= no distance) everywhere. This messes
|
||||
* up the NUMA heuristics which wants the local node to have a smaller
|
||||
* distance than the others.
|
||||
* Do some quick checks here and only use the SLIT if it passes.
|
||||
*/
|
||||
static __init int slit_valid(struct acpi_table_slit *slit)
|
||||
{
|
||||
int i, j;
|
||||
int d = slit->locality_count;
|
||||
for (i = 0; i < d; i++) {
|
||||
for (j = 0; j < d; j++) {
|
||||
u8 val = slit->entry[d*i + j];
|
||||
if (i == j) {
|
||||
if (val != LOCAL_DISTANCE)
|
||||
return 0;
|
||||
} else if (val <= LOCAL_DISTANCE)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Callback for SLIT parsing */
|
||||
void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
|
||||
{
|
||||
if (!slit_valid(slit)) {
|
||||
printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
|
||||
return;
|
||||
}
|
||||
acpi_slit = slit;
|
||||
}
|
||||
|
||||
|
@ -301,16 +301,20 @@ static int bay_add(acpi_handle handle, int id)
|
||||
*/
|
||||
pdev->dev.uevent_suppress = 0;
|
||||
|
||||
if (acpi_bay_add_fs(new_bay)) {
|
||||
platform_device_unregister(new_bay->pdev);
|
||||
goto bay_add_err;
|
||||
}
|
||||
|
||||
/* register for events on this device */
|
||||
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
bay_notify, new_bay);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX "Error installing bay notify handler\n");
|
||||
printk(KERN_INFO PREFIX "Error installing bay notify handler\n");
|
||||
platform_device_unregister(new_bay->pdev);
|
||||
goto bay_add_err;
|
||||
}
|
||||
|
||||
if (acpi_bay_add_fs(new_bay)) {
|
||||
acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
bay_notify);
|
||||
platform_device_unregister(new_bay->pdev);
|
||||
goto bay_add_err;
|
||||
}
|
||||
|
||||
/* if we are on a dock station, we should register for dock
|
||||
|
@ -450,10 +450,6 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
return_ACPI_STATUS(AE_AML_NO_OPERAND);
|
||||
}
|
||||
|
||||
/* Creating new namespace node(s), should not already exist */
|
||||
|
||||
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
|
||||
@ -467,6 +463,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
|
||||
|
||||
/*
|
||||
* Walk the list of entries in the field_list
|
||||
* Note: field_list can be of zero length. In this case, Arg will be NULL.
|
||||
*/
|
||||
while (arg) {
|
||||
/*
|
||||
|
@ -834,7 +834,7 @@ static int dock_add(acpi_handle handle)
|
||||
goto dock_add_err;
|
||||
}
|
||||
|
||||
printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
|
||||
printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -194,7 +194,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
|
||||
while (time_before(jiffies, delay)) {
|
||||
if (acpi_ec_check_status(ec, event))
|
||||
return 0;
|
||||
udelay(ACPI_EC_UDELAY);
|
||||
msleep(1);
|
||||
}
|
||||
}
|
||||
pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",
|
||||
|
@ -375,9 +375,15 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the table to the namespace.
|
||||
*
|
||||
* Note: We load the table objects relative to the root of the namespace.
|
||||
* This appears to go against the ACPI specification, but we do it for
|
||||
* compatibility with other ACPI implementations.
|
||||
*/
|
||||
status =
|
||||
acpi_ex_add_table(table_index, walk_state->scope_info->scope.node,
|
||||
&ddb_handle);
|
||||
acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* On error, table_ptr was deallocated above */
|
||||
|
@ -272,6 +272,12 @@ static u32 rtc_handler(void *context)
|
||||
static inline void rtc_wake_setup(void)
|
||||
{
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
|
||||
/*
|
||||
* After the RTC handler is installed, the Fixed_RTC event should
|
||||
* be disabled. Only when the RTC alarm is set will it be enabled.
|
||||
*/
|
||||
acpi_clear_event(ACPI_EVENT_RTC);
|
||||
acpi_disable_event(ACPI_EVENT_RTC, 0);
|
||||
}
|
||||
|
||||
static void rtc_wake_on(struct device *dev)
|
||||
|
@ -223,15 +223,17 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the system indicators to show the desired sleep state. */
|
||||
|
||||
/*
|
||||
* Set the system indicators to show the desired sleep state.
|
||||
* _SST is an optional method (return no error if not found)
|
||||
*/
|
||||
status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"While executing method _SST"));
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
|
||||
|
@ -140,19 +140,42 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A lot of BIOS fill in 10 (= no distance) everywhere. This messes
|
||||
* up the NUMA heuristics which wants the local node to have a smaller
|
||||
* distance than the others.
|
||||
* Do some quick checks here and only use the SLIT if it passes.
|
||||
*/
|
||||
static __init int slit_valid(struct acpi_table_slit *slit)
|
||||
{
|
||||
int i, j;
|
||||
int d = slit->locality_count;
|
||||
for (i = 0; i < d; i++) {
|
||||
for (j = 0; j < d; j++) {
|
||||
u8 val = slit->entry[d*i + j];
|
||||
if (i == j) {
|
||||
if (val != LOCAL_DISTANCE)
|
||||
return 0;
|
||||
} else if (val <= LOCAL_DISTANCE)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init acpi_parse_slit(struct acpi_table_header *table)
|
||||
{
|
||||
struct acpi_table_slit *slit;
|
||||
u32 localities;
|
||||
|
||||
if (!table)
|
||||
return -EINVAL;
|
||||
|
||||
slit = (struct acpi_table_slit *)table;
|
||||
|
||||
/* downcast just for %llu vs %lu for i386/ia64 */
|
||||
localities = (u32) slit->locality_count;
|
||||
|
||||
if (!slit_valid(slit)) {
|
||||
printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
acpi_numa_slit_init(slit);
|
||||
|
||||
return 0;
|
||||
|
@ -268,7 +268,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
|
||||
*/
|
||||
if (ACPI_SUCCESS(status) &&
|
||||
possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
|
||||
if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
|
||||
if (walk_state->opcode == AML_UNLOAD_OP) {
|
||||
/*
|
||||
* acpi_ps_get_next_namestring has increased the AML pointer,
|
||||
* so we need to restore the saved AML pointer for method call.
|
||||
@ -691,7 +691,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* To support super_name arg of Unload */
|
||||
|
||||
if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
|
||||
if (walk_state->opcode == AML_UNLOAD_OP) {
|
||||
status =
|
||||
acpi_ps_get_next_namepath(walk_state,
|
||||
parser_state, arg,
|
||||
|
@ -86,7 +86,6 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
|
||||
static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
|
||||
static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
|
||||
static int acpi_processor_handle_eject(struct acpi_processor *pr);
|
||||
extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
|
||||
|
||||
|
||||
static const struct acpi_device_id processor_device_ids[] = {
|
||||
|
@ -1669,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->cpu = pr->id;
|
||||
for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
|
||||
dev->states[i].name[0] = '\0';
|
||||
dev->states[i].desc[0] = '\0';
|
||||
@ -1738,7 +1739,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
|
||||
|
||||
int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (boot_option_idle_override)
|
||||
return 0;
|
||||
@ -1756,8 +1757,10 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
||||
cpuidle_pause_and_lock();
|
||||
cpuidle_disable_device(&pr->power.dev);
|
||||
acpi_processor_get_power_info(pr);
|
||||
acpi_processor_setup_cpuidle(pr);
|
||||
ret = cpuidle_enable_device(&pr->power.dev);
|
||||
if (pr->flags.power) {
|
||||
acpi_processor_setup_cpuidle(pr);
|
||||
ret = cpuidle_enable_device(&pr->power.dev);
|
||||
}
|
||||
cpuidle_resume_and_unlock();
|
||||
|
||||
return ret;
|
||||
@ -1813,7 +1816,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||
if (pr->flags.power) {
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
acpi_processor_setup_cpuidle(pr);
|
||||
pr->power.dev.cpu = pr->id;
|
||||
if (cpuidle_register_device(&pr->power.dev))
|
||||
return -EIO;
|
||||
#endif
|
||||
@ -1850,8 +1852,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
if (pr->flags.power)
|
||||
cpuidle_unregister_device(&pr->power.dev);
|
||||
cpuidle_unregister_device(&pr->power.dev);
|
||||
#endif
|
||||
pr->flags.power_setup_done = 0;
|
||||
|
||||
|
@ -495,6 +495,12 @@ static int __init acpi_sleep_proc_init(void)
|
||||
acpi_root_dir, &acpi_system_alarm_fops);
|
||||
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
|
||||
/*
|
||||
* Disable the RTC event after installing RTC handler.
|
||||
* Only when RTC alarm is set will it be enabled.
|
||||
*/
|
||||
acpi_clear_event(ACPI_EVENT_RTC);
|
||||
acpi_disable_event(ACPI_EVENT_RTC, 0);
|
||||
#endif /* HAVE_ACPI_LEGACY_ALARM */
|
||||
|
||||
/* 'wakeup device' [R/W] */
|
||||
|
@ -77,7 +77,6 @@ static ssize_t acpi_table_show(struct kobject *kobj,
|
||||
container_of(bin_attr, struct acpi_table_attr, attr);
|
||||
struct acpi_table_header *table_header = NULL;
|
||||
acpi_status status;
|
||||
ssize_t ret_count = count;
|
||||
|
||||
status =
|
||||
acpi_get_table(table_attr->name, table_attr->instance,
|
||||
@ -85,18 +84,8 @@ static ssize_t acpi_table_show(struct kobject *kobj,
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
if (offset >= table_header->length) {
|
||||
ret_count = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (offset + ret_count > table_header->length)
|
||||
ret_count = table_header->length - offset;
|
||||
|
||||
memcpy(buf, ((char *)table_header) + offset, ret_count);
|
||||
|
||||
end:
|
||||
return ret_count;
|
||||
return memory_read_from_buffer(buf, count, &offset,
|
||||
table_header, table_header->length);
|
||||
}
|
||||
|
||||
static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
|
||||
|
@ -123,24 +123,13 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc,
|
||||
}
|
||||
}
|
||||
|
||||
/* The table must be either an SSDT or a PSDT or an OEMx */
|
||||
|
||||
if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&&
|
||||
!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&&
|
||||
strncmp(table_desc->pointer->signature, "OEM", 3)) {
|
||||
/* Check for a printable name */
|
||||
if (acpi_ut_valid_acpi_name(
|
||||
*(u32 *) table_desc->pointer->signature)) {
|
||||
ACPI_ERROR((AE_INFO, "Table has invalid signature "
|
||||
"[%4.4s], must be SSDT or PSDT",
|
||||
table_desc->pointer->signature));
|
||||
} else {
|
||||
ACPI_ERROR((AE_INFO, "Table has invalid signature "
|
||||
"(0x%8.8X), must be SSDT or PSDT",
|
||||
*(u32 *) table_desc->pointer->signature));
|
||||
}
|
||||
return_ACPI_STATUS(AE_BAD_SIGNATURE);
|
||||
}
|
||||
/*
|
||||
* Originally, we checked the table signature for "SSDT" or "PSDT" here.
|
||||
* Next, we added support for OEMx tables, signature "OEM".
|
||||
* Valid tables were encountered with a null signature, so we've just
|
||||
* given up on validating the signature, since it seems to be a waste
|
||||
* of code. The original code was removed (05/2008).
|
||||
*/
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
|
@ -540,7 +540,7 @@ static acpi_status acpi_tb_load_namespace(void)
|
||||
acpi_tb_print_table_header(0, table);
|
||||
|
||||
if (no_auto_ssdt == 0) {
|
||||
printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"");
|
||||
printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,10 +364,17 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
if (flag & ACPI_TRIPS_CRITICAL) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_CRT", NULL, &tz->trips.critical.temperature);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
/*
|
||||
* Treat freezing temperatures as invalid as well; some
|
||||
* BIOSes return really low values and cause reboots at startup.
|
||||
* Below zero (Celcius) values clearly aren't right for sure..
|
||||
* ... so lets discard those as invalid.
|
||||
*/
|
||||
if (ACPI_FAILURE(status) ||
|
||||
tz->trips.critical.temperature <= 2732) {
|
||||
tz->trips.critical.flags.valid = 0;
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"No critical threshold"));
|
||||
"No or invalid critical threshold"));
|
||||
return -ENODEV;
|
||||
} else {
|
||||
tz->trips.critical.flags.valid = 1;
|
||||
|
@ -1048,6 +1048,7 @@ acpi_ut_exception(char *module_name,
|
||||
va_start(args, format);
|
||||
acpi_os_vprintf(format, args);
|
||||
acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(acpi_ut_exception);
|
||||
@ -1063,7 +1064,6 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
|
||||
acpi_os_vprintf(format, args);
|
||||
acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
|
||||
va_end(args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE
|
||||
|
@ -38,6 +38,8 @@ static void cpuidle_kick_cpus(void)
|
||||
static void cpuidle_kick_cpus(void) {}
|
||||
#endif
|
||||
|
||||
static int __cpuidle_register_device(struct cpuidle_device *dev);
|
||||
|
||||
/**
|
||||
* cpuidle_idle_call - the main idle loop
|
||||
*
|
||||
@ -138,6 +140,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
|
||||
if (!dev->state_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->registered == 0) {
|
||||
ret = __cpuidle_register_device(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = cpuidle_add_state_sysfs(dev)))
|
||||
return ret;
|
||||
|
||||
@ -232,10 +240,13 @@ static void poll_idle_init(struct cpuidle_device *dev) {}
|
||||
#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
|
||||
|
||||
/**
|
||||
* cpuidle_register_device - registers a CPU's idle PM feature
|
||||
* __cpuidle_register_device - internal register function called before register
|
||||
* and enable routines
|
||||
* @dev: the cpu
|
||||
*
|
||||
* cpuidle_lock mutex must be held before this is called
|
||||
*/
|
||||
int cpuidle_register_device(struct cpuidle_device *dev)
|
||||
static int __cpuidle_register_device(struct cpuidle_device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
|
||||
@ -247,18 +258,34 @@ int cpuidle_register_device(struct cpuidle_device *dev)
|
||||
|
||||
init_completion(&dev->kobj_unregister);
|
||||
|
||||
mutex_lock(&cpuidle_lock);
|
||||
|
||||
poll_idle_init(dev);
|
||||
|
||||
per_cpu(cpuidle_devices, dev->cpu) = dev;
|
||||
list_add(&dev->device_list, &cpuidle_detected_devices);
|
||||
if ((ret = cpuidle_add_sysfs(sys_dev))) {
|
||||
mutex_unlock(&cpuidle_lock);
|
||||
module_put(cpuidle_curr_driver->owner);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev->registered = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpuidle_register_device - registers a CPU's idle PM feature
|
||||
* @dev: the cpu
|
||||
*/
|
||||
int cpuidle_register_device(struct cpuidle_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&cpuidle_lock);
|
||||
|
||||
if ((ret = __cpuidle_register_device(dev))) {
|
||||
mutex_unlock(&cpuidle_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cpuidle_enable_device(dev);
|
||||
cpuidle_install_idle_handler();
|
||||
|
||||
@ -278,6 +305,9 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
|
||||
{
|
||||
struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
|
||||
|
||||
if (dev->registered == 0)
|
||||
return;
|
||||
|
||||
cpuidle_pause_and_lock();
|
||||
|
||||
cpuidle_disable_device(dev);
|
||||
|
@ -1293,7 +1293,7 @@ static void tpacpi_input_send_radiosw(void)
|
||||
mutex_lock(&tpacpi_inputdev_send_mutex);
|
||||
|
||||
input_report_switch(tpacpi_inputdev,
|
||||
SW_RADIO, !!wlsw);
|
||||
SW_RFKILL_ALL, !!wlsw);
|
||||
input_sync(tpacpi_inputdev);
|
||||
|
||||
mutex_unlock(&tpacpi_inputdev_send_mutex);
|
||||
@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
|
||||
&dev_attr_hotkey_wakeup_hotunplug_complete.attr,
|
||||
};
|
||||
|
||||
static void hotkey_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
|
||||
hotkey_poll_stop_sync();
|
||||
#endif
|
||||
|
||||
if (hotkey_dev_attributes)
|
||||
delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
|
||||
|
||||
kfree(hotkey_keycode_map);
|
||||
|
||||
if (tp_features.hotkey) {
|
||||
dbg_printk(TPACPI_DBG_EXIT,
|
||||
"restoring original hot key mask\n");
|
||||
/* no short-circuit boolean operator below! */
|
||||
if ((hotkey_mask_set(hotkey_orig_mask) |
|
||||
hotkey_status_set(hotkey_orig_status)) != 0)
|
||||
printk(TPACPI_ERR
|
||||
"failed to restore hot key mask "
|
||||
"to BIOS defaults\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int __init hotkey_init(struct ibm_init_struct *iibm)
|
||||
{
|
||||
/* Requirements for changing the default keymaps:
|
||||
@ -2060,226 +2083,220 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
|
||||
vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
|
||||
str_supported(tp_features.hotkey));
|
||||
|
||||
if (tp_features.hotkey) {
|
||||
hotkey_dev_attributes = create_attr_set(13, NULL);
|
||||
if (!hotkey_dev_attributes)
|
||||
return -ENOMEM;
|
||||
res = add_many_to_attr_set(hotkey_dev_attributes,
|
||||
hotkey_attributes,
|
||||
ARRAY_SIZE(hotkey_attributes));
|
||||
if (!tp_features.hotkey)
|
||||
return 1;
|
||||
|
||||
hotkey_dev_attributes = create_attr_set(13, NULL);
|
||||
if (!hotkey_dev_attributes)
|
||||
return -ENOMEM;
|
||||
res = add_many_to_attr_set(hotkey_dev_attributes,
|
||||
hotkey_attributes,
|
||||
ARRAY_SIZE(hotkey_attributes));
|
||||
if (res)
|
||||
goto err_exit;
|
||||
|
||||
/* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
|
||||
A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
|
||||
for HKEY interface version 0x100 */
|
||||
if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
|
||||
if ((hkeyv >> 8) != 1) {
|
||||
printk(TPACPI_ERR "unknown version of the "
|
||||
"HKEY interface: 0x%x\n", hkeyv);
|
||||
printk(TPACPI_ERR "please report this to %s\n",
|
||||
TPACPI_MAIL);
|
||||
} else {
|
||||
/*
|
||||
* MHKV 0x100 in A31, R40, R40e,
|
||||
* T4x, X31, and later
|
||||
*/
|
||||
tp_features.hotkey_mask = 1;
|
||||
}
|
||||
}
|
||||
|
||||
vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
|
||||
str_supported(tp_features.hotkey_mask));
|
||||
|
||||
if (tp_features.hotkey_mask) {
|
||||
if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
|
||||
"MHKA", "qd")) {
|
||||
printk(TPACPI_ERR
|
||||
"missing MHKA handler, "
|
||||
"please report this to %s\n",
|
||||
TPACPI_MAIL);
|
||||
/* FN+F12, FN+F4, FN+F3 */
|
||||
hotkey_all_mask = 0x080cU;
|
||||
}
|
||||
}
|
||||
|
||||
/* hotkey_source_mask *must* be zero for
|
||||
* the first hotkey_mask_get */
|
||||
res = hotkey_status_get(&hotkey_orig_status);
|
||||
if (res)
|
||||
goto err_exit;
|
||||
|
||||
if (tp_features.hotkey_mask) {
|
||||
res = hotkey_mask_get();
|
||||
if (res)
|
||||
return res;
|
||||
goto err_exit;
|
||||
|
||||
/* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
|
||||
A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
|
||||
for HKEY interface version 0x100 */
|
||||
if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
|
||||
if ((hkeyv >> 8) != 1) {
|
||||
printk(TPACPI_ERR "unknown version of the "
|
||||
"HKEY interface: 0x%x\n", hkeyv);
|
||||
printk(TPACPI_ERR "please report this to %s\n",
|
||||
TPACPI_MAIL);
|
||||
} else {
|
||||
/*
|
||||
* MHKV 0x100 in A31, R40, R40e,
|
||||
* T4x, X31, and later
|
||||
*/
|
||||
tp_features.hotkey_mask = 1;
|
||||
}
|
||||
}
|
||||
|
||||
vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
|
||||
str_supported(tp_features.hotkey_mask));
|
||||
|
||||
if (tp_features.hotkey_mask) {
|
||||
if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
|
||||
"MHKA", "qd")) {
|
||||
printk(TPACPI_ERR
|
||||
"missing MHKA handler, "
|
||||
"please report this to %s\n",
|
||||
TPACPI_MAIL);
|
||||
/* FN+F12, FN+F4, FN+F3 */
|
||||
hotkey_all_mask = 0x080cU;
|
||||
}
|
||||
}
|
||||
|
||||
/* hotkey_source_mask *must* be zero for
|
||||
* the first hotkey_mask_get */
|
||||
res = hotkey_status_get(&hotkey_orig_status);
|
||||
if (!res && tp_features.hotkey_mask) {
|
||||
res = hotkey_mask_get();
|
||||
hotkey_orig_mask = hotkey_mask;
|
||||
if (!res) {
|
||||
res = add_many_to_attr_set(
|
||||
hotkey_dev_attributes,
|
||||
hotkey_mask_attributes,
|
||||
ARRAY_SIZE(hotkey_mask_attributes));
|
||||
}
|
||||
}
|
||||
hotkey_orig_mask = hotkey_mask;
|
||||
res = add_many_to_attr_set(
|
||||
hotkey_dev_attributes,
|
||||
hotkey_mask_attributes,
|
||||
ARRAY_SIZE(hotkey_mask_attributes));
|
||||
if (res)
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
|
||||
if (tp_features.hotkey_mask) {
|
||||
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
|
||||
& ~hotkey_all_mask;
|
||||
} else {
|
||||
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
|
||||
}
|
||||
if (tp_features.hotkey_mask) {
|
||||
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
|
||||
& ~hotkey_all_mask;
|
||||
} else {
|
||||
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
|
||||
}
|
||||
|
||||
vdbg_printk(TPACPI_DBG_INIT,
|
||||
"hotkey source mask 0x%08x, polling freq %d\n",
|
||||
hotkey_source_mask, hotkey_poll_freq);
|
||||
vdbg_printk(TPACPI_DBG_INIT,
|
||||
"hotkey source mask 0x%08x, polling freq %d\n",
|
||||
hotkey_source_mask, hotkey_poll_freq);
|
||||
#endif
|
||||
|
||||
/* Not all thinkpads have a hardware radio switch */
|
||||
if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
|
||||
tp_features.hotkey_wlsw = 1;
|
||||
printk(TPACPI_INFO
|
||||
"radio switch found; radios are %s\n",
|
||||
enabled(status, 0));
|
||||
res = add_to_attr_set(hotkey_dev_attributes,
|
||||
&dev_attr_hotkey_radio_sw.attr);
|
||||
}
|
||||
/* Not all thinkpads have a hardware radio switch */
|
||||
if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
|
||||
tp_features.hotkey_wlsw = 1;
|
||||
printk(TPACPI_INFO
|
||||
"radio switch found; radios are %s\n",
|
||||
enabled(status, 0));
|
||||
res = add_to_attr_set(hotkey_dev_attributes,
|
||||
&dev_attr_hotkey_radio_sw.attr);
|
||||
}
|
||||
|
||||
/* For X41t, X60t, X61t Tablets... */
|
||||
if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
|
||||
tp_features.hotkey_tablet = 1;
|
||||
printk(TPACPI_INFO
|
||||
"possible tablet mode switch found; "
|
||||
"ThinkPad in %s mode\n",
|
||||
(status & TP_HOTKEY_TABLET_MASK)?
|
||||
"tablet" : "laptop");
|
||||
res = add_to_attr_set(hotkey_dev_attributes,
|
||||
&dev_attr_hotkey_tablet_mode.attr);
|
||||
}
|
||||
/* For X41t, X60t, X61t Tablets... */
|
||||
if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
|
||||
tp_features.hotkey_tablet = 1;
|
||||
printk(TPACPI_INFO
|
||||
"possible tablet mode switch found; "
|
||||
"ThinkPad in %s mode\n",
|
||||
(status & TP_HOTKEY_TABLET_MASK)?
|
||||
"tablet" : "laptop");
|
||||
res = add_to_attr_set(hotkey_dev_attributes,
|
||||
&dev_attr_hotkey_tablet_mode.attr);
|
||||
}
|
||||
|
||||
if (!res)
|
||||
res = register_attr_set_with_sysfs(
|
||||
hotkey_dev_attributes,
|
||||
&tpacpi_pdev->dev.kobj);
|
||||
if (res)
|
||||
return res;
|
||||
if (!res)
|
||||
res = register_attr_set_with_sysfs(
|
||||
hotkey_dev_attributes,
|
||||
&tpacpi_pdev->dev.kobj);
|
||||
if (res)
|
||||
goto err_exit;
|
||||
|
||||
/* Set up key map */
|
||||
/* Set up key map */
|
||||
|
||||
hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (!hotkey_keycode_map) {
|
||||
printk(TPACPI_ERR
|
||||
"failed to allocate memory for key map\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (!hotkey_keycode_map) {
|
||||
printk(TPACPI_ERR
|
||||
"failed to allocate memory for key map\n");
|
||||
res = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"using Lenovo default hot key map\n");
|
||||
memcpy(hotkey_keycode_map, &lenovo_keycode_map,
|
||||
TPACPI_HOTKEY_MAP_SIZE);
|
||||
if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"using Lenovo default hot key map\n");
|
||||
memcpy(hotkey_keycode_map, &lenovo_keycode_map,
|
||||
TPACPI_HOTKEY_MAP_SIZE);
|
||||
} else {
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"using IBM default hot key map\n");
|
||||
memcpy(hotkey_keycode_map, &ibm_keycode_map,
|
||||
TPACPI_HOTKEY_MAP_SIZE);
|
||||
}
|
||||
|
||||
set_bit(EV_KEY, tpacpi_inputdev->evbit);
|
||||
set_bit(EV_MSC, tpacpi_inputdev->evbit);
|
||||
set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
|
||||
tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
|
||||
tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
|
||||
tpacpi_inputdev->keycode = hotkey_keycode_map;
|
||||
for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
|
||||
if (hotkey_keycode_map[i] != KEY_RESERVED) {
|
||||
set_bit(hotkey_keycode_map[i],
|
||||
tpacpi_inputdev->keybit);
|
||||
} else {
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"using IBM default hot key map\n");
|
||||
memcpy(hotkey_keycode_map, &ibm_keycode_map,
|
||||
TPACPI_HOTKEY_MAP_SIZE);
|
||||
if (i < sizeof(hotkey_reserved_mask)*8)
|
||||
hotkey_reserved_mask |= 1 << i;
|
||||
}
|
||||
|
||||
set_bit(EV_KEY, tpacpi_inputdev->evbit);
|
||||
set_bit(EV_MSC, tpacpi_inputdev->evbit);
|
||||
set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
|
||||
tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
|
||||
tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
|
||||
tpacpi_inputdev->keycode = hotkey_keycode_map;
|
||||
for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
|
||||
if (hotkey_keycode_map[i] != KEY_RESERVED) {
|
||||
set_bit(hotkey_keycode_map[i],
|
||||
tpacpi_inputdev->keybit);
|
||||
} else {
|
||||
if (i < sizeof(hotkey_reserved_mask)*8)
|
||||
hotkey_reserved_mask |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
if (tp_features.hotkey_wlsw) {
|
||||
set_bit(EV_SW, tpacpi_inputdev->evbit);
|
||||
set_bit(SW_RADIO, tpacpi_inputdev->swbit);
|
||||
}
|
||||
if (tp_features.hotkey_tablet) {
|
||||
set_bit(EV_SW, tpacpi_inputdev->evbit);
|
||||
set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
|
||||
}
|
||||
|
||||
/* Do not issue duplicate brightness change events to
|
||||
* userspace */
|
||||
if (!tp_features.bright_acpimode)
|
||||
/* update bright_acpimode... */
|
||||
tpacpi_check_std_acpi_brightness_support();
|
||||
|
||||
if (tp_features.bright_acpimode) {
|
||||
printk(TPACPI_INFO
|
||||
"This ThinkPad has standard ACPI backlight "
|
||||
"brightness control, supported by the ACPI "
|
||||
"video driver\n");
|
||||
printk(TPACPI_NOTICE
|
||||
"Disabling thinkpad-acpi brightness events "
|
||||
"by default...\n");
|
||||
|
||||
/* The hotkey_reserved_mask change below is not
|
||||
* necessary while the keys are at KEY_RESERVED in the
|
||||
* default map, but better safe than sorry, leave it
|
||||
* here as a marker of what we have to do, especially
|
||||
* when we finally become able to set this at runtime
|
||||
* on response to X.org requests */
|
||||
hotkey_reserved_mask |=
|
||||
(1 << TP_ACPI_HOTKEYSCAN_FNHOME)
|
||||
| (1 << TP_ACPI_HOTKEYSCAN_FNEND);
|
||||
}
|
||||
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"enabling hot key handling\n");
|
||||
res = hotkey_status_set(1);
|
||||
if (res)
|
||||
return res;
|
||||
res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask)
|
||||
& ~hotkey_reserved_mask)
|
||||
| hotkey_orig_mask);
|
||||
if (res < 0 && res != -ENXIO)
|
||||
return res;
|
||||
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"legacy hot key reporting over procfs %s\n",
|
||||
(hotkey_report_mode < 2) ?
|
||||
"enabled" : "disabled");
|
||||
|
||||
tpacpi_inputdev->open = &hotkey_inputdev_open;
|
||||
tpacpi_inputdev->close = &hotkey_inputdev_close;
|
||||
|
||||
hotkey_poll_setup_safe(1);
|
||||
tpacpi_input_send_radiosw();
|
||||
tpacpi_input_send_tabletsw();
|
||||
}
|
||||
|
||||
return (tp_features.hotkey)? 0 : 1;
|
||||
}
|
||||
|
||||
static void hotkey_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
|
||||
hotkey_poll_stop_sync();
|
||||
#endif
|
||||
|
||||
if (tp_features.hotkey) {
|
||||
dbg_printk(TPACPI_DBG_EXIT,
|
||||
"restoring original hot key mask\n");
|
||||
/* no short-circuit boolean operator below! */
|
||||
if ((hotkey_mask_set(hotkey_orig_mask) |
|
||||
hotkey_status_set(hotkey_orig_status)) != 0)
|
||||
printk(TPACPI_ERR
|
||||
"failed to restore hot key mask "
|
||||
"to BIOS defaults\n");
|
||||
if (tp_features.hotkey_wlsw) {
|
||||
set_bit(EV_SW, tpacpi_inputdev->evbit);
|
||||
set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
|
||||
}
|
||||
if (tp_features.hotkey_tablet) {
|
||||
set_bit(EV_SW, tpacpi_inputdev->evbit);
|
||||
set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
|
||||
}
|
||||
|
||||
if (hotkey_dev_attributes) {
|
||||
delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
|
||||
hotkey_dev_attributes = NULL;
|
||||
/* Do not issue duplicate brightness change events to
|
||||
* userspace */
|
||||
if (!tp_features.bright_acpimode)
|
||||
/* update bright_acpimode... */
|
||||
tpacpi_check_std_acpi_brightness_support();
|
||||
|
||||
if (tp_features.bright_acpimode) {
|
||||
printk(TPACPI_INFO
|
||||
"This ThinkPad has standard ACPI backlight "
|
||||
"brightness control, supported by the ACPI "
|
||||
"video driver\n");
|
||||
printk(TPACPI_NOTICE
|
||||
"Disabling thinkpad-acpi brightness events "
|
||||
"by default...\n");
|
||||
|
||||
/* The hotkey_reserved_mask change below is not
|
||||
* necessary while the keys are at KEY_RESERVED in the
|
||||
* default map, but better safe than sorry, leave it
|
||||
* here as a marker of what we have to do, especially
|
||||
* when we finally become able to set this at runtime
|
||||
* on response to X.org requests */
|
||||
hotkey_reserved_mask |=
|
||||
(1 << TP_ACPI_HOTKEYSCAN_FNHOME)
|
||||
| (1 << TP_ACPI_HOTKEYSCAN_FNEND);
|
||||
}
|
||||
|
||||
dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n");
|
||||
res = hotkey_status_set(1);
|
||||
if (res) {
|
||||
hotkey_exit();
|
||||
return res;
|
||||
}
|
||||
res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask)
|
||||
& ~hotkey_reserved_mask)
|
||||
| hotkey_orig_mask);
|
||||
if (res < 0 && res != -ENXIO) {
|
||||
hotkey_exit();
|
||||
return res;
|
||||
}
|
||||
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"legacy hot key reporting over procfs %s\n",
|
||||
(hotkey_report_mode < 2) ?
|
||||
"enabled" : "disabled");
|
||||
|
||||
tpacpi_inputdev->open = &hotkey_inputdev_open;
|
||||
tpacpi_inputdev->close = &hotkey_inputdev_close;
|
||||
|
||||
hotkey_poll_setup_safe(1);
|
||||
tpacpi_input_send_radiosw();
|
||||
tpacpi_input_send_tabletsw();
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
|
||||
hotkey_dev_attributes = NULL;
|
||||
|
||||
return (res < 0)? res : 1;
|
||||
}
|
||||
|
||||
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
|
||||
@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = {
|
||||
|
||||
static int __init light_init(struct ibm_init_struct *iibm)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
|
||||
|
||||
@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm)
|
||||
tp_features.light_status =
|
||||
acpi_evalf(ec_handle, NULL, "KBLT", "qv");
|
||||
|
||||
vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
|
||||
str_supported(tp_features.light));
|
||||
vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n",
|
||||
str_supported(tp_features.light),
|
||||
str_supported(tp_features.light_status));
|
||||
|
||||
if (tp_features.light) {
|
||||
rc = led_classdev_register(&tpacpi_pdev->dev,
|
||||
&tpacpi_led_thinklight.led_classdev);
|
||||
}
|
||||
if (!tp_features.light)
|
||||
return 1;
|
||||
|
||||
rc = led_classdev_register(&tpacpi_pdev->dev,
|
||||
&tpacpi_led_thinklight.led_classdev);
|
||||
|
||||
if (rc < 0) {
|
||||
tp_features.light = 0;
|
||||
tp_features.light_status = 0;
|
||||
} else {
|
||||
rc = (tp_features.light)? 0 : 1;
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3833,7 +3853,7 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
|
||||
"tpacpi::standby",
|
||||
};
|
||||
|
||||
static int led_get_status(unsigned int led)
|
||||
static int led_get_status(const unsigned int led)
|
||||
{
|
||||
int status;
|
||||
enum led_status_t led_s;
|
||||
@ -3857,41 +3877,42 @@ static int led_get_status(unsigned int led)
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
static int led_set_status(unsigned int led, enum led_status_t ledstatus)
|
||||
static int led_set_status(const unsigned int led,
|
||||
const enum led_status_t ledstatus)
|
||||
{
|
||||
/* off, on, blink. Index is led_status_t */
|
||||
static const int led_sled_arg1[] = { 0, 1, 3 };
|
||||
static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
|
||||
static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
|
||||
static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
|
||||
static const unsigned int led_sled_arg1[] = { 0, 1, 3 };
|
||||
static const unsigned int led_led_arg1[] = { 0, 0x80, 0xc0 };
|
||||
|
||||
int rc = 0;
|
||||
|
||||
switch (led_supported) {
|
||||
case TPACPI_LED_570:
|
||||
/* 570 */
|
||||
led = 1 << led;
|
||||
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
|
||||
led, led_sled_arg1[ledstatus]))
|
||||
rc = -EIO;
|
||||
break;
|
||||
/* 570 */
|
||||
if (led > 7)
|
||||
return -EINVAL;
|
||||
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
|
||||
(1 << led), led_sled_arg1[ledstatus]))
|
||||
rc = -EIO;
|
||||
break;
|
||||
case TPACPI_LED_OLD:
|
||||
/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
|
||||
led = 1 << led;
|
||||
rc = ec_write(TPACPI_LED_EC_HLMS, led);
|
||||
if (rc >= 0)
|
||||
rc = ec_write(TPACPI_LED_EC_HLBL,
|
||||
led * led_exp_hlbl[ledstatus]);
|
||||
if (rc >= 0)
|
||||
rc = ec_write(TPACPI_LED_EC_HLCL,
|
||||
led * led_exp_hlcl[ledstatus]);
|
||||
break;
|
||||
/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
|
||||
if (led > 7)
|
||||
return -EINVAL;
|
||||
rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led));
|
||||
if (rc >= 0)
|
||||
rc = ec_write(TPACPI_LED_EC_HLBL,
|
||||
(ledstatus == TPACPI_LED_BLINK) << led);
|
||||
if (rc >= 0)
|
||||
rc = ec_write(TPACPI_LED_EC_HLCL,
|
||||
(ledstatus != TPACPI_LED_OFF) << led);
|
||||
break;
|
||||
case TPACPI_LED_NEW:
|
||||
/* all others */
|
||||
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
|
||||
led, led_led_arg1[ledstatus]))
|
||||
rc = -EIO;
|
||||
break;
|
||||
/* all others */
|
||||
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
|
||||
led, led_led_arg1[ledstatus]))
|
||||
rc = -EIO;
|
||||
break;
|
||||
default:
|
||||
rc = -ENXIO;
|
||||
}
|
||||
@ -3978,7 +3999,6 @@ static void led_exit(void)
|
||||
}
|
||||
|
||||
kfree(tpacpi_leds);
|
||||
tpacpi_leds = NULL;
|
||||
}
|
||||
|
||||
static int __init led_init(struct ibm_init_struct *iibm)
|
||||
@ -4802,7 +4822,6 @@ static void brightness_exit(void)
|
||||
vdbg_printk(TPACPI_DBG_EXIT,
|
||||
"calling backlight_device_unregister()\n");
|
||||
backlight_device_unregister(ibm_backlight_device);
|
||||
ibm_backlight_device = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5764,11 +5783,16 @@ static int __init fan_init(struct ibm_init_struct *iibm)
|
||||
fan_control_access_mode != TPACPI_FAN_WR_NONE) {
|
||||
rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
|
||||
&fan_attr_group);
|
||||
if (!(rc < 0))
|
||||
rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
|
||||
&driver_attr_fan_watchdog);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
|
||||
&driver_attr_fan_watchdog);
|
||||
if (rc < 0) {
|
||||
sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
|
||||
&fan_attr_group);
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
|
@ -50,15 +50,17 @@ static int irq_flags(int triggering, int polarity, int shareable)
|
||||
flags = IORESOURCE_IRQ_HIGHEDGE;
|
||||
}
|
||||
|
||||
if (shareable)
|
||||
if (shareable == ACPI_SHARED)
|
||||
flags |= IORESOURCE_IRQ_SHAREABLE;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void decode_irq_flags(int flag, int *triggering, int *polarity)
|
||||
static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
|
||||
int *polarity, int *shareable)
|
||||
{
|
||||
switch (flag) {
|
||||
switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
|
||||
IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) {
|
||||
case IORESOURCE_IRQ_LOWLEVEL:
|
||||
*triggering = ACPI_LEVEL_SENSITIVE;
|
||||
*polarity = ACPI_ACTIVE_LOW;
|
||||
@ -75,7 +77,18 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
|
||||
*triggering = ACPI_EDGE_SENSITIVE;
|
||||
*polarity = ACPI_ACTIVE_HIGH;
|
||||
break;
|
||||
default:
|
||||
dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
|
||||
flags);
|
||||
*triggering = ACPI_EDGE_SENSITIVE;
|
||||
*polarity = ACPI_ACTIVE_HIGH;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & IORESOURCE_IRQ_SHAREABLE)
|
||||
*shareable = ACPI_SHARED;
|
||||
else
|
||||
*shareable = ACPI_EXCLUSIVE;
|
||||
}
|
||||
|
||||
static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
|
||||
@ -742,6 +755,9 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
|
||||
if (pnpacpi_supported_resource(res)) {
|
||||
(*resource)->type = res->type;
|
||||
(*resource)->length = sizeof(struct acpi_resource);
|
||||
if (res->type == ACPI_RESOURCE_TYPE_IRQ)
|
||||
(*resource)->data.irq.descriptor_length =
|
||||
res->data.irq.descriptor_length;
|
||||
(*resource)++;
|
||||
}
|
||||
|
||||
@ -788,22 +804,21 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
|
||||
struct resource *p)
|
||||
{
|
||||
struct acpi_resource_irq *irq = &resource->data.irq;
|
||||
int triggering, polarity;
|
||||
int triggering, polarity, shareable;
|
||||
|
||||
decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
|
||||
decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
|
||||
irq->triggering = triggering;
|
||||
irq->polarity = polarity;
|
||||
if (triggering == ACPI_EDGE_SENSITIVE)
|
||||
irq->sharable = ACPI_EXCLUSIVE;
|
||||
else
|
||||
irq->sharable = ACPI_SHARED;
|
||||
irq->sharable = shareable;
|
||||
irq->interrupt_count = 1;
|
||||
irq->interrupts[0] = p->start;
|
||||
|
||||
dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
|
||||
dev_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n",
|
||||
(int) p->start,
|
||||
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
|
||||
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
|
||||
irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
|
||||
irq->sharable == ACPI_SHARED ? "shared" : "exclusive",
|
||||
irq->descriptor_length);
|
||||
}
|
||||
|
||||
static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
|
||||
@ -811,16 +826,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
|
||||
struct resource *p)
|
||||
{
|
||||
struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
|
||||
int triggering, polarity;
|
||||
int triggering, polarity, shareable;
|
||||
|
||||
decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
|
||||
decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
|
||||
extended_irq->producer_consumer = ACPI_CONSUMER;
|
||||
extended_irq->triggering = triggering;
|
||||
extended_irq->polarity = polarity;
|
||||
if (triggering == ACPI_EDGE_SENSITIVE)
|
||||
extended_irq->sharable = ACPI_EXCLUSIVE;
|
||||
else
|
||||
extended_irq->sharable = ACPI_SHARED;
|
||||
extended_irq->sharable = shareable;
|
||||
extended_irq->interrupt_count = 1;
|
||||
extended_irq->interrupts[0] = p->start;
|
||||
|
||||
|
@ -319,6 +319,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
|
||||
/* in processor_throttling.c */
|
||||
int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
|
||||
int acpi_processor_get_throttling_info(struct acpi_processor *pr);
|
||||
extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
|
||||
extern struct file_operations acpi_processor_throttling_fops;
|
||||
|
@ -82,6 +82,7 @@ struct cpuidle_state_kobj {
|
||||
};
|
||||
|
||||
struct cpuidle_device {
|
||||
unsigned int registered:1;
|
||||
unsigned int enabled:1;
|
||||
unsigned int cpu;
|
||||
|
||||
|
@ -53,14 +53,14 @@ struct resource_list {
|
||||
#define IORESOURCE_AUTO 0x40000000
|
||||
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
|
||||
|
||||
/* ISA PnP IRQ specific bits (IORESOURCE_BITS) */
|
||||
/* PnP IRQ specific bits (IORESOURCE_BITS) */
|
||||
#define IORESOURCE_IRQ_HIGHEDGE (1<<0)
|
||||
#define IORESOURCE_IRQ_LOWEDGE (1<<1)
|
||||
#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)
|
||||
#define IORESOURCE_IRQ_LOWLEVEL (1<<3)
|
||||
#define IORESOURCE_IRQ_SHAREABLE (1<<4)
|
||||
|
||||
/* ISA PnP DMA specific bits (IORESOURCE_BITS) */
|
||||
/* PnP DMA specific bits (IORESOURCE_BITS) */
|
||||
#define IORESOURCE_DMA_TYPE_MASK (3<<0)
|
||||
#define IORESOURCE_DMA_8BIT (0<<0)
|
||||
#define IORESOURCE_DMA_8AND16BIT (1<<0)
|
||||
@ -76,7 +76,7 @@ struct resource_list {
|
||||
#define IORESOURCE_DMA_TYPEB (2<<6)
|
||||
#define IORESOURCE_DMA_TYPEF (3<<6)
|
||||
|
||||
/* ISA PnP memory I/O specific bits (IORESOURCE_BITS) */
|
||||
/* PnP memory I/O specific bits (IORESOURCE_BITS) */
|
||||
#define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */
|
||||
#define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */
|
||||
#define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */
|
||||
|
Loading…
Reference in New Issue
Block a user