Merge back earlier ACPICA-related changes for 5.10.

This commit is contained in:
Rafael J. Wysocki 2020-10-08 18:04:04 +02:00
commit 9a15da1b84
12 changed files with 202 additions and 49 deletions

View File

@ -42,6 +42,12 @@ ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_enable);
ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_status); ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_status);
ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_enable); ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_enable);
#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
ACPI_GLOBAL(unsigned long, acpi_gbl_xgpe0_block_logical_address);
ACPI_GLOBAL(unsigned long, acpi_gbl_xgpe1_block_logical_address);
#endif /* ACPI_GPE_USE_LOGICAL_ADDRESSES */
/* /*
* Handle both ACPI 1.0 and ACPI 2.0+ Integer widths. The integer width is * Handle both ACPI 1.0 and ACPI 2.0+ Integer widths. The integer width is
* determined by the revision of the DSDT: If the DSDT revision is less than * determined by the revision of the DSDT: If the DSDT revision is less than

View File

@ -73,9 +73,15 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width);
acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
acpi_status acpi_hw_validate_io_block(u64 address, u32 bit_width, u32 count);
/* /*
* hwgpe - GPE support * hwgpe - GPE support
*/ */
acpi_status acpi_hw_gpe_read(u64 *value, struct acpi_gpe_address *reg);
acpi_status acpi_hw_gpe_write(u64 value, struct acpi_gpe_address *reg);
u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info); u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info);
acpi_status acpi_status

View File

@ -454,11 +454,18 @@ struct acpi_gpe_event_info {
u8 disable_for_dispatch; /* Masked during dispatching */ u8 disable_for_dispatch; /* Masked during dispatching */
}; };
/* GPE register address */
struct acpi_gpe_address {
u8 space_id; /* Address space where the register exists */
u64 address; /* 64-bit address of the register */
};
/* Information about a GPE register pair, one per each status/enable pair in an array */ /* Information about a GPE register pair, one per each status/enable pair in an array */
struct acpi_gpe_register_info { struct acpi_gpe_register_info {
struct acpi_generic_address status_address; /* Address of status reg */ struct acpi_gpe_address status_address; /* Address of status reg */
struct acpi_generic_address enable_address; /* Address of enable reg */ struct acpi_gpe_address enable_address; /* Address of enable reg */
u16 base_gpe_number; /* Base GPE number for this register */ u16 base_gpe_number; /* Base GPE number for this register */
u8 enable_for_wake; /* GPEs to keep enabled when sleeping */ u8 enable_for_wake; /* GPEs to keep enabled when sleeping */
u8 enable_for_run; /* GPEs to keep enabled when running */ u8 enable_for_run; /* GPEs to keep enabled when running */

View File

@ -656,14 +656,14 @@ acpi_ev_detect_gpe(struct acpi_namespace_node *gpe_device,
/* GPE currently enabled (enable bit == 1)? */ /* GPE currently enabled (enable bit == 1)? */
status = acpi_hw_read(&enable_reg, &gpe_register_info->enable_address); status = acpi_hw_gpe_read(&enable_reg, &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto error_exit; goto error_exit;
} }
/* GPE currently active (status bit == 1)? */ /* GPE currently active (status bit == 1)? */
status = acpi_hw_read(&status_reg, &gpe_register_info->status_address); status = acpi_hw_gpe_read(&status_reg, &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto error_exit; goto error_exit;
} }

View File

@ -233,12 +233,6 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
this_register->status_address.space_id = gpe_block->space_id; this_register->status_address.space_id = gpe_block->space_id;
this_register->enable_address.space_id = gpe_block->space_id; this_register->enable_address.space_id = gpe_block->space_id;
this_register->status_address.bit_width =
ACPI_GPE_REGISTER_WIDTH;
this_register->enable_address.bit_width =
ACPI_GPE_REGISTER_WIDTH;
this_register->status_address.bit_offset = 0;
this_register->enable_address.bit_offset = 0;
/* Init the event_info for each GPE within this register */ /* Init the event_info for each GPE within this register */
@ -251,14 +245,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
/* Disable all GPEs within this register */ /* Disable all GPEs within this register */
status = acpi_hw_write(0x00, &this_register->enable_address); status = acpi_hw_gpe_write(0x00, &this_register->enable_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto error_exit; goto error_exit;
} }
/* Clear any pending GPE events within this register */ /* Clear any pending GPE events within this register */
status = acpi_hw_write(0xFF, &this_register->status_address); status = acpi_hw_gpe_write(0xFF, &this_register->status_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto error_exit; goto error_exit;
} }
@ -317,6 +311,23 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
/* Validate the space_ID */
if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
ACPI_ERROR((AE_INFO,
"Unsupported address space: 0x%X", space_id));
return_ACPI_STATUS(AE_SUPPORT);
}
if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
status = acpi_hw_validate_io_block(address,
ACPI_GPE_REGISTER_WIDTH,
register_count);
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
}
/* Allocate a new GPE block */ /* Allocate a new GPE block */
gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info)); gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));

View File

@ -32,6 +32,16 @@ ACPI_MODULE_NAME("evgpeinit")
* kernel boot time as well. * kernel boot time as well.
*/ */
#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
#define ACPI_FADT_GPE_BLOCK_ADDRESS(N) \
acpi_gbl_FADT.xgpe##N##_block.space_id == \
ACPI_ADR_SPACE_SYSTEM_MEMORY ? \
(u64)acpi_gbl_xgpe##N##_block_logical_address : \
acpi_gbl_FADT.xgpe##N##_block.address
#else
#define ACPI_FADT_GPE_BLOCK_ADDRESS(N) acpi_gbl_FADT.xgpe##N##_block.address
#endif /* ACPI_GPE_USE_LOGICAL_ADDRESSES */
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ev_gpe_initialize * FUNCTION: acpi_ev_gpe_initialize
@ -49,6 +59,7 @@ acpi_status acpi_ev_gpe_initialize(void)
u32 register_count1 = 0; u32 register_count1 = 0;
u32 gpe_number_max = 0; u32 gpe_number_max = 0;
acpi_status status; acpi_status status;
u64 address;
ACPI_FUNCTION_TRACE(ev_gpe_initialize); ACPI_FUNCTION_TRACE(ev_gpe_initialize);
@ -85,8 +96,9 @@ acpi_status acpi_ev_gpe_initialize(void)
* If EITHER the register length OR the block address are zero, then that * If EITHER the register length OR the block address are zero, then that
* particular block is not supported. * particular block is not supported.
*/ */
if (acpi_gbl_FADT.gpe0_block_length && address = ACPI_FADT_GPE_BLOCK_ADDRESS(0);
acpi_gbl_FADT.xgpe0_block.address) {
if (acpi_gbl_FADT.gpe0_block_length && address) {
/* GPE block 0 exists (has both length and address > 0) */ /* GPE block 0 exists (has both length and address > 0) */
@ -97,7 +109,6 @@ acpi_status acpi_ev_gpe_initialize(void)
/* Install GPE Block 0 */ /* Install GPE Block 0 */
status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
acpi_gbl_FADT.xgpe0_block.
address, address,
acpi_gbl_FADT.xgpe0_block. acpi_gbl_FADT.xgpe0_block.
space_id, register_count0, 0, space_id, register_count0, 0,
@ -110,8 +121,9 @@ acpi_status acpi_ev_gpe_initialize(void)
} }
} }
if (acpi_gbl_FADT.gpe1_block_length && address = ACPI_FADT_GPE_BLOCK_ADDRESS(1);
acpi_gbl_FADT.xgpe1_block.address) {
if (acpi_gbl_FADT.gpe1_block_length && address) {
/* GPE block 1 exists (has both length and address > 0) */ /* GPE block 1 exists (has both length and address > 0) */
@ -137,7 +149,6 @@ acpi_status acpi_ev_gpe_initialize(void)
status = status =
acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
acpi_gbl_FADT.xgpe1_block.
address, address,
acpi_gbl_FADT.xgpe1_block. acpi_gbl_FADT.xgpe1_block.
space_id, register_count1, space_id, register_count1,

View File

@ -24,6 +24,76 @@ static acpi_status
acpi_hw_gpe_enable_write(u8 enable_mask, acpi_hw_gpe_enable_write(u8 enable_mask,
struct acpi_gpe_register_info *gpe_register_info); struct acpi_gpe_register_info *gpe_register_info);
/******************************************************************************
*
* FUNCTION: acpi_hw_gpe_read
*
* PARAMETERS: value - Where the value is returned
* reg - GPE register structure
*
* RETURN: Status
*
* DESCRIPTION: Read from a GPE register in either memory or IO space.
*
* LIMITATIONS: <These limitations also apply to acpi_hw_gpe_write>
* space_ID must be system_memory or system_IO.
*
******************************************************************************/
acpi_status acpi_hw_gpe_read(u64 *value, struct acpi_gpe_address *reg)
{
acpi_status status;
u32 value32;
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
*value = (u64)ACPI_GET8(reg->address);
return_ACPI_STATUS(AE_OK);
#else
return acpi_os_read_memory((acpi_physical_address)reg->address,
value, ACPI_GPE_REGISTER_WIDTH);
#endif
}
status = acpi_os_read_port((acpi_io_address)reg->address,
&value32, ACPI_GPE_REGISTER_WIDTH);
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
*value = (u64)value32;
return_ACPI_STATUS(AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_gpe_write
*
* PARAMETERS: value - Value to be written
* reg - GPE register structure
*
* RETURN: Status
*
* DESCRIPTION: Write to a GPE register in either memory or IO space.
*
******************************************************************************/
acpi_status acpi_hw_gpe_write(u64 value, struct acpi_gpe_address *reg)
{
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
ACPI_SET8(reg->address, value);
return_ACPI_STATUS(AE_OK);
#else
return acpi_os_write_memory((acpi_physical_address)reg->address,
value, ACPI_GPE_REGISTER_WIDTH);
#endif
}
return acpi_os_write_port((acpi_io_address)reg->address, (u32)value,
ACPI_GPE_REGISTER_WIDTH);
}
/****************************************************************************** /******************************************************************************
* *
* FUNCTION: acpi_hw_get_gpe_register_bit * FUNCTION: acpi_hw_get_gpe_register_bit
@ -79,7 +149,8 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
/* Get current value of the enable register that contains this GPE */ /* Get current value of the enable register that contains this GPE */
status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address); status = acpi_hw_gpe_read(&enable_mask,
&gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return (status); return (status);
} }
@ -118,9 +189,8 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
/* Write the updated enable mask */ /* Write the updated enable mask */
status = status = acpi_hw_gpe_write(enable_mask,
acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
&gpe_register_info->enable_address);
} }
return (status); return (status);
} }
@ -158,8 +228,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info)
*/ */
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
status = status = acpi_hw_gpe_write(register_bit,
acpi_hw_write(register_bit, &gpe_register_info->status_address); &gpe_register_info->status_address);
return (status); return (status);
} }
@ -227,7 +297,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
/* GPE currently enabled (enable bit == 1)? */ /* GPE currently enabled (enable bit == 1)? */
status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address); status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return (status); return (status);
} }
@ -238,7 +308,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
/* GPE currently active (status bit == 1)? */ /* GPE currently active (status bit == 1)? */
status = acpi_hw_read(&in_byte, &gpe_register_info->status_address); status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return (status); return (status);
} }
@ -274,7 +344,8 @@ acpi_hw_gpe_enable_write(u8 enable_mask,
gpe_register_info->enable_mask = enable_mask; gpe_register_info->enable_mask = enable_mask;
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); status = acpi_hw_gpe_write(enable_mask,
&gpe_register_info->enable_address);
return (status); return (status);
} }
@ -341,9 +412,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Clear status on all GPEs in this register */ /* Clear status on all GPEs in this register */
status = status = acpi_hw_gpe_write(0xFF,
acpi_hw_write(0xFF, &gpe_block->register_info[i].status_address);
&gpe_block->register_info[i].status_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return (status); return (status);
} }
@ -481,14 +551,14 @@ acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
for (i = 0; i < gpe_block->register_count; i++) { for (i = 0; i < gpe_block->register_count; i++) {
gpe_register_info = &gpe_block->register_info[i]; gpe_register_info = &gpe_block->register_info[i];
status = acpi_hw_read(&in_enable, status = acpi_hw_gpe_read(&in_enable,
&gpe_register_info->enable_address); &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
continue; continue;
} }
status = acpi_hw_read(&in_status, status = acpi_hw_gpe_read(&in_status,
&gpe_register_info->status_address); &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
continue; continue;
} }

View File

@ -292,3 +292,33 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
return (AE_OK); return (AE_OK);
} }
/******************************************************************************
*
* FUNCTION: acpi_hw_validate_io_block
*
* PARAMETERS: Address Address of I/O port/register blobk
* bit_width Number of bits (8,16,32) in each register
* count Number of registers in the block
*
* RETURN: Status
*
* DESCRIPTION: Validates a block of I/O ports/registers.
*
******************************************************************************/
acpi_status acpi_hw_validate_io_block(u64 address, u32 bit_width, u32 count)
{
acpi_status status;
while (count--) {
status = acpi_hw_validate_io_request((acpi_io_address)address,
bit_width);
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
address += ACPI_DIV_8(bit_width);
}
return_ACPI_STATUS(AE_OK);
}

View File

@ -632,7 +632,11 @@ int apei_map_generic_address(struct acpi_generic_address *reg)
rc = apei_check_gar(reg, &address, &access_bit_width); rc = apei_check_gar(reg, &address, &access_bit_width);
if (rc) if (rc)
return rc; return rc;
return acpi_os_map_generic_address(reg);
if (!acpi_os_map_generic_address(reg))
return -ENXIO;
return 0;
} }
EXPORT_SYMBOL_GPL(apei_map_generic_address); EXPORT_SYMBOL_GPL(apei_map_generic_address);

View File

@ -447,24 +447,19 @@ void __ref acpi_os_unmap_memory(void *virt, acpi_size size)
} }
EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
int acpi_os_map_generic_address(struct acpi_generic_address *gas) void __iomem *acpi_os_map_generic_address(struct acpi_generic_address *gas)
{ {
u64 addr; u64 addr;
void __iomem *virt;
if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return 0; return NULL;
/* Handle possible alignment issues */ /* Handle possible alignment issues */
memcpy(&addr, &gas->address, sizeof(addr)); memcpy(&addr, &gas->address, sizeof(addr));
if (!addr || !gas->bit_width) if (!addr || !gas->bit_width)
return -EINVAL; return NULL;
virt = acpi_os_map_iomem(addr, gas->bit_width / 8); return acpi_os_map_iomem(addr, gas->bit_width / 8);
if (!virt)
return -EIO;
return 0;
} }
EXPORT_SYMBOL(acpi_os_map_generic_address); EXPORT_SYMBOL(acpi_os_map_generic_address);
@ -1749,17 +1744,22 @@ acpi_status __init acpi_os_initialize(void)
{ {
acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block); acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1b_event_block); acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe0_block);
acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe1_block); acpi_gbl_xgpe0_block_logical_address =
(unsigned long)acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe0_block);
acpi_gbl_xgpe1_block_logical_address =
(unsigned long)acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe1_block);
if (acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) { if (acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) {
/* /*
* Use acpi_os_map_generic_address to pre-map the reset * Use acpi_os_map_generic_address to pre-map the reset
* register if it's in system memory. * register if it's in system memory.
*/ */
int rv; void *rv;
rv = acpi_os_map_generic_address(&acpi_gbl_FADT.reset_register); rv = acpi_os_map_generic_address(&acpi_gbl_FADT.reset_register);
pr_debug(PREFIX "%s: map reset_reg status %d\n", __func__, rv); pr_debug(PREFIX "%s: map reset_reg %s\n", __func__,
rv ? "successful" : "failed");
} }
acpi_os_initialized = true; acpi_os_initialized = true;
@ -1787,8 +1787,12 @@ acpi_status acpi_os_terminate(void)
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe1_block); acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe1_block);
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe0_block); acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe0_block);
acpi_gbl_xgpe0_block_logical_address = 0UL;
acpi_gbl_xgpe1_block_logical_address = 0UL;
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1b_event_block); acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1a_event_block); acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
if (acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) if (acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER)
acpi_os_unmap_generic_address(&acpi_gbl_FADT.reset_register); acpi_os_unmap_generic_address(&acpi_gbl_FADT.reset_register);

View File

@ -21,7 +21,7 @@ void __iomem __ref
void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size); void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size);
void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size);
int acpi_os_map_generic_address(struct acpi_generic_address *addr); void __iomem *acpi_os_map_generic_address(struct acpi_generic_address *addr);
void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); void acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
#endif #endif

View File

@ -118,6 +118,10 @@
#define USE_NATIVE_ALLOCATE_ZEROED #define USE_NATIVE_ALLOCATE_ZEROED
/* Use logical addresses for accessing GPE registers in system memory */
#define ACPI_GPE_USE_LOGICAL_ADDRESSES
/* /*
* Overrides for in-kernel ACPICA * Overrides for in-kernel ACPICA
*/ */