mirror of https://gitee.com/openkylin/linux.git
Merge branch 'atomicio-remove' into release
This commit is contained in:
commit
cb7971756b
|
@ -34,13 +34,13 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/acpi_io.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
#include <linux/rculist.h>
|
#include <linux/rculist.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <acpi/atomicio.h>
|
|
||||||
|
|
||||||
#include "apei-internal.h"
|
#include "apei-internal.h"
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = acpi_atomic_read(val, &entry->register_region);
|
rc = apei_read(val, &entry->register_region);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
*val >>= entry->register_region.bit_offset;
|
*val >>= entry->register_region.bit_offset;
|
||||||
|
@ -116,13 +116,13 @@ int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val)
|
||||||
val <<= entry->register_region.bit_offset;
|
val <<= entry->register_region.bit_offset;
|
||||||
if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
|
if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
|
||||||
u64 valr = 0;
|
u64 valr = 0;
|
||||||
rc = acpi_atomic_read(&valr, &entry->register_region);
|
rc = apei_read(&valr, &entry->register_region);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
valr &= ~(entry->mask << entry->register_region.bit_offset);
|
valr &= ~(entry->mask << entry->register_region.bit_offset);
|
||||||
val |= valr;
|
val |= valr;
|
||||||
}
|
}
|
||||||
rc = acpi_atomic_write(val, &entry->register_region);
|
rc = apei_write(val, &entry->register_region);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx,
|
||||||
u8 ins = entry->instruction;
|
u8 ins = entry->instruction;
|
||||||
|
|
||||||
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
|
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
|
||||||
return acpi_pre_map_gar(&entry->register_region);
|
return acpi_os_map_generic_address(&entry->register_region);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx,
|
||||||
u8 ins = entry->instruction;
|
u8 ins = entry->instruction;
|
||||||
|
|
||||||
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
|
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
|
||||||
acpi_post_unmap_gar(&entry->register_region);
|
acpi_os_unmap_generic_address(&entry->register_region);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -591,6 +591,96 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read GAR in interrupt (including NMI) or process context */
|
||||||
|
int apei_read(u64 *val, struct acpi_generic_address *reg)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
u64 address;
|
||||||
|
u32 tmp, width = reg->bit_width;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
rc = apei_check_gar(reg, &address);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (width == 64)
|
||||||
|
width = 32; /* Break into two 32-bit transfers */
|
||||||
|
|
||||||
|
*val = 0;
|
||||||
|
switch(reg->space_id) {
|
||||||
|
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||||
|
status = acpi_os_read_memory((acpi_physical_address)
|
||||||
|
address, &tmp, width);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -EIO;
|
||||||
|
*val = tmp;
|
||||||
|
|
||||||
|
if (reg->bit_width == 64) {
|
||||||
|
/* Read the top 32 bits */
|
||||||
|
status = acpi_os_read_memory((acpi_physical_address)
|
||||||
|
(address + 4), &tmp, 32);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -EIO;
|
||||||
|
*val |= ((u64)tmp << 32);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||||
|
status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -EIO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(apei_read);
|
||||||
|
|
||||||
|
/* write GAR in interrupt (including NMI) or process context */
|
||||||
|
int apei_write(u64 val, struct acpi_generic_address *reg)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
u64 address;
|
||||||
|
u32 width = reg->bit_width;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
rc = apei_check_gar(reg, &address);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (width == 64)
|
||||||
|
width = 32; /* Break into two 32-bit transfers */
|
||||||
|
|
||||||
|
switch (reg->space_id) {
|
||||||
|
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||||
|
status = acpi_os_write_memory((acpi_physical_address)
|
||||||
|
address, ACPI_LODWORD(val),
|
||||||
|
width);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (reg->bit_width == 64) {
|
||||||
|
status = acpi_os_write_memory((acpi_physical_address)
|
||||||
|
(address + 4),
|
||||||
|
ACPI_HIDWORD(val), 32);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||||
|
status = acpi_os_write_port(address, val, reg->bit_width);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -EIO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(apei_write);
|
||||||
|
|
||||||
static int collect_res_callback(struct apei_exec_context *ctx,
|
static int collect_res_callback(struct apei_exec_context *ctx,
|
||||||
struct acpi_whea_header *entry,
|
struct acpi_whea_header *entry,
|
||||||
void *data)
|
void *data)
|
||||||
|
|
|
@ -68,6 +68,9 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio
|
||||||
/* IP has been set in instruction function */
|
/* IP has been set in instruction function */
|
||||||
#define APEI_EXEC_SET_IP 1
|
#define APEI_EXEC_SET_IP 1
|
||||||
|
|
||||||
|
int apei_read(u64 *val, struct acpi_generic_address *reg);
|
||||||
|
int apei_write(u64 val, struct acpi_generic_address *reg);
|
||||||
|
|
||||||
int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val);
|
int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val);
|
||||||
int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val);
|
int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val);
|
||||||
int apei_exec_read_register(struct apei_exec_context *ctx,
|
int apei_exec_read_register(struct apei_exec_context *ctx,
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/acpi_io.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
|
@ -48,7 +49,6 @@
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
#include <acpi/apei.h>
|
#include <acpi/apei.h>
|
||||||
#include <acpi/atomicio.h>
|
|
||||||
#include <acpi/hed.h>
|
#include <acpi/hed.h>
|
||||||
#include <asm/mce.h>
|
#include <asm/mce.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
|
@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
|
||||||
if (!ghes)
|
if (!ghes)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
ghes->generic = generic;
|
ghes->generic = generic;
|
||||||
rc = acpi_pre_map_gar(&generic->error_status_address);
|
rc = acpi_os_map_generic_address(&generic->error_status_address);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_free;
|
goto err_free;
|
||||||
error_block_length = generic->error_block_length;
|
error_block_length = generic->error_block_length;
|
||||||
|
@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
|
||||||
return ghes;
|
return ghes;
|
||||||
|
|
||||||
err_unmap:
|
err_unmap:
|
||||||
acpi_post_unmap_gar(&generic->error_status_address);
|
acpi_os_unmap_generic_address(&generic->error_status_address);
|
||||||
err_free:
|
err_free:
|
||||||
kfree(ghes);
|
kfree(ghes);
|
||||||
return ERR_PTR(rc);
|
return ERR_PTR(rc);
|
||||||
|
@ -330,7 +330,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
|
||||||
static void ghes_fini(struct ghes *ghes)
|
static void ghes_fini(struct ghes *ghes)
|
||||||
{
|
{
|
||||||
kfree(ghes->estatus);
|
kfree(ghes->estatus);
|
||||||
acpi_post_unmap_gar(&ghes->generic->error_status_address);
|
acpi_os_unmap_generic_address(&ghes->generic->error_status_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -401,7 +401,7 @@ static int ghes_read_estatus(struct ghes *ghes, int silent)
|
||||||
u32 len;
|
u32 len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = acpi_atomic_read(&buf_paddr, &g->error_status_address);
|
rc = apei_read(&buf_paddr, &g->error_status_address);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (!silent && printk_ratelimit())
|
if (!silent && printk_ratelimit())
|
||||||
pr_warning(FW_WARN GHES_PFX
|
pr_warning(FW_WARN GHES_PFX
|
||||||
|
|
|
@ -153,17 +153,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
|
||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init acpi_request_region (struct acpi_generic_address *addr,
|
static void __init acpi_request_region (struct acpi_generic_address *gas,
|
||||||
unsigned int length, char *desc)
|
unsigned int length, char *desc)
|
||||||
{
|
{
|
||||||
if (!addr->address || !length)
|
u64 addr;
|
||||||
|
|
||||||
|
/* Handle possible alignment issues */
|
||||||
|
memcpy(&addr, &gas->address, sizeof(addr));
|
||||||
|
if (!addr || !length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Resources are never freed */
|
/* Resources are never freed */
|
||||||
if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
||||||
request_region(addr->address, length, desc);
|
request_region(addr, length, desc);
|
||||||
else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||||
request_mem_region(addr->address, length, desc);
|
request_mem_region(addr, length, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init acpi_reserve_resources(void)
|
static int __init acpi_reserve_resources(void)
|
||||||
|
@ -414,35 +418,42 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
|
||||||
__acpi_unmap_table(virt, size);
|
__acpi_unmap_table(virt, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
|
int acpi_os_map_generic_address(struct acpi_generic_address *gas)
|
||||||
{
|
{
|
||||||
|
u64 addr;
|
||||||
void __iomem *virt;
|
void __iomem *virt;
|
||||||
|
|
||||||
if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!addr->address || !addr->bit_width)
|
/* Handle possible alignment issues */
|
||||||
|
memcpy(&addr, &gas->address, sizeof(addr));
|
||||||
|
if (!addr || !gas->bit_width)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
virt = acpi_os_map_memory(addr->address, addr->bit_width / 8);
|
virt = acpi_os_map_memory(addr, gas->bit_width / 8);
|
||||||
if (!virt)
|
if (!virt)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(acpi_os_map_generic_address);
|
||||||
|
|
||||||
static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
|
void acpi_os_unmap_generic_address(struct acpi_generic_address *gas)
|
||||||
{
|
{
|
||||||
|
u64 addr;
|
||||||
struct acpi_ioremap *map;
|
struct acpi_ioremap *map;
|
||||||
|
|
||||||
if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!addr->address || !addr->bit_width)
|
/* Handle possible alignment issues */
|
||||||
|
memcpy(&addr, &gas->address, sizeof(addr));
|
||||||
|
if (!addr || !gas->bit_width)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&acpi_ioremap_lock);
|
mutex_lock(&acpi_ioremap_lock);
|
||||||
map = acpi_map_lookup(addr->address, addr->bit_width / 8);
|
map = acpi_map_lookup(addr, gas->bit_width / 8);
|
||||||
if (!map) {
|
if (!map) {
|
||||||
mutex_unlock(&acpi_ioremap_lock);
|
mutex_unlock(&acpi_ioremap_lock);
|
||||||
return;
|
return;
|
||||||
|
@ -452,6 +463,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
|
||||||
|
|
||||||
acpi_os_map_cleanup(map);
|
acpi_os_map_cleanup(map);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(acpi_os_unmap_generic_address);
|
||||||
|
|
||||||
#ifdef ACPI_FUTURE_USAGE
|
#ifdef ACPI_FUTURE_USAGE
|
||||||
acpi_status
|
acpi_status
|
||||||
|
|
|
@ -12,4 +12,7 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
|
||||||
|
|
||||||
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 acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue