mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
Merge branches 'arm/omap', 'arm/msm', 'arm/rockchip', 'arm/renesas', 'arm/smmu', 'x86/vt-d', 'x86/amd' and 'core' into next
Conflicts: drivers/iommu/arm-smmu.c
This commit is contained in:
commit
76771c938e
1388 changed files with 26406 additions and 11768 deletions
|
|
@ -144,7 +144,7 @@ config ACPI_VIDEO
|
|||
|
||||
config ACPI_FAN
|
||||
tristate "Fan"
|
||||
select THERMAL
|
||||
depends on THERMAL
|
||||
default y
|
||||
help
|
||||
This driver supports ACPI fan devices, allowing user-mode
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ acpi-y += pci_root.o pci_link.o pci_irq.o
|
|||
acpi-y += acpi_lpss.o
|
||||
acpi-y += acpi_platform.o
|
||||
acpi-y += acpi_pnp.o
|
||||
acpi-y += int340x_thermal.o
|
||||
acpi-y += power.o
|
||||
acpi-y += event.o
|
||||
acpi-y += sysfs.o
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
|
@ -102,6 +103,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
|
|||
pdevinfo.res = resources;
|
||||
pdevinfo.num_res = count;
|
||||
pdevinfo.acpi_node.companion = adev;
|
||||
pdevinfo.dma_mask = DMA_BIT_MASK(32);
|
||||
pdev = platform_device_register_full(&pdevinfo);
|
||||
if (IS_ERR(pdev))
|
||||
dev_err(&adev->dev, "platform device creation failed: %ld\n",
|
||||
|
|
@ -113,3 +115,4 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
|
|||
kfree(resources);
|
||||
return pdev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_create_platform_device);
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
|
|||
|
||||
acpi_status
|
||||
acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
|
||||
acpi_event_status * event_status);
|
||||
acpi_event_status *event_status);
|
||||
|
||||
acpi_status acpi_hw_disable_all_gpes(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -413,8 +413,8 @@ struct acpi_gpe_handler_info {
|
|||
acpi_gpe_handler address; /* Address of handler, if any */
|
||||
void *context; /* Context to be passed to handler */
|
||||
struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
|
||||
u8 original_flags; /* Original (pre-handler) GPE info */
|
||||
u8 originally_enabled; /* True if GPE was originally enabled */
|
||||
u8 original_flags; /* Original (pre-handler) GPE info */
|
||||
u8 originally_enabled; /* True if GPE was originally enabled */
|
||||
};
|
||||
|
||||
/* Notify info for implicit notify, multiple device objects */
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count);
|
|||
/*
|
||||
* tbxfroot - Root pointer utilities
|
||||
*/
|
||||
u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp);
|
||||
|
||||
acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
|
||||
|
||||
u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,12 @@ struct asl_resource_node {
|
|||
struct asl_resource_node *next;
|
||||
};
|
||||
|
||||
struct asl_resource_info {
|
||||
union acpi_parse_object *descriptor_type_op; /* Resource descriptor parse node */
|
||||
union acpi_parse_object *mapping_op; /* Used for mapfile support */
|
||||
u32 current_byte_offset; /* Offset in resource template */
|
||||
};
|
||||
|
||||
/* Macros used to generate AML resource length fields */
|
||||
|
||||
#define ACPI_AML_SIZE_LARGE(r) (sizeof (r) - sizeof (struct aml_resource_large_header))
|
||||
|
|
@ -449,4 +455,32 @@ union aml_resource {
|
|||
u8 byte_item;
|
||||
};
|
||||
|
||||
/* Interfaces used by both the disassembler and compiler */
|
||||
|
||||
void
|
||||
mp_save_gpio_info(union acpi_parse_object *op,
|
||||
union aml_resource *resource,
|
||||
u32 pin_count, u16 *pin_list, char *device_name);
|
||||
|
||||
void
|
||||
mp_save_serial_info(union acpi_parse_object *op,
|
||||
union aml_resource *resource, char *device_name);
|
||||
|
||||
char *mp_get_hid_from_parse_tree(struct acpi_namespace_node *hid_node);
|
||||
|
||||
char *mp_get_hid_via_namestring(char *device_name);
|
||||
|
||||
char *mp_get_connection_info(union acpi_parse_object *op,
|
||||
u32 pin_index,
|
||||
struct acpi_namespace_node **target_node,
|
||||
char **target_name);
|
||||
|
||||
char *mp_get_parent_device_hid(union acpi_parse_object *op,
|
||||
struct acpi_namespace_node **target_node,
|
||||
char **parent_device_name);
|
||||
|
||||
char *mp_get_ddn_value(char *device_name);
|
||||
|
||||
char *mp_get_hid_value(struct acpi_namespace_node *device_node);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -100,13 +100,14 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
|
|||
*
|
||||
* FUNCTION: acpi_ev_enable_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_event_info - GPE to enable
|
||||
* PARAMETERS: gpe_event_info - GPE to enable
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Clear a GPE of stale events and enable it.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
||||
{
|
||||
acpi_status status;
|
||||
|
|
@ -125,6 +126,7 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
|||
}
|
||||
|
||||
/* Clear the GPE (of stale events) */
|
||||
|
||||
status = acpi_hw_clear_gpe(gpe_event_info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
|
|
@ -136,7 +138,6 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
|||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_add_gpe_reference
|
||||
|
|
@ -212,7 +213,7 @@ acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
|
|||
if (ACPI_SUCCESS(status)) {
|
||||
status =
|
||||
acpi_hw_low_set_gpe(gpe_event_info,
|
||||
ACPI_GPE_DISABLE);
|
||||
ACPI_GPE_DISABLE);
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
|
@ -334,7 +335,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
|
|||
*
|
||||
******************************************************************************/
|
||||
|
||||
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
|
||||
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_gpe_block_info *gpe_block;
|
||||
|
|
@ -427,7 +428,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
|
|||
|
||||
/* Check if there is anything active at all in this register */
|
||||
|
||||
enabled_status_byte = (u8) (status_reg & enable_reg);
|
||||
enabled_status_byte = (u8)(status_reg & enable_reg);
|
||||
if (!enabled_status_byte) {
|
||||
|
||||
/* No active GPEs in this register, move on */
|
||||
|
|
@ -450,7 +451,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
|
|||
acpi_ev_gpe_dispatch(gpe_block->
|
||||
node,
|
||||
&gpe_block->
|
||||
event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);
|
||||
event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -636,7 +637,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
|
|||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
||||
acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info * gpe_event_info)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
|
@ -666,9 +667,9 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
|||
*
|
||||
* FUNCTION: acpi_ev_gpe_dispatch
|
||||
*
|
||||
* PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
|
||||
* gpe_event_info - Info for this GPE
|
||||
* gpe_number - Number relative to the parent GPE block
|
||||
* PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
|
||||
* gpe_event_info - Info for this GPE
|
||||
* gpe_number - Number relative to the parent GPE block
|
||||
*
|
||||
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
|
||||
*
|
||||
|
|
@ -681,7 +682,7 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
|||
|
||||
u32
|
||||
acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
|
||||
struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
|
||||
struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 return_value;
|
||||
|
|
|
|||
|
|
@ -424,6 +424,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
|
|||
}
|
||||
|
||||
/* Disable the GPE in case it's been enabled already. */
|
||||
|
||||
(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -786,18 +786,26 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
|
|||
handler->method_node = gpe_event_info->dispatch.method_node;
|
||||
handler->original_flags = (u8)(gpe_event_info->flags &
|
||||
(ACPI_GPE_XRUPT_TYPE_MASK |
|
||||
ACPI_GPE_DISPATCH_MASK));
|
||||
ACPI_GPE_DISPATCH_MASK));
|
||||
|
||||
/*
|
||||
* If the GPE is associated with a method, it may have been enabled
|
||||
* automatically during initialization, in which case it has to be
|
||||
* disabled now to avoid spurious execution of the handler.
|
||||
*/
|
||||
|
||||
if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
|
||||
&& gpe_event_info->runtime_count) {
|
||||
handler->originally_enabled = 1;
|
||||
if (((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) ||
|
||||
(handler->original_flags & ACPI_GPE_DISPATCH_NOTIFY)) &&
|
||||
gpe_event_info->runtime_count) {
|
||||
handler->originally_enabled = TRUE;
|
||||
(void)acpi_ev_remove_gpe_reference(gpe_event_info);
|
||||
|
||||
/* Sanity check of original type against new type */
|
||||
|
||||
if (type !=
|
||||
(u32)(gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"GPE type mismatch (level/edge)"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Install the handler */
|
||||
|
|
@ -808,7 +816,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
|
|||
|
||||
gpe_event_info->flags &=
|
||||
~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
|
||||
gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
|
||||
gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_HANDLER);
|
||||
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
|
||||
|
|
@ -893,7 +901,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
|
|||
|
||||
gpe_event_info->dispatch.method_node = handler->method_node;
|
||||
gpe_event_info->flags &=
|
||||
~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
|
||||
~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
|
||||
gpe_event_info->flags |= handler->original_flags;
|
||||
|
||||
/*
|
||||
|
|
@ -901,7 +909,8 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
|
|||
* enabled, it should be enabled at this point to restore the
|
||||
* post-initialization configuration.
|
||||
*/
|
||||
if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) &&
|
||||
if (((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) ||
|
||||
(handler->original_flags & ACPI_GPE_DISPATCH_NOTIFY)) &&
|
||||
handler->originally_enabled) {
|
||||
(void)acpi_ev_add_gpe_reference(gpe_event_info);
|
||||
}
|
||||
|
|
@ -946,7 +955,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
|
|||
* handle is returned.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
|
||||
acpi_status acpi_acquire_global_lock(u16 timeout, u32 *handle)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
|
|
|||
|
|
@ -324,8 +324,9 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event)
|
|||
******************************************************************************/
|
||||
acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u32 value;
|
||||
acpi_status status;
|
||||
acpi_event_status local_event_status = 0;
|
||||
u32 in_byte;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_get_event_status);
|
||||
|
||||
|
|
@ -339,29 +340,40 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
|
|||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Get the status of the requested fixed event */
|
||||
/* Fixed event currently can be dispatched? */
|
||||
|
||||
if (acpi_gbl_fixed_event_handlers[event].handler) {
|
||||
local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
|
||||
}
|
||||
|
||||
/* Fixed event currently enabled? */
|
||||
|
||||
status =
|
||||
acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
|
||||
enable_register_id, &value);
|
||||
if (ACPI_FAILURE(status))
|
||||
enable_register_id, &in_byte);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
*event_status = value;
|
||||
if (in_byte) {
|
||||
local_event_status |= ACPI_EVENT_FLAG_ENABLED;
|
||||
}
|
||||
|
||||
/* Fixed event currently active? */
|
||||
|
||||
status =
|
||||
acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
|
||||
status_register_id, &value);
|
||||
if (ACPI_FAILURE(status))
|
||||
status_register_id, &in_byte);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
if (value)
|
||||
*event_status |= ACPI_EVENT_FLAG_SET;
|
||||
if (in_byte) {
|
||||
local_event_status |= ACPI_EVENT_FLAG_SET;
|
||||
}
|
||||
|
||||
if (acpi_gbl_fixed_event_handlers[event].handler)
|
||||
*event_status |= ACPI_EVENT_FLAG_HANDLE;
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
(*event_status) = local_event_status;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_get_event_status)
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
|
|||
*
|
||||
* FUNCTION: acpi_enable_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* gpe_number - GPE level within the GPE block
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
|
|
@ -115,7 +115,6 @@ ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
|
|||
* hardware-enabled.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
|
@ -490,8 +489,8 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
|
|||
*
|
||||
* FUNCTION: acpi_get_gpe_status
|
||||
*
|
||||
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* event_status - Where the current status of the event
|
||||
* will be returned
|
||||
*
|
||||
|
|
@ -524,9 +523,6 @@ acpi_get_gpe_status(acpi_handle gpe_device,
|
|||
|
||||
status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
|
||||
|
||||
if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
|
||||
*event_status |= ACPI_EVENT_FLAG_HANDLE;
|
||||
|
||||
unlock_and_exit:
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
return_ACPI_STATUS(status);
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
|
|||
|
||||
acpi_status
|
||||
acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
|
||||
acpi_event_status * event_status)
|
||||
acpi_event_status *event_status)
|
||||
{
|
||||
u32 in_byte;
|
||||
u32 register_bit;
|
||||
|
|
@ -216,6 +216,13 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
|
|||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* GPE currently handled? */
|
||||
|
||||
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
|
||||
ACPI_GPE_DISPATCH_NONE) {
|
||||
local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
|
||||
}
|
||||
|
||||
/* Get the info block for the entire GPE register */
|
||||
|
||||
gpe_register_info = gpe_event_info->register_info;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,36 @@
|
|||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbxfroot")
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_get_rsdp_length
|
||||
*
|
||||
* PARAMETERS: rsdp - Pointer to RSDP
|
||||
*
|
||||
* RETURN: Table length
|
||||
*
|
||||
* DESCRIPTION: Get the length of the RSDP
|
||||
*
|
||||
******************************************************************************/
|
||||
u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp)
|
||||
{
|
||||
|
||||
if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
|
||||
|
||||
/* BAD Signature */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* "Length" field is available if table version >= 2 */
|
||||
|
||||
if (rsdp->revision >= 2) {
|
||||
return (rsdp->length);
|
||||
} else {
|
||||
return (ACPI_RSDP_CHECKSUM_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_validate_rsdp
|
||||
|
|
@ -59,7 +89,8 @@ ACPI_MODULE_NAME("tbxfroot")
|
|||
* DESCRIPTION: Validate the RSDP (ptr)
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
|
||||
|
||||
acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp * rsdp)
|
||||
{
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -290,6 +290,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = dmi_disable_osi_win8,
|
||||
.ident = "Dell Vostro 3546",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
|
||||
|
|
|
|||
|
|
@ -343,6 +343,7 @@ int acpi_device_update_power(struct acpi_device *device, int *state_p)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_device_update_power);
|
||||
|
||||
int acpi_bus_update_power(acpi_handle handle, int *state_p)
|
||||
{
|
||||
|
|
@ -710,7 +711,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
return acpi_device_wakeup(adev, enable, ACPI_STATE_S0);
|
||||
return acpi_device_wakeup(adev, ACPI_STATE_S0, enable);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_pm_device_run_wake);
|
||||
#endif /* CONFIG_PM_RUNTIME */
|
||||
|
|
|
|||
|
|
@ -126,14 +126,16 @@ static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
|
|||
static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
|
||||
static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
|
||||
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
|
||||
static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Transaction Management
|
||||
-------------------------------------------------------------------------- */
|
||||
* Transaction Management
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
|
||||
{
|
||||
u8 x = inb(ec->command_addr);
|
||||
|
||||
pr_debug("EC_SC(R) = 0x%2.2x "
|
||||
"SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n",
|
||||
x,
|
||||
|
|
@ -148,6 +150,7 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
|
|||
static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
|
||||
{
|
||||
u8 x = inb(ec->data_addr);
|
||||
|
||||
pr_debug("EC_DATA(R) = 0x%2.2x\n", x);
|
||||
return x;
|
||||
}
|
||||
|
|
@ -164,10 +167,32 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
|
|||
outb(data, ec->data_addr);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *acpi_ec_cmd_string(u8 cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case 0x80:
|
||||
return "RD_EC";
|
||||
case 0x81:
|
||||
return "WR_EC";
|
||||
case 0x82:
|
||||
return "BE_EC";
|
||||
case 0x83:
|
||||
return "BD_EC";
|
||||
case 0x84:
|
||||
return "QR_EC";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
#else
|
||||
#define acpi_ec_cmd_string(cmd) "UNDEF"
|
||||
#endif
|
||||
|
||||
static int ec_transaction_completed(struct acpi_ec *ec)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
|
||||
ret = 1;
|
||||
|
|
@ -181,7 +206,8 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
u8 status;
|
||||
bool wakeup = false;
|
||||
|
||||
pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK");
|
||||
pr_debug("===== %s (%d) =====\n",
|
||||
in_interrupt() ? "IRQ" : "TASK", smp_processor_id());
|
||||
status = acpi_ec_read_status(ec);
|
||||
t = ec->curr;
|
||||
if (!t)
|
||||
|
|
@ -198,7 +224,8 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
if (t->rlen == t->ri) {
|
||||
t->flags |= ACPI_EC_COMMAND_COMPLETE;
|
||||
if (t->command == ACPI_EC_COMMAND_QUERY)
|
||||
pr_debug("hardware QR_EC completion\n");
|
||||
pr_debug("***** Command(%s) hardware completion *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
wakeup = true;
|
||||
}
|
||||
} else
|
||||
|
|
@ -210,18 +237,14 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
}
|
||||
return wakeup;
|
||||
} else {
|
||||
/*
|
||||
* There is firmware refusing to respond QR_EC when SCI_EVT
|
||||
* is not set, for which case, we complete the QR_EC
|
||||
* without issuing it to the firmware.
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=86211
|
||||
*/
|
||||
if (!(status & ACPI_EC_FLAG_SCI) &&
|
||||
if (EC_FLAGS_QUERY_HANDSHAKE &&
|
||||
!(status & ACPI_EC_FLAG_SCI) &&
|
||||
(t->command == ACPI_EC_COMMAND_QUERY)) {
|
||||
t->flags |= ACPI_EC_COMMAND_POLL;
|
||||
t->rdata[t->ri++] = 0x00;
|
||||
t->flags |= ACPI_EC_COMMAND_COMPLETE;
|
||||
pr_debug("software QR_EC completion\n");
|
||||
pr_debug("***** Command(%s) software completion *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
wakeup = true;
|
||||
} else if ((status & ACPI_EC_FLAG_IBF) == 0) {
|
||||
acpi_ec_write_cmd(ec, t->command);
|
||||
|
|
@ -264,6 +287,7 @@ static int ec_poll(struct acpi_ec *ec)
|
|||
{
|
||||
unsigned long flags;
|
||||
int repeat = 5; /* number of command restarts */
|
||||
|
||||
while (repeat--) {
|
||||
unsigned long delay = jiffies +
|
||||
msecs_to_jiffies(ec_delay);
|
||||
|
|
@ -296,18 +320,25 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
|
|||
{
|
||||
unsigned long tmp;
|
||||
int ret = 0;
|
||||
|
||||
if (EC_FLAGS_MSI)
|
||||
udelay(ACPI_EC_MSI_UDELAY);
|
||||
/* start transaction */
|
||||
spin_lock_irqsave(&ec->lock, tmp);
|
||||
/* following two actions should be kept atomic */
|
||||
ec->curr = t;
|
||||
pr_debug("***** Command(%s) started *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
start_transaction(ec);
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
pr_debug("***** Event stopped *****\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&ec->lock, tmp);
|
||||
ret = ec_poll(ec);
|
||||
spin_lock_irqsave(&ec->lock, tmp);
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
pr_debug("***** Command(%s) stopped *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
ec->curr = NULL;
|
||||
spin_unlock_irqrestore(&ec->lock, tmp);
|
||||
return ret;
|
||||
|
|
@ -317,6 +348,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
{
|
||||
int status;
|
||||
u32 glk;
|
||||
|
||||
if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
|
||||
return -EINVAL;
|
||||
if (t->rdata)
|
||||
|
|
@ -333,8 +365,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
goto unlock;
|
||||
}
|
||||
}
|
||||
pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
|
||||
t->command, t->wdata ? t->wdata[0] : 0);
|
||||
/* disable GPE during transaction if storm is detected */
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
/* It has to be disabled, so that it doesn't trigger. */
|
||||
|
|
@ -355,7 +385,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
t->irq_count);
|
||||
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
|
||||
}
|
||||
pr_debug("transaction end\n");
|
||||
if (ec->global_lock)
|
||||
acpi_release_global_lock(glk);
|
||||
unlock:
|
||||
|
|
@ -383,7 +412,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
|
|||
acpi_ec_transaction(ec, &t) : 0;
|
||||
}
|
||||
|
||||
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
|
||||
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
|
|
@ -419,10 +448,9 @@ int ec_read(u8 addr, u8 *val)
|
|||
if (!err) {
|
||||
*val = temp_data;
|
||||
return 0;
|
||||
} else
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_read);
|
||||
|
||||
int ec_write(u8 addr, u8 val)
|
||||
|
|
@ -436,22 +464,21 @@ int ec_write(u8 addr, u8 val)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_write);
|
||||
|
||||
int ec_transaction(u8 command,
|
||||
const u8 * wdata, unsigned wdata_len,
|
||||
u8 * rdata, unsigned rdata_len)
|
||||
const u8 *wdata, unsigned wdata_len,
|
||||
u8 *rdata, unsigned rdata_len)
|
||||
{
|
||||
struct transaction t = {.command = command,
|
||||
.wdata = wdata, .rdata = rdata,
|
||||
.wlen = wdata_len, .rlen = rdata_len};
|
||||
|
||||
if (!first_ec)
|
||||
return -ENODEV;
|
||||
|
||||
return acpi_ec_transaction(first_ec, &t);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_transaction);
|
||||
|
||||
/* Get the handle to the EC device */
|
||||
|
|
@ -461,7 +488,6 @@ acpi_handle ec_get_handle(void)
|
|||
return NULL;
|
||||
return first_ec->handle;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_get_handle);
|
||||
|
||||
/*
|
||||
|
|
@ -525,13 +551,14 @@ void acpi_ec_unblock_transactions_early(void)
|
|||
clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
|
||||
}
|
||||
|
||||
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
|
||||
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
|
||||
.wdata = NULL, .rdata = &d,
|
||||
.wlen = 0, .rlen = 1};
|
||||
|
||||
if (!ec || !data)
|
||||
return -EINVAL;
|
||||
/*
|
||||
|
|
@ -557,6 +584,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|||
{
|
||||
struct acpi_ec_query_handler *handler =
|
||||
kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
|
||||
|
||||
if (!handler)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -569,12 +597,12 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|||
mutex_unlock(&ec->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
|
||||
|
||||
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
||||
{
|
||||
struct acpi_ec_query_handler *handler, *tmp;
|
||||
|
||||
mutex_lock(&ec->mutex);
|
||||
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
|
||||
if (query_bit == handler->query_bit) {
|
||||
|
|
@ -584,20 +612,20 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
|||
}
|
||||
mutex_unlock(&ec->mutex);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
||||
|
||||
static void acpi_ec_run(void *cxt)
|
||||
{
|
||||
struct acpi_ec_query_handler *handler = cxt;
|
||||
|
||||
if (!handler)
|
||||
return;
|
||||
pr_debug("start query execution\n");
|
||||
pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit);
|
||||
if (handler->func)
|
||||
handler->func(handler->data);
|
||||
else if (handler->handle)
|
||||
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
||||
pr_debug("stop query execution\n");
|
||||
pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit);
|
||||
kfree(handler);
|
||||
}
|
||||
|
||||
|
|
@ -620,8 +648,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
|
|||
if (!copy)
|
||||
return -ENOMEM;
|
||||
memcpy(copy, handler, sizeof(*copy));
|
||||
pr_debug("push query execution (0x%2x) on queue\n",
|
||||
value);
|
||||
pr_debug("##### Query(0x%02x) scheduled #####\n",
|
||||
handler->query_bit);
|
||||
return acpi_os_execute((copy->func) ?
|
||||
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
|
||||
acpi_ec_run, copy);
|
||||
|
|
@ -633,6 +661,7 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
|
|||
static void acpi_ec_gpe_query(void *ec_cxt)
|
||||
{
|
||||
struct acpi_ec *ec = ec_cxt;
|
||||
|
||||
if (!ec)
|
||||
return;
|
||||
mutex_lock(&ec->mutex);
|
||||
|
|
@ -644,7 +673,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
|
|||
{
|
||||
if (state & ACPI_EC_FLAG_SCI) {
|
||||
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
|
||||
pr_debug("push gpe query to the queue\n");
|
||||
pr_debug("***** Event started *****\n");
|
||||
return acpi_os_execute(OSL_NOTIFY_HANDLER,
|
||||
acpi_ec_gpe_query, ec);
|
||||
}
|
||||
|
|
@ -667,8 +696,8 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
|
|||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Address Space Management
|
||||
-------------------------------------------------------------------------- */
|
||||
* Address Space Management
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static acpi_status
|
||||
acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
||||
|
|
@ -699,27 +728,26 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
|||
switch (result) {
|
||||
case -EINVAL:
|
||||
return AE_BAD_PARAMETER;
|
||||
break;
|
||||
case -ENODEV:
|
||||
return AE_NOT_FOUND;
|
||||
break;
|
||||
case -ETIME:
|
||||
return AE_TIME;
|
||||
break;
|
||||
default:
|
||||
return AE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Driver Interface
|
||||
-------------------------------------------------------------------------- */
|
||||
* Driver Interface
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static acpi_status
|
||||
ec_parse_io_ports(struct acpi_resource *resource, void *context);
|
||||
|
||||
static struct acpi_ec *make_acpi_ec(void)
|
||||
{
|
||||
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
||||
|
||||
if (!ec)
|
||||
return NULL;
|
||||
ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
|
||||
|
|
@ -742,9 +770,8 @@ acpi_ec_register_query_methods(acpi_handle handle, u32 level,
|
|||
|
||||
status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
|
||||
|
||||
if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1) {
|
||||
if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1)
|
||||
acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
|
|
@ -753,7 +780,6 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
|||
{
|
||||
acpi_status status;
|
||||
unsigned long long tmp = 0;
|
||||
|
||||
struct acpi_ec *ec = context;
|
||||
|
||||
/* clear addr values, ec_parse_io_ports depend on it */
|
||||
|
|
@ -781,6 +807,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
|||
static int ec_install_handlers(struct acpi_ec *ec)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
|
||||
return 0;
|
||||
status = acpi_install_gpe_handler(NULL, ec->gpe,
|
||||
|
|
@ -980,6 +1007,18 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Acer EC firmware refuses to respond QR_EC when SCI_EVT is not set, for
|
||||
* which case, we complete the QR_EC without issuing it to the firmware.
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=86211
|
||||
*/
|
||||
static int ec_flag_query_handshake(const struct dmi_system_id *id)
|
||||
{
|
||||
pr_debug("Detected the EC firmware requiring QR_EC issued when SCI_EVT set\n");
|
||||
EC_FLAGS_QUERY_HANDSHAKE = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On some hardware it is necessary to clear events accumulated by the EC during
|
||||
* sleep. These ECs stop reporting GPEs until they are manually polled, if too
|
||||
|
|
@ -1054,6 +1093,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
|
|||
{
|
||||
ec_clear_on_resume, "Samsung hardware", {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
|
||||
{
|
||||
ec_flag_query_handshake, "Acer hardware", {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"), }, NULL},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
@ -1078,7 +1120,8 @@ int __init acpi_ec_ecdt_probe(void)
|
|||
boot_ec->data_addr = ecdt_ptr->data.address;
|
||||
boot_ec->gpe = ecdt_ptr->gpe;
|
||||
boot_ec->handle = ACPI_ROOT_OBJECT;
|
||||
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
|
||||
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id,
|
||||
&boot_ec->handle);
|
||||
/* Don't trust ECDT, which comes from ASUSTek */
|
||||
if (!EC_FLAGS_VALIDATE_ECDT)
|
||||
goto install;
|
||||
|
|
@ -1162,6 +1205,5 @@ static void __exit acpi_ec_exit(void)
|
|||
{
|
||||
|
||||
acpi_bus_unregister_driver(&acpi_ec_driver);
|
||||
return;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
|
|
|||
|
|
@ -30,22 +30,19 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#define ACPI_FAN_CLASS "fan"
|
||||
#define ACPI_FAN_FILE_STATE "state"
|
||||
|
||||
#define _COMPONENT ACPI_FAN_COMPONENT
|
||||
ACPI_MODULE_NAME("fan");
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
MODULE_AUTHOR("Paul Diefenbaugh");
|
||||
MODULE_DESCRIPTION("ACPI Fan Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int acpi_fan_add(struct acpi_device *device);
|
||||
static int acpi_fan_remove(struct acpi_device *device);
|
||||
static int acpi_fan_probe(struct platform_device *pdev);
|
||||
static int acpi_fan_remove(struct platform_device *pdev);
|
||||
|
||||
static const struct acpi_device_id fan_device_ids[] = {
|
||||
{"PNP0C0B", 0},
|
||||
{"INT3404", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, fan_device_ids);
|
||||
|
|
@ -64,37 +61,100 @@ static struct dev_pm_ops acpi_fan_pm = {
|
|||
#define FAN_PM_OPS_PTR NULL
|
||||
#endif
|
||||
|
||||
static struct acpi_driver acpi_fan_driver = {
|
||||
.name = "fan",
|
||||
.class = ACPI_FAN_CLASS,
|
||||
.ids = fan_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_fan_add,
|
||||
.remove = acpi_fan_remove,
|
||||
},
|
||||
.drv.pm = FAN_PM_OPS_PTR,
|
||||
struct acpi_fan_fps {
|
||||
u64 control;
|
||||
u64 trip_point;
|
||||
u64 speed;
|
||||
u64 noise_level;
|
||||
u64 power;
|
||||
};
|
||||
|
||||
struct acpi_fan_fif {
|
||||
u64 revision;
|
||||
u64 fine_grain_ctrl;
|
||||
u64 step_size;
|
||||
u64 low_speed_notification;
|
||||
};
|
||||
|
||||
struct acpi_fan {
|
||||
bool acpi4;
|
||||
struct acpi_fan_fif fif;
|
||||
struct acpi_fan_fps *fps;
|
||||
int fps_count;
|
||||
struct thermal_cooling_device *cdev;
|
||||
};
|
||||
|
||||
static struct platform_driver acpi_fan_driver = {
|
||||
.probe = acpi_fan_probe,
|
||||
.remove = acpi_fan_remove,
|
||||
.driver = {
|
||||
.name = "acpi-fan",
|
||||
.acpi_match_table = fan_device_ids,
|
||||
.pm = FAN_PM_OPS_PTR,
|
||||
},
|
||||
};
|
||||
|
||||
/* thermal cooling device callbacks */
|
||||
static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
*state)
|
||||
{
|
||||
/* ACPI fan device only support two states: ON/OFF */
|
||||
*state = 1;
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
struct acpi_fan *fan = acpi_driver_data(device);
|
||||
|
||||
if (fan->acpi4)
|
||||
*state = fan->fps_count - 1;
|
||||
else
|
||||
*state = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
*state)
|
||||
static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state)
|
||||
{
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_fan *fan = acpi_driver_data(device);
|
||||
union acpi_object *obj;
|
||||
acpi_status status;
|
||||
int control, i;
|
||||
|
||||
status = acpi_evaluate_object(device->handle, "_FST", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_err(&device->dev, "Get fan state failed\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
obj = buffer.pointer;
|
||||
if (!obj || obj->type != ACPI_TYPE_PACKAGE ||
|
||||
obj->package.count != 3 ||
|
||||
obj->package.elements[1].type != ACPI_TYPE_INTEGER) {
|
||||
dev_err(&device->dev, "Invalid _FST data\n");
|
||||
status = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
control = obj->package.elements[1].integer.value;
|
||||
for (i = 0; i < fan->fps_count; i++) {
|
||||
if (control == fan->fps[i].control)
|
||||
break;
|
||||
}
|
||||
if (i == fan->fps_count) {
|
||||
dev_dbg(&device->dev, "Invalid control value returned\n");
|
||||
status = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
*state = i;
|
||||
|
||||
err:
|
||||
kfree(obj);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int fan_get_state(struct acpi_device *device, unsigned long *state)
|
||||
{
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
int result;
|
||||
int acpi_state = ACPI_STATE_D0;
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
result = acpi_bus_update_power(device->handle, &acpi_state);
|
||||
result = acpi_device_update_power(device, &acpi_state);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
|
|
@ -103,20 +163,56 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
*state)
|
||||
{
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
struct acpi_fan *fan = acpi_driver_data(device);
|
||||
|
||||
if (fan->acpi4)
|
||||
return fan_get_state_acpi4(device, state);
|
||||
else
|
||||
return fan_get_state(device, state);
|
||||
}
|
||||
|
||||
static int fan_set_state(struct acpi_device *device, unsigned long state)
|
||||
{
|
||||
if (state != 0 && state != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return acpi_device_set_power(device,
|
||||
state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
|
||||
}
|
||||
|
||||
static int fan_set_state_acpi4(struct acpi_device *device, unsigned long state)
|
||||
{
|
||||
struct acpi_fan *fan = acpi_driver_data(device);
|
||||
acpi_status status;
|
||||
|
||||
if (state >= fan->fps_count)
|
||||
return -EINVAL;
|
||||
|
||||
status = acpi_execute_simple_method(device->handle, "_FSL",
|
||||
fan->fps[state].control);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_dbg(&device->dev, "Failed to set state by _FSL\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
|
||||
{
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
int result;
|
||||
struct acpi_fan *fan = acpi_driver_data(device);
|
||||
|
||||
if (!device || (state != 0 && state != 1))
|
||||
return -EINVAL;
|
||||
|
||||
result = acpi_bus_set_power(device->handle,
|
||||
state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
|
||||
|
||||
return result;
|
||||
}
|
||||
if (fan->acpi4)
|
||||
return fan_set_state_acpi4(device, state);
|
||||
else
|
||||
return fan_set_state(device, state);
|
||||
}
|
||||
|
||||
static const struct thermal_cooling_device_ops fan_cooling_ops = {
|
||||
.get_max_state = fan_get_max_state,
|
||||
|
|
@ -129,21 +225,125 @@ static const struct thermal_cooling_device_ops fan_cooling_ops = {
|
|||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int acpi_fan_add(struct acpi_device *device)
|
||||
static bool acpi_fan_is_acpi4(struct acpi_device *device)
|
||||
{
|
||||
return acpi_has_method(device->handle, "_FIF") &&
|
||||
acpi_has_method(device->handle, "_FPS") &&
|
||||
acpi_has_method(device->handle, "_FSL") &&
|
||||
acpi_has_method(device->handle, "_FST");
|
||||
}
|
||||
|
||||
static int acpi_fan_get_fif(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_fan *fan = acpi_driver_data(device);
|
||||
struct acpi_buffer format = { sizeof("NNNN"), "NNNN" };
|
||||
struct acpi_buffer fif = { sizeof(fan->fif), &fan->fif };
|
||||
union acpi_object *obj;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_object(device->handle, "_FIF", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
|
||||
obj = buffer.pointer;
|
||||
if (!obj || obj->type != ACPI_TYPE_PACKAGE) {
|
||||
dev_err(&device->dev, "Invalid _FIF data\n");
|
||||
status = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
status = acpi_extract_package(obj, &format, &fif);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_err(&device->dev, "Invalid _FIF element\n");
|
||||
status = -EINVAL;
|
||||
}
|
||||
|
||||
err:
|
||||
kfree(obj);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int acpi_fan_speed_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct acpi_fan_fps *fps1 = a;
|
||||
const struct acpi_fan_fps *fps2 = b;
|
||||
return fps1->speed - fps2->speed;
|
||||
}
|
||||
|
||||
static int acpi_fan_get_fps(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_fan *fan = acpi_driver_data(device);
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *obj;
|
||||
acpi_status status;
|
||||
int i;
|
||||
|
||||
status = acpi_evaluate_object(device->handle, "_FPS", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
|
||||
obj = buffer.pointer;
|
||||
if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) {
|
||||
dev_err(&device->dev, "Invalid _FPS data\n");
|
||||
status = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
fan->fps_count = obj->package.count - 1; /* minus revision field */
|
||||
fan->fps = devm_kzalloc(&device->dev,
|
||||
fan->fps_count * sizeof(struct acpi_fan_fps),
|
||||
GFP_KERNEL);
|
||||
if (!fan->fps) {
|
||||
dev_err(&device->dev, "Not enough memory\n");
|
||||
status = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < fan->fps_count; i++) {
|
||||
struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
|
||||
struct acpi_buffer fps = { sizeof(fan->fps[i]), &fan->fps[i] };
|
||||
status = acpi_extract_package(&obj->package.elements[i + 1],
|
||||
&format, &fps);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_err(&device->dev, "Invalid _FPS element\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* sort the state array according to fan speed in increase order */
|
||||
sort(fan->fps, fan->fps_count, sizeof(*fan->fps),
|
||||
acpi_fan_speed_cmp, NULL);
|
||||
|
||||
err:
|
||||
kfree(obj);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int acpi_fan_probe(struct platform_device *pdev)
|
||||
{
|
||||
int result = 0;
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct acpi_fan *fan;
|
||||
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
|
||||
if (!fan) {
|
||||
dev_err(&device->dev, "No memory for fan\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
device->driver_data = fan;
|
||||
platform_set_drvdata(pdev, fan);
|
||||
|
||||
strcpy(acpi_device_name(device), "Fan");
|
||||
strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
|
||||
|
||||
result = acpi_bus_update_power(device->handle, NULL);
|
||||
if (result) {
|
||||
dev_err(&device->dev, "Setting initial power state\n");
|
||||
goto end;
|
||||
if (acpi_fan_is_acpi4(device)) {
|
||||
if (acpi_fan_get_fif(device) || acpi_fan_get_fps(device))
|
||||
goto end;
|
||||
fan->acpi4 = true;
|
||||
} else {
|
||||
result = acpi_device_update_power(device, NULL);
|
||||
if (result) {
|
||||
dev_err(&device->dev, "Setting initial power state\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
cdev = thermal_cooling_device_register("Fan", device,
|
||||
|
|
@ -153,44 +353,32 @@ static int acpi_fan_add(struct acpi_device *device)
|
|||
goto end;
|
||||
}
|
||||
|
||||
dev_dbg(&device->dev, "registered as cooling_device%d\n", cdev->id);
|
||||
dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);
|
||||
|
||||
device->driver_data = cdev;
|
||||
result = sysfs_create_link(&device->dev.kobj,
|
||||
fan->cdev = cdev;
|
||||
result = sysfs_create_link(&pdev->dev.kobj,
|
||||
&cdev->device.kobj,
|
||||
"thermal_cooling");
|
||||
if (result)
|
||||
dev_err(&device->dev, "Failed to create sysfs link "
|
||||
"'thermal_cooling'\n");
|
||||
dev_err(&pdev->dev, "Failed to create sysfs link 'thermal_cooling'\n");
|
||||
|
||||
result = sysfs_create_link(&cdev->device.kobj,
|
||||
&device->dev.kobj,
|
||||
&pdev->dev.kobj,
|
||||
"device");
|
||||
if (result)
|
||||
dev_err(&device->dev, "Failed to create sysfs link 'device'\n");
|
||||
|
||||
dev_info(&device->dev, "ACPI: %s [%s] (%s)\n",
|
||||
acpi_device_name(device), acpi_device_bid(device),
|
||||
!device->power.state ? "on" : "off");
|
||||
dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");
|
||||
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_fan_remove(struct acpi_device *device)
|
||||
static int acpi_fan_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct acpi_fan *fan = platform_get_drvdata(pdev);
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
cdev = acpi_driver_data(device);
|
||||
if (!cdev)
|
||||
return -EINVAL;
|
||||
|
||||
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
|
||||
sysfs_remove_link(&cdev->device.kobj, "device");
|
||||
thermal_cooling_device_unregister(cdev);
|
||||
sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling");
|
||||
sysfs_remove_link(&fan->cdev->device.kobj, "device");
|
||||
thermal_cooling_device_unregister(fan->cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -198,10 +386,11 @@ static int acpi_fan_remove(struct acpi_device *device)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int acpi_fan_suspend(struct device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
struct acpi_fan *fan = dev_get_drvdata(dev);
|
||||
if (fan->acpi4)
|
||||
return 0;
|
||||
|
||||
acpi_bus_set_power(to_acpi_device(dev)->handle, ACPI_STATE_D0);
|
||||
acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D0);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
|
@ -209,11 +398,12 @@ static int acpi_fan_suspend(struct device *dev)
|
|||
static int acpi_fan_resume(struct device *dev)
|
||||
{
|
||||
int result;
|
||||
struct acpi_fan *fan = dev_get_drvdata(dev);
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
if (fan->acpi4)
|
||||
return 0;
|
||||
|
||||
result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL);
|
||||
result = acpi_device_update_power(ACPI_COMPANION(dev), NULL);
|
||||
if (result)
|
||||
dev_err(dev, "Error updating fan power state\n");
|
||||
|
||||
|
|
@ -221,4 +411,4 @@ static int acpi_fan_resume(struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
module_acpi_driver(acpi_fan_driver);
|
||||
module_platform_driver(acpi_fan_driver);
|
||||
|
|
|
|||
51
drivers/acpi/int340x_thermal.c
Normal file
51
drivers/acpi/int340x_thermal.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* ACPI support for int340x thermal drivers
|
||||
*
|
||||
* Copyright (C) 2014, Intel Corporation
|
||||
* Authors: Zhang Rui <rui.zhang@intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define DO_ENUMERATION 0x01
|
||||
static const struct acpi_device_id int340x_thermal_device_ids[] = {
|
||||
{"INT3400", DO_ENUMERATION },
|
||||
{"INT3401"},
|
||||
{"INT3402"},
|
||||
{"INT3403"},
|
||||
{"INT3404"},
|
||||
{"INT3406"},
|
||||
{"INT3407"},
|
||||
{"INT3408"},
|
||||
{"INT3409"},
|
||||
{"INT340A"},
|
||||
{"INT340B"},
|
||||
{""},
|
||||
};
|
||||
|
||||
static int int340x_thermal_handler_attach(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id)
|
||||
{
|
||||
#if defined(CONFIG_INT340X_THERMAL) || defined(CONFIG_INT340X_THERMAL_MODULE)
|
||||
if (id->driver_data == DO_ENUMERATION)
|
||||
acpi_create_platform_device(adev);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct acpi_scan_handler int340x_thermal_handler = {
|
||||
.ids = int340x_thermal_device_ids,
|
||||
.attach = int340x_thermal_handler_attach,
|
||||
};
|
||||
|
||||
void __init acpi_int340x_thermal_init(void)
|
||||
{
|
||||
acpi_scan_add_handler(&int340x_thermal_handler);
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ void acpi_pci_link_init(void);
|
|||
void acpi_processor_init(void);
|
||||
void acpi_platform_init(void);
|
||||
void acpi_pnp_init(void);
|
||||
void acpi_int340x_thermal_init(void);
|
||||
int acpi_sysfs_init(void);
|
||||
void acpi_container_init(void);
|
||||
void acpi_memory_hotplug_init(void);
|
||||
|
|
@ -103,8 +104,6 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
|
|||
int acpi_power_on_resources(struct acpi_device *device, int state);
|
||||
int acpi_power_transition(struct acpi_device *device, int state);
|
||||
|
||||
int acpi_device_update_power(struct acpi_device *device, int *state_p);
|
||||
|
||||
int acpi_wakeup_device_init(void);
|
||||
|
||||
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
|
||||
|
|
@ -167,13 +166,6 @@ static inline int suspend_nvs_save(void) { return 0; }
|
|||
static inline void suspend_nvs_restore(void) {}
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Platform bus support
|
||||
-------------------------------------------------------------------------- */
|
||||
struct platform_device;
|
||||
|
||||
struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Video
|
||||
-------------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <linux/pci-aspm.h>
|
||||
#include <linux/dmar.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dmi.h>
|
||||
|
|
@ -525,6 +526,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|||
struct acpi_pci_root *root;
|
||||
acpi_handle handle = device->handle;
|
||||
int no_aspm = 0, clear_aspm = 0;
|
||||
bool hotadd = system_state != SYSTEM_BOOTING;
|
||||
|
||||
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
|
||||
if (!root)
|
||||
|
|
@ -571,6 +573,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|||
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
|
||||
device->driver_data = root;
|
||||
|
||||
if (hotadd && dmar_device_add(handle)) {
|
||||
result = -ENXIO;
|
||||
goto end;
|
||||
}
|
||||
|
||||
pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
|
||||
acpi_device_name(device), acpi_device_bid(device),
|
||||
root->segment, &root->secondary);
|
||||
|
|
@ -597,7 +604,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|||
root->segment, (unsigned int)root->secondary.start);
|
||||
device->driver_data = NULL;
|
||||
result = -ENODEV;
|
||||
goto end;
|
||||
goto remove_dmar;
|
||||
}
|
||||
|
||||
if (clear_aspm) {
|
||||
|
|
@ -611,7 +618,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|||
if (device->wakeup.flags.run_wake)
|
||||
device_set_run_wake(root->bus->bridge, true);
|
||||
|
||||
if (system_state != SYSTEM_BOOTING) {
|
||||
if (hotadd) {
|
||||
pcibios_resource_survey_bus(root->bus);
|
||||
pci_assign_unassigned_root_bus_resources(root->bus);
|
||||
}
|
||||
|
|
@ -621,6 +628,9 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|||
pci_unlock_rescan_remove();
|
||||
return 1;
|
||||
|
||||
remove_dmar:
|
||||
if (hotadd)
|
||||
dmar_device_remove(handle);
|
||||
end:
|
||||
kfree(root);
|
||||
return result;
|
||||
|
|
@ -639,6 +649,8 @@ static void acpi_pci_root_remove(struct acpi_device *device)
|
|||
|
||||
pci_remove_root_bus(root->bus);
|
||||
|
||||
dmar_device_remove(device->handle);
|
||||
|
||||
pci_unlock_rescan_remove();
|
||||
|
||||
kfree(root);
|
||||
|
|
|
|||
|
|
@ -141,6 +141,53 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
|
|||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* acpi_companion_match() - Can we match via ACPI companion device
|
||||
* @dev: Device in question
|
||||
*
|
||||
* Check if the given device has an ACPI companion and if that companion has
|
||||
* a valid list of PNP IDs, and if the device is the first (primary) physical
|
||||
* device associated with it.
|
||||
*
|
||||
* If multiple physical devices are attached to a single ACPI companion, we need
|
||||
* to be careful. The usage scenario for this kind of relationship is that all
|
||||
* of the physical devices in question use resources provided by the ACPI
|
||||
* companion. A typical case is an MFD device where all the sub-devices share
|
||||
* the parent's ACPI companion. In such cases we can only allow the primary
|
||||
* (first) physical device to be matched with the help of the companion's PNP
|
||||
* IDs.
|
||||
*
|
||||
* Additional physical devices sharing the ACPI companion can still use
|
||||
* resources available from it but they will be matched normally using functions
|
||||
* provided by their bus types (and analogously for their modalias).
|
||||
*/
|
||||
static bool acpi_companion_match(const struct device *dev)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
bool ret;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (!adev)
|
||||
return false;
|
||||
|
||||
if (list_empty(&adev->pnp.ids))
|
||||
return false;
|
||||
|
||||
mutex_lock(&adev->physical_node_lock);
|
||||
if (list_empty(&adev->physical_node_list)) {
|
||||
ret = false;
|
||||
} else {
|
||||
const struct acpi_device_physical_node *node;
|
||||
|
||||
node = list_first_entry(&adev->physical_node_list,
|
||||
struct acpi_device_physical_node, node);
|
||||
ret = node->dev == dev;
|
||||
}
|
||||
mutex_unlock(&adev->physical_node_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates uevent modalias field for ACPI enumerated devices.
|
||||
* Because the other buses does not support ACPI HIDs & CIDs.
|
||||
|
|
@ -149,20 +196,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
|
|||
*/
|
||||
int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct acpi_device *acpi_dev;
|
||||
int len;
|
||||
|
||||
acpi_dev = ACPI_COMPANION(dev);
|
||||
if (!acpi_dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Fall back to bus specific way of modalias exporting */
|
||||
if (list_empty(&acpi_dev->pnp.ids))
|
||||
if (!acpi_companion_match(dev))
|
||||
return -ENODEV;
|
||||
|
||||
if (add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
|
||||
len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1],
|
||||
sizeof(env->buf) - env->buflen);
|
||||
if (len <= 0)
|
||||
return len;
|
||||
|
|
@ -179,18 +220,12 @@ EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
|
|||
*/
|
||||
int acpi_device_modalias(struct device *dev, char *buf, int size)
|
||||
{
|
||||
struct acpi_device *acpi_dev;
|
||||
int len;
|
||||
|
||||
acpi_dev = ACPI_COMPANION(dev);
|
||||
if (!acpi_dev)
|
||||
if (!acpi_companion_match(dev))
|
||||
return -ENODEV;
|
||||
|
||||
/* Fall back to bus specific way of modalias exporting */
|
||||
if (list_empty(&acpi_dev->pnp.ids))
|
||||
return -ENODEV;
|
||||
|
||||
len = create_modalias(acpi_dev, buf, size -1);
|
||||
len = create_modalias(ACPI_COMPANION(dev), buf, size -1);
|
||||
if (len <= 0)
|
||||
return len;
|
||||
buf[len++] = '\n';
|
||||
|
|
@ -853,6 +888,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
|
|||
if (!ids || !handle || acpi_bus_get_device(handle, &adev))
|
||||
return NULL;
|
||||
|
||||
if (!acpi_companion_match(dev))
|
||||
return NULL;
|
||||
|
||||
return __acpi_match_device(adev, ids);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_match_device);
|
||||
|
|
@ -1470,7 +1508,7 @@ static void acpi_wakeup_gpe_init(struct acpi_device *device)
|
|||
if (ACPI_FAILURE(status))
|
||||
return;
|
||||
|
||||
wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HANDLE);
|
||||
wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HAS_HANDLER);
|
||||
}
|
||||
|
||||
static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
||||
|
|
@ -2315,6 +2353,7 @@ int __init acpi_scan_init(void)
|
|||
acpi_container_init();
|
||||
acpi_memory_hotplug_init();
|
||||
acpi_pnp_init();
|
||||
acpi_int340x_thermal_init();
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ static ssize_t counter_show(struct kobject *kobj,
|
|||
if (result)
|
||||
goto end;
|
||||
|
||||
if (!(status & ACPI_EVENT_FLAG_HANDLE))
|
||||
if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER))
|
||||
size += sprintf(buf + size, " invalid");
|
||||
else if (status & ACPI_EVENT_FLAG_ENABLED)
|
||||
size += sprintf(buf + size, " enabled");
|
||||
|
|
@ -581,7 +581,7 @@ static ssize_t counter_set(struct kobject *kobj,
|
|||
if (result)
|
||||
goto end;
|
||||
|
||||
if (!(status & ACPI_EVENT_FLAG_HANDLE)) {
|
||||
if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER)) {
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Can not change Invalid GPE/Fixed Event status\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -528,7 +528,6 @@ static void acpi_thermal_check(void *data)
|
|||
}
|
||||
|
||||
/* sys I/F for generic thermal sysfs support */
|
||||
#define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
|
||||
|
||||
static int thermal_get_temp(struct thermal_zone_device *thermal,
|
||||
unsigned long *temp)
|
||||
|
|
@ -543,7 +542,8 @@ static int thermal_get_temp(struct thermal_zone_device *thermal,
|
|||
if (result)
|
||||
return result;
|
||||
|
||||
*temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(tz->temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -647,7 +647,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
|||
|
||||
if (tz->trips.critical.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
tz->trips.critical.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
|
|
@ -657,7 +657,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
|||
|
||||
if (tz->trips.hot.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
tz->trips.hot.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
|
|
@ -667,7 +667,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
|||
|
||||
if (tz->trips.passive.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
tz->trips.passive.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
|
|
@ -678,7 +678,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
|||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
|
||||
tz->trips.active[i].flags.valid; i++) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
tz->trips.active[i].temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
|
|
@ -694,7 +694,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
|
|||
struct acpi_thermal *tz = thermal->devdata;
|
||||
|
||||
if (tz->trips.critical.flags.valid) {
|
||||
*temperature = KELVIN_TO_MILLICELSIUS(
|
||||
*temperature = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
tz->trips.critical.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
|
|
@ -714,8 +714,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
|
|||
|
||||
if (type == THERMAL_TRIP_ACTIVE) {
|
||||
unsigned long trip_temp;
|
||||
unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature,
|
||||
tz->kelvin_offset);
|
||||
unsigned long temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
tz->temperature, tz->kelvin_offset);
|
||||
if (thermal_get_trip_temp(thermal, trip, &trip_temp))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,21 @@ acpi_extract_package(union acpi_object *package,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
switch (format_string[i]) {
|
||||
case 'R':
|
||||
size_required += sizeof(void *);
|
||||
tail_offset += sizeof(void *);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING PREFIX "Invalid package element"
|
||||
" [%d] got reference,"
|
||||
" expecting [%c]\n",
|
||||
i, format_string[i]);
|
||||
return AE_BAD_DATA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
default:
|
||||
|
|
@ -247,7 +262,18 @@ acpi_extract_package(union acpi_object *package,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
switch (format_string[i]) {
|
||||
case 'R':
|
||||
*(void **)head =
|
||||
(void *)element->reference.handle;
|
||||
head += sizeof(void *);
|
||||
break;
|
||||
default:
|
||||
/* Should never get here */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
/* TBD: handle nested packages... */
|
||||
default:
|
||||
|
|
|
|||
Loading…
Reference in a new issue