diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/apei/Kconfig | 1 | ||||
-rw-r--r-- | drivers/acpi/apei/erst.c | 61 |
2 files changed, 46 insertions, 16 deletions
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 66a03caa2ad9..f739a70b1c70 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config ACPI_APEI | 1 | config ACPI_APEI |
2 | bool "ACPI Platform Error Interface (APEI)" | 2 | bool "ACPI Platform Error Interface (APEI)" |
3 | select MISC_FILESYSTEMS | ||
3 | select PSTORE | 4 | select PSTORE |
4 | depends on X86 | 5 | depends on X86 |
5 | help | 6 | help |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index d6cb0ff6988e..e6cef8e1b534 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -929,13 +929,17 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) | |||
929 | return 0; | 929 | return 0; |
930 | } | 930 | } |
931 | 931 | ||
932 | static size_t erst_reader(u64 *id, enum pstore_type_id *type, | 932 | static int erst_open_pstore(struct pstore_info *psi); |
933 | static int erst_close_pstore(struct pstore_info *psi); | ||
934 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | ||
933 | struct timespec *time); | 935 | struct timespec *time); |
934 | static u64 erst_writer(enum pstore_type_id type, size_t size); | 936 | static u64 erst_writer(enum pstore_type_id type, size_t size); |
935 | 937 | ||
936 | static struct pstore_info erst_info = { | 938 | static struct pstore_info erst_info = { |
937 | .owner = THIS_MODULE, | 939 | .owner = THIS_MODULE, |
938 | .name = "erst", | 940 | .name = "erst", |
941 | .open = erst_open_pstore, | ||
942 | .close = erst_close_pstore, | ||
939 | .read = erst_reader, | 943 | .read = erst_reader, |
940 | .write = erst_writer, | 944 | .write = erst_writer, |
941 | .erase = erst_clear | 945 | .erase = erst_clear |
@@ -957,12 +961,32 @@ struct cper_pstore_record { | |||
957 | char data[]; | 961 | char data[]; |
958 | } __packed; | 962 | } __packed; |
959 | 963 | ||
960 | static size_t erst_reader(u64 *id, enum pstore_type_id *type, | 964 | static int reader_pos; |
965 | |||
966 | static int erst_open_pstore(struct pstore_info *psi) | ||
967 | { | ||
968 | int rc; | ||
969 | |||
970 | if (erst_disable) | ||
971 | return -ENODEV; | ||
972 | |||
973 | rc = erst_get_record_id_begin(&reader_pos); | ||
974 | |||
975 | return rc; | ||
976 | } | ||
977 | |||
978 | static int erst_close_pstore(struct pstore_info *psi) | ||
979 | { | ||
980 | erst_get_record_id_end(); | ||
981 | |||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | ||
961 | struct timespec *time) | 986 | struct timespec *time) |
962 | { | 987 | { |
963 | int rc; | 988 | int rc; |
964 | ssize_t len; | 989 | ssize_t len = 0; |
965 | unsigned long flags; | ||
966 | u64 record_id; | 990 | u64 record_id; |
967 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) | 991 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) |
968 | (erst_info.buf - sizeof(*rcd)); | 992 | (erst_info.buf - sizeof(*rcd)); |
@@ -970,24 +994,28 @@ static size_t erst_reader(u64 *id, enum pstore_type_id *type, | |||
970 | if (erst_disable) | 994 | if (erst_disable) |
971 | return -ENODEV; | 995 | return -ENODEV; |
972 | 996 | ||
973 | raw_spin_lock_irqsave(&erst_lock, flags); | ||
974 | skip: | 997 | skip: |
975 | rc = __erst_get_next_record_id(&record_id); | 998 | rc = erst_get_record_id_next(&reader_pos, &record_id); |
976 | if (rc) { | 999 | if (rc) |
977 | raw_spin_unlock_irqrestore(&erst_lock, flags); | 1000 | goto out; |
978 | return rc; | 1001 | |
979 | } | ||
980 | /* no more record */ | 1002 | /* no more record */ |
981 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { | 1003 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { |
982 | raw_spin_unlock_irqrestore(&erst_lock, flags); | 1004 | rc = -1; |
983 | return 0; | 1005 | goto out; |
984 | } | 1006 | } |
985 | 1007 | ||
986 | len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) + | 1008 | len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) + |
987 | erst_erange.size); | 1009 | erst_info.bufsize); |
1010 | /* The record may be cleared by others, try read next record */ | ||
1011 | if (len == -ENOENT) | ||
1012 | goto skip; | ||
1013 | else if (len < 0) { | ||
1014 | rc = -1; | ||
1015 | goto out; | ||
1016 | } | ||
988 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) | 1017 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) |
989 | goto skip; | 1018 | goto skip; |
990 | raw_spin_unlock_irqrestore(&erst_lock, flags); | ||
991 | 1019 | ||
992 | *id = record_id; | 1020 | *id = record_id; |
993 | if (uuid_le_cmp(rcd->sec_hdr.section_type, | 1021 | if (uuid_le_cmp(rcd->sec_hdr.section_type, |
@@ -1005,7 +1033,8 @@ skip: | |||
1005 | time->tv_sec = 0; | 1033 | time->tv_sec = 0; |
1006 | time->tv_nsec = 0; | 1034 | time->tv_nsec = 0; |
1007 | 1035 | ||
1008 | return len - sizeof(*rcd); | 1036 | out: |
1037 | return (rc < 0) ? rc : (len - sizeof(*rcd)); | ||
1009 | } | 1038 | } |
1010 | 1039 | ||
1011 | static u64 erst_writer(enum pstore_type_id type, size_t size) | 1040 | static u64 erst_writer(enum pstore_type_id type, size_t size) |