aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgengdongjiu <gengdongjiu@huawei.com>2017-08-17 08:07:18 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-08-23 21:29:46 -0400
commitc4335fdd38227788178953c101b77180504d7ea0 (patch)
treeaee9af84eabebc7d57f91df74589f553b7b76757
parentbdb9458a3382ba745a66be5526d3899103c76eda (diff)
ACPI: APEI: fix the wrong iteration of generic error status block
The revision 0x300 generic error data entry is different from the old version, but currently iterating through the GHES estatus blocks does not take into account this difference. This will lead to failure to get the right data entry if GHES has revision 0x300 error data entry. Update the GHES estatus iteration macro to properly increment using acpi_hest_get_next(), and correct the iteration termination condition because the status block data length only includes error data length. Convert the CPER estatus checking and printing iteration logic to use same macro. Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com> Tested-by: Tyler Baicar <tbaicar@codeaurora.org> Reviewed-by: Borislav Petkov <bp@suse.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/apei/apei-internal.h5
-rw-r--r--drivers/firmware/efi/cper.c12
-rw-r--r--include/acpi/ghes.h5
3 files changed, 7 insertions, 15 deletions
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index 6e9f14c0a71b..cb4126051f62 100644
--- a/drivers/acpi/apei/apei-internal.h
+++ b/drivers/acpi/apei/apei-internal.h
@@ -120,11 +120,6 @@ int apei_exec_collect_resources(struct apei_exec_context *ctx,
120struct dentry; 120struct dentry;
121struct dentry *apei_get_debugfs_dir(void); 121struct dentry *apei_get_debugfs_dir(void);
122 122
123#define apei_estatus_for_each_section(estatus, section) \
124 for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
125 (void *)section - (void *)estatus < estatus->data_length; \
126 section = (void *)(section+1) + section->error_data_length)
127
128static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus) 123static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus)
129{ 124{
130 if (estatus->raw_data_length) 125 if (estatus->raw_data_length)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 48a8f69da42a..bf3672a81e49 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -606,7 +606,6 @@ void cper_estatus_print(const char *pfx,
606 const struct acpi_hest_generic_status *estatus) 606 const struct acpi_hest_generic_status *estatus)
607{ 607{
608 struct acpi_hest_generic_data *gdata; 608 struct acpi_hest_generic_data *gdata;
609 unsigned int data_len;
610 int sec_no = 0; 609 int sec_no = 0;
611 char newpfx[64]; 610 char newpfx[64];
612 __u16 severity; 611 __u16 severity;
@@ -617,14 +616,10 @@ void cper_estatus_print(const char *pfx,
617 "It has been corrected by h/w " 616 "It has been corrected by h/w "
618 "and requires no further action"); 617 "and requires no further action");
619 printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); 618 printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
620 data_len = estatus->data_length;
621 gdata = (struct acpi_hest_generic_data *)(estatus + 1);
622 snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); 619 snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
623 620
624 while (data_len >= acpi_hest_get_size(gdata)) { 621 apei_estatus_for_each_section(estatus, gdata) {
625 cper_estatus_print_section(newpfx, gdata, sec_no); 622 cper_estatus_print_section(newpfx, gdata, sec_no);
626 data_len -= acpi_hest_get_record_size(gdata);
627 gdata = acpi_hest_get_next(gdata);
628 sec_no++; 623 sec_no++;
629 } 624 }
630} 625}
@@ -653,15 +648,12 @@ int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
653 if (rc) 648 if (rc)
654 return rc; 649 return rc;
655 data_len = estatus->data_length; 650 data_len = estatus->data_length;
656 gdata = (struct acpi_hest_generic_data *)(estatus + 1);
657 651
658 while (data_len >= acpi_hest_get_size(gdata)) { 652 apei_estatus_for_each_section(estatus, gdata) {
659 gedata_len = acpi_hest_get_error_length(gdata); 653 gedata_len = acpi_hest_get_error_length(gdata);
660 if (gedata_len > data_len - acpi_hest_get_size(gdata)) 654 if (gedata_len > data_len - acpi_hest_get_size(gdata))
661 return -EINVAL; 655 return -EINVAL;
662
663 data_len -= acpi_hest_get_record_size(gdata); 656 data_len -= acpi_hest_get_record_size(gdata);
664 gdata = acpi_hest_get_next(gdata);
665 } 657 }
666 if (data_len) 658 if (data_len)
667 return -EINVAL; 659 return -EINVAL;
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 9f26e01186ae..9061c5c743b3 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -113,6 +113,11 @@ static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata)
113 return (void *)(gdata) + acpi_hest_get_record_size(gdata); 113 return (void *)(gdata) + acpi_hest_get_record_size(gdata);
114} 114}
115 115
116#define apei_estatus_for_each_section(estatus, section) \
117 for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
118 (void *)section - (void *)(estatus + 1) < estatus->data_length; \
119 section = acpi_hest_get_next(section))
120
116int ghes_notify_sea(void); 121int ghes_notify_sea(void);
117 122
118#endif /* GHES_H */ 123#endif /* GHES_H */