aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/apei
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2012-03-30 16:12:23 -0400
committerLen Brown <len.brown@intel.com>2012-03-30 16:14:02 -0400
commit73f05330497b98c45d157b7d0c60673798bb4c3b (patch)
tree67fc16c0f55c482882aea49eaa1d8d95b23722e0 /drivers/acpi/apei
parent1a05e4678724c4a5fe7b9e4e208b616dfe8c3a32 (diff)
parent8cdde126aa60ced0d63ff137378e09dd01dfadda (diff)
Merge branch 'apei' into release
Conflicts: drivers/acpi/apei/apei-base.c This was a conflict between 15afae604651d4e17652d2ffb56f5e36f991cfef (CPI, APEI: Fix incorrect APEI register bit width check and usage) and 653f4b538f66d37db560e0f56af08117136d29b7 (ACPICA: Expand OSL memory read/write interfaces to 64 bits) The former changed a parameter in the call to acpi_os_read_memory64() and the later replaced all calls to acpi_os_read_memory64() with calls to acpi_os_read_memory(). Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/apei')
-rw-r--r--drivers/acpi/apei/apei-base.c61
-rw-r--r--drivers/acpi/apei/cper.c2
-rw-r--r--drivers/acpi/apei/einj.c17
-rw-r--r--drivers/acpi/apei/erst.c2
4 files changed, 56 insertions, 26 deletions
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index ca773683d87..5577762daee 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -558,33 +558,48 @@ void apei_resources_release(struct apei_resources *resources)
558} 558}
559EXPORT_SYMBOL_GPL(apei_resources_release); 559EXPORT_SYMBOL_GPL(apei_resources_release);
560 560
561static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr) 561static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
562 u32 *access_bit_width)
562{ 563{
563 u32 width, space_id; 564 u32 bit_width, bit_offset, access_size_code, space_id;
564 565
565 width = reg->bit_width; 566 bit_width = reg->bit_width;
567 bit_offset = reg->bit_offset;
568 access_size_code = reg->access_width;
566 space_id = reg->space_id; 569 space_id = reg->space_id;
567 /* Handle possible alignment issues */ 570 /* Handle possible alignment issues */
568 memcpy(paddr, &reg->address, sizeof(*paddr)); 571 memcpy(paddr, &reg->address, sizeof(*paddr));
569 if (!*paddr) { 572 if (!*paddr) {
570 pr_warning(FW_BUG APEI_PFX 573 pr_warning(FW_BUG APEI_PFX
571 "Invalid physical address in GAR [0x%llx/%u/%u]\n", 574 "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
572 *paddr, width, space_id); 575 *paddr, bit_width, bit_offset, access_size_code,
576 space_id);
573 return -EINVAL; 577 return -EINVAL;
574 } 578 }
575 579
576 if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) { 580 if (access_size_code < 1 || access_size_code > 4) {
577 pr_warning(FW_BUG APEI_PFX 581 pr_warning(FW_BUG APEI_PFX
578 "Invalid bit width in GAR [0x%llx/%u/%u]\n", 582 "Invalid access size code in GAR [0x%llx/%u/%u/%u/%u]\n",
579 *paddr, width, space_id); 583 *paddr, bit_width, bit_offset, access_size_code,
584 space_id);
585 return -EINVAL;
586 }
587 *access_bit_width = 1UL << (access_size_code + 2);
588
589 if ((bit_width + bit_offset) > *access_bit_width) {
590 pr_warning(FW_BUG APEI_PFX
591 "Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n",
592 *paddr, bit_width, bit_offset, access_size_code,
593 space_id);
580 return -EINVAL; 594 return -EINVAL;
581 } 595 }
582 596
583 if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY && 597 if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
584 space_id != ACPI_ADR_SPACE_SYSTEM_IO) { 598 space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
585 pr_warning(FW_BUG APEI_PFX 599 pr_warning(FW_BUG APEI_PFX
586 "Invalid address space type in GAR [0x%llx/%u/%u]\n", 600 "Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n",
587 *paddr, width, space_id); 601 *paddr, bit_width, bit_offset, access_size_code,
602 space_id);
588 return -EINVAL; 603 return -EINVAL;
589 } 604 }
590 605
@@ -595,23 +610,25 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
595int apei_read(u64 *val, struct acpi_generic_address *reg) 610int apei_read(u64 *val, struct acpi_generic_address *reg)
596{ 611{
597 int rc; 612 int rc;
613 u32 access_bit_width;
598 u64 address; 614 u64 address;
599 acpi_status status; 615 acpi_status status;
600 616
601 rc = apei_check_gar(reg, &address); 617 rc = apei_check_gar(reg, &address, &access_bit_width);
602 if (rc) 618 if (rc)
603 return rc; 619 return rc;
604 620
605 *val = 0; 621 *val = 0;
606 switch(reg->space_id) { 622 switch(reg->space_id) {
607 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 623 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
608 status = acpi_os_read_memory((acpi_physical_address) 624 status = acpi_os_read_memory((acpi_physical_address) address,
609 address, val, reg->bit_width); 625 val, access_bit_width);
610 if (ACPI_FAILURE(status)) 626 if (ACPI_FAILURE(status))
611 return -EIO; 627 return -EIO;
612 break; 628 break;
613 case ACPI_ADR_SPACE_SYSTEM_IO: 629 case ACPI_ADR_SPACE_SYSTEM_IO:
614 status = acpi_os_read_port(address, (u32 *)val, reg->bit_width); 630 status = acpi_os_read_port(address, (u32 *)val,
631 access_bit_width);
615 if (ACPI_FAILURE(status)) 632 if (ACPI_FAILURE(status))
616 return -EIO; 633 return -EIO;
617 break; 634 break;
@@ -627,22 +644,23 @@ EXPORT_SYMBOL_GPL(apei_read);
627int apei_write(u64 val, struct acpi_generic_address *reg) 644int apei_write(u64 val, struct acpi_generic_address *reg)
628{ 645{
629 int rc; 646 int rc;
647 u32 access_bit_width;
630 u64 address; 648 u64 address;
631 acpi_status status; 649 acpi_status status;
632 650
633 rc = apei_check_gar(reg, &address); 651 rc = apei_check_gar(reg, &address, &access_bit_width);
634 if (rc) 652 if (rc)
635 return rc; 653 return rc;
636 654
637 switch (reg->space_id) { 655 switch (reg->space_id) {
638 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 656 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
639 status = acpi_os_write_memory((acpi_physical_address) 657 status = acpi_os_write_memory((acpi_physical_address) address,
640 address, val, reg->bit_width); 658 val, access_bit_width);
641 if (ACPI_FAILURE(status)) 659 if (ACPI_FAILURE(status))
642 return -EIO; 660 return -EIO;
643 break; 661 break;
644 case ACPI_ADR_SPACE_SYSTEM_IO: 662 case ACPI_ADR_SPACE_SYSTEM_IO:
645 status = acpi_os_write_port(address, val, reg->bit_width); 663 status = acpi_os_write_port(address, val, access_bit_width);
646 if (ACPI_FAILURE(status)) 664 if (ACPI_FAILURE(status))
647 return -EIO; 665 return -EIO;
648 break; 666 break;
@@ -661,23 +679,24 @@ static int collect_res_callback(struct apei_exec_context *ctx,
661 struct apei_resources *resources = data; 679 struct apei_resources *resources = data;
662 struct acpi_generic_address *reg = &entry->register_region; 680 struct acpi_generic_address *reg = &entry->register_region;
663 u8 ins = entry->instruction; 681 u8 ins = entry->instruction;
682 u32 access_bit_width;
664 u64 paddr; 683 u64 paddr;
665 int rc; 684 int rc;
666 685
667 if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)) 686 if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
668 return 0; 687 return 0;
669 688
670 rc = apei_check_gar(reg, &paddr); 689 rc = apei_check_gar(reg, &paddr, &access_bit_width);
671 if (rc) 690 if (rc)
672 return rc; 691 return rc;
673 692
674 switch (reg->space_id) { 693 switch (reg->space_id) {
675 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 694 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
676 return apei_res_add(&resources->iomem, paddr, 695 return apei_res_add(&resources->iomem, paddr,
677 reg->bit_width / 8); 696 access_bit_width / 8);
678 case ACPI_ADR_SPACE_SYSTEM_IO: 697 case ACPI_ADR_SPACE_SYSTEM_IO:
679 return apei_res_add(&resources->ioport, paddr, 698 return apei_res_add(&resources->ioport, paddr,
680 reg->bit_width / 8); 699 access_bit_width / 8);
681 default: 700 default:
682 return -EINVAL; 701 return -EINVAL;
683 } 702 }
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c
index 5d4189464d6..e6defd86b42 100644
--- a/drivers/acpi/apei/cper.c
+++ b/drivers/acpi/apei/cper.c
@@ -362,6 +362,7 @@ void apei_estatus_print(const char *pfx,
362 gedata_len = gdata->error_data_length; 362 gedata_len = gdata->error_data_length;
363 apei_estatus_print_section(pfx, gdata, sec_no); 363 apei_estatus_print_section(pfx, gdata, sec_no);
364 data_len -= gedata_len + sizeof(*gdata); 364 data_len -= gedata_len + sizeof(*gdata);
365 gdata = (void *)(gdata + 1) + gedata_len;
365 sec_no++; 366 sec_no++;
366 } 367 }
367} 368}
@@ -396,6 +397,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
396 if (gedata_len > data_len - sizeof(*gdata)) 397 if (gedata_len > data_len - sizeof(*gdata))
397 return -EINVAL; 398 return -EINVAL;
398 data_len -= gedata_len + sizeof(*gdata); 399 data_len -= gedata_len + sizeof(*gdata);
400 gdata = (void *)(gdata + 1) + gedata_len;
399 } 401 }
400 if (data_len) 402 if (data_len)
401 return -EINVAL; 403 return -EINVAL;
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 4ca087dd5f4..8e1793649ec 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -74,6 +74,8 @@ struct vendor_error_type_extension {
74 u8 reserved[3]; 74 u8 reserved[3];
75}; 75};
76 76
77static u32 notrigger;
78
77static u32 vendor_flags; 79static u32 vendor_flags;
78static struct debugfs_blob_wrapper vendor_blob; 80static struct debugfs_blob_wrapper vendor_blob;
79static char vendor_dev[64]; 81static char vendor_dev[64];
@@ -238,7 +240,7 @@ static void *einj_get_parameter_address(void)
238 return v5param; 240 return v5param;
239 } 241 }
240 } 242 }
241 if (paddrv4) { 243 if (param_extension && paddrv4) {
242 struct einj_parameter *v4param; 244 struct einj_parameter *v4param;
243 245
244 v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param)); 246 v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
@@ -496,9 +498,11 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
496 if (rc) 498 if (rc)
497 return rc; 499 return rc;
498 trigger_paddr = apei_exec_ctx_get_output(&ctx); 500 trigger_paddr = apei_exec_ctx_get_output(&ctx);
499 rc = __einj_error_trigger(trigger_paddr, type, param1, param2); 501 if (notrigger == 0) {
500 if (rc) 502 rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
501 return rc; 503 if (rc)
504 return rc;
505 }
502 rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION); 506 rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
503 507
504 return rc; 508 return rc;
@@ -700,6 +704,11 @@ static int __init einj_init(void)
700 einj_debug_dir, &error_param2); 704 einj_debug_dir, &error_param2);
701 if (!fentry) 705 if (!fentry)
702 goto err_unmap; 706 goto err_unmap;
707
708 fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
709 einj_debug_dir, &notrigger);
710 if (!fentry)
711 goto err_unmap;
703 } 712 }
704 713
705 if (vendor_dev[0]) { 714 if (vendor_dev[0]) {
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index eb9fab5b96e..e4d9d24eb73 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -917,7 +917,7 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
917{ 917{
918 if ((erst_tab->header_length != 918 if ((erst_tab->header_length !=
919 (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header))) 919 (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
920 && (erst_tab->header_length != sizeof(struct acpi_table_einj))) 920 && (erst_tab->header_length != sizeof(struct acpi_table_erst)))
921 return -EINVAL; 921 return -EINVAL;
922 if (erst_tab->header.length < sizeof(struct acpi_table_erst)) 922 if (erst_tab->header.length < sizeof(struct acpi_table_erst))
923 return -EINVAL; 923 return -EINVAL;