Lines Matching +full:entry +full:- +full:address
1 // SPDX-License-Identifier: GPL-2.0-only
3 * apei-base.c - ACPI Platform Error Interface (APEI) supporting
33 #include "apei-internal.h"
50 ctx->ins_table = ins_table; in apei_exec_ctx_init()
51 ctx->instructions = instructions; in apei_exec_ctx_init()
52 ctx->action_table = action_table; in apei_exec_ctx_init()
53 ctx->entries = entries; in apei_exec_ctx_init()
57 int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val) in __apei_exec_read_register() argument
61 rc = apei_read(val, &entry->register_region); in __apei_exec_read_register()
64 *val >>= entry->register_region.bit_offset; in __apei_exec_read_register()
65 *val &= entry->mask; in __apei_exec_read_register()
71 struct acpi_whea_header *entry) in apei_exec_read_register() argument
76 rc = __apei_exec_read_register(entry, &val); in apei_exec_read_register()
79 ctx->value = val; in apei_exec_read_register()
86 struct acpi_whea_header *entry) in apei_exec_read_register_value() argument
90 rc = apei_exec_read_register(ctx, entry); in apei_exec_read_register_value()
93 ctx->value = (ctx->value == entry->value); in apei_exec_read_register_value()
99 int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val) in __apei_exec_write_register() argument
103 val &= entry->mask; in __apei_exec_write_register()
104 val <<= entry->register_region.bit_offset; in __apei_exec_write_register()
105 if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) { in __apei_exec_write_register()
107 rc = apei_read(&valr, &entry->register_region); in __apei_exec_write_register()
110 valr &= ~(entry->mask << entry->register_region.bit_offset); in __apei_exec_write_register()
113 rc = apei_write(val, &entry->register_region); in __apei_exec_write_register()
119 struct acpi_whea_header *entry) in apei_exec_write_register() argument
121 return __apei_exec_write_register(entry, ctx->value); in apei_exec_write_register()
126 struct acpi_whea_header *entry) in apei_exec_write_register_value() argument
128 ctx->value = entry->value; in apei_exec_write_register_value()
130 return apei_exec_write_register(ctx, entry); in apei_exec_write_register_value()
135 struct acpi_whea_header *entry) in apei_exec_noop() argument
148 int rc = -ENOENT; in __apei_exec_run()
150 struct acpi_whea_header *entry; in __apei_exec_run() local
153 ctx->ip = 0; in __apei_exec_run()
157 * "ctx->ip" specifies the next instruction to executed, in __apei_exec_run()
158 * instruction "run" function may change the "ctx->ip" to in __apei_exec_run()
163 for (i = 0; i < ctx->entries; i++) { in __apei_exec_run()
164 entry = &ctx->action_table[i]; in __apei_exec_run()
165 if (entry->action != action) in __apei_exec_run()
167 if (ip == ctx->ip) { in __apei_exec_run()
168 if (entry->instruction >= ctx->instructions || in __apei_exec_run()
169 !ctx->ins_table[entry->instruction].run) { in __apei_exec_run()
172 entry->instruction); in __apei_exec_run()
173 return -EINVAL; in __apei_exec_run()
175 run = ctx->ins_table[entry->instruction].run; in __apei_exec_run()
176 rc = run(ctx, entry); in __apei_exec_run()
180 ctx->ip++; in __apei_exec_run()
183 if (ctx->ip < ip) in __apei_exec_run()
192 struct acpi_whea_header *entry,
202 struct acpi_whea_header *entry; in apei_exec_for_each_entry() local
203 struct apei_exec_ins_type *ins_table = ctx->ins_table; in apei_exec_for_each_entry()
205 for (i = 0; i < ctx->entries; i++) { in apei_exec_for_each_entry()
206 entry = ctx->action_table + i; in apei_exec_for_each_entry()
207 ins = entry->instruction; in apei_exec_for_each_entry()
210 if (ins >= ctx->instructions || !ins_table[ins].run) { in apei_exec_for_each_entry()
214 return -EINVAL; in apei_exec_for_each_entry()
216 rc = func(ctx, entry, data); in apei_exec_for_each_entry()
225 struct acpi_whea_header *entry, in pre_map_gar_callback() argument
228 u8 ins = entry->instruction; in pre_map_gar_callback()
230 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) in pre_map_gar_callback()
231 return apei_map_generic_address(&entry->register_region); in pre_map_gar_callback()
237 * Pre-map all GARs in action table to make it possible to access them
258 struct acpi_whea_header *entry, in post_unmap_gar_callback() argument
261 u8 ins = entry->instruction; in post_unmap_gar_callback()
263 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) in post_unmap_gar_callback()
264 apei_unmap_generic_address(&entry->register_region); in post_unmap_gar_callback()
269 /* Post-unmap all GAR in action table. */
302 if (res->start > end || res->end < start) in apei_res_add()
304 else if (end <= res->end && start >= res->start) { in apei_res_add()
308 list_del(&res->list); in apei_res_add()
309 res->start = start = min(res->start, start); in apei_res_add()
310 res->end = end = max(res->end, end); in apei_res_add()
317 list_add(&res_ins->list, res_list); in apei_res_add()
321 return -ENOMEM; in apei_res_add()
322 res_ins->start = start; in apei_res_add()
323 res_ins->end = end; in apei_res_add()
324 list_add(&res_ins->list, res_list); in apei_res_add()
334 res1 = list_entry(res_list1->next, struct apei_res, list); in apei_res_sub()
335 resn1 = list_entry(res1->list.next, struct apei_res, list); in apei_res_sub()
336 while (&res1->list != res_list1) { in apei_res_sub()
338 if (res1->start >= res2->end || in apei_res_sub()
339 res1->end <= res2->start) in apei_res_sub()
341 else if (res1->end <= res2->end && in apei_res_sub()
342 res1->start >= res2->start) { in apei_res_sub()
343 list_del(&res1->list); in apei_res_sub()
346 } else if (res1->end > res2->end && in apei_res_sub()
347 res1->start < res2->start) { in apei_res_sub()
350 return -ENOMEM; in apei_res_sub()
351 res->start = res2->end; in apei_res_sub()
352 res->end = res1->end; in apei_res_sub()
353 res1->end = res2->start; in apei_res_sub()
354 list_add(&res->list, &res1->list); in apei_res_sub()
357 if (res1->start < res2->start) in apei_res_sub()
358 res1->end = res2->start; in apei_res_sub()
360 res1->start = res2->end; in apei_res_sub()
364 resn1 = list_entry(resn1->list.next, struct apei_res, list); in apei_res_sub()
375 list_del(&res->list); in apei_res_clean()
382 apei_res_clean(&resources->iomem); in apei_resources_fini()
383 apei_res_clean(&resources->ioport); in apei_resources_fini()
393 list_for_each_entry(res, &resources2->iomem, list) { in apei_resources_merge()
394 rc = apei_res_add(&resources1->iomem, res->start, in apei_resources_merge()
395 res->end - res->start); in apei_resources_merge()
399 list_for_each_entry(res, &resources2->ioport, list) { in apei_resources_merge()
400 rc = apei_res_add(&resources1->ioport, res->start, in apei_resources_merge()
401 res->end - res->start); in apei_resources_merge()
414 return apei_res_add(&resources->iomem, start, size); in apei_resources_add()
416 return apei_res_add(&resources->ioport, start, size); in apei_resources_add()
421 * EINJ has two groups of GARs (EINJ table entry and trigger table
422 * entry), so common resources are subtracted from the trigger table
430 rc = apei_res_sub(&resources1->iomem, &resources2->iomem); in apei_resources_sub()
433 return apei_res_sub(&resources1->ioport, &resources2->ioport); in apei_resources_sub()
440 return apei_res_add(&resources->iomem, start, size); in apei_get_res_callback()
496 rc = -EINVAL; in apei_resources_request()
497 list_for_each_entry(res, &resources->iomem, list) { in apei_resources_request()
498 r = request_mem_region(res->start, res->end - res->start, in apei_resources_request()
502 "Can not request [mem %#010llx-%#010llx] for %s registers\n", in apei_resources_request()
503 (unsigned long long)res->start, in apei_resources_request()
504 (unsigned long long)res->end - 1, desc); in apei_resources_request()
510 list_for_each_entry(res, &resources->ioport, list) { in apei_resources_request()
511 r = request_region(res->start, res->end - res->start, desc); in apei_resources_request()
514 "Can not request [io %#06llx-%#06llx] for %s registers\n", in apei_resources_request()
515 (unsigned long long)res->start, in apei_resources_request()
516 (unsigned long long)res->end - 1, desc); in apei_resources_request()
531 list_for_each_entry(res, &resources->ioport, list) { in apei_resources_request()
534 release_region(res->start, res->end - res->start); in apei_resources_request()
538 list_for_each_entry(res, &resources->iomem, list) { in apei_resources_request()
541 release_mem_region(res->start, res->end - res->start); in apei_resources_request()
557 list_for_each_entry(res, &resources->iomem, list) in apei_resources_release()
558 release_mem_region(res->start, res->end - res->start); in apei_resources_release()
559 list_for_each_entry(res, &resources->ioport, list) in apei_resources_release()
560 release_region(res->start, res->end - res->start); in apei_resources_release()
573 bit_width = reg->bit_width; in apei_check_gar()
574 bit_offset = reg->bit_offset; in apei_check_gar()
575 access_size_code = reg->access_width; in apei_check_gar()
576 space_id = reg->space_id; in apei_check_gar()
577 *paddr = get_unaligned(®->address); in apei_check_gar()
580 "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n", in apei_check_gar()
583 return -EINVAL; in apei_check_gar()
591 return -EINVAL; in apei_check_gar()
608 return -EINVAL; in apei_check_gar()
614 "Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n", in apei_check_gar()
617 return -EINVAL; in apei_check_gar()
627 u64 address; in apei_map_generic_address() local
629 rc = apei_check_gar(reg, &address, &access_bit_width); in apei_map_generic_address()
634 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) in apei_map_generic_address()
638 return -ENXIO; in apei_map_generic_address()
649 u64 address; in apei_read() local
652 rc = apei_check_gar(reg, &address, &access_bit_width); in apei_read()
657 switch(reg->space_id) { in apei_read()
659 status = acpi_os_read_memory((acpi_physical_address) address, in apei_read()
662 return -EIO; in apei_read()
665 status = acpi_os_read_port(address, (u32 *)val, in apei_read()
668 return -EIO; in apei_read()
671 return -EINVAL; in apei_read()
683 u64 address; in apei_write() local
686 rc = apei_check_gar(reg, &address, &access_bit_width); in apei_write()
690 switch (reg->space_id) { in apei_write()
692 status = acpi_os_write_memory((acpi_physical_address) address, in apei_write()
695 return -EIO; in apei_write()
698 status = acpi_os_write_port(address, val, access_bit_width); in apei_write()
700 return -EIO; in apei_write()
703 return -EINVAL; in apei_write()
711 struct acpi_whea_header *entry, in collect_res_callback() argument
715 struct acpi_generic_address *reg = &entry->register_region; in collect_res_callback()
716 u8 ins = entry->instruction; in collect_res_callback()
721 if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)) in collect_res_callback()
728 switch (reg->space_id) { in collect_res_callback()
730 return apei_res_add(&resources->iomem, paddr, in collect_res_callback()
733 return apei_res_add(&resources->ioport, paddr, in collect_res_callback()
736 return -EINVAL; in collect_res_callback()
778 static u8 whea_uuid_str[] = "ed855e0c-6c90-47bf-a62a-26de0fc5ad5c"; in apei_osc_setup()
794 return -EIO; in apei_osc_setup()