33 #include <linux/kernel.h>
34 #include <linux/module.h>
38 #include <linux/slab.h>
47 #define APEI_PFX "APEI: "
54 #define APEI_EXEC_PRESERVE_REGISTER 0x1
178 for (i = 0; i < ctx->
entries; i++) {
180 if (entry->
action != action)
186 "Invalid action table, unknown instruction type: %d\n",
191 rc =
run(ctx, entry);
202 return !optional && rc < 0 ? rc : 0;
220 for (i = 0; i < ctx->
entries; i++) {
227 "Invalid action table, unknown instruction type: %d\n",
231 rc =
func(ctx, entry, data);
259 rc = apei_exec_for_each_entry(ctx, pre_map_gar_callback,
263 memcpy(&ctx_unmap, ctx,
sizeof(*ctx));
287 return apei_exec_for_each_entry(ctx, post_unmap_gar_callback,
307 static int apei_res_add(
struct list_head *res_list,
311 unsigned long end = start +
size;
317 if (res->
start > end || res->
end < start)
319 else if (end <= res->end && start >= res->
start) {
332 list_add(&res_ins->
list, res_list);
339 list_add(&res_ins->
list, res_list);
345 static int apei_res_sub(
struct list_head *res_list1,
351 while (&res1->
list != res_list1) {
356 else if (res1->
end <= res2->
end &&
361 }
else if (res1->
end > res2->
end &&
385 static void apei_res_clean(
struct list_head *res_list)
397 apei_res_clean(&resources->
iomem);
398 apei_res_clean(&resources->
ioport);
402 static int apei_resources_merge(
struct apei_resources *resources1,
409 rc = apei_res_add(&resources1->
iomem, res->
start,
425 unsigned long start,
unsigned long size,
429 return apei_res_add(&resources->
iomem, start, size);
431 return apei_res_add(&resources->
ioport, start, size);
445 rc = apei_res_sub(&resources1->
iomem, &resources2->
iomem);
448 return apei_res_sub(&resources1->
ioport, &resources2->
ioport);
452 static int apei_get_nvs_callback(
__u64 start,
__u64 size,
void *data)
455 return apei_res_add(&resources->
iomem, start, size);
485 apei_resources_init(&nvs_resources);
486 rc = apei_get_nvs_resources(&nvs_resources);
499 "Can not request [mem %#010llx-%#010llx] for %s registers\n",
500 (
unsigned long long)res->
start,
501 (
unsigned long long)res->
end - 1, desc);
503 goto err_unmap_iomem;
511 "Can not request [io %#06llx-%#06llx] for %s registers\n",
512 (
unsigned long long)res->
start,
513 (
unsigned long long)res->
end - 1, desc);
515 goto err_unmap_ioport;
519 rc = apei_resources_merge(&apei_resources_all, resources);
522 goto err_unmap_ioport;
562 u32 *access_bit_width)
574 "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
575 *paddr, bit_width, bit_offset, access_size_code,
580 if (access_size_code < 1 || access_size_code > 4) {
582 "Invalid access size code in GAR [0x%llx/%u/%u/%u/%u]\n",
583 *paddr, bit_width, bit_offset, access_size_code,
587 *access_bit_width = 1
UL << (access_size_code + 2);
590 if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 &&
591 *access_bit_width < 32)
592 *access_bit_width = 32;
594 if ((bit_width + bit_offset) > *access_bit_width) {
596 "Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n",
597 *paddr, bit_width, bit_offset, access_size_code,
605 "Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n",
606 *paddr, bit_width, bit_offset, access_size_code,
617 u32 access_bit_width;
620 rc = apei_check_gar(reg, &address, &access_bit_width);
631 u32 access_bit_width;
635 rc = apei_check_gar(reg, &address, &access_bit_width);
643 val, access_bit_width);
665 u32 access_bit_width;
669 rc = apei_check_gar(reg, &address, &access_bit_width);
676 val, access_bit_width);
700 u32 access_bit_width;
707 rc = apei_check_gar(reg, &paddr, &access_bit_width);
713 return apei_res_add(&resources->
iomem, paddr,
714 access_bit_width / 8);
716 return apei_res_add(&resources->
ioport, paddr,
717 access_bit_width / 8);
730 return apei_exec_for_each_entry(ctx, collect_res_callback,
737 static struct dentry *dapei;
748 static u8 whea_uuid_str[] =
"ed855e0c-6c90-47bf-a62a-26de0fc5ad5c";
751 struct acpi_osc_context context = {
752 .uuid_str = whea_uuid_str,
754 .cap.length =
sizeof(capbuf),
755 .
cap.pointer = capbuf,
758 capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
759 capbuf[OSC_SUPPORT_TYPE] = 1;
760 capbuf[OSC_CONTROL_TYPE] = 0;
766 kfree(context.ret.pointer);