Merge bca21755b9
("Merge tag 'acpi-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm") into android-mainline
Steps on the way to 5.17-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Id3a7dff17df89b6bc1103ca3feae3217077503cd
This commit is contained in:
commit
3185b45ec7
@ -524,6 +524,23 @@ config ACPI_PPTT
|
||||
bool
|
||||
endif
|
||||
|
||||
config ACPI_PCC
|
||||
bool "ACPI PCC Address Space"
|
||||
depends on PCC
|
||||
default y
|
||||
help
|
||||
The PCC Address Space also referred as PCC Operation Region pertains
|
||||
to the region of PCC subspace that succeeds the PCC signature.
|
||||
|
||||
The PCC Operation Region works in conjunction with the PCC Table
|
||||
(Platform Communications Channel Table). PCC subspaces that are
|
||||
marked for use as PCC Operation Regions must not be used as PCC
|
||||
subspaces for the standard ACPI features such as CPPC, RASF, PDTT and
|
||||
MPST. These standard features must always use the PCC Table instead.
|
||||
|
||||
Enable this feature if you want to set up and install the PCC Address
|
||||
Space handler to handle PCC OpRegion in the firmware.
|
||||
|
||||
source "drivers/acpi/pmic/Kconfig"
|
||||
|
||||
config ACPI_VIOT
|
||||
|
@ -67,6 +67,7 @@ acpi-$(CONFIG_ACPI_LPIT) += acpi_lpit.o
|
||||
acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o
|
||||
acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o
|
||||
acpi-$(CONFIG_ACPI_PRMT) += prmt.o
|
||||
acpi-$(CONFIG_ACPI_PCC) += acpi_pcc.o
|
||||
|
||||
# Address translation
|
||||
acpi-$(CONFIG_ACPI_ADXL) += acpi_adxl.o
|
||||
|
@ -48,19 +48,12 @@ static const struct acpi_device_id ac_device_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
|
||||
|
||||
/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
|
||||
static const struct acpi_ac_bl acpi_ac_blacklist[] = {
|
||||
{ "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
|
||||
{ "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int acpi_ac_resume(struct device *dev);
|
||||
#endif
|
||||
static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
|
||||
|
||||
static int ac_sleep_before_get_state_ms;
|
||||
static int ac_check_pmic = 1;
|
||||
static int ac_only;
|
||||
|
||||
static struct acpi_driver acpi_ac_driver = {
|
||||
@ -200,12 +193,6 @@ static int __init thinkpad_e530_quirk(const struct dmi_system_id *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d)
|
||||
{
|
||||
ac_check_pmic = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init ac_only_quirk(const struct dmi_system_id *d)
|
||||
{
|
||||
ac_only = 1;
|
||||
@ -214,13 +201,6 @@ static int __init ac_only_quirk(const struct dmi_system_id *d)
|
||||
|
||||
/* Please keep this list alphabetically sorted */
|
||||
static const struct dmi_system_id ac_dmi_table[] __initconst = {
|
||||
{
|
||||
/* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
|
||||
.callback = ac_do_not_check_pmic_quirk,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Kodlix GK45 returning incorrect state */
|
||||
.callback = ac_only_quirk,
|
||||
@ -228,15 +208,6 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GK45"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
|
||||
.callback = ac_do_not_check_pmic_quirk,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Thinkpad e530, see comment in acpi_ac_notify() */
|
||||
.callback = thinkpad_e530_quirk,
|
||||
@ -341,23 +312,15 @@ static int acpi_ac_remove(struct acpi_device *device)
|
||||
|
||||
static int __init acpi_ac_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
int result;
|
||||
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
dmi_check_system(ac_dmi_table);
|
||||
if (acpi_quirk_skip_acpi_ac_and_battery())
|
||||
return -ENODEV;
|
||||
|
||||
if (ac_check_pmic) {
|
||||
for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
|
||||
if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
|
||||
acpi_ac_blacklist[i].hrv)) {
|
||||
pr_info("found native %s PMIC, not loading\n",
|
||||
acpi_ac_blacklist[i].hid);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
dmi_check_system(ac_dmi_table);
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_ac_driver);
|
||||
if (result < 0)
|
||||
|
120
drivers/acpi/acpi_pcc.c
Normal file
120
drivers/acpi/acpi_pcc.c
Normal file
@ -0,0 +1,120 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Author: Sudeep Holla <sudeep.holla@arm.com>
|
||||
* Copyright 2021 Arm Limited
|
||||
*
|
||||
* The PCC Address Space also referred as PCC Operation Region pertains to the
|
||||
* region of PCC subspace that succeeds the PCC signature. The PCC Operation
|
||||
* Region works in conjunction with the PCC Table(Platform Communications
|
||||
* Channel Table). PCC subspaces that are marked for use as PCC Operation
|
||||
* Regions must not be used as PCC subspaces for the standard ACPI features
|
||||
* such as CPPC, RASF, PDTT and MPST. These standard features must always use
|
||||
* the PCC Table instead.
|
||||
*
|
||||
* This driver sets up the PCC Address Space and installs an handler to enable
|
||||
* handling of PCC OpRegion in the firmware.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <acpi/pcc.h>
|
||||
|
||||
struct pcc_data {
|
||||
struct pcc_mbox_chan *pcc_chan;
|
||||
void __iomem *pcc_comm_addr;
|
||||
struct completion done;
|
||||
struct mbox_client cl;
|
||||
struct acpi_pcc_info ctx;
|
||||
};
|
||||
|
||||
struct acpi_pcc_info pcc_ctx;
|
||||
|
||||
static void pcc_rx_callback(struct mbox_client *cl, void *m)
|
||||
{
|
||||
struct pcc_data *data = container_of(cl, struct pcc_data, cl);
|
||||
|
||||
complete(&data->done);
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
|
||||
void *handler_context, void **region_context)
|
||||
{
|
||||
struct pcc_data *data;
|
||||
struct acpi_pcc_info *ctx = handler_context;
|
||||
struct pcc_mbox_chan *pcc_chan;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return AE_NO_MEMORY;
|
||||
|
||||
data->cl.rx_callback = pcc_rx_callback;
|
||||
data->cl.knows_txdone = true;
|
||||
data->ctx.length = ctx->length;
|
||||
data->ctx.subspace_id = ctx->subspace_id;
|
||||
data->ctx.internal_buffer = ctx->internal_buffer;
|
||||
|
||||
init_completion(&data->done);
|
||||
data->pcc_chan = pcc_mbox_request_channel(&data->cl, ctx->subspace_id);
|
||||
if (IS_ERR(data->pcc_chan)) {
|
||||
pr_err("Failed to find PCC channel for subspace %d\n",
|
||||
ctx->subspace_id);
|
||||
return AE_NOT_FOUND;
|
||||
}
|
||||
|
||||
pcc_chan = data->pcc_chan;
|
||||
data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr,
|
||||
pcc_chan->shmem_size);
|
||||
if (!data->pcc_comm_addr) {
|
||||
pr_err("Failed to ioremap PCC comm region mem for %d\n",
|
||||
ctx->subspace_id);
|
||||
return AE_NO_MEMORY;
|
||||
}
|
||||
|
||||
*region_context = data;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
|
||||
u32 bits, acpi_integer *value,
|
||||
void *handler_context, void *region_context)
|
||||
{
|
||||
int ret;
|
||||
struct pcc_data *data = region_context;
|
||||
|
||||
reinit_completion(&data->done);
|
||||
|
||||
/* Write to Shared Memory */
|
||||
memcpy_toio(data->pcc_comm_addr, (void *)value, data->ctx.length);
|
||||
|
||||
ret = mbox_send_message(data->pcc_chan->mchan, NULL);
|
||||
if (ret < 0)
|
||||
return AE_ERROR;
|
||||
|
||||
if (data->pcc_chan->mchan->mbox->txdone_irq)
|
||||
wait_for_completion(&data->done);
|
||||
|
||||
mbox_client_txdone(data->pcc_chan->mchan, ret);
|
||||
|
||||
memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
void __init acpi_init_pcc(void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
|
||||
ACPI_ADR_SPACE_PLATFORM_COMM,
|
||||
&acpi_pcc_address_space_handler,
|
||||
&acpi_pcc_address_space_setup,
|
||||
&pcc_ctx);
|
||||
if (ACPI_FAILURE(status))
|
||||
pr_alert("OperationRegion handler could not be installed\n");
|
||||
}
|
@ -1733,13 +1733,12 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
|
||||
{
|
||||
struct acpi_device *device = context;
|
||||
struct acpi_device *sibling;
|
||||
int result;
|
||||
|
||||
if (handle == device->handle)
|
||||
return AE_CTRL_TERMINATE;
|
||||
|
||||
result = acpi_bus_get_device(handle, &sibling);
|
||||
if (result)
|
||||
sibling = acpi_fetch_acpi_dev(handle);
|
||||
if (!sibling)
|
||||
return AE_OK;
|
||||
|
||||
if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME))
|
||||
|
@ -223,6 +223,11 @@ acpi_ev_pci_bar_region_setup(acpi_handle handle,
|
||||
u32 function,
|
||||
void *handler_context, void **region_context);
|
||||
|
||||
acpi_status
|
||||
acpi_ev_data_table_region_setup(acpi_handle handle,
|
||||
u32 function,
|
||||
void *handler_context, void **region_context);
|
||||
|
||||
acpi_status
|
||||
acpi_ev_default_region_setup(acpi_handle handle,
|
||||
u32 function,
|
||||
|
@ -138,6 +138,7 @@ struct acpi_object_region {
|
||||
union acpi_operand_object *next;
|
||||
acpi_physical_address address;
|
||||
u32 length;
|
||||
void *pointer; /* Only for data table regions */
|
||||
};
|
||||
|
||||
struct acpi_object_method {
|
||||
|
@ -35,7 +35,8 @@ acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
|
||||
|
||||
acpi_status
|
||||
acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
|
||||
acpi_physical_address address, u8 flags);
|
||||
acpi_physical_address address,
|
||||
u8 flags, struct acpi_table_header *table);
|
||||
|
||||
void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc);
|
||||
|
||||
@ -86,6 +87,7 @@ acpi_tb_release_table(struct acpi_table_header *table,
|
||||
acpi_status
|
||||
acpi_tb_install_standard_table(acpi_physical_address address,
|
||||
u8 flags,
|
||||
struct acpi_table_header *table,
|
||||
u8 reload, u8 override, u32 *table_index);
|
||||
|
||||
void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc);
|
||||
@ -95,7 +97,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node);
|
||||
|
||||
acpi_status
|
||||
acpi_tb_install_and_load_table(acpi_physical_address address,
|
||||
u8 flags, u8 override, u32 *table_index);
|
||||
u8 flags,
|
||||
struct acpi_table_header *table,
|
||||
u8 override, u32 *table_index);
|
||||
|
||||
acpi_status acpi_tb_unload_table(u32 table_index);
|
||||
|
||||
|
@ -531,6 +531,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
||||
|
||||
obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
|
||||
obj_desc->region.length = table->length;
|
||||
obj_desc->region.pointer = table;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
|
||||
obj_desc,
|
||||
|
@ -386,7 +386,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node *node,
|
||||
case ACPI_ADR_SPACE_DATA_TABLE:
|
||||
|
||||
handler = acpi_ex_data_table_space_handler;
|
||||
setup = NULL;
|
||||
setup = acpi_ev_data_table_region_setup;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -162,6 +162,16 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
||||
return_ACPI_STATUS(AE_NOT_EXIST);
|
||||
}
|
||||
|
||||
if (region_obj->region.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
|
||||
struct acpi_pcc_info *ctx =
|
||||
handler_desc->address_space.context;
|
||||
|
||||
ctx->internal_buffer =
|
||||
field_obj->field.internal_pcc_buffer;
|
||||
ctx->length = (u16)region_obj->region.length;
|
||||
ctx->subspace_id = (u8)region_obj->region.address;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must exit the interpreter because the region setup will
|
||||
* potentially execute control methods (for example, the _REG method
|
||||
|
@ -406,6 +406,58 @@ acpi_ev_cmos_region_setup(acpi_handle handle,
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_data_table_region_setup
|
||||
*
|
||||
* PARAMETERS: handle - Region we are interested in
|
||||
* function - Start or stop
|
||||
* handler_context - Address space handler context
|
||||
* region_context - Region specific context
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Setup a data_table_region
|
||||
*
|
||||
* MUTEX: Assumes namespace is not locked
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ev_data_table_region_setup(acpi_handle handle,
|
||||
u32 function,
|
||||
void *handler_context, void **region_context)
|
||||
{
|
||||
union acpi_operand_object *region_desc =
|
||||
(union acpi_operand_object *)handle;
|
||||
struct acpi_data_table_space_context *local_region_context;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_data_table_region_setup);
|
||||
|
||||
if (function == ACPI_REGION_DEACTIVATE) {
|
||||
if (*region_context) {
|
||||
ACPI_FREE(*region_context);
|
||||
*region_context = NULL;
|
||||
}
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* Create a new context */
|
||||
|
||||
local_region_context =
|
||||
ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_space_context));
|
||||
if (!(local_region_context)) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Save the data table pointer for use in the handler */
|
||||
|
||||
local_region_context->pointer = region_desc->region.pointer;
|
||||
|
||||
*region_context = local_region_context;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_default_region_setup
|
||||
|
@ -411,7 +411,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
||||
acpi_ex_exit_interpreter();
|
||||
status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
|
||||
TRUE, &table_index);
|
||||
table, TRUE, &table_index);
|
||||
acpi_ex_enter_interpreter();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
|
@ -279,6 +279,7 @@ acpi_ex_create_region(u8 * aml_start,
|
||||
obj_desc->region.space_id = space_id;
|
||||
obj_desc->region.address = 0;
|
||||
obj_desc->region.length = 0;
|
||||
obj_desc->region.pointer = NULL;
|
||||
obj_desc->region.node = node;
|
||||
obj_desc->region.handler = NULL;
|
||||
obj_desc->common.flags &=
|
||||
|
@ -330,12 +330,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
||||
obj_desc->field.base_byte_offset,
|
||||
source_desc->buffer.pointer, data_length);
|
||||
|
||||
if ((obj_desc->field.region_obj->region.address ==
|
||||
PCC_MASTER_SUBSPACE
|
||||
&& MASTER_SUBSPACE_COMMAND(obj_desc->field.
|
||||
base_byte_offset))
|
||||
|| GENERIC_SUBSPACE_COMMAND(obj_desc->field.
|
||||
base_byte_offset)) {
|
||||
if (MASTER_SUBSPACE_COMMAND(obj_desc->field.base_byte_offset)) {
|
||||
|
||||
/* Perform the write */
|
||||
|
||||
|
@ -1007,7 +1007,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
||||
(walk_state, return_desc,
|
||||
&temp_desc);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto cleanup;
|
||||
return_ACPI_STATUS
|
||||
(status);
|
||||
}
|
||||
|
||||
return_desc = temp_desc;
|
||||
|
@ -509,8 +509,15 @@ acpi_ex_data_table_space_handler(u32 function,
|
||||
u64 *value,
|
||||
void *handler_context, void *region_context)
|
||||
{
|
||||
struct acpi_data_table_space_context *mapping;
|
||||
char *pointer;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
|
||||
|
||||
mapping = (struct acpi_data_table_space_context *) region_context;
|
||||
pointer = ACPI_CAST_PTR(char, mapping->pointer) +
|
||||
(address - ACPI_PTR_TO_PHYSADDR(mapping->pointer));
|
||||
|
||||
/*
|
||||
* Perform the memory read or write. The bit_width was already
|
||||
* validated.
|
||||
@ -518,14 +525,14 @@ acpi_ex_data_table_space_handler(u32 function,
|
||||
switch (function) {
|
||||
case ACPI_READ:
|
||||
|
||||
memcpy(ACPI_CAST_PTR(char, value),
|
||||
ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width));
|
||||
memcpy(ACPI_CAST_PTR(char, value), pointer,
|
||||
ACPI_DIV_8(bit_width));
|
||||
break;
|
||||
|
||||
case ACPI_WRITE:
|
||||
|
||||
memcpy(ACPI_PHYSADDR_TO_PTR(address),
|
||||
ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width));
|
||||
memcpy(pointer, ACPI_CAST_PTR(char, value),
|
||||
ACPI_DIV_8(bit_width));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -104,7 +104,9 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
|
||||
|
||||
/* Flush caches, as per ACPI specification */
|
||||
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
if (sleep_state < ACPI_STATE_S4) {
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
}
|
||||
|
||||
status = acpi_os_enter_sleep(sleep_state, sleep_control, 0);
|
||||
if (status == AE_CTRL_TERMINATE) {
|
||||
|
@ -110,7 +110,9 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
|
||||
|
||||
/* Flush caches, as per ACPI specification */
|
||||
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
if (sleep_state < ACPI_STATE_S4) {
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
}
|
||||
|
||||
status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control);
|
||||
if (status == AE_CTRL_TERMINATE) {
|
||||
|
@ -162,8 +162,6 @@ acpi_status acpi_enter_sleep_state_s4bios(void)
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
|
||||
status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,
|
||||
(u32)acpi_gbl_FADT.s4_bios_request, 8);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
@ -89,14 +89,27 @@ acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
|
||||
{
|
||||
|
||||
/*
|
||||
* Initialize the table descriptor. Set the pointer to NULL, since the
|
||||
* table is not fully mapped at this time.
|
||||
* Initialize the table descriptor. Set the pointer to NULL for external
|
||||
* tables, since the table is not fully mapped at this time.
|
||||
*/
|
||||
memset(table_desc, 0, sizeof(struct acpi_table_desc));
|
||||
table_desc->address = address;
|
||||
table_desc->length = table->length;
|
||||
table_desc->flags = flags;
|
||||
ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
|
||||
|
||||
switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
|
||||
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
|
||||
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
|
||||
|
||||
table_desc->pointer = table;
|
||||
break;
|
||||
|
||||
case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -132,9 +145,7 @@ acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
|
||||
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
|
||||
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
|
||||
|
||||
table = ACPI_CAST_PTR(struct acpi_table_header,
|
||||
ACPI_PHYSADDR_TO_PTR(table_desc->
|
||||
address));
|
||||
table = table_desc->pointer;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -196,6 +207,8 @@ acpi_tb_release_table(struct acpi_table_header *table,
|
||||
* PARAMETERS: table_desc - Table descriptor to be acquired
|
||||
* address - Address of the table
|
||||
* flags - Allocation flags of the table
|
||||
* table - Pointer to the table (required for virtual
|
||||
* origins, optional for physical)
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
@ -208,49 +221,52 @@ acpi_tb_release_table(struct acpi_table_header *table,
|
||||
|
||||
acpi_status
|
||||
acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
|
||||
acpi_physical_address address, u8 flags)
|
||||
acpi_physical_address address,
|
||||
u8 flags, struct acpi_table_header *table)
|
||||
{
|
||||
struct acpi_table_header *table_header;
|
||||
u8 mapped_table = FALSE;
|
||||
|
||||
switch (flags & ACPI_TABLE_ORIGIN_MASK) {
|
||||
case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
|
||||
|
||||
/* Get the length of the full table from the header */
|
||||
|
||||
table_header =
|
||||
acpi_os_map_memory(address,
|
||||
sizeof(struct acpi_table_header));
|
||||
if (!table_header) {
|
||||
return (AE_NO_MEMORY);
|
||||
if (!table) {
|
||||
table =
|
||||
acpi_os_map_memory(address,
|
||||
sizeof(struct
|
||||
acpi_table_header));
|
||||
if (!table) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
mapped_table = TRUE;
|
||||
}
|
||||
|
||||
acpi_tb_init_table_descriptor(table_desc, address, flags,
|
||||
table_header);
|
||||
acpi_os_unmap_memory(table_header,
|
||||
sizeof(struct acpi_table_header));
|
||||
return (AE_OK);
|
||||
break;
|
||||
|
||||
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
|
||||
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
|
||||
|
||||
table_header = ACPI_CAST_PTR(struct acpi_table_header,
|
||||
ACPI_PHYSADDR_TO_PTR(address));
|
||||
if (!table_header) {
|
||||
return (AE_NO_MEMORY);
|
||||
if (!table) {
|
||||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
acpi_tb_init_table_descriptor(table_desc, address, flags,
|
||||
table_header);
|
||||
return (AE_OK);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
/* Table is not valid yet */
|
||||
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Table is not valid yet */
|
||||
acpi_tb_init_table_descriptor(table_desc, address, flags, table);
|
||||
if (mapped_table) {
|
||||
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
|
||||
}
|
||||
|
||||
return (AE_NO_MEMORY);
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -335,7 +351,19 @@ void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
|
||||
|
||||
acpi_tb_release_table(table_desc->pointer, table_desc->length,
|
||||
table_desc->flags);
|
||||
table_desc->pointer = NULL;
|
||||
|
||||
switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
|
||||
case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
|
||||
|
||||
table_desc->pointer = NULL;
|
||||
break;
|
||||
|
||||
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
|
||||
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
@ -959,6 +987,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
|
||||
*
|
||||
* PARAMETERS: address - Physical address of the table
|
||||
* flags - Allocation flags of the table
|
||||
* table - Pointer to the table (required for
|
||||
* virtual origins, optional for
|
||||
* physical)
|
||||
* override - Whether override should be performed
|
||||
* table_index - Where table index is returned
|
||||
*
|
||||
@ -970,7 +1001,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
|
||||
|
||||
acpi_status
|
||||
acpi_tb_install_and_load_table(acpi_physical_address address,
|
||||
u8 flags, u8 override, u32 *table_index)
|
||||
u8 flags,
|
||||
struct acpi_table_header *table,
|
||||
u8 override, u32 *table_index)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
@ -979,7 +1012,7 @@ acpi_tb_install_and_load_table(acpi_physical_address address,
|
||||
|
||||
/* Install the table and load it into the namespace */
|
||||
|
||||
status = acpi_tb_install_standard_table(address, flags, TRUE,
|
||||
status = acpi_tb_install_standard_table(address, flags, table, TRUE,
|
||||
override, &i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
|
@ -313,7 +313,7 @@ void acpi_tb_parse_fadt(void)
|
||||
acpi_tb_install_standard_table((acpi_physical_address)acpi_gbl_FADT.
|
||||
Xdsdt,
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
|
||||
FALSE, TRUE, &acpi_gbl_dsdt_index);
|
||||
NULL, FALSE, TRUE, &acpi_gbl_dsdt_index);
|
||||
|
||||
/* If Hardware Reduced flag is set, there is no FACS */
|
||||
|
||||
@ -322,14 +322,14 @@ void acpi_tb_parse_fadt(void)
|
||||
acpi_tb_install_standard_table((acpi_physical_address)
|
||||
acpi_gbl_FADT.facs,
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
|
||||
FALSE, TRUE,
|
||||
NULL, FALSE, TRUE,
|
||||
&acpi_gbl_facs_index);
|
||||
}
|
||||
if (acpi_gbl_FADT.Xfacs) {
|
||||
acpi_tb_install_standard_table((acpi_physical_address)
|
||||
acpi_gbl_FADT.Xfacs,
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
|
||||
FALSE, TRUE,
|
||||
NULL, FALSE, TRUE,
|
||||
&acpi_gbl_xfacs_index);
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +79,8 @@ acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
|
||||
* PARAMETERS: address - Address of the table (might be a virtual
|
||||
* address depending on the table_flags)
|
||||
* flags - Flags for the table
|
||||
* table - Pointer to the table (required for virtual
|
||||
* origins, optional for physical)
|
||||
* reload - Whether reload should be performed
|
||||
* override - Whether override should be performed
|
||||
* table_index - Where the table index is returned
|
||||
@ -96,6 +98,7 @@ acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
|
||||
acpi_status
|
||||
acpi_tb_install_standard_table(acpi_physical_address address,
|
||||
u8 flags,
|
||||
struct acpi_table_header *table,
|
||||
u8 reload, u8 override, u32 *table_index)
|
||||
{
|
||||
u32 i;
|
||||
@ -106,7 +109,8 @@ acpi_tb_install_standard_table(acpi_physical_address address,
|
||||
|
||||
/* Acquire a temporary table descriptor for validation */
|
||||
|
||||
status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags);
|
||||
status =
|
||||
acpi_tb_acquire_temp_table(&new_table_desc, address, flags, table);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not acquire table length at %8.8X%8.8X",
|
||||
@ -209,7 +213,8 @@ void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
|
||||
if (ACPI_SUCCESS(status) && table) {
|
||||
acpi_tb_acquire_temp_table(&new_table_desc,
|
||||
ACPI_PTR_TO_PHYSADDR(table),
|
||||
ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
|
||||
ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
|
||||
table);
|
||||
ACPI_ERROR_ONLY(override_type = "Logical");
|
||||
goto finish_override;
|
||||
}
|
||||
@ -220,7 +225,8 @@ void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
|
||||
&address, &length);
|
||||
if (ACPI_SUCCESS(status) && address && length) {
|
||||
acpi_tb_acquire_temp_table(&new_table_desc, address,
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
|
||||
NULL);
|
||||
ACPI_ERROR_ONLY(override_type = "Physical");
|
||||
goto finish_override;
|
||||
}
|
||||
@ -289,7 +295,8 @@ void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
|
||||
|
||||
if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) {
|
||||
ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc->address));
|
||||
ACPI_FREE(table_desc->pointer);
|
||||
table_desc->pointer = NULL;
|
||||
}
|
||||
|
||||
table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
|
||||
|
@ -101,7 +101,8 @@ acpi_tb_print_table_header(acpi_physical_address address,
|
||||
ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X",
|
||||
header->signature, ACPI_FORMAT_UINT64(address),
|
||||
header->length));
|
||||
} else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
|
||||
} else if (ACPI_VALIDATE_RSDP_SIG(ACPI_CAST_PTR(struct acpi_table_rsdp,
|
||||
header)->signature)) {
|
||||
|
||||
/* RSDP has no common fields */
|
||||
|
||||
|
@ -328,7 +328,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
|
||||
|
||||
status = acpi_tb_install_standard_table(address,
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
|
||||
FALSE, TRUE,
|
||||
NULL, FALSE, TRUE,
|
||||
&table_index);
|
||||
|
||||
if (ACPI_SUCCESS(status) &&
|
||||
|
@ -227,9 +227,7 @@ acpi_status acpi_tb_load_namespace(void)
|
||||
*
|
||||
* FUNCTION: acpi_install_table
|
||||
*
|
||||
* PARAMETERS: address - Address of the ACPI table to be installed.
|
||||
* physical - Whether the address is a physical table
|
||||
* address or not
|
||||
* PARAMETERS: table - Pointer to the ACPI table to be installed.
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
@ -240,28 +238,54 @@ acpi_status acpi_tb_load_namespace(void)
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status ACPI_INIT_FUNCTION
|
||||
acpi_install_table(acpi_physical_address address, u8 physical)
|
||||
acpi_install_table(struct acpi_table_header *table)
|
||||
{
|
||||
acpi_status status;
|
||||
u8 flags;
|
||||
u32 table_index;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_install_table);
|
||||
|
||||
if (physical) {
|
||||
flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
|
||||
} else {
|
||||
flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
|
||||
}
|
||||
|
||||
status = acpi_tb_install_standard_table(address, flags,
|
||||
FALSE, FALSE, &table_index);
|
||||
status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
|
||||
ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
|
||||
table, FALSE, FALSE,
|
||||
&table_index);
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_install_physical_table
|
||||
*
|
||||
* PARAMETERS: address - Address of the ACPI table to be installed.
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Dynamically install an ACPI table.
|
||||
* Note: This function should only be invoked after
|
||||
* acpi_initialize_tables() and before acpi_load_tables().
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status ACPI_INIT_FUNCTION
|
||||
acpi_install_physical_table(acpi_physical_address address)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 table_index;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_install_physical_table);
|
||||
|
||||
status = acpi_tb_install_standard_table(address,
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
|
||||
NULL, FALSE, FALSE,
|
||||
&table_index);
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL_INIT(acpi_install_physical_table)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_load_table
|
||||
@ -298,7 +322,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table, u32 *table_idx)
|
||||
ACPI_INFO(("Host-directed Dynamic ACPI Table Load:"));
|
||||
status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
|
||||
ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
|
||||
FALSE, &table_index);
|
||||
table, FALSE, &table_index);
|
||||
if (table_idx) {
|
||||
*table_idx = table_index;
|
||||
}
|
||||
|
@ -422,6 +422,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Obj %p, Reference Count is already zero, cannot decrement\n",
|
||||
object));
|
||||
return;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_ALLOCATIONS,
|
||||
|
@ -52,7 +52,7 @@ static bool battery_driver_registered;
|
||||
static int battery_bix_broken_package;
|
||||
static int battery_notification_delay_ms;
|
||||
static int battery_ac_is_broken;
|
||||
static int battery_check_pmic = 1;
|
||||
static int battery_quirk_notcharging;
|
||||
static unsigned int cache_time = 1000;
|
||||
module_param(cache_time, uint, 0644);
|
||||
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
||||
@ -64,11 +64,6 @@ static const struct acpi_device_id battery_device_ids[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
|
||||
|
||||
/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
|
||||
static const char * const acpi_battery_blacklist[] = {
|
||||
"INT33F4", /* X-Powers AXP288 PMIC */
|
||||
};
|
||||
|
||||
enum {
|
||||
ACPI_BATTERY_ALARM_PRESENT,
|
||||
ACPI_BATTERY_XINFO_PRESENT,
|
||||
@ -217,6 +212,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
||||
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else if (acpi_battery_is_charged(battery))
|
||||
val->intval = POWER_SUPPLY_STATUS_FULL;
|
||||
else if (battery_quirk_notcharging)
|
||||
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
break;
|
||||
@ -1104,10 +1101,9 @@ battery_ac_is_broken_quirk(const struct dmi_system_id *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
|
||||
static int __init battery_quirk_not_charging(const struct dmi_system_id *d)
|
||||
{
|
||||
battery_check_pmic = 0;
|
||||
battery_quirk_notcharging = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1140,19 +1136,16 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
|
||||
},
|
||||
},
|
||||
{
|
||||
/* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
|
||||
.callback = battery_do_not_check_pmic_quirk,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
|
||||
.callback = battery_do_not_check_pmic_quirk,
|
||||
/*
|
||||
* On Lenovo ThinkPads the BIOS specification defines
|
||||
* a state when the bits for charging and discharging
|
||||
* are both set to 0. That state is "Not Charging".
|
||||
*/
|
||||
.callback = battery_quirk_not_charging,
|
||||
.ident = "Lenovo ThinkPad",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
@ -1279,19 +1272,12 @@ static struct acpi_driver acpi_battery_driver = {
|
||||
|
||||
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
||||
{
|
||||
unsigned int i;
|
||||
int result;
|
||||
|
||||
dmi_check_system(bat_dmi_table);
|
||||
if (acpi_quirk_skip_acpi_ac_and_battery())
|
||||
return;
|
||||
|
||||
if (battery_check_pmic) {
|
||||
for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
|
||||
if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
|
||||
pr_info("found native %s PMIC, not loading\n",
|
||||
acpi_battery_blacklist[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
dmi_check_system(bat_dmi_table);
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_battery_driver);
|
||||
battery_driver_registered = (result == 0);
|
||||
|
@ -98,8 +98,8 @@ int acpi_bus_get_status(struct acpi_device *device)
|
||||
acpi_status status;
|
||||
unsigned long long sta;
|
||||
|
||||
if (acpi_device_always_present(device)) {
|
||||
acpi_set_device_status(device, ACPI_STA_DEFAULT);
|
||||
if (acpi_device_override_status(device, &sta)) {
|
||||
acpi_set_device_status(device, sta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1320,6 +1320,7 @@ static int __init acpi_init(void)
|
||||
pr_debug("%s: kset create error\n", __func__);
|
||||
|
||||
init_prmt();
|
||||
acpi_init_pcc();
|
||||
result = acpi_bus_init();
|
||||
if (result) {
|
||||
kobject_put(acpi_kobj);
|
||||
|
@ -179,10 +179,11 @@ static struct attribute *cppc_attrs[] = {
|
||||
&lowest_freq.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(cppc);
|
||||
|
||||
static struct kobj_type cppc_ktype = {
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
.default_attrs = cppc_attrs,
|
||||
.default_groups = cppc_groups,
|
||||
};
|
||||
|
||||
static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit)
|
||||
@ -604,47 +605,30 @@ static bool is_cppc_supported(int revision, int num_ent)
|
||||
/*
|
||||
* An example CPC table looks like the following.
|
||||
*
|
||||
* Name(_CPC, Package()
|
||||
* {
|
||||
* 17,
|
||||
* NumEntries
|
||||
* 1,
|
||||
* // Revision
|
||||
* ResourceTemplate(){Register(PCC, 32, 0, 0x120, 2)},
|
||||
* // Highest Performance
|
||||
* ResourceTemplate(){Register(PCC, 32, 0, 0x124, 2)},
|
||||
* // Nominal Performance
|
||||
* ResourceTemplate(){Register(PCC, 32, 0, 0x128, 2)},
|
||||
* // Lowest Nonlinear Performance
|
||||
* ResourceTemplate(){Register(PCC, 32, 0, 0x12C, 2)},
|
||||
* // Lowest Performance
|
||||
* ResourceTemplate(){Register(PCC, 32, 0, 0x130, 2)},
|
||||
* // Guaranteed Performance Register
|
||||
* ResourceTemplate(){Register(PCC, 32, 0, 0x110, 2)},
|
||||
* // Desired Performance Register
|
||||
* ResourceTemplate(){Register(SystemMemory, 0, 0, 0, 0)},
|
||||
* ..
|
||||
* ..
|
||||
* ..
|
||||
*
|
||||
* }
|
||||
* Name (_CPC, Package() {
|
||||
* 17, // NumEntries
|
||||
* 1, // Revision
|
||||
* ResourceTemplate() {Register(PCC, 32, 0, 0x120, 2)}, // Highest Performance
|
||||
* ResourceTemplate() {Register(PCC, 32, 0, 0x124, 2)}, // Nominal Performance
|
||||
* ResourceTemplate() {Register(PCC, 32, 0, 0x128, 2)}, // Lowest Nonlinear Performance
|
||||
* ResourceTemplate() {Register(PCC, 32, 0, 0x12C, 2)}, // Lowest Performance
|
||||
* ResourceTemplate() {Register(PCC, 32, 0, 0x130, 2)}, // Guaranteed Performance Register
|
||||
* ResourceTemplate() {Register(PCC, 32, 0, 0x110, 2)}, // Desired Performance Register
|
||||
* ResourceTemplate() {Register(SystemMemory, 0, 0, 0, 0)},
|
||||
* ...
|
||||
* ...
|
||||
* ...
|
||||
* }
|
||||
* Each Register() encodes how to access that specific register.
|
||||
* e.g. a sample PCC entry has the following encoding:
|
||||
*
|
||||
* Register (
|
||||
* PCC,
|
||||
* AddressSpaceKeyword
|
||||
* 8,
|
||||
* //RegisterBitWidth
|
||||
* 8,
|
||||
* //RegisterBitOffset
|
||||
* 0x30,
|
||||
* //RegisterAddress
|
||||
* 9
|
||||
* //AccessSize (subspace ID)
|
||||
* 0
|
||||
* )
|
||||
* }
|
||||
* Register (
|
||||
* PCC, // AddressSpaceKeyword
|
||||
* 8, // RegisterBitWidth
|
||||
* 8, // RegisterBitOffset
|
||||
* 0x30, // RegisterAddress
|
||||
* 9, // AccessSize (subspace ID)
|
||||
* )
|
||||
*/
|
||||
|
||||
#ifndef init_freq_invariance_cppc
|
||||
|
@ -285,14 +285,12 @@ EXPORT_SYMBOL(acpi_device_set_power);
|
||||
|
||||
int acpi_bus_set_power(acpi_handle handle, int state)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
int result;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
if (result)
|
||||
return result;
|
||||
if (device)
|
||||
return acpi_device_set_power(device, state);
|
||||
|
||||
return acpi_device_set_power(device, state);
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_set_power);
|
||||
|
||||
@ -410,21 +408,20 @@ EXPORT_SYMBOL_GPL(acpi_device_update_power);
|
||||
|
||||
int acpi_bus_update_power(acpi_handle handle, int *state_p)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
int result;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
return result ? result : acpi_device_update_power(device, state_p);
|
||||
if (device)
|
||||
return acpi_device_update_power(device, state_p);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_bus_update_power);
|
||||
|
||||
bool acpi_bus_power_manageable(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
int result;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
return result ? false : device->flags.power_manageable;
|
||||
return device && device->flags.power_manageable;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_power_manageable);
|
||||
|
||||
@ -543,11 +540,9 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
|
||||
|
||||
bool acpi_bus_can_wakeup(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
int result;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
return result ? false : device->wakeup.flags.valid;
|
||||
return device && device->wakeup.flags.valid;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_can_wakeup);
|
||||
|
||||
|
@ -53,6 +53,7 @@ static struct attribute *acpi_data_node_default_attrs[] = {
|
||||
&data_node_path.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(acpi_data_node_default);
|
||||
|
||||
#define to_data_node(k) container_of(k, struct acpi_data_node, kobj)
|
||||
#define to_attr(a) container_of(a, struct acpi_data_node_attr, attr)
|
||||
@ -79,7 +80,7 @@ static void acpi_data_node_release(struct kobject *kobj)
|
||||
|
||||
static struct kobj_type acpi_data_node_ktype = {
|
||||
.sysfs_ops = &acpi_data_node_sysfs_ops,
|
||||
.default_attrs = acpi_data_node_default_attrs,
|
||||
.default_groups = acpi_data_node_default_groups,
|
||||
.release = acpi_data_node_release,
|
||||
};
|
||||
|
||||
|
@ -489,9 +489,8 @@ static ssize_t docked_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dock_station *dock_station = dev->platform_data;
|
||||
struct acpi_device *adev = NULL;
|
||||
struct acpi_device *adev = acpi_fetch_acpi_dev(dock_station->handle);
|
||||
|
||||
acpi_bus_get_device(dock_station->handle, &adev);
|
||||
return sysfs_emit(buf, "%u\n", acpi_device_enumerated(adev));
|
||||
}
|
||||
static DEVICE_ATTR_RO(docked);
|
||||
|
@ -46,7 +46,7 @@ static int pch_fivr_read(acpi_handle handle, char *method, struct pch_fivr_resp
|
||||
}
|
||||
|
||||
/*
|
||||
* Presentation of attributes which are defined for INT1045
|
||||
* Presentation of attributes which are defined for INTC10xx
|
||||
* They are:
|
||||
* freq_mhz_low_clock : Set PCH FIVR switching freq for
|
||||
* FIVR clock 19.2MHz and 24MHz
|
||||
|
@ -92,8 +92,6 @@ enum ec_command {
|
||||
|
||||
enum {
|
||||
EC_FLAGS_QUERY_ENABLED, /* Query is enabled */
|
||||
EC_FLAGS_QUERY_PENDING, /* Query is pending */
|
||||
EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */
|
||||
EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */
|
||||
EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */
|
||||
EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */
|
||||
@ -166,12 +164,12 @@ struct acpi_ec_query {
|
||||
struct transaction transaction;
|
||||
struct work_struct work;
|
||||
struct acpi_ec_query_handler *handler;
|
||||
struct acpi_ec *ec;
|
||||
};
|
||||
|
||||
static int acpi_ec_query(struct acpi_ec *ec, u8 *data);
|
||||
static void advance_transaction(struct acpi_ec *ec, bool interrupt);
|
||||
static int acpi_ec_submit_query(struct acpi_ec *ec);
|
||||
static bool advance_transaction(struct acpi_ec *ec, bool interrupt);
|
||||
static void acpi_ec_event_handler(struct work_struct *work);
|
||||
static void acpi_ec_event_processor(struct work_struct *work);
|
||||
|
||||
struct acpi_ec *first_ec;
|
||||
EXPORT_SYMBOL(first_ec);
|
||||
@ -443,24 +441,51 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void acpi_ec_submit_query(struct acpi_ec *ec)
|
||||
static bool acpi_ec_submit_event(struct acpi_ec *ec)
|
||||
{
|
||||
acpi_ec_mask_events(ec);
|
||||
if (!acpi_ec_event_enabled(ec))
|
||||
return;
|
||||
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
|
||||
return false;
|
||||
|
||||
if (ec->event_state == EC_EVENT_READY) {
|
||||
ec_dbg_evt("Command(%s) submitted/blocked",
|
||||
acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
|
||||
ec->nr_pending_queries++;
|
||||
queue_work(ec_wq, &ec->work);
|
||||
|
||||
ec->event_state = EC_EVENT_IN_PROGRESS;
|
||||
/*
|
||||
* If events_to_process is greqter than 0 at this point, the
|
||||
* while () loop in acpi_ec_event_handler() is still running
|
||||
* and incrementing events_to_process will cause it to invoke
|
||||
* acpi_ec_submit_query() once more, so it is not necessary to
|
||||
* queue up the event work to start the same loop again.
|
||||
*/
|
||||
if (ec->events_to_process++ > 0)
|
||||
return true;
|
||||
|
||||
ec->events_in_progress++;
|
||||
return queue_work(ec_wq, &ec->work);
|
||||
}
|
||||
|
||||
/*
|
||||
* The event handling work has not been completed yet, so it needs to be
|
||||
* flushed.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
static void acpi_ec_complete_query(struct acpi_ec *ec)
|
||||
static void acpi_ec_complete_event(struct acpi_ec *ec)
|
||||
{
|
||||
if (test_and_clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
|
||||
if (ec->event_state == EC_EVENT_IN_PROGRESS)
|
||||
ec->event_state = EC_EVENT_COMPLETE;
|
||||
}
|
||||
|
||||
static void acpi_ec_close_event(struct acpi_ec *ec)
|
||||
{
|
||||
if (ec->event_state != EC_EVENT_READY)
|
||||
ec_dbg_evt("Command(%s) unblocked",
|
||||
acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
|
||||
|
||||
ec->event_state = EC_EVENT_READY;
|
||||
acpi_ec_unmask_events(ec);
|
||||
}
|
||||
|
||||
@ -487,12 +512,10 @@ static inline void __acpi_ec_disable_event(struct acpi_ec *ec)
|
||||
*/
|
||||
static void acpi_ec_clear(struct acpi_ec *ec)
|
||||
{
|
||||
int i, status;
|
||||
u8 value = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
|
||||
status = acpi_ec_query(ec, &value);
|
||||
if (status || !value)
|
||||
if (acpi_ec_submit_query(ec))
|
||||
break;
|
||||
}
|
||||
if (unlikely(i == ACPI_EC_CLEAR_MAX))
|
||||
@ -518,7 +541,7 @@ static void acpi_ec_enable_event(struct acpi_ec *ec)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static void __acpi_ec_flush_work(void)
|
||||
{
|
||||
drain_workqueue(ec_wq); /* flush ec->work */
|
||||
flush_workqueue(ec_wq); /* flush ec->work */
|
||||
flush_workqueue(ec_query_wq); /* flush queries */
|
||||
}
|
||||
|
||||
@ -549,8 +572,8 @@ void acpi_ec_flush_work(void)
|
||||
|
||||
static bool acpi_ec_guard_event(struct acpi_ec *ec)
|
||||
{
|
||||
bool guarded = true;
|
||||
unsigned long flags;
|
||||
bool guarded;
|
||||
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
/*
|
||||
@ -559,19 +582,15 @@ static bool acpi_ec_guard_event(struct acpi_ec *ec)
|
||||
* evaluating _Qxx, so we need to re-check SCI_EVT after waiting an
|
||||
* acceptable period.
|
||||
*
|
||||
* The guarding period begins when EC_FLAGS_QUERY_PENDING is
|
||||
* flagged, which means SCI_EVT check has just been performed.
|
||||
* But if the current transaction is ACPI_EC_COMMAND_QUERY, the
|
||||
* guarding should have already been performed (via
|
||||
* EC_FLAGS_QUERY_GUARDING) and should not be applied so that the
|
||||
* ACPI_EC_COMMAND_QUERY transaction can be transitioned into
|
||||
* ACPI_EC_COMMAND_POLL state immediately.
|
||||
* The guarding period is applicable if the event state is not
|
||||
* EC_EVENT_READY, but otherwise if the current transaction is of the
|
||||
* ACPI_EC_COMMAND_QUERY type, the guarding should have elapsed already
|
||||
* and it should not be applied to let the transaction transition into
|
||||
* the ACPI_EC_COMMAND_POLL state immediately.
|
||||
*/
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS ||
|
||||
ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY ||
|
||||
!test_bit(EC_FLAGS_QUERY_PENDING, &ec->flags) ||
|
||||
(ec->curr && ec->curr->command == ACPI_EC_COMMAND_QUERY))
|
||||
guarded = false;
|
||||
guarded = ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT &&
|
||||
ec->event_state != EC_EVENT_READY &&
|
||||
(!ec->curr || ec->curr->command != ACPI_EC_COMMAND_QUERY);
|
||||
spin_unlock_irqrestore(&ec->lock, flags);
|
||||
return guarded;
|
||||
}
|
||||
@ -603,16 +622,26 @@ static int ec_transaction_completed(struct acpi_ec *ec)
|
||||
static inline void ec_transaction_transition(struct acpi_ec *ec, unsigned long flag)
|
||||
{
|
||||
ec->curr->flags |= flag;
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS &&
|
||||
flag == ACPI_EC_COMMAND_POLL)
|
||||
acpi_ec_complete_query(ec);
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY &&
|
||||
flag == ACPI_EC_COMMAND_COMPLETE)
|
||||
acpi_ec_complete_query(ec);
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT &&
|
||||
flag == ACPI_EC_COMMAND_COMPLETE)
|
||||
set_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags);
|
||||
|
||||
if (ec->curr->command != ACPI_EC_COMMAND_QUERY)
|
||||
return;
|
||||
|
||||
switch (ec_event_clearing) {
|
||||
case ACPI_EC_EVT_TIMING_STATUS:
|
||||
if (flag == ACPI_EC_COMMAND_POLL)
|
||||
acpi_ec_close_event(ec);
|
||||
|
||||
return;
|
||||
|
||||
case ACPI_EC_EVT_TIMING_QUERY:
|
||||
if (flag == ACPI_EC_COMMAND_COMPLETE)
|
||||
acpi_ec_close_event(ec);
|
||||
|
||||
return;
|
||||
|
||||
case ACPI_EC_EVT_TIMING_EVENT:
|
||||
if (flag == ACPI_EC_COMMAND_COMPLETE)
|
||||
acpi_ec_complete_event(ec);
|
||||
}
|
||||
}
|
||||
|
||||
@ -626,10 +655,11 @@ static void acpi_ec_spurious_interrupt(struct acpi_ec *ec, struct transaction *t
|
||||
acpi_ec_mask_events(ec);
|
||||
}
|
||||
|
||||
static void advance_transaction(struct acpi_ec *ec, bool interrupt)
|
||||
static bool advance_transaction(struct acpi_ec *ec, bool interrupt)
|
||||
{
|
||||
struct transaction *t = ec->curr;
|
||||
bool wakeup = false;
|
||||
bool ret = false;
|
||||
u8 status;
|
||||
|
||||
ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id());
|
||||
@ -657,11 +687,9 @@ static void advance_transaction(struct acpi_ec *ec, bool interrupt)
|
||||
*/
|
||||
if (!t || !(t->flags & ACPI_EC_COMMAND_POLL)) {
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT &&
|
||||
(!ec->nr_pending_queries ||
|
||||
test_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags))) {
|
||||
clear_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags);
|
||||
acpi_ec_complete_query(ec);
|
||||
}
|
||||
ec->event_state == EC_EVENT_COMPLETE)
|
||||
acpi_ec_close_event(ec);
|
||||
|
||||
if (!t)
|
||||
goto out;
|
||||
}
|
||||
@ -696,10 +724,12 @@ static void advance_transaction(struct acpi_ec *ec, bool interrupt)
|
||||
|
||||
out:
|
||||
if (status & ACPI_EC_FLAG_SCI)
|
||||
acpi_ec_submit_query(ec);
|
||||
ret = acpi_ec_submit_event(ec);
|
||||
|
||||
if (wakeup && interrupt)
|
||||
wake_up(&ec->wait);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void start_transaction(struct acpi_ec *ec)
|
||||
@ -1103,7 +1133,30 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
||||
|
||||
static struct acpi_ec_query *acpi_ec_create_query(u8 *pval)
|
||||
static void acpi_ec_event_processor(struct work_struct *work)
|
||||
{
|
||||
struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work);
|
||||
struct acpi_ec_query_handler *handler = q->handler;
|
||||
struct acpi_ec *ec = q->ec;
|
||||
|
||||
ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
|
||||
|
||||
if (handler->func)
|
||||
handler->func(handler->data);
|
||||
else if (handler->handle)
|
||||
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
||||
|
||||
ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
|
||||
|
||||
spin_lock_irq(&ec->lock);
|
||||
ec->queries_in_progress--;
|
||||
spin_unlock_irq(&ec->lock);
|
||||
|
||||
acpi_ec_put_query_handler(handler);
|
||||
kfree(q);
|
||||
}
|
||||
|
||||
static struct acpi_ec_query *acpi_ec_create_query(struct acpi_ec *ec, u8 *pval)
|
||||
{
|
||||
struct acpi_ec_query *q;
|
||||
struct transaction *t;
|
||||
@ -1111,44 +1164,23 @@ static struct acpi_ec_query *acpi_ec_create_query(u8 *pval)
|
||||
q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL);
|
||||
if (!q)
|
||||
return NULL;
|
||||
|
||||
INIT_WORK(&q->work, acpi_ec_event_processor);
|
||||
t = &q->transaction;
|
||||
t->command = ACPI_EC_COMMAND_QUERY;
|
||||
t->rdata = pval;
|
||||
t->rlen = 1;
|
||||
q->ec = ec;
|
||||
return q;
|
||||
}
|
||||
|
||||
static void acpi_ec_delete_query(struct acpi_ec_query *q)
|
||||
{
|
||||
if (q) {
|
||||
if (q->handler)
|
||||
acpi_ec_put_query_handler(q->handler);
|
||||
kfree(q);
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_ec_event_processor(struct work_struct *work)
|
||||
{
|
||||
struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work);
|
||||
struct acpi_ec_query_handler *handler = q->handler;
|
||||
|
||||
ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
|
||||
if (handler->func)
|
||||
handler->func(handler->data);
|
||||
else if (handler->handle)
|
||||
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
||||
ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
|
||||
acpi_ec_delete_query(q);
|
||||
}
|
||||
|
||||
static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
|
||||
static int acpi_ec_submit_query(struct acpi_ec *ec)
|
||||
{
|
||||
struct acpi_ec_query *q;
|
||||
u8 value = 0;
|
||||
int result;
|
||||
struct acpi_ec_query *q;
|
||||
|
||||
q = acpi_ec_create_query(&value);
|
||||
q = acpi_ec_create_query(ec, &value);
|
||||
if (!q)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1158,11 +1190,14 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
|
||||
* bit to be cleared (and thus clearing the interrupt source).
|
||||
*/
|
||||
result = acpi_ec_transaction(ec, &q->transaction);
|
||||
if (!value)
|
||||
result = -ENODATA;
|
||||
if (result)
|
||||
goto err_exit;
|
||||
|
||||
if (!value) {
|
||||
result = -ENODATA;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
q->handler = acpi_ec_get_query_handler_by_value(ec, value);
|
||||
if (!q->handler) {
|
||||
result = -ENODATA;
|
||||
@ -1170,76 +1205,73 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
|
||||
}
|
||||
|
||||
/*
|
||||
* It is reported that _Qxx are evaluated in a parallel way on
|
||||
* Windows:
|
||||
* It is reported that _Qxx are evaluated in a parallel way on Windows:
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=94411
|
||||
*
|
||||
* Put this log entry before schedule_work() in order to make
|
||||
* it appearing before any other log entries occurred during the
|
||||
* work queue execution.
|
||||
* Put this log entry before queue_work() to make it appear in the log
|
||||
* before any other messages emitted during workqueue handling.
|
||||
*/
|
||||
ec_dbg_evt("Query(0x%02x) scheduled", value);
|
||||
if (!queue_work(ec_query_wq, &q->work)) {
|
||||
ec_dbg_evt("Query(0x%02x) overlapped", value);
|
||||
result = -EBUSY;
|
||||
}
|
||||
|
||||
spin_lock_irq(&ec->lock);
|
||||
|
||||
ec->queries_in_progress++;
|
||||
queue_work(ec_query_wq, &q->work);
|
||||
|
||||
spin_unlock_irq(&ec->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
if (result)
|
||||
acpi_ec_delete_query(q);
|
||||
if (data)
|
||||
*data = value;
|
||||
kfree(q);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void acpi_ec_check_event(struct acpi_ec *ec)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT) {
|
||||
if (ec_guard(ec)) {
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
/*
|
||||
* Take care of the SCI_EVT unless no one else is
|
||||
* taking care of it.
|
||||
*/
|
||||
if (!ec->curr)
|
||||
advance_transaction(ec, false);
|
||||
spin_unlock_irqrestore(&ec->lock, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_ec_event_handler(struct work_struct *work)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct acpi_ec *ec = container_of(work, struct acpi_ec, work);
|
||||
|
||||
ec_dbg_evt("Event started");
|
||||
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
while (ec->nr_pending_queries) {
|
||||
spin_unlock_irqrestore(&ec->lock, flags);
|
||||
(void)acpi_ec_query(ec, NULL);
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
ec->nr_pending_queries--;
|
||||
/*
|
||||
* Before exit, make sure that this work item can be
|
||||
* scheduled again. There might be QR_EC failures, leaving
|
||||
* EC_FLAGS_QUERY_PENDING uncleared and preventing this work
|
||||
* item from being scheduled again.
|
||||
*/
|
||||
if (!ec->nr_pending_queries) {
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS ||
|
||||
ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY)
|
||||
acpi_ec_complete_query(ec);
|
||||
}
|
||||
spin_lock_irq(&ec->lock);
|
||||
|
||||
while (ec->events_to_process) {
|
||||
spin_unlock_irq(&ec->lock);
|
||||
|
||||
acpi_ec_submit_query(ec);
|
||||
|
||||
spin_lock_irq(&ec->lock);
|
||||
ec->events_to_process--;
|
||||
}
|
||||
spin_unlock_irqrestore(&ec->lock, flags);
|
||||
|
||||
/*
|
||||
* Before exit, make sure that the it will be possible to queue up the
|
||||
* event handling work again regardless of whether or not the query
|
||||
* queued up above is processed successfully.
|
||||
*/
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT)
|
||||
acpi_ec_complete_event(ec);
|
||||
else
|
||||
acpi_ec_close_event(ec);
|
||||
|
||||
spin_unlock_irq(&ec->lock);
|
||||
|
||||
ec_dbg_evt("Event stopped");
|
||||
|
||||
acpi_ec_check_event(ec);
|
||||
if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && ec_guard(ec)) {
|
||||
spin_lock_irq(&ec->lock);
|
||||
|
||||
/* Take care of SCI_EVT unless someone else is doing that. */
|
||||
if (!ec->curr)
|
||||
advance_transaction(ec, false);
|
||||
|
||||
spin_unlock_irq(&ec->lock);
|
||||
}
|
||||
|
||||
spin_lock_irq(&ec->lock);
|
||||
ec->events_in_progress--;
|
||||
spin_unlock_irq(&ec->lock);
|
||||
}
|
||||
|
||||
static void acpi_ec_handle_interrupt(struct acpi_ec *ec)
|
||||
@ -2021,7 +2053,7 @@ void acpi_ec_set_gpe_wake_mask(u8 action)
|
||||
|
||||
bool acpi_ec_dispatch_gpe(void)
|
||||
{
|
||||
u32 ret;
|
||||
bool work_in_progress = false;
|
||||
|
||||
if (!first_ec)
|
||||
return acpi_any_gpe_status_set(U32_MAX);
|
||||
@ -2037,12 +2069,31 @@ bool acpi_ec_dispatch_gpe(void)
|
||||
* Dispatch the EC GPE in-band, but do not report wakeup in any case
|
||||
* to allow the caller to process events properly after that.
|
||||
*/
|
||||
ret = acpi_dispatch_gpe(NULL, first_ec->gpe);
|
||||
if (ret == ACPI_INTERRUPT_HANDLED)
|
||||
pm_pr_dbg("ACPI EC GPE dispatched\n");
|
||||
spin_lock_irq(&first_ec->lock);
|
||||
|
||||
/* Flush the event and query workqueues. */
|
||||
acpi_ec_flush_work();
|
||||
if (acpi_ec_gpe_status_set(first_ec))
|
||||
work_in_progress = advance_transaction(first_ec, false);
|
||||
|
||||
spin_unlock_irq(&first_ec->lock);
|
||||
|
||||
if (!work_in_progress)
|
||||
return false;
|
||||
|
||||
pm_pr_dbg("ACPI EC GPE dispatched\n");
|
||||
|
||||
/* Drain EC work. */
|
||||
do {
|
||||
acpi_ec_flush_work();
|
||||
|
||||
pm_pr_dbg("ACPI EC work flushed\n");
|
||||
|
||||
spin_lock_irq(&first_ec->lock);
|
||||
|
||||
work_in_progress = first_ec->events_in_progress +
|
||||
first_ec->queries_in_progress > 0;
|
||||
|
||||
spin_unlock_irq(&first_ec->lock);
|
||||
} while (work_in_progress && !pm_wakeup_pending());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ MODULE_DESCRIPTION("ACPI EC sysfs access driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static bool write_support;
|
||||
module_param(write_support, bool, 0644);
|
||||
module_param_hw(write_support, bool, other, 0644);
|
||||
MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may "
|
||||
"be needed.");
|
||||
|
||||
|
@ -166,6 +166,13 @@ static inline void acpi_early_processor_osc(void) {}
|
||||
/* --------------------------------------------------------------------------
|
||||
Embedded Controller
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
enum acpi_ec_event_state {
|
||||
EC_EVENT_READY = 0, /* Event work can be submitted */
|
||||
EC_EVENT_IN_PROGRESS, /* Event work is pending or being processed */
|
||||
EC_EVENT_COMPLETE, /* Event work processing has completed */
|
||||
};
|
||||
|
||||
struct acpi_ec {
|
||||
acpi_handle handle;
|
||||
int gpe;
|
||||
@ -182,7 +189,10 @@ struct acpi_ec {
|
||||
spinlock_t lock;
|
||||
struct work_struct work;
|
||||
unsigned long timestamp;
|
||||
unsigned long nr_pending_queries;
|
||||
enum acpi_ec_event_state event_state;
|
||||
unsigned int events_to_process;
|
||||
unsigned int events_in_progress;
|
||||
unsigned int queries_in_progress;
|
||||
bool busy_polling;
|
||||
unsigned int polling_guard;
|
||||
};
|
||||
|
@ -254,9 +254,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
|
||||
}
|
||||
if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
|
||||
goto out_err;
|
||||
hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
|
||||
if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
|
||||
goto out_err;
|
||||
hotpluggable = IS_ENABLED(CONFIG_MEMORY_HOTPLUG) &&
|
||||
(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE);
|
||||
|
||||
start = ma->base_address;
|
||||
end = start + ma->length;
|
||||
|
@ -606,12 +606,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
|
||||
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
|
||||
int *polarity, char **name)
|
||||
{
|
||||
int result;
|
||||
struct acpi_device *device;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
struct acpi_pci_link *link;
|
||||
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
if (result) {
|
||||
if (!device) {
|
||||
acpi_handle_err(handle, "Invalid link device\n");
|
||||
return -1;
|
||||
}
|
||||
@ -658,12 +656,10 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
|
||||
*/
|
||||
int acpi_pci_link_free_irq(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
struct acpi_pci_link *link;
|
||||
acpi_status result;
|
||||
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
if (result) {
|
||||
if (!device) {
|
||||
acpi_handle_err(handle, "Invalid link device\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -67,11 +67,10 @@ static struct acpi_scan_handler pci_root_handler = {
|
||||
*/
|
||||
int acpi_is_root_bridge(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
int ret;
|
||||
struct acpi_device *device;
|
||||
|
||||
ret = acpi_bus_get_device(handle, &device);
|
||||
if (ret)
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
ret = acpi_match_device_ids(device, root_device_ids);
|
||||
@ -215,11 +214,10 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
|
||||
|
||||
struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
struct acpi_pci_root *root;
|
||||
struct acpi_device *device;
|
||||
|
||||
if (acpi_bus_get_device(handle, &device) ||
|
||||
acpi_match_device_ids(device, root_device_ids))
|
||||
if (!device || acpi_match_device_ids(device, root_device_ids))
|
||||
return NULL;
|
||||
|
||||
root = acpi_driver_data(device);
|
||||
@ -324,7 +322,7 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
|
||||
* acpi_pci_osc_control_set - Request control of PCI root _OSC features.
|
||||
* @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex).
|
||||
* @mask: Mask of _OSC bits to request control of, place to store control mask.
|
||||
* @req: Mask of _OSC bits the control of is essential to the caller.
|
||||
* @support: _OSC supported capability.
|
||||
*
|
||||
* Run _OSC query for @mask and if that is successful, compare the returned
|
||||
* mask of control bits with @req. If all of the @req bits are set in the
|
||||
|
@ -25,7 +25,7 @@ struct intel_pmic_opregion {
|
||||
struct mutex lock;
|
||||
struct acpi_lpat_conversion_table *lpat_table;
|
||||
struct regmap *regmap;
|
||||
struct intel_pmic_opregion_data *data;
|
||||
const struct intel_pmic_opregion_data *data;
|
||||
struct intel_pmic_regs_handler_ctx ctx;
|
||||
};
|
||||
|
||||
@ -53,7 +53,7 @@ static acpi_status intel_pmic_power_handler(u32 function,
|
||||
{
|
||||
struct intel_pmic_opregion *opregion = region_context;
|
||||
struct regmap *regmap = opregion->regmap;
|
||||
struct intel_pmic_opregion_data *d = opregion->data;
|
||||
const struct intel_pmic_opregion_data *d = opregion->data;
|
||||
int reg, bit, result;
|
||||
|
||||
if (bits != 32 || !value64)
|
||||
@ -95,7 +95,7 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion,
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp = acpi_lpat_raw_to_temp(opregion->lpat_table, raw_temp);
|
||||
temp = opregion->data->lpat_raw_to_temp(opregion->lpat_table, raw_temp);
|
||||
if (temp < 0)
|
||||
return temp;
|
||||
|
||||
@ -135,7 +135,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
|
||||
static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
|
||||
int bit, u32 function, u64 *value)
|
||||
{
|
||||
struct intel_pmic_opregion_data *d = opregion->data;
|
||||
const struct intel_pmic_opregion_data *d = opregion->data;
|
||||
struct regmap *regmap = opregion->regmap;
|
||||
|
||||
if (!d->get_policy || !d->update_policy)
|
||||
@ -171,7 +171,7 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
|
||||
void *handler_context, void *region_context)
|
||||
{
|
||||
struct intel_pmic_opregion *opregion = region_context;
|
||||
struct intel_pmic_opregion_data *d = opregion->data;
|
||||
const struct intel_pmic_opregion_data *d = opregion->data;
|
||||
int reg, bit, result;
|
||||
|
||||
if (bits != 32 || !value64)
|
||||
@ -255,7 +255,7 @@ static acpi_status intel_pmic_regs_handler(u32 function,
|
||||
|
||||
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
|
||||
struct regmap *regmap,
|
||||
struct intel_pmic_opregion_data *d)
|
||||
const struct intel_pmic_opregion_data *d)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct intel_pmic_opregion *opregion;
|
||||
@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);
|
||||
int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
|
||||
u32 value, u32 mask)
|
||||
{
|
||||
struct intel_pmic_opregion_data *d;
|
||||
const struct intel_pmic_opregion_data *d;
|
||||
int ret;
|
||||
|
||||
if (!intel_pmic_opregion) {
|
||||
|
@ -2,6 +2,8 @@
|
||||
#ifndef __INTEL_PMIC_H
|
||||
#define __INTEL_PMIC_H
|
||||
|
||||
#include <acpi/acpi_lpat.h>
|
||||
|
||||
struct pmic_table {
|
||||
int address; /* operation region address */
|
||||
int reg; /* corresponding thermal register */
|
||||
@ -17,6 +19,8 @@ struct intel_pmic_opregion_data {
|
||||
int (*update_policy)(struct regmap *r, int reg, int bit, int enable);
|
||||
int (*exec_mipi_pmic_seq_element)(struct regmap *r, u16 i2c_address,
|
||||
u32 reg_address, u32 value, u32 mask);
|
||||
int (*lpat_raw_to_temp)(struct acpi_lpat_conversion_table *lpat_table,
|
||||
int raw);
|
||||
struct pmic_table *power_table;
|
||||
int power_table_count;
|
||||
struct pmic_table *thermal_table;
|
||||
@ -25,6 +29,8 @@ struct intel_pmic_opregion_data {
|
||||
int pmic_i2c_address;
|
||||
};
|
||||
|
||||
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, struct regmap *regmap, struct intel_pmic_opregion_data *d);
|
||||
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
|
||||
struct regmap *regmap,
|
||||
const struct intel_pmic_opregion_data *d);
|
||||
|
||||
#endif
|
||||
|
@ -369,13 +369,14 @@ intel_bxtwc_pmic_update_policy(struct regmap *regmap,
|
||||
return regmap_update_bits(regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
static struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = {
|
||||
static const struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = {
|
||||
.get_power = intel_bxtwc_pmic_get_power,
|
||||
.update_power = intel_bxtwc_pmic_update_power,
|
||||
.get_raw_temp = intel_bxtwc_pmic_get_raw_temp,
|
||||
.update_aux = intel_bxtwc_pmic_update_aux,
|
||||
.get_policy = intel_bxtwc_pmic_get_policy,
|
||||
.update_policy = intel_bxtwc_pmic_update_policy,
|
||||
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
|
||||
.power_table = power_table,
|
||||
.power_table_count = ARRAY_SIZE(power_table),
|
||||
.thermal_table = thermal_table,
|
||||
|
@ -271,13 +271,14 @@ static int intel_crc_pmic_update_policy(struct regmap *regmap,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = {
|
||||
static const struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = {
|
||||
.get_power = intel_crc_pmic_get_power,
|
||||
.update_power = intel_crc_pmic_update_power,
|
||||
.get_raw_temp = intel_crc_pmic_get_raw_temp,
|
||||
.update_aux = intel_crc_pmic_update_aux,
|
||||
.get_policy = intel_crc_pmic_get_policy,
|
||||
.update_policy = intel_crc_pmic_update_policy,
|
||||
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
|
||||
.power_table = power_table,
|
||||
.power_table_count= ARRAY_SIZE(power_table),
|
||||
.thermal_table = thermal_table,
|
||||
|
@ -23,7 +23,8 @@
|
||||
* intel_soc_pmic_exec_mipi_pmic_seq_element work on devices with a
|
||||
* CHT Crystal Cove PMIC.
|
||||
*/
|
||||
static struct intel_pmic_opregion_data intel_chtcrc_pmic_opregion_data = {
|
||||
static const struct intel_pmic_opregion_data intel_chtcrc_pmic_opregion_data = {
|
||||
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
|
||||
.pmic_i2c_address = 0x6e,
|
||||
};
|
||||
|
||||
|
@ -94,10 +94,11 @@ static int chtdc_ti_pmic_get_raw_temp(struct regmap *regmap, int reg)
|
||||
return ((buf[0] & 0x03) << 8) | buf[1];
|
||||
}
|
||||
|
||||
static struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = {
|
||||
static const struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = {
|
||||
.get_power = chtdc_ti_pmic_get_power,
|
||||
.update_power = chtdc_ti_pmic_update_power,
|
||||
.get_raw_temp = chtdc_ti_pmic_get_raw_temp,
|
||||
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
|
||||
.power_table = chtdc_ti_power_table,
|
||||
.power_table_count = ARRAY_SIZE(chtdc_ti_power_table),
|
||||
.thermal_table = chtdc_ti_thermal_table,
|
||||
|
@ -253,10 +253,11 @@ static int intel_cht_wc_exec_mipi_pmic_seq_element(struct regmap *regmap,
|
||||
* The thermal table and ops are empty, we do not support the Thermal opregion
|
||||
* (DPTF) due to lacking documentation.
|
||||
*/
|
||||
static struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
|
||||
static const struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
|
||||
.get_power = intel_cht_wc_pmic_get_power,
|
||||
.update_power = intel_cht_wc_pmic_update_power,
|
||||
.exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element,
|
||||
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
|
||||
.power_table = power_table,
|
||||
.power_table_count = ARRAY_SIZE(power_table),
|
||||
};
|
||||
|
@ -293,11 +293,33 @@ static int intel_xpower_exec_mipi_pmic_seq_element(struct regmap *regmap,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = {
|
||||
static int intel_xpower_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table,
|
||||
int raw)
|
||||
{
|
||||
struct acpi_lpat first = lpat_table->lpat[0];
|
||||
struct acpi_lpat last = lpat_table->lpat[lpat_table->lpat_count - 1];
|
||||
|
||||
/*
|
||||
* Some LPAT tables in the ACPI Device for the AXP288 PMIC for some
|
||||
* reason only describe a small temperature range, e.g. 27° - 37°
|
||||
* Celcius. Resulting in errors when the tablet is idle in a cool room.
|
||||
*
|
||||
* To avoid these errors clamp the raw value to be inside the LPAT.
|
||||
*/
|
||||
if (first.raw < last.raw)
|
||||
raw = clamp(raw, first.raw, last.raw);
|
||||
else
|
||||
raw = clamp(raw, last.raw, first.raw);
|
||||
|
||||
return acpi_lpat_raw_to_temp(lpat_table, raw);
|
||||
}
|
||||
|
||||
static const struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = {
|
||||
.get_power = intel_xpower_pmic_get_power,
|
||||
.update_power = intel_xpower_pmic_update_power,
|
||||
.get_raw_temp = intel_xpower_pmic_get_raw_temp,
|
||||
.exec_mipi_pmic_seq_element = intel_xpower_exec_mipi_pmic_seq_element,
|
||||
.lpat_raw_to_temp = intel_xpower_lpat_raw_to_temp,
|
||||
.power_table = power_table,
|
||||
.power_table_count = ARRAY_SIZE(power_table),
|
||||
.thermal_table = thermal_table,
|
||||
|
@ -81,9 +81,9 @@ struct acpi_power_resource *to_power_resource(struct acpi_device *device)
|
||||
|
||||
static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
|
||||
if (acpi_bus_get_device(handle, &device))
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
return to_power_resource(device);
|
||||
@ -716,6 +716,9 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
||||
|
||||
mutex_lock(&acpi_device_lock);
|
||||
|
||||
dev_dbg(&dev->dev, "Enabling wakeup power (count %d)\n",
|
||||
dev->wakeup.prepare_count);
|
||||
|
||||
if (dev->wakeup.prepare_count++)
|
||||
goto out;
|
||||
|
||||
@ -734,8 +737,11 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
||||
if (err) {
|
||||
acpi_power_off_list(&dev->wakeup.resources);
|
||||
dev->wakeup.prepare_count = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, "Wakeup power enabled\n");
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
return err;
|
||||
@ -757,6 +763,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
|
||||
|
||||
mutex_lock(&acpi_device_lock);
|
||||
|
||||
dev_dbg(&dev->dev, "Disabling wakeup power (count %d)\n",
|
||||
dev->wakeup.prepare_count);
|
||||
|
||||
/* Do nothing if wakeup power has not been enabled for this device. */
|
||||
if (dev->wakeup.prepare_count <= 0)
|
||||
goto out;
|
||||
@ -782,8 +791,11 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "Cannot turn off wakeup power resources\n");
|
||||
dev->wakeup.flags.valid = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, "Wakeup power disabled\n");
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
return err;
|
||||
@ -916,15 +928,14 @@ static void acpi_power_add_resource_to_list(struct acpi_power_resource *resource
|
||||
|
||||
struct acpi_device *acpi_add_power_resource(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
struct acpi_power_resource *resource;
|
||||
struct acpi_device *device = NULL;
|
||||
union acpi_object acpi_object;
|
||||
struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
|
||||
acpi_status status;
|
||||
u8 state_dummy;
|
||||
int result;
|
||||
|
||||
acpi_bus_get_device(handle, &device);
|
||||
if (device)
|
||||
return device;
|
||||
|
||||
|
@ -98,8 +98,13 @@ static int acpi_soft_cpu_online(unsigned int cpu)
|
||||
struct acpi_processor *pr = per_cpu(processors, cpu);
|
||||
struct acpi_device *device;
|
||||
|
||||
if (!pr || acpi_bus_get_device(pr->handle, &device))
|
||||
if (!pr)
|
||||
return 0;
|
||||
|
||||
device = acpi_fetch_acpi_dev(pr->handle);
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* CPU got physically hotplugged and onlined for the first time:
|
||||
* Initialize missing things.
|
||||
@ -125,9 +130,8 @@ static int acpi_soft_cpu_online(unsigned int cpu)
|
||||
static int acpi_soft_cpu_dead(unsigned int cpu)
|
||||
{
|
||||
struct acpi_processor *pr = per_cpu(processors, cpu);
|
||||
struct acpi_device *device;
|
||||
|
||||
if (!pr || acpi_bus_get_device(pr->handle, &device))
|
||||
if (!pr || !acpi_fetch_acpi_dev(pr->handle))
|
||||
return 0;
|
||||
|
||||
acpi_processor_reevaluate_tstate(pr, true);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/tick.h>
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <acpi/processor.h>
|
||||
|
||||
/*
|
||||
@ -400,13 +401,10 @@ static int acpi_cst_latency_cmp(const void *a, const void *b)
|
||||
static void acpi_cst_latency_swap(void *a, void *b, int n)
|
||||
{
|
||||
struct acpi_processor_cx *x = a, *y = b;
|
||||
u32 tmp;
|
||||
|
||||
if (!(x->valid && y->valid))
|
||||
return;
|
||||
tmp = x->latency;
|
||||
x->latency = y->latency;
|
||||
y->latency = tmp;
|
||||
swap(x->latency, y->latency);
|
||||
}
|
||||
|
||||
static int acpi_processor_power_verify(struct acpi_processor *pr)
|
||||
@ -567,7 +565,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
|
||||
{
|
||||
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
|
||||
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
if (cx->type == ACPI_STATE_C3)
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
|
||||
while (1) {
|
||||
|
||||
@ -1101,7 +1100,7 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
|
||||
|
||||
status = acpi_get_parent(handle, &pr_ahandle);
|
||||
while (ACPI_SUCCESS(status)) {
|
||||
acpi_bus_get_device(pr_ahandle, &d);
|
||||
d = acpi_fetch_acpi_dev(pr_ahandle);
|
||||
handle = pr_ahandle;
|
||||
|
||||
if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID))
|
||||
|
@ -53,10 +53,17 @@ static int phys_package_first_cpu(int cpu)
|
||||
|
||||
static int cpu_has_cpufreq(unsigned int cpu)
|
||||
{
|
||||
struct cpufreq_policy policy;
|
||||
if (!acpi_processor_cpufreq_init || cpufreq_get_policy(&policy, cpu))
|
||||
struct cpufreq_policy *policy;
|
||||
|
||||
if (!acpi_processor_cpufreq_init)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
policy = cpufreq_cpu_get(cpu);
|
||||
if (policy) {
|
||||
cpufreq_cpu_put(policy);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpufreq_get_max_state(unsigned int cpu)
|
||||
|
@ -687,9 +687,9 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
|
||||
if (index)
|
||||
return -EINVAL;
|
||||
|
||||
ret = acpi_bus_get_device(obj->reference.handle, &device);
|
||||
if (ret)
|
||||
return ret == -ENODEV ? -EINVAL : ret;
|
||||
device = acpi_fetch_acpi_dev(obj->reference.handle);
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
args->fwnode = acpi_fwnode_handle(device);
|
||||
args->nargs = 0;
|
||||
@ -719,9 +719,8 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
|
||||
if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
struct fwnode_handle *ref_fwnode;
|
||||
|
||||
ret = acpi_bus_get_device(element->reference.handle,
|
||||
&device);
|
||||
if (ret)
|
||||
device = acpi_fetch_acpi_dev(element->reference.handle);
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
nargs = 0;
|
||||
|
@ -791,9 +791,9 @@ static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,
|
||||
{
|
||||
struct resource *res = context;
|
||||
struct acpi_device **consumer = (struct acpi_device **) ret;
|
||||
struct acpi_device *adev;
|
||||
struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
|
||||
|
||||
if (acpi_bus_get_device(handle, &adev))
|
||||
if (!adev)
|
||||
return AE_OK;
|
||||
|
||||
if (acpi_dev_consumes_res(adev, res)) {
|
||||
|
@ -135,12 +135,12 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
|
||||
static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
|
||||
void **ret_p)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
struct acpi_device_physical_node *pn;
|
||||
bool second_pass = (bool)data;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
if (acpi_bus_get_device(handle, &device))
|
||||
if (!device)
|
||||
return AE_OK;
|
||||
|
||||
if (device->handler && !device->handler->hotplug.enabled) {
|
||||
@ -180,10 +180,10 @@ static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
|
||||
static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data,
|
||||
void **ret_p)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
struct acpi_device_physical_node *pn;
|
||||
|
||||
if (acpi_bus_get_device(handle, &device))
|
||||
if (!device)
|
||||
return AE_OK;
|
||||
|
||||
mutex_lock(&device->physical_node_lock);
|
||||
@ -599,6 +599,19 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_get_device);
|
||||
|
||||
/**
|
||||
* acpi_fetch_acpi_dev - Retrieve ACPI device object.
|
||||
* @handle: ACPI handle associated with the requested ACPI device object.
|
||||
*
|
||||
* Return a pointer to the ACPI device object associated with @handle, if
|
||||
* present, or NULL otherwise.
|
||||
*/
|
||||
struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle)
|
||||
{
|
||||
return handle_to_device(handle, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_fetch_acpi_dev);
|
||||
|
||||
static void get_acpi_device(void *dev)
|
||||
{
|
||||
acpi_dev_get(dev);
|
||||
@ -805,7 +818,7 @@ static const char * const acpi_honor_dep_ids[] = {
|
||||
|
||||
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_device *device;
|
||||
acpi_status status;
|
||||
|
||||
/*
|
||||
@ -820,7 +833,9 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
|
||||
status = acpi_get_parent(handle, &handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status == AE_NULL_ENTRY ? NULL : acpi_root;
|
||||
} while (acpi_bus_get_device(handle, &device));
|
||||
|
||||
device = acpi_fetch_acpi_dev(handle);
|
||||
} while (!device);
|
||||
return device;
|
||||
}
|
||||
|
||||
@ -1346,11 +1361,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
|
||||
if (info->valid & ACPI_VALID_HID) {
|
||||
acpi_add_id(pnp, info->hardware_id.string);
|
||||
pnp->type.platform_id = 1;
|
||||
}
|
||||
if (info->valid & ACPI_VALID_CID) {
|
||||
cid_list = &info->compatible_id_list;
|
||||
for (i = 0; i < cid_list->count; i++)
|
||||
acpi_add_id(pnp, cid_list->ids[i].string);
|
||||
if (info->valid & ACPI_VALID_CID) {
|
||||
cid_list = &info->compatible_id_list;
|
||||
for (i = 0; i < cid_list->count; i++)
|
||||
acpi_add_id(pnp, cid_list->ids[i].string);
|
||||
}
|
||||
}
|
||||
if (info->valid & ACPI_VALID_ADR) {
|
||||
pnp->bus_address = info->address;
|
||||
@ -1701,6 +1716,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
|
||||
{
|
||||
struct list_head resource_list;
|
||||
bool is_serial_bus_slave = false;
|
||||
static const struct acpi_device_id ignore_serial_bus_ids[] = {
|
||||
/*
|
||||
* These devices have multiple I2cSerialBus resources and an i2c-client
|
||||
* must be instantiated for each, each with its own i2c_device_id.
|
||||
@ -1709,11 +1725,18 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
|
||||
* drivers/platform/x86/i2c-multi-instantiate.c driver, which knows
|
||||
* which i2c_device_id to use for each resource.
|
||||
*/
|
||||
static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
|
||||
{"BSG1160", },
|
||||
{"BSG2150", },
|
||||
{"INT33FE", },
|
||||
{"INT3515", },
|
||||
/*
|
||||
* HIDs of device with an UartSerialBusV2 resource for which userspace
|
||||
* expects a regular tty cdev to be created (instead of the in kernel
|
||||
* serdev) and which have a kernel driver which expects a platform_dev
|
||||
* such as the rfkill-gpio driver.
|
||||
*/
|
||||
{"BCM4752", },
|
||||
{"LNV4752", },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -1727,8 +1750,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
|
||||
fwnode_property_present(&device->fwnode, "baud")))
|
||||
return true;
|
||||
|
||||
/* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */
|
||||
if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids))
|
||||
if (!acpi_match_device_ids(device, ignore_serial_bus_ids))
|
||||
return false;
|
||||
|
||||
INIT_LIST_HEAD(&resource_list);
|
||||
@ -2015,11 +2037,10 @@ static bool acpi_bus_scan_second_pass;
|
||||
static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
|
||||
struct acpi_device **adev_p)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
|
||||
acpi_object_type acpi_type;
|
||||
int type;
|
||||
|
||||
acpi_bus_get_device(handle, &device);
|
||||
if (device)
|
||||
goto out;
|
||||
|
||||
@ -2577,8 +2598,8 @@ int __init acpi_scan_init(void)
|
||||
if (result)
|
||||
goto out;
|
||||
|
||||
result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root);
|
||||
if (result)
|
||||
acpi_root = acpi_fetch_acpi_dev(ACPI_ROOT_OBJECT);
|
||||
if (!acpi_root)
|
||||
goto out;
|
||||
|
||||
/* Fixed feature devices do not exist on HW-reduced platform */
|
||||
|
@ -73,7 +73,6 @@ static int acpi_sleep_prepare(u32 acpi_state)
|
||||
acpi_set_waking_vector(acpi_wakeup_address);
|
||||
|
||||
}
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
#endif
|
||||
pr_info("Preparing to enter system sleep state S%d\n", acpi_state);
|
||||
acpi_enable_wakeup_devices(acpi_state);
|
||||
@ -566,8 +565,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
|
||||
u32 acpi_state = acpi_target_sleep_state;
|
||||
int error;
|
||||
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
|
||||
trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true);
|
||||
switch (acpi_state) {
|
||||
case ACPI_STATE_S1:
|
||||
@ -903,8 +900,6 @@ static int acpi_hibernation_enter(void)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
|
||||
/* This shouldn't return. If it returns, we have a problem */
|
||||
status = acpi_enter_sleep_state(ACPI_STATE_S4);
|
||||
/* Reprogram control registers */
|
||||
|
@ -939,10 +939,11 @@ static struct attribute *hotplug_profile_attrs[] = {
|
||||
&hotplug_enabled_attr.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(hotplug_profile);
|
||||
|
||||
static struct kobj_type acpi_hotplug_profile_ktype = {
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
.default_attrs = hotplug_profile_attrs,
|
||||
.default_groups = hotplug_profile_groups,
|
||||
};
|
||||
|
||||
void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
|
||||
|
@ -500,7 +500,7 @@ static const char table_sigs[][ACPI_NAMESEG_SIZE] __initconst = {
|
||||
ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT,
|
||||
ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT,
|
||||
ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT,
|
||||
ACPI_SIG_NHLT };
|
||||
ACPI_SIG_NHLT, ACPI_SIG_AEST };
|
||||
|
||||
#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
|
||||
|
||||
@ -723,7 +723,7 @@ static void __init acpi_table_initrd_scan(void)
|
||||
/*
|
||||
* Mark the table to avoid being used in
|
||||
* acpi_table_initrd_override(). Though this is not possible
|
||||
* because override is disabled in acpi_install_table().
|
||||
* because override is disabled in acpi_install_physical_table().
|
||||
*/
|
||||
if (test_and_set_bit(table_index, acpi_initrd_installed)) {
|
||||
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
|
||||
@ -734,7 +734,7 @@ static void __init acpi_table_initrd_scan(void)
|
||||
table->signature, table->oem_id,
|
||||
table->oem_table_id);
|
||||
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
|
||||
acpi_install_table(acpi_tables_addr + table_offset, TRUE);
|
||||
acpi_install_physical_table(acpi_tables_addr + table_offset);
|
||||
next_table:
|
||||
table_offset += table_length;
|
||||
table_index++;
|
||||
|
@ -697,7 +697,6 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
struct acpi_thermal *tz = thermal->devdata;
|
||||
struct acpi_device *dev;
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
int i;
|
||||
int j;
|
||||
@ -715,8 +714,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
|
||||
for (i = 0; i < tz->trips.passive.devices.count;
|
||||
i++) {
|
||||
handle = tz->trips.passive.devices.handles[i];
|
||||
status = acpi_bus_get_device(handle, &dev);
|
||||
if (ACPI_FAILURE(status) || dev != device)
|
||||
dev = acpi_fetch_acpi_dev(handle);
|
||||
if (dev != device)
|
||||
continue;
|
||||
if (bind)
|
||||
result =
|
||||
@ -741,8 +740,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
|
||||
j < tz->trips.active[i].devices.count;
|
||||
j++) {
|
||||
handle = tz->trips.active[i].devices.handles[j];
|
||||
status = acpi_bus_get_device(handle, &dev);
|
||||
if (ACPI_FAILURE(status) || dev != device)
|
||||
dev = acpi_fetch_acpi_dev(handle);
|
||||
if (dev != device)
|
||||
continue;
|
||||
if (bind)
|
||||
result = thermal_zone_bind_cooling_device
|
||||
@ -1098,8 +1097,6 @@ static int acpi_thermal_resume(struct device *dev)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
|
||||
if (!(&tz->trips.active[i]))
|
||||
break;
|
||||
if (!tz->trips.active[i].flags.valid)
|
||||
break;
|
||||
tz->trips.active[i].flags.enabled = 1;
|
||||
|
@ -59,18 +59,16 @@ static void acpi_video_parse_cmdline(void)
|
||||
static acpi_status
|
||||
find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
struct acpi_device *acpi_dev = acpi_fetch_acpi_dev(handle);
|
||||
long *cap = context;
|
||||
struct pci_dev *dev;
|
||||
struct acpi_device *acpi_dev;
|
||||
|
||||
static const struct acpi_device_id video_ids[] = {
|
||||
{ACPI_VIDEO_HID, 0},
|
||||
{"", 0},
|
||||
};
|
||||
if (acpi_bus_get_device(handle, &acpi_dev))
|
||||
return AE_OK;
|
||||
|
||||
if (!acpi_match_device_ids(acpi_dev, video_ids)) {
|
||||
if (acpi_dev && !acpi_match_device_ids(acpi_dev, video_ids)) {
|
||||
dev = acpi_get_pci_dev(handle);
|
||||
if (!dev)
|
||||
return AE_OK;
|
||||
|
@ -293,9 +293,9 @@ static void lpi_check_constraints(void)
|
||||
|
||||
for (i = 0; i < lpi_constraints_table_size; ++i) {
|
||||
acpi_handle handle = lpi_constraints_table[i].handle;
|
||||
struct acpi_device *adev;
|
||||
struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
|
||||
|
||||
if (!handle || acpi_bus_get_device(handle, &adev))
|
||||
if (!adev)
|
||||
continue;
|
||||
|
||||
acpi_handle_debug(handle,
|
||||
|
@ -8,8 +8,11 @@
|
||||
* Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ACPI: " fmt
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include "../internal.h"
|
||||
@ -22,58 +25,77 @@
|
||||
* Some BIOS-es (temporarily) hide specific APCI devices to work around Windows
|
||||
* driver bugs. We use DMI matching to match known cases of this.
|
||||
*
|
||||
* We work around this by always reporting ACPI_STA_DEFAULT for these
|
||||
* devices. Note this MUST only be done for devices where this is safe.
|
||||
* Likewise sometimes some not-actually present devices are sometimes
|
||||
* reported as present, which may cause issues.
|
||||
*
|
||||
* This forcing of devices to be present is limited to specific CPU (SoC)
|
||||
* models both to avoid potentially causing trouble on other models and
|
||||
* because some HIDs are re-used on different SoCs for completely
|
||||
* different devices.
|
||||
* We work around this by using the below quirk list to override the status
|
||||
* reported by the _STA method with a fixed value (ACPI_STA_DEFAULT or 0).
|
||||
* Note this MUST only be done for devices where this is safe.
|
||||
*
|
||||
* This status overriding is limited to specific CPU (SoC) models both to
|
||||
* avoid potentially causing trouble on other models and because some HIDs
|
||||
* are re-used on different SoCs for completely different devices.
|
||||
*/
|
||||
struct always_present_id {
|
||||
struct override_status_id {
|
||||
struct acpi_device_id hid[2];
|
||||
struct x86_cpu_id cpu_ids[2];
|
||||
struct dmi_system_id dmi_ids[2]; /* Optional */
|
||||
const char *uid;
|
||||
const char *path;
|
||||
unsigned long long status;
|
||||
};
|
||||
|
||||
#define X86_MATCH(model) X86_MATCH_INTEL_FAM6_MODEL(model, NULL)
|
||||
|
||||
#define ENTRY(hid, uid, cpu_models, dmi...) { \
|
||||
#define ENTRY(status, hid, uid, path, cpu_model, dmi...) { \
|
||||
{ { hid, }, {} }, \
|
||||
{ cpu_models, {} }, \
|
||||
{ X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} }, \
|
||||
{ { .matches = dmi }, {} }, \
|
||||
uid, \
|
||||
path, \
|
||||
status, \
|
||||
}
|
||||
|
||||
static const struct always_present_id always_present_ids[] = {
|
||||
#define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
|
||||
ENTRY(ACPI_STA_DEFAULT, hid, uid, NULL, cpu_model, dmi)
|
||||
|
||||
#define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
|
||||
ENTRY(0, hid, uid, NULL, cpu_model, dmi)
|
||||
|
||||
#define PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
|
||||
ENTRY(ACPI_STA_DEFAULT, "", NULL, path, cpu_model, dmi)
|
||||
|
||||
#define NOT_PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
|
||||
ENTRY(0, "", NULL, path, cpu_model, dmi)
|
||||
|
||||
static const struct override_status_id override_status_ids[] = {
|
||||
/*
|
||||
* Bay / Cherry Trail PWM directly poked by GPU driver in win10,
|
||||
* but Linux uses a separate PWM driver, harmless if not used.
|
||||
*/
|
||||
ENTRY("80860F09", "1", X86_MATCH(ATOM_SILVERMONT), {}),
|
||||
ENTRY("80862288", "1", X86_MATCH(ATOM_AIRMONT), {}),
|
||||
PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}),
|
||||
PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}),
|
||||
|
||||
/* The Xiaomi Mi Pad 2 uses PWM2 for touchkeys backlight control */
|
||||
PRESENT_ENTRY_HID("80862289", "2", ATOM_AIRMONT, {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
|
||||
}),
|
||||
|
||||
/* Lenovo Yoga Book uses PWM2 for keyboard backlight control */
|
||||
ENTRY("80862289", "2", X86_MATCH(ATOM_AIRMONT), {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
|
||||
}),
|
||||
/*
|
||||
* The INT0002 device is necessary to clear wakeup interrupt sources
|
||||
* on Cherry Trail devices, without it we get nobody cared IRQ msgs.
|
||||
*/
|
||||
ENTRY("INT0002", "1", X86_MATCH(ATOM_AIRMONT), {}),
|
||||
PRESENT_ENTRY_HID("INT0002", "1", ATOM_AIRMONT, {}),
|
||||
/*
|
||||
* On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides
|
||||
* the touchscreen ACPI device until a certain time
|
||||
* after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
|
||||
* *and* _STA has been called at least 3 times since.
|
||||
*/
|
||||
ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), {
|
||||
PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
|
||||
}),
|
||||
ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), {
|
||||
PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
|
||||
}),
|
||||
@ -81,54 +103,83 @@ static const struct always_present_id always_present_ids[] = {
|
||||
/*
|
||||
* The GPD win BIOS dated 20170221 has disabled the accelerometer, the
|
||||
* drivers sometimes cause crashes under Windows and this is how the
|
||||
* manufacturer has solved this :| Note that the the DMI data is less
|
||||
* generic then it seems, a board_vendor of "AMI Corporation" is quite
|
||||
* rare and a board_name of "Default String" also is rare.
|
||||
* manufacturer has solved this :| The DMI match may not seem unique,
|
||||
* but it is. In the 67000+ DMI decode dumps from linux-hardware.org
|
||||
* only 116 have board_vendor set to "AMI Corporation" and of those 116
|
||||
* only the GPD win and pocket entries' board_name is "Default string".
|
||||
*
|
||||
* Unfortunately the GPD pocket also uses these strings and its BIOS
|
||||
* was copy-pasted from the GPD win, so it has a disabled KIOX000A
|
||||
* node which we should not enable, thus we also check the BIOS date.
|
||||
*/
|
||||
ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), {
|
||||
PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Default string"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
|
||||
DMI_MATCH(DMI_BIOS_DATE, "02/21/2017")
|
||||
}),
|
||||
ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), {
|
||||
PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Default string"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
|
||||
DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
|
||||
}),
|
||||
ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), {
|
||||
PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Default string"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
|
||||
DMI_MATCH(DMI_BIOS_DATE, "05/25/2017")
|
||||
}),
|
||||
|
||||
/*
|
||||
* The GPD win/pocket have a PCI wifi card, but its DSDT has the SDIO
|
||||
* mmc controller enabled and that has a child-device which _PS3
|
||||
* method sets a GPIO causing the PCI wifi card to turn off.
|
||||
* See above remark about uniqueness of the DMI match.
|
||||
*/
|
||||
NOT_PRESENT_ENTRY_PATH("\\_SB_.PCI0.SDHB.BRC1", ATOM_AIRMONT, {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
|
||||
}),
|
||||
};
|
||||
|
||||
bool acpi_device_always_present(struct acpi_device *adev)
|
||||
bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status)
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
|
||||
if (acpi_match_device_ids(adev, always_present_ids[i].hid))
|
||||
for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) {
|
||||
if (!x86_match_cpu(override_status_ids[i].cpu_ids))
|
||||
continue;
|
||||
|
||||
if (!adev->pnp.unique_id ||
|
||||
strcmp(adev->pnp.unique_id, always_present_ids[i].uid))
|
||||
if (override_status_ids[i].dmi_ids[0].matches[0].slot &&
|
||||
!dmi_check_system(override_status_ids[i].dmi_ids))
|
||||
continue;
|
||||
|
||||
if (!x86_match_cpu(always_present_ids[i].cpu_ids))
|
||||
continue;
|
||||
if (override_status_ids[i].path) {
|
||||
struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
bool match;
|
||||
|
||||
if (always_present_ids[i].dmi_ids[0].matches[0].slot &&
|
||||
!dmi_check_system(always_present_ids[i].dmi_ids))
|
||||
continue;
|
||||
if (acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &path))
|
||||
continue;
|
||||
|
||||
match = strcmp((char *)path.pointer, override_status_ids[i].path) == 0;
|
||||
kfree(path.pointer);
|
||||
|
||||
if (!match)
|
||||
continue;
|
||||
} else {
|
||||
if (acpi_match_device_ids(adev, override_status_ids[i].hid))
|
||||
continue;
|
||||
|
||||
if (!adev->pnp.unique_id ||
|
||||
strcmp(adev->pnp.unique_id, override_status_ids[i].uid))
|
||||
continue;
|
||||
}
|
||||
|
||||
*status = override_status_ids[i].status;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
@ -160,3 +211,183 @@ bool force_storage_d3(void)
|
||||
{
|
||||
return x86_match_cpu(storage_d3_cpu_ids);
|
||||
}
|
||||
|
||||
/*
|
||||
* x86 ACPI boards which ship with only Android as their factory image usually
|
||||
* declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes
|
||||
* there are issues with serdev devices on these boards too, e.g. the resource
|
||||
* points to the wrong serdev_controller.
|
||||
*
|
||||
* Instantiating I2C / serdev devs for these bogus devs causes various issues,
|
||||
* e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them.
|
||||
* The Android x86 kernel fork shipped on these devices has some special code
|
||||
* to remove the bogus I2C clients (and AFAICT serdevs are ignored completely).
|
||||
*
|
||||
* The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or
|
||||
* serdev code to skip instantiating any I2C or serdev devs on broken boards.
|
||||
*
|
||||
* In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids
|
||||
* list. These are known to always be correct (and in case of the audio-codecs
|
||||
* the drivers heavily rely on the codec being enumerated through ACPI).
|
||||
*
|
||||
* Note these boards typically do actually have I2C and serdev devices,
|
||||
* just different ones then the ones described in their DSDT. The devices
|
||||
* which are actually present are manually instantiated by the
|
||||
* drivers/platform/x86/x86-android-tablets.c kernel module.
|
||||
*/
|
||||
#define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0)
|
||||
#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1)
|
||||
#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2)
|
||||
#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3)
|
||||
|
||||
static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
|
||||
/*
|
||||
* 1. Devices with only the skip / don't-skip AC and battery quirks,
|
||||
* sorted alphabetically.
|
||||
*/
|
||||
{
|
||||
/* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
|
||||
},
|
||||
.driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
|
||||
},
|
||||
{
|
||||
/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
|
||||
},
|
||||
.driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
|
||||
},
|
||||
|
||||
/*
|
||||
* 2. Devices which also have the skip i2c/serdev quirks and which
|
||||
* need the x86-android-tablets module to properly work.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
|
||||
},
|
||||
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
|
||||
ACPI_QUIRK_UART1_TTY_UART2_SKIP |
|
||||
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
|
||||
},
|
||||
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
|
||||
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
|
||||
},
|
||||
{
|
||||
/* Whitelabel (sold as various brands) TM800A550L */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
|
||||
/* Above strings are too generic, also match on BIOS version */
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
|
||||
},
|
||||
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
|
||||
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
|
||||
},
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
|
||||
static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
|
||||
{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
|
||||
{ "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
|
||||
{ "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
|
||||
{ "NPCE69A", 0 }, /* Asus Transformer keyboard dock */
|
||||
{}
|
||||
};
|
||||
|
||||
bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
long quirks;
|
||||
|
||||
dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
|
||||
if (!dmi_id)
|
||||
return false;
|
||||
|
||||
quirks = (unsigned long)dmi_id->driver_data;
|
||||
if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS))
|
||||
return false;
|
||||
|
||||
return acpi_match_device_ids(adev, i2c_acpi_known_good_ids);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration);
|
||||
|
||||
int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(controller_parent);
|
||||
const struct dmi_system_id *dmi_id;
|
||||
long quirks = 0;
|
||||
|
||||
*skip = false;
|
||||
|
||||
/* !dev_is_platform() to not match on PNP enumerated debug UARTs */
|
||||
if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent))
|
||||
return 0;
|
||||
|
||||
dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
|
||||
if (dmi_id)
|
||||
quirks = (unsigned long)dmi_id->driver_data;
|
||||
|
||||
if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
|
||||
if (!strcmp(adev->pnp.unique_id, "1"))
|
||||
return -ENODEV; /* Create tty cdev instead of serdev */
|
||||
|
||||
if (!strcmp(adev->pnp.unique_id, "2"))
|
||||
*skip = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
|
||||
#endif
|
||||
|
||||
/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
|
||||
static const struct {
|
||||
const char *hid;
|
||||
int hrv;
|
||||
} acpi_skip_ac_and_battery_pmic_ids[] = {
|
||||
{ "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
|
||||
{ "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
|
||||
};
|
||||
|
||||
bool acpi_quirk_skip_acpi_ac_and_battery(void)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
long quirks = 0;
|
||||
int i;
|
||||
|
||||
dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
|
||||
if (dmi_id)
|
||||
quirks = (unsigned long)dmi_id->driver_data;
|
||||
|
||||
if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY)
|
||||
return true;
|
||||
|
||||
if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) {
|
||||
if (acpi_dev_present(acpi_skip_ac_and_battery_pmic_ids[i].hid, "1",
|
||||
acpi_skip_ac_and_battery_pmic_ids[i].hrv)) {
|
||||
pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n",
|
||||
acpi_skip_ac_and_battery_pmic_ids[i].hid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery);
|
||||
|
@ -257,6 +257,13 @@ static void i2c_acpi_register_device(struct i2c_adapter *adapter,
|
||||
struct acpi_device *adev,
|
||||
struct i2c_board_info *info)
|
||||
{
|
||||
/*
|
||||
* Skip registration on boards where the ACPI tables are
|
||||
* known to contain bogus I2C devices.
|
||||
*/
|
||||
if (acpi_quirk_skip_i2c_client_enumeration(adev))
|
||||
return;
|
||||
|
||||
adev->power.flags.ignore_parent = true;
|
||||
acpi_device_set_enumerated(adev);
|
||||
|
||||
|
@ -31,10 +31,8 @@
|
||||
#include <linux/mmc/slot-gpio.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <linux/platform_data/x86/soc.h>
|
||||
#include <asm/iosf_mbi.h>
|
||||
#include <linux/pci.h>
|
||||
#endif
|
||||
|
||||
#include "sdhci.h"
|
||||
@ -240,26 +238,6 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
|
||||
static bool sdhci_acpi_byt(void)
|
||||
{
|
||||
static const struct x86_cpu_id byt[] = {
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, NULL),
|
||||
{}
|
||||
};
|
||||
|
||||
return x86_match_cpu(byt);
|
||||
}
|
||||
|
||||
static bool sdhci_acpi_cht(void)
|
||||
{
|
||||
static const struct x86_cpu_id cht[] = {
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL),
|
||||
{}
|
||||
};
|
||||
|
||||
return x86_match_cpu(cht);
|
||||
}
|
||||
|
||||
#define BYT_IOSF_SCCEP 0x63
|
||||
#define BYT_IOSF_OCP_NETCTRL0 0x1078
|
||||
#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
|
||||
@ -268,7 +246,7 @@ static void sdhci_acpi_byt_setting(struct device *dev)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
if (!sdhci_acpi_byt())
|
||||
if (!soc_intel_is_byt())
|
||||
return;
|
||||
|
||||
if (iosf_mbi_read(BYT_IOSF_SCCEP, MBI_CR_READ, BYT_IOSF_OCP_NETCTRL0,
|
||||
@ -293,7 +271,7 @@ static void sdhci_acpi_byt_setting(struct device *dev)
|
||||
|
||||
static bool sdhci_acpi_byt_defer(struct device *dev)
|
||||
{
|
||||
if (!sdhci_acpi_byt())
|
||||
if (!soc_intel_is_byt())
|
||||
return false;
|
||||
|
||||
if (!iosf_mbi_available())
|
||||
@ -304,43 +282,6 @@ static bool sdhci_acpi_byt_defer(struct device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device,
|
||||
unsigned int slot, unsigned int parent_slot)
|
||||
{
|
||||
struct pci_dev *dev, *parent, *from = NULL;
|
||||
|
||||
while (1) {
|
||||
dev = pci_get_device(vendor, device, from);
|
||||
pci_dev_put(from);
|
||||
if (!dev)
|
||||
break;
|
||||
parent = pci_upstream_bridge(dev);
|
||||
if (ACPI_COMPANION(&dev->dev) && PCI_SLOT(dev->devfn) == slot &&
|
||||
parent && PCI_SLOT(parent->devfn) == parent_slot &&
|
||||
!pci_upstream_bridge(parent)) {
|
||||
pci_dev_put(dev);
|
||||
return true;
|
||||
}
|
||||
from = dev;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* GPDwin uses PCI wifi which conflicts with SDIO's use of
|
||||
* acpi_device_fix_up_power() on child device nodes. Identifying GPDwin is
|
||||
* problematic, but since SDIO is only used for wifi, the presence of the PCI
|
||||
* wifi card in the expected slot with an ACPI companion node, is used to
|
||||
* indicate that acpi_device_fix_up_power() should be avoided.
|
||||
*/
|
||||
static inline bool sdhci_acpi_no_fixup_child_power(struct acpi_device *adev)
|
||||
{
|
||||
return sdhci_acpi_cht() &&
|
||||
acpi_dev_hid_uid_match(adev, "80860F14", "2") &&
|
||||
sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void sdhci_acpi_byt_setting(struct device *dev)
|
||||
@ -352,11 +293,6 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool sdhci_acpi_no_fixup_child_power(struct acpi_device *adev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int bxt_get_cd(struct mmc_host *mmc)
|
||||
@ -861,11 +797,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
||||
|
||||
/* Power on the SDHCI controller and its children */
|
||||
acpi_device_fix_up_power(device);
|
||||
if (!sdhci_acpi_no_fixup_child_power(device)) {
|
||||
list_for_each_entry(child, &device->children, node)
|
||||
if (child->status.present && child->status.enabled)
|
||||
acpi_device_fix_up_power(child);
|
||||
}
|
||||
list_for_each_entry(child, &device->children, node)
|
||||
if (child->status.present && child->status.enabled)
|
||||
acpi_device_fix_up_power(child);
|
||||
|
||||
if (sdhci_acpi_byt_defer(dev))
|
||||
return -EPROBE_DEFER;
|
||||
|
@ -727,10 +727,24 @@ static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
|
||||
static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
|
||||
{
|
||||
acpi_status status;
|
||||
bool skip;
|
||||
int ret;
|
||||
|
||||
if (!has_acpi_companion(ctrl->dev.parent))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Skip registration on boards where the ACPI tables are known to
|
||||
* contain buggy devices. Note serdev_controller_add() must still
|
||||
* succeed in this case, so that the proper serdev devices can be
|
||||
* added "manually" later.
|
||||
*/
|
||||
ret = acpi_quirk_skip_serdev_enumeration(ctrl->dev.parent, &skip);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (skip)
|
||||
return 0;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
SERDEV_ACPI_MAX_SCAN_DEPTH,
|
||||
acpi_serdev_add_device, NULL, ctrl, NULL);
|
||||
|
@ -507,6 +507,7 @@ extern int unregister_acpi_notifier(struct notifier_block *);
|
||||
*/
|
||||
|
||||
int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
|
||||
struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
|
||||
acpi_status acpi_bus_get_status_handle(acpi_handle handle,
|
||||
unsigned long long *sta);
|
||||
int acpi_bus_get_status(struct acpi_device *device);
|
||||
@ -615,12 +616,34 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
|
||||
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
bool acpi_device_always_present(struct acpi_device *adev);
|
||||
bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status);
|
||||
bool acpi_quirk_skip_acpi_ac_and_battery(void);
|
||||
#else
|
||||
static inline bool acpi_device_always_present(struct acpi_device *adev)
|
||||
static inline bool acpi_device_override_status(struct acpi_device *adev,
|
||||
unsigned long long *status)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool acpi_quirk_skip_acpi_ac_and_battery(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
|
||||
bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev);
|
||||
int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip);
|
||||
#else
|
||||
static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline int
|
||||
acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
|
||||
{
|
||||
*skip = false;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define __ACPI_NUMA_H
|
||||
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/numa.h>
|
||||
|
||||
/* Proximity bitmap length */
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
/* Current ACPICA subsystem version in YYYYMMDD format */
|
||||
|
||||
#define ACPI_CA_VERSION 0x20210930
|
||||
#define ACPI_CA_VERSION 0x20211217
|
||||
|
||||
#include <acpi/acconfig.h>
|
||||
#include <acpi/actypes.h>
|
||||
@ -454,9 +454,11 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
|
||||
* ACPI table load/unload interfaces
|
||||
*/
|
||||
ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_INIT_FUNCTION
|
||||
acpi_install_table(acpi_physical_address address,
|
||||
u8 physical))
|
||||
acpi_install_table(struct acpi_table_header *table))
|
||||
|
||||
ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_INIT_FUNCTION
|
||||
acpi_install_physical_table(acpi_physical_address
|
||||
address))
|
||||
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
|
||||
acpi_load_table(struct acpi_table_header *table,
|
||||
u32 *table_idx))
|
||||
|
@ -24,6 +24,7 @@
|
||||
* file. Useful because they make it more difficult to inadvertently type in
|
||||
* the wrong signature.
|
||||
*/
|
||||
#define ACPI_SIG_AGDI "AGDI" /* Arm Generic Diagnostic Dump and Reset Device Interface */
|
||||
#define ACPI_SIG_BDAT "BDAT" /* BIOS Data ACPI Table */
|
||||
#define ACPI_SIG_IORT "IORT" /* IO Remapping Table */
|
||||
#define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */
|
||||
@ -48,6 +49,7 @@
|
||||
#define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */
|
||||
#define ACPI_SIG_SDEV "SDEV" /* Secure Devices table */
|
||||
#define ACPI_SIG_SVKL "SVKL" /* Storage Volume Key Location Table */
|
||||
#define ACPI_SIG_TDEL "TDEL" /* TD Event Log Table */
|
||||
|
||||
/*
|
||||
* All tables must be byte-packed to match the ACPI specification, since
|
||||
@ -154,7 +156,7 @@ typedef struct acpi_aest_processor_tlb {
|
||||
/* 2R: Processor Generic Resource Substructure */
|
||||
|
||||
typedef struct acpi_aest_processor_generic {
|
||||
u8 *resource;
|
||||
u32 resource;
|
||||
|
||||
} acpi_aest_processor_generic;
|
||||
|
||||
@ -237,6 +239,25 @@ typedef struct acpi_aest_node_interrupt {
|
||||
#define ACPI_AEST_NODE_ERROR_RECOVERY 1
|
||||
#define ACPI_AEST_XRUPT_RESERVED 2 /* 2 and above are reserved */
|
||||
|
||||
/*******************************************************************************
|
||||
* AGDI - Arm Generic Diagnostic Dump and Reset Device Interface
|
||||
*
|
||||
* Conforms to "ACPI for Arm Components 1.1, Platform Design Document"
|
||||
* ARM DEN0093 v1.1
|
||||
*
|
||||
******************************************************************************/
|
||||
struct acpi_table_agdi {
|
||||
struct acpi_table_header header; /* Common ACPI table header */
|
||||
u8 flags;
|
||||
u8 reserved[3];
|
||||
u32 sdei_event;
|
||||
u32 gsiv;
|
||||
};
|
||||
|
||||
/* Mask for Flags field above */
|
||||
|
||||
#define ACPI_AGDI_SIGNALING_MODE (1)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* BDAT - BIOS Data ACPI Table
|
||||
@ -1495,12 +1516,10 @@ struct acpi_nhlt_device_specific_config_a {
|
||||
|
||||
/* Values for Config Type above */
|
||||
|
||||
#define ACPI_NHLT_TYPE_MIC_ARRAY 0x01
|
||||
#define ACPI_NHLT_TYPE_GENERIC 0x00
|
||||
|
||||
/* Mask for Extension field of array_type */
|
||||
|
||||
#define ACPI_NHLT_ARRAY_TYPE_MASK 0x10
|
||||
#define ACPI_NHLT_CONFIG_TYPE_GENERIC 0x00
|
||||
#define ACPI_NHLT_CONFIG_TYPE_MIC_ARRAY 0x01
|
||||
#define ACPI_NHLT_CONFIG_TYPE_RENDER_FEEDBACK 0x03
|
||||
#define ACPI_NHLT_CONFIG_TYPE_RESERVED 0x04 /* 4 and above are reserved */
|
||||
|
||||
struct acpi_nhlt_device_specific_config_b {
|
||||
u32 capabilities_size;
|
||||
@ -1511,6 +1530,11 @@ struct acpi_nhlt_device_specific_config_c {
|
||||
u8 virtual_slot;
|
||||
};
|
||||
|
||||
struct acpi_nhlt_render_device_specific_config {
|
||||
u32 capabilities_size;
|
||||
u8 virtual_slot;
|
||||
};
|
||||
|
||||
struct acpi_nhlt_wave_extensible {
|
||||
u16 format_tag;
|
||||
u16 channel_count;
|
||||
@ -1573,17 +1597,22 @@ struct acpi_nhlt_mic_device_specific_config {
|
||||
|
||||
/* Values for array_type_ext above */
|
||||
|
||||
#define SMALL_LINEAR_2ELEMENT 0x0A
|
||||
#define BIG_LINEAR_2ELEMENT 0x0B
|
||||
#define FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C
|
||||
#define PLANAR_LSHAPED_4ELEMENT 0x0D
|
||||
#define SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E
|
||||
#define VENDOR_DEFINED 0x0F
|
||||
#define ARRAY_TYPE_MASK 0x0F
|
||||
#define ARRAY_TYPE_EXT_MASK 0x10
|
||||
#define ACPI_NHLT_ARRAY_TYPE_RESERVED 0x09 // 9 and below are reserved
|
||||
#define ACPI_NHLT_SMALL_LINEAR_2ELEMENT 0x0A
|
||||
#define ACPI_NHLT_BIG_LINEAR_2ELEMENT 0x0B
|
||||
#define ACPI_NHLT_FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C
|
||||
#define ACPI_NHLT_PLANAR_LSHAPED_4ELEMENT 0x0D
|
||||
#define ACPI_NHLT_SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E
|
||||
#define ACPI_NHLT_VENDOR_DEFINED 0x0F
|
||||
#define ACPI_NHLT_ARRAY_TYPE_MASK 0x0F
|
||||
#define ACPI_NHLT_ARRAY_TYPE_EXT_MASK 0x10
|
||||
|
||||
#define NO_EXTENSION 0x0
|
||||
#define MIC_SNR_SENSITIVITY_EXT 0x1
|
||||
#define ACPI_NHLT_NO_EXTENSION 0x0
|
||||
#define ACPI_NHLT_MIC_SNR_SENSITIVITY_EXT (1<<4)
|
||||
|
||||
struct acpi_nhlt_vendor_mic_count {
|
||||
u8 microphone_count;
|
||||
};
|
||||
|
||||
struct acpi_nhlt_vendor_mic_config {
|
||||
u8 type;
|
||||
@ -1603,22 +1632,25 @@ struct acpi_nhlt_vendor_mic_config {
|
||||
|
||||
/* Values for Type field above */
|
||||
|
||||
#define MIC_OMNIDIRECTIONAL 0
|
||||
#define MIC_SUBCARDIOID 1
|
||||
#define MIC_CARDIOID 2
|
||||
#define MIC_SUPER_CARDIOID 3
|
||||
#define MIC_HYPER_CARDIOID 4
|
||||
#define MIC_8_SHAPED 5
|
||||
#define MIC_VENDOR_DEFINED 7
|
||||
#define ACPI_NHLT_MIC_OMNIDIRECTIONAL 0
|
||||
#define ACPI_NHLT_MIC_SUBCARDIOID 1
|
||||
#define ACPI_NHLT_MIC_CARDIOID 2
|
||||
#define ACPI_NHLT_MIC_SUPER_CARDIOID 3
|
||||
#define ACPI_NHLT_MIC_HYPER_CARDIOID 4
|
||||
#define ACPI_NHLT_MIC_8_SHAPED 5
|
||||
#define ACPI_NHLT_MIC_RESERVED6 6 // 6 is reserved
|
||||
#define ACPI_NHLT_MIC_VENDOR_DEFINED 7
|
||||
#define ACPI_NHLT_MIC_RESERVED 8 // 8 and above are reserved
|
||||
|
||||
/* Values for Panel field above */
|
||||
|
||||
#define MIC_TOP 0
|
||||
#define MIC_BOTTOM 1
|
||||
#define MIC_LEFT 2
|
||||
#define MIC_RIGHT 3
|
||||
#define MIC_FRONT 4
|
||||
#define MIC_REAR 5
|
||||
#define ACPI_NHLT_MIC_POSITION_TOP 0
|
||||
#define ACPI_NHLT_MIC_POSITION_BOTTOM 1
|
||||
#define ACPI_NHLT_MIC_POSITION_LEFT 2
|
||||
#define ACPI_NHLT_MIC_POSITION_RIGHT 3
|
||||
#define ACPI_NHLT_MIC_POSITION_FRONT 4
|
||||
#define ACPI_NHLT_MIC_POSITION_BACK 5
|
||||
#define ACPI_NHLT_MIC_POSITION_RESERVED 6 // 6 and above are reserved
|
||||
|
||||
struct acpi_nhlt_vendor_mic_device_specific_config {
|
||||
struct acpi_nhlt_mic_device_specific_config mic_array_device_config;
|
||||
@ -1633,8 +1665,9 @@ struct acpi_nhlt_mic_snr_sensitivity_extension {
|
||||
u32 sensitivity;
|
||||
};
|
||||
|
||||
/* Render device with feedback */
|
||||
|
||||
struct acpi_nhlt_render_feedback_device_specific_config {
|
||||
struct acpi_nhlt_device_specific_config device_config;
|
||||
u8 feedback_virtual_slot; // render slot in case of capture
|
||||
u16 feedback_channels; // informative only
|
||||
u16 feedback_valid_bits_per_sample;
|
||||
@ -1650,7 +1683,10 @@ struct acpi_nhlt_linux_specific_data {
|
||||
u8 device_id[16];
|
||||
u8 device_instance_id;
|
||||
u8 device_port_id;
|
||||
u8 filler[18];
|
||||
};
|
||||
|
||||
struct acpi_nhlt_linux_specific_data_b {
|
||||
u8 specific_data[18];
|
||||
};
|
||||
|
||||
struct acpi_nhlt_table_terminator {
|
||||
@ -2455,6 +2491,22 @@ enum acpi_svkl_format {
|
||||
ACPI_SVKL_FORMAT_RESERVED = 1 /* 1 and greater are reserved */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TDEL - TD-Event Log
|
||||
* From: "Guest-Host-Communication Interface (GHCI) for Intel
|
||||
* Trust Domain Extensions (Intel TDX)".
|
||||
* September 2020
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
struct acpi_table_tdel {
|
||||
struct acpi_table_header header; /* Common ACPI table header */
|
||||
u32 reserved;
|
||||
u64 log_area_minimum_length;
|
||||
u64 log_area_start_address;
|
||||
};
|
||||
|
||||
/* Reset to default packing */
|
||||
|
||||
#pragma pack()
|
||||
|
@ -509,7 +509,6 @@ typedef u64 acpi_integer;
|
||||
#define ACPI_TO_POINTER(i) ACPI_CAST_PTR (void, (acpi_size) (i))
|
||||
#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0)
|
||||
#define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) 0)
|
||||
#define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i)
|
||||
#define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i)
|
||||
|
||||
/* Optimizations for 4-character (32-bit) acpi_name manipulation */
|
||||
@ -536,8 +535,14 @@ typedef u64 acpi_integer;
|
||||
* Can be used with access_width of struct acpi_generic_address and access_size of
|
||||
* struct acpi_resource_generic_register.
|
||||
*/
|
||||
#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2))
|
||||
#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1))
|
||||
#define ACPI_ACCESS_BIT_SHIFT 2
|
||||
#define ACPI_ACCESS_BYTE_SHIFT -1
|
||||
#define ACPI_ACCESS_BIT_MAX (31 - ACPI_ACCESS_BIT_SHIFT)
|
||||
#define ACPI_ACCESS_BYTE_MAX (31 - ACPI_ACCESS_BYTE_SHIFT)
|
||||
#define ACPI_ACCESS_BIT_DEFAULT (8 - ACPI_ACCESS_BIT_SHIFT)
|
||||
#define ACPI_ACCESS_BYTE_DEFAULT (8 - ACPI_ACCESS_BYTE_SHIFT)
|
||||
#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BIT_SHIFT))
|
||||
#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BYTE_SHIFT))
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -1098,6 +1103,14 @@ struct acpi_connection_info {
|
||||
u8 access_length;
|
||||
};
|
||||
|
||||
/* Special Context data for PCC Opregion (ACPI 6.3) */
|
||||
|
||||
struct acpi_pcc_info {
|
||||
u8 subspace_id;
|
||||
u16 length;
|
||||
u8 *internal_buffer;
|
||||
};
|
||||
|
||||
typedef
|
||||
acpi_status (*acpi_adr_space_setup) (acpi_handle region_handle,
|
||||
u32 function,
|
||||
@ -1215,6 +1228,10 @@ struct acpi_mem_space_context {
|
||||
struct acpi_mem_mapping *first_mm;
|
||||
};
|
||||
|
||||
struct acpi_data_table_space_context {
|
||||
void *pointer;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct acpi_memory_list is used only if the ACPICA local cache is enabled
|
||||
*/
|
||||
|
@ -2,11 +2,16 @@
|
||||
#ifndef __ACPI_PROCESSOR_H
|
||||
#define __ACPI_PROCESSOR_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <asm/acpi.h>
|
||||
|
||||
#define ACPI_PROCESSOR_CLASS "processor"
|
||||
|
@ -1389,6 +1389,12 @@ static inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI_PCC
|
||||
void acpi_init_pcc(void);
|
||||
#else
|
||||
static inline void acpi_init_pcc(void) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern void acpi_device_notify(struct device *dev);
|
||||
extern void acpi_device_notify_remove(struct device *dev);
|
||||
|
@ -8273,6 +8273,7 @@ static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *cha
|
||||
rule = list_entry(&chain->rules, struct nft_rule, list);
|
||||
i = 0;
|
||||
|
||||
data_size = 0;
|
||||
list_for_each_entry_continue(rule, &chain->rules, list) {
|
||||
if (nft_is_active_next(net, rule)) {
|
||||
data_size += sizeof(*prule) + rule->dlen;
|
||||
|
Loading…
Reference in New Issue
Block a user