diff options
author | Lv Zheng <lv.zheng@intel.com> | 2014-05-20 03:39:41 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-05-27 12:13:08 -0400 |
commit | a238317ce8185519ed083e81e84260907fbbcf7f (patch) | |
tree | f5b228ac40941946db2e7427b1085a90c78c85b5 | |
parent | 92985ef1db428cc6129a1d375a68c277aa05820b (diff) |
ACPI: Clean up acpi_os_map/unmap_memory() to eliminate __iomem.
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 <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/acpi_extlog.c | 16 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 14 | ||||
-rw-r--r-- | drivers/acpi/nvs.c | 4 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 21 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_acpi.c | 4 | ||||
-rw-r--r-- | include/acpi/acpi_io.h | 3 | ||||
-rw-r--r-- | include/acpi/platform/aclinux.h | 6 | ||||
-rw-r--r-- | include/acpi/platform/aclinuxex.h | 4 |
8 files changed, 39 insertions, 33 deletions
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index c4a5d87ede7e..185334114d71 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c | |||
@@ -220,13 +220,13 @@ static int __init extlog_init(void) | |||
220 | goto err; | 220 | goto err; |
221 | } | 221 | } |
222 | 222 | ||
223 | extlog_l1_hdr = acpi_os_map_memory(l1_dirbase, l1_hdr_size); | 223 | extlog_l1_hdr = acpi_os_map_iomem(l1_dirbase, l1_hdr_size); |
224 | l1_head = (struct extlog_l1_head *)extlog_l1_hdr; | 224 | l1_head = (struct extlog_l1_head *)extlog_l1_hdr; |
225 | l1_size = l1_head->total_len; | 225 | l1_size = l1_head->total_len; |
226 | l1_percpu_entry = l1_head->entries; | 226 | l1_percpu_entry = l1_head->entries; |
227 | elog_base = l1_head->elog_base; | 227 | elog_base = l1_head->elog_base; |
228 | elog_size = l1_head->elog_len; | 228 | elog_size = l1_head->elog_len; |
229 | acpi_os_unmap_memory(extlog_l1_hdr, l1_hdr_size); | 229 | acpi_os_unmap_iomem(extlog_l1_hdr, l1_hdr_size); |
230 | release_mem_region(l1_dirbase, l1_hdr_size); | 230 | release_mem_region(l1_dirbase, l1_hdr_size); |
231 | 231 | ||
232 | /* remap L1 header again based on completed information */ | 232 | /* remap L1 header again based on completed information */ |
@@ -237,7 +237,7 @@ static int __init extlog_init(void) | |||
237 | (unsigned long long)l1_dirbase + l1_size); | 237 | (unsigned long long)l1_dirbase + l1_size); |
238 | goto err; | 238 | goto err; |
239 | } | 239 | } |
240 | extlog_l1_addr = acpi_os_map_memory(l1_dirbase, l1_size); | 240 | extlog_l1_addr = acpi_os_map_iomem(l1_dirbase, l1_size); |
241 | l1_entry_base = (u64 *)((u8 *)extlog_l1_addr + l1_hdr_size); | 241 | l1_entry_base = (u64 *)((u8 *)extlog_l1_addr + l1_hdr_size); |
242 | 242 | ||
243 | /* remap elog table */ | 243 | /* remap elog table */ |
@@ -248,7 +248,7 @@ static int __init extlog_init(void) | |||
248 | (unsigned long long)elog_base + elog_size); | 248 | (unsigned long long)elog_base + elog_size); |
249 | goto err_release_l1_dir; | 249 | goto err_release_l1_dir; |
250 | } | 250 | } |
251 | elog_addr = acpi_os_map_memory(elog_base, elog_size); | 251 | elog_addr = acpi_os_map_iomem(elog_base, elog_size); |
252 | 252 | ||
253 | rc = -ENOMEM; | 253 | rc = -ENOMEM; |
254 | /* allocate buffer to save elog record */ | 254 | /* allocate buffer to save elog record */ |
@@ -270,11 +270,11 @@ static int __init extlog_init(void) | |||
270 | 270 | ||
271 | err_release_elog: | 271 | err_release_elog: |
272 | if (elog_addr) | 272 | if (elog_addr) |
273 | acpi_os_unmap_memory(elog_addr, elog_size); | 273 | acpi_os_unmap_iomem(elog_addr, elog_size); |
274 | release_mem_region(elog_base, elog_size); | 274 | release_mem_region(elog_base, elog_size); |
275 | err_release_l1_dir: | 275 | err_release_l1_dir: |
276 | if (extlog_l1_addr) | 276 | if (extlog_l1_addr) |
277 | acpi_os_unmap_memory(extlog_l1_addr, l1_size); | 277 | acpi_os_unmap_iomem(extlog_l1_addr, l1_size); |
278 | release_mem_region(l1_dirbase, l1_size); | 278 | release_mem_region(l1_dirbase, l1_size); |
279 | err: | 279 | err: |
280 | pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n"); | 280 | pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n"); |
@@ -287,9 +287,9 @@ static void __exit extlog_exit(void) | |||
287 | mce_unregister_decode_chain(&extlog_mce_dec); | 287 | mce_unregister_decode_chain(&extlog_mce_dec); |
288 | ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; | 288 | ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; |
289 | if (extlog_l1_addr) | 289 | if (extlog_l1_addr) |
290 | acpi_os_unmap_memory(extlog_l1_addr, l1_size); | 290 | acpi_os_unmap_iomem(extlog_l1_addr, l1_size); |
291 | if (elog_addr) | 291 | if (elog_addr) |
292 | acpi_os_unmap_memory(elog_addr, elog_size); | 292 | acpi_os_unmap_iomem(elog_addr, elog_size); |
293 | release_mem_region(elog_base, elog_size); | 293 | release_mem_region(elog_base, elog_size); |
294 | release_mem_region(l1_dirbase, l1_size); | 294 | release_mem_region(l1_dirbase, l1_size); |
295 | kfree(elog_buf); | 295 | kfree(elog_buf); |
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 1be6f5564485..a095d4f858da 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -202,7 +202,7 @@ static void check_vendor_extension(u64 paddr, | |||
202 | 202 | ||
203 | if (!offset) | 203 | if (!offset) |
204 | return; | 204 | return; |
205 | v = acpi_os_map_memory(paddr + offset, sizeof(*v)); | 205 | v = acpi_os_map_iomem(paddr + offset, sizeof(*v)); |
206 | if (!v) | 206 | if (!v) |
207 | return; | 207 | return; |
208 | sbdf = v->pcie_sbdf; | 208 | sbdf = v->pcie_sbdf; |
@@ -210,7 +210,7 @@ static void check_vendor_extension(u64 paddr, | |||
210 | sbdf >> 24, (sbdf >> 16) & 0xff, | 210 | sbdf >> 24, (sbdf >> 16) & 0xff, |
211 | (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7, | 211 | (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7, |
212 | v->vendor_id, v->device_id, v->rev_id); | 212 | v->vendor_id, v->device_id, v->rev_id); |
213 | acpi_os_unmap_memory(v, sizeof(*v)); | 213 | acpi_os_unmap_iomem(v, sizeof(*v)); |
214 | } | 214 | } |
215 | 215 | ||
216 | static void *einj_get_parameter_address(void) | 216 | static void *einj_get_parameter_address(void) |
@@ -236,7 +236,7 @@ static void *einj_get_parameter_address(void) | |||
236 | if (pa_v5) { | 236 | if (pa_v5) { |
237 | struct set_error_type_with_address *v5param; | 237 | struct set_error_type_with_address *v5param; |
238 | 238 | ||
239 | v5param = acpi_os_map_memory(pa_v5, sizeof(*v5param)); | 239 | v5param = acpi_os_map_iomem(pa_v5, sizeof(*v5param)); |
240 | if (v5param) { | 240 | if (v5param) { |
241 | acpi5 = 1; | 241 | acpi5 = 1; |
242 | check_vendor_extension(pa_v5, v5param); | 242 | check_vendor_extension(pa_v5, v5param); |
@@ -246,11 +246,11 @@ static void *einj_get_parameter_address(void) | |||
246 | if (param_extension && pa_v4) { | 246 | if (param_extension && pa_v4) { |
247 | struct einj_parameter *v4param; | 247 | struct einj_parameter *v4param; |
248 | 248 | ||
249 | v4param = acpi_os_map_memory(pa_v4, sizeof(*v4param)); | 249 | v4param = acpi_os_map_iomem(pa_v4, sizeof(*v4param)); |
250 | if (!v4param) | 250 | if (!v4param) |
251 | return NULL; | 251 | return NULL; |
252 | if (v4param->reserved1 || v4param->reserved2) { | 252 | if (v4param->reserved1 || v4param->reserved2) { |
253 | acpi_os_unmap_memory(v4param, sizeof(*v4param)); | 253 | acpi_os_unmap_iomem(v4param, sizeof(*v4param)); |
254 | return NULL; | 254 | return NULL; |
255 | } | 255 | } |
256 | return v4param; | 256 | return v4param; |
@@ -794,7 +794,7 @@ err_unmap: | |||
794 | sizeof(struct set_error_type_with_address) : | 794 | sizeof(struct set_error_type_with_address) : |
795 | sizeof(struct einj_parameter); | 795 | sizeof(struct einj_parameter); |
796 | 796 | ||
797 | acpi_os_unmap_memory(einj_param, size); | 797 | acpi_os_unmap_iomem(einj_param, size); |
798 | } | 798 | } |
799 | apei_exec_post_unmap_gars(&ctx); | 799 | apei_exec_post_unmap_gars(&ctx); |
800 | err_release: | 800 | err_release: |
@@ -816,7 +816,7 @@ static void __exit einj_exit(void) | |||
816 | sizeof(struct set_error_type_with_address) : | 816 | sizeof(struct set_error_type_with_address) : |
817 | sizeof(struct einj_parameter); | 817 | sizeof(struct einj_parameter); |
818 | 818 | ||
819 | acpi_os_unmap_memory(einj_param, size); | 819 | acpi_os_unmap_iomem(einj_param, size); |
820 | } | 820 | } |
821 | einj_exec_ctx_init(&ctx); | 821 | einj_exec_ctx_init(&ctx); |
822 | apei_exec_post_unmap_gars(&ctx); | 822 | apei_exec_post_unmap_gars(&ctx); |
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index de4fe03873c5..85287b8fe3aa 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c | |||
@@ -139,8 +139,8 @@ void suspend_nvs_free(void) | |||
139 | iounmap(entry->kaddr); | 139 | iounmap(entry->kaddr); |
140 | entry->unmap = false; | 140 | entry->unmap = false; |
141 | } else { | 141 | } else { |
142 | acpi_os_unmap_memory(entry->kaddr, | 142 | acpi_os_unmap_iomem(entry->kaddr, |
143 | entry->size); | 143 | entry->size); |
144 | } | 144 | } |
145 | entry->kaddr = NULL; | 145 | entry->kaddr = NULL; |
146 | } | 146 | } |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 9aeae41e22fb..147bc1b91b42 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -355,7 +355,7 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) | |||
355 | } | 355 | } |
356 | 356 | ||
357 | void __iomem *__init_refok | 357 | void __iomem *__init_refok |
358 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | 358 | acpi_os_map_iomem(acpi_physical_address phys, acpi_size size) |
359 | { | 359 | { |
360 | struct acpi_ioremap *map; | 360 | struct acpi_ioremap *map; |
361 | void __iomem *virt; | 361 | void __iomem *virt; |
@@ -401,10 +401,17 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
401 | 401 | ||
402 | list_add_tail_rcu(&map->list, &acpi_ioremaps); | 402 | list_add_tail_rcu(&map->list, &acpi_ioremaps); |
403 | 403 | ||
404 | out: | 404 | out: |
405 | mutex_unlock(&acpi_ioremap_lock); | 405 | mutex_unlock(&acpi_ioremap_lock); |
406 | return map->virt + (phys - map->phys); | 406 | return map->virt + (phys - map->phys); |
407 | } | 407 | } |
408 | EXPORT_SYMBOL_GPL(acpi_os_map_iomem); | ||
409 | |||
410 | void *__init_refok | ||
411 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | ||
412 | { | ||
413 | return (void *)acpi_os_map_iomem(phys, size); | ||
414 | } | ||
408 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); | 415 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); |
409 | 416 | ||
410 | static void acpi_os_drop_map_ref(struct acpi_ioremap *map) | 417 | static void acpi_os_drop_map_ref(struct acpi_ioremap *map) |
@@ -422,7 +429,7 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map) | |||
422 | } | 429 | } |
423 | } | 430 | } |
424 | 431 | ||
425 | void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | 432 | void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size) |
426 | { | 433 | { |
427 | struct acpi_ioremap *map; | 434 | struct acpi_ioremap *map; |
428 | 435 | ||
@@ -443,6 +450,12 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | |||
443 | 450 | ||
444 | acpi_os_map_cleanup(map); | 451 | acpi_os_map_cleanup(map); |
445 | } | 452 | } |
453 | EXPORT_SYMBOL_GPL(acpi_os_unmap_iomem); | ||
454 | |||
455 | void __ref acpi_os_unmap_memory(void *virt, acpi_size size) | ||
456 | { | ||
457 | return acpi_os_unmap_iomem((void __iomem *)virt, size); | ||
458 | } | ||
446 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); | 459 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); |
447 | 460 | ||
448 | void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | 461 | void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) |
@@ -464,7 +477,7 @@ int acpi_os_map_generic_address(struct acpi_generic_address *gas) | |||
464 | if (!addr || !gas->bit_width) | 477 | if (!addr || !gas->bit_width) |
465 | return -EINVAL; | 478 | return -EINVAL; |
466 | 479 | ||
467 | virt = acpi_os_map_memory(addr, gas->bit_width / 8); | 480 | virt = acpi_os_map_iomem(addr, gas->bit_width / 8); |
468 | if (!virt) | 481 | if (!virt) |
469 | return -EIO; | 482 | return -EIO; |
470 | 483 | ||
diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c index b9a57fa4b710..565a9478cb94 100644 --- a/drivers/char/tpm/tpm_acpi.c +++ b/drivers/char/tpm/tpm_acpi.c | |||
@@ -95,7 +95,7 @@ int read_log(struct tpm_bios_log *log) | |||
95 | 95 | ||
96 | log->bios_event_log_end = log->bios_event_log + len; | 96 | log->bios_event_log_end = log->bios_event_log + len; |
97 | 97 | ||
98 | virt = acpi_os_map_memory(start, len); | 98 | virt = acpi_os_map_iomem(start, len); |
99 | if (!virt) { | 99 | if (!virt) { |
100 | kfree(log->bios_event_log); | 100 | kfree(log->bios_event_log); |
101 | printk("%s: ERROR - Unable to map memory\n", __func__); | 101 | printk("%s: ERROR - Unable to map memory\n", __func__); |
@@ -104,6 +104,6 @@ int read_log(struct tpm_bios_log *log) | |||
104 | 104 | ||
105 | memcpy_fromio(log->bios_event_log, virt, len); | 105 | memcpy_fromio(log->bios_event_log, virt, len); |
106 | 106 | ||
107 | acpi_os_unmap_memory(virt, len); | 107 | acpi_os_unmap_iomem(virt, len); |
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
diff --git a/include/acpi/acpi_io.h b/include/acpi/acpi_io.h index 2be858018c7f..444671e9c65d 100644 --- a/include/acpi/acpi_io.h +++ b/include/acpi/acpi_io.h | |||
@@ -9,6 +9,9 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, | |||
9 | return ioremap_cache(phys, size); | 9 | return ioremap_cache(phys, size); |
10 | } | 10 | } |
11 | 11 | ||
12 | void __iomem *__init_refok | ||
13 | acpi_os_map_iomem(acpi_physical_address phys, acpi_size size); | ||
14 | void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size); | ||
12 | void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); | 15 | void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); |
13 | 16 | ||
14 | int acpi_os_map_generic_address(struct acpi_generic_address *addr); | 17 | int acpi_os_map_generic_address(struct acpi_generic_address *addr); |
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index e70012956db3..cd1f052d55bb 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h | |||
@@ -128,8 +128,6 @@ | |||
128 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object | 128 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object |
129 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id | 129 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id |
130 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock | 130 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock |
131 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory | ||
132 | #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory | ||
133 | 131 | ||
134 | /* | 132 | /* |
135 | * OSL interfaces used by debugger/disassembler | 133 | * OSL interfaces used by debugger/disassembler |
@@ -163,10 +161,6 @@ | |||
163 | #define __init | 161 | #define __init |
164 | #endif | 162 | #endif |
165 | 163 | ||
166 | #ifndef __iomem | ||
167 | #define __iomem | ||
168 | #endif | ||
169 | |||
170 | /* Host-dependent types and defines for user-space ACPICA */ | 164 | /* Host-dependent types and defines for user-space ACPICA */ |
171 | 165 | ||
172 | #define ACPI_FLUSH_CPU_CACHE() | 166 | #define ACPI_FLUSH_CPU_CACHE() |
diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h index cce0723d05a9..191e741cfa0e 100644 --- a/include/acpi/platform/aclinuxex.h +++ b/include/acpi/platform/aclinuxex.h | |||
@@ -102,10 +102,6 @@ static inline acpi_thread_id acpi_os_get_thread_id(void) | |||
102 | lock ? AE_OK : AE_NO_MEMORY; \ | 102 | lock ? AE_OK : AE_NO_MEMORY; \ |
103 | }) | 103 | }) |
104 | 104 | ||
105 | void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_size length); | ||
106 | |||
107 | void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); | ||
108 | |||
109 | /* | 105 | /* |
110 | * OSL interfaces added by Linux | 106 | * OSL interfaces added by Linux |
111 | */ | 107 | */ |