Skip to content

Commit

Permalink
ACPI: Clean up acpi_os_map/unmap_memory() to eliminate __iomem.
Browse files Browse the repository at this point in the history
ACPICA doesn't include protections around address space checking, Linux
build tests always complain increased sparse warnings around ACPICA
internal acpi_os_map/unmap_memory() invocations.  This patch tries to fix
this issue permanently.

There are 2 choices left for us to solve this issue:
 1. Add __iomem address space awareness into ACPICA.
 2. Remove sparse checker of __iomem from ACPICA source code.

This patch chooses solution 2, because:
 1.  Most of the acpi_os_map/unmap_memory() invocations are used for ACPICA.
     table mappings, which in fact are not IO addresses.
 2.  The only IO addresses usage is for "system memory space" mapping code in:
      drivers/acpi/acpica/exregion.c
      drivers/acpi/acpica/evrgnini.c
      drivers/acpi/acpica/exregion.c
    The mapped address is accessed in the handler of "system memory space"
    - acpi_ex_system_memory_space_handler().  This function in fact can be
    changed to invoke acpi_os_read/write_memory() so that __iomem can
    always be type-casted in the OSL layer.

According to the above investigation, we drew the following conclusion:
It is not a good idea to introduce __iomem address space awareness into
ACPICA mostly in order to protect non-IO addresses.

We can simply remove __iomem for acpi_os_map/unmap_memory() to remove
__iomem checker for ACPICA code. Then we need to enforce external usages
to invoke other APIs that are aware of __iomem address space.
The external usages are:
 drivers/acpi/apei/einj.c
 drivers/acpi/acpi_extlog.c
 drivers/char/tpm/tpm_acpi.c
 drivers/acpi/nvs.c

This patch thus performs cleanups in this way:
 1. Add acpi_os_map/unmap_iomem() to be invoked by non-ACPICA code.
 2. Remove __iomem from acpi_os_map/unmap_memory().

Signed-off-by: Lv Zheng <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
  • Loading branch information
Lv Zheng authored and rafaeljw committed May 27, 2014
1 parent 92985ef commit a238317
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 33 deletions.
16 changes: 8 additions & 8 deletions drivers/acpi/acpi_extlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,13 @@ static int __init extlog_init(void)
goto err;
}

extlog_l1_hdr = acpi_os_map_memory(l1_dirbase, l1_hdr_size);
extlog_l1_hdr = acpi_os_map_iomem(l1_dirbase, l1_hdr_size);
l1_head = (struct extlog_l1_head *)extlog_l1_hdr;
l1_size = l1_head->total_len;
l1_percpu_entry = l1_head->entries;
elog_base = l1_head->elog_base;
elog_size = l1_head->elog_len;
acpi_os_unmap_memory(extlog_l1_hdr, l1_hdr_size);
acpi_os_unmap_iomem(extlog_l1_hdr, l1_hdr_size);
release_mem_region(l1_dirbase, l1_hdr_size);

/* remap L1 header again based on completed information */
Expand All @@ -237,7 +237,7 @@ static int __init extlog_init(void)
(unsigned long long)l1_dirbase + l1_size);
goto err;
}
extlog_l1_addr = acpi_os_map_memory(l1_dirbase, l1_size);
extlog_l1_addr = acpi_os_map_iomem(l1_dirbase, l1_size);
l1_entry_base = (u64 *)((u8 *)extlog_l1_addr + l1_hdr_size);

/* remap elog table */
Expand All @@ -248,7 +248,7 @@ static int __init extlog_init(void)
(unsigned long long)elog_base + elog_size);
goto err_release_l1_dir;
}
elog_addr = acpi_os_map_memory(elog_base, elog_size);
elog_addr = acpi_os_map_iomem(elog_base, elog_size);

rc = -ENOMEM;
/* allocate buffer to save elog record */
Expand All @@ -270,11 +270,11 @@ static int __init extlog_init(void)

err_release_elog:
if (elog_addr)
acpi_os_unmap_memory(elog_addr, elog_size);
acpi_os_unmap_iomem(elog_addr, elog_size);
release_mem_region(elog_base, elog_size);
err_release_l1_dir:
if (extlog_l1_addr)
acpi_os_unmap_memory(extlog_l1_addr, l1_size);
acpi_os_unmap_iomem(extlog_l1_addr, l1_size);
release_mem_region(l1_dirbase, l1_size);
err:
pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n");
Expand All @@ -287,9 +287,9 @@ static void __exit extlog_exit(void)
mce_unregister_decode_chain(&extlog_mce_dec);
((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN;
if (extlog_l1_addr)
acpi_os_unmap_memory(extlog_l1_addr, l1_size);
acpi_os_unmap_iomem(extlog_l1_addr, l1_size);
if (elog_addr)
acpi_os_unmap_memory(elog_addr, elog_size);
acpi_os_unmap_iomem(elog_addr, elog_size);
release_mem_region(elog_base, elog_size);
release_mem_region(l1_dirbase, l1_size);
kfree(elog_buf);
Expand Down
14 changes: 7 additions & 7 deletions drivers/acpi/apei/einj.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,15 @@ static void check_vendor_extension(u64 paddr,

if (!offset)
return;
v = acpi_os_map_memory(paddr + offset, sizeof(*v));
v = acpi_os_map_iomem(paddr + offset, sizeof(*v));
if (!v)
return;
sbdf = v->pcie_sbdf;
sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
sbdf >> 24, (sbdf >> 16) & 0xff,
(sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7,
v->vendor_id, v->device_id, v->rev_id);
acpi_os_unmap_memory(v, sizeof(*v));
acpi_os_unmap_iomem(v, sizeof(*v));
}

static void *einj_get_parameter_address(void)
Expand All @@ -236,7 +236,7 @@ static void *einj_get_parameter_address(void)
if (pa_v5) {
struct set_error_type_with_address *v5param;

v5param = acpi_os_map_memory(pa_v5, sizeof(*v5param));
v5param = acpi_os_map_iomem(pa_v5, sizeof(*v5param));
if (v5param) {
acpi5 = 1;
check_vendor_extension(pa_v5, v5param);
Expand All @@ -246,11 +246,11 @@ static void *einj_get_parameter_address(void)
if (param_extension && pa_v4) {
struct einj_parameter *v4param;

v4param = acpi_os_map_memory(pa_v4, sizeof(*v4param));
v4param = acpi_os_map_iomem(pa_v4, sizeof(*v4param));
if (!v4param)
return NULL;
if (v4param->reserved1 || v4param->reserved2) {
acpi_os_unmap_memory(v4param, sizeof(*v4param));
acpi_os_unmap_iomem(v4param, sizeof(*v4param));
return NULL;
}
return v4param;
Expand Down Expand Up @@ -794,7 +794,7 @@ static int __init einj_init(void)
sizeof(struct set_error_type_with_address) :
sizeof(struct einj_parameter);

acpi_os_unmap_memory(einj_param, size);
acpi_os_unmap_iomem(einj_param, size);
}
apei_exec_post_unmap_gars(&ctx);
err_release:
Expand All @@ -816,7 +816,7 @@ static void __exit einj_exit(void)
sizeof(struct set_error_type_with_address) :
sizeof(struct einj_parameter);

acpi_os_unmap_memory(einj_param, size);
acpi_os_unmap_iomem(einj_param, size);
}
einj_exec_ctx_init(&ctx);
apei_exec_post_unmap_gars(&ctx);
Expand Down
4 changes: 2 additions & 2 deletions drivers/acpi/nvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ void suspend_nvs_free(void)
iounmap(entry->kaddr);
entry->unmap = false;
} else {
acpi_os_unmap_memory(entry->kaddr,
entry->size);
acpi_os_unmap_iomem(entry->kaddr,
entry->size);
}
entry->kaddr = NULL;
}
Expand Down
21 changes: 17 additions & 4 deletions drivers/acpi/osl.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
}

void __iomem *__init_refok
acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
{
struct acpi_ioremap *map;
void __iomem *virt;
Expand Down Expand Up @@ -401,10 +401,17 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)

list_add_tail_rcu(&map->list, &acpi_ioremaps);

out:
out:
mutex_unlock(&acpi_ioremap_lock);
return map->virt + (phys - map->phys);
}
EXPORT_SYMBOL_GPL(acpi_os_map_iomem);

void *__init_refok
acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
{
return (void *)acpi_os_map_iomem(phys, size);
}
EXPORT_SYMBOL_GPL(acpi_os_map_memory);

static void acpi_os_drop_map_ref(struct acpi_ioremap *map)
Expand All @@ -422,7 +429,7 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map)
}
}

void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size)
{
struct acpi_ioremap *map;

Expand All @@ -443,6 +450,12 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)

acpi_os_map_cleanup(map);
}
EXPORT_SYMBOL_GPL(acpi_os_unmap_iomem);

void __ref acpi_os_unmap_memory(void *virt, acpi_size size)
{
return acpi_os_unmap_iomem((void __iomem *)virt, size);
}
EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);

void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
Expand All @@ -464,7 +477,7 @@ int acpi_os_map_generic_address(struct acpi_generic_address *gas)
if (!addr || !gas->bit_width)
return -EINVAL;

virt = acpi_os_map_memory(addr, gas->bit_width / 8);
virt = acpi_os_map_iomem(addr, gas->bit_width / 8);
if (!virt)
return -EIO;

Expand Down
4 changes: 2 additions & 2 deletions drivers/char/tpm/tpm_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ int read_log(struct tpm_bios_log *log)

log->bios_event_log_end = log->bios_event_log + len;

virt = acpi_os_map_memory(start, len);
virt = acpi_os_map_iomem(start, len);
if (!virt) {
kfree(log->bios_event_log);
printk("%s: ERROR - Unable to map memory\n", __func__);
Expand All @@ -104,6 +104,6 @@ int read_log(struct tpm_bios_log *log)

memcpy_fromio(log->bios_event_log, virt, len);

acpi_os_unmap_memory(virt, len);
acpi_os_unmap_iomem(virt, len);
return 0;
}
3 changes: 3 additions & 0 deletions include/acpi/acpi_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
return ioremap_cache(phys, size);
}

void __iomem *__init_refok
acpi_os_map_iomem(acpi_physical_address phys, 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);

int acpi_os_map_generic_address(struct acpi_generic_address *addr);
Expand Down
6 changes: 0 additions & 6 deletions include/acpi/platform/aclinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory

/*
* OSL interfaces used by debugger/disassembler
Expand Down Expand Up @@ -163,10 +161,6 @@
#define __init
#endif

#ifndef __iomem
#define __iomem
#endif

/* Host-dependent types and defines for user-space ACPICA */

#define ACPI_FLUSH_CPU_CACHE()
Expand Down
4 changes: 0 additions & 4 deletions include/acpi/platform/aclinuxex.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,6 @@ static inline acpi_thread_id acpi_os_get_thread_id(void)
lock ? AE_OK : AE_NO_MEMORY; \
})

void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_size length);

void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size);

/*
* OSL interfaces added by Linux
*/
Expand Down

0 comments on commit a238317

Please sign in to comment.