aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2010-08-14 23:55:47 -0400
committerLen Brown <len.brown@intel.com>2010-08-14 23:55:47 -0400
commitfeb29c5175e61d0f1ec2cbcaccdfa55e588780be (patch)
treee904f95a4ef4e601af0c2d6619671b8a210c8a65
parentf2a66185bed21427d8d347a42eaf0ad1d3d9fc63 (diff)
parent2ff729d506e8db82d76a93bc963df4d0a4d46b57 (diff)
Merge branch 'apei' into release
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-apei.c4
-rw-r--r--drivers/acpi/apei/Kconfig9
-rw-r--r--drivers/acpi/apei/Makefile1
-rw-r--r--drivers/acpi/apei/apei-base.c4
-rw-r--r--drivers/acpi/apei/erst-dbg.c207
-rw-r--r--drivers/acpi/apei/ghes.c172
-rw-r--r--drivers/acpi/apei/hest.c76
-rw-r--r--include/linux/cper.h8
8 files changed, 386 insertions, 95 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-apei.c b/arch/x86/kernel/cpu/mcheck/mce-apei.c
index 745b54f9be89..8209472b27a5 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-apei.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-apei.c
@@ -80,7 +80,7 @@ int apei_write_mce(struct mce *m)
80 rcd.hdr.revision = CPER_RECORD_REV; 80 rcd.hdr.revision = CPER_RECORD_REV;
81 rcd.hdr.signature_end = CPER_SIG_END; 81 rcd.hdr.signature_end = CPER_SIG_END;
82 rcd.hdr.section_count = 1; 82 rcd.hdr.section_count = 1;
83 rcd.hdr.error_severity = CPER_SER_FATAL; 83 rcd.hdr.error_severity = CPER_SEV_FATAL;
84 /* timestamp, platform_id, partition_id are all invalid */ 84 /* timestamp, platform_id, partition_id are all invalid */
85 rcd.hdr.validation_bits = 0; 85 rcd.hdr.validation_bits = 0;
86 rcd.hdr.record_length = sizeof(rcd); 86 rcd.hdr.record_length = sizeof(rcd);
@@ -96,7 +96,7 @@ int apei_write_mce(struct mce *m)
96 rcd.sec_hdr.validation_bits = 0; 96 rcd.sec_hdr.validation_bits = 0;
97 rcd.sec_hdr.flags = CPER_SEC_PRIMARY; 97 rcd.sec_hdr.flags = CPER_SEC_PRIMARY;
98 rcd.sec_hdr.section_type = CPER_SECTION_TYPE_MCE; 98 rcd.sec_hdr.section_type = CPER_SECTION_TYPE_MCE;
99 rcd.sec_hdr.section_severity = CPER_SER_FATAL; 99 rcd.sec_hdr.section_severity = CPER_SEV_FATAL;
100 100
101 memcpy(&rcd.mce, m, sizeof(*m)); 101 memcpy(&rcd.mce, m, sizeof(*m));
102 102
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index f8c668f27b5a..907e350f1c7d 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -28,3 +28,12 @@ config ACPI_APEI_EINJ
28 EINJ provides a hardware error injection mechanism, it is 28 EINJ provides a hardware error injection mechanism, it is
29 mainly used for debugging and testing the other parts of 29 mainly used for debugging and testing the other parts of
30 APEI and some other RAS features. 30 APEI and some other RAS features.
31
32config ACPI_APEI_ERST_DEBUG
33 tristate "APEI Error Record Serialization Table (ERST) Debug Support"
34 depends on ACPI_APEI
35 help
36 ERST is a way provided by APEI to save and retrieve hardware
37 error infomation to and from a persistent store. Enable this
38 if you want to debugging and testing the ERST kernel support
39 and firmware implementation.
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
index b13b03a17789..d1d1bc0a4ee1 100644
--- a/drivers/acpi/apei/Makefile
+++ b/drivers/acpi/apei/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_ACPI_APEI) += apei.o 1obj-$(CONFIG_ACPI_APEI) += apei.o
2obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o 2obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o
3obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o 3obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o
4obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o
4 5
5apei-y := apei-base.o hest.o cper.o erst.o 6apei-y := apei-base.o hest.o cper.o erst.o
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 216e1e948ff6..73fd0c7487c1 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -482,14 +482,14 @@ err_unmap_ioport:
482 list_for_each_entry(res, &resources->ioport, list) { 482 list_for_each_entry(res, &resources->ioport, list) {
483 if (res == res_bak) 483 if (res == res_bak)
484 break; 484 break;
485 release_mem_region(res->start, res->end - res->start); 485 release_region(res->start, res->end - res->start);
486 } 486 }
487 res_bak = NULL; 487 res_bak = NULL;
488err_unmap_iomem: 488err_unmap_iomem:
489 list_for_each_entry(res, &resources->iomem, list) { 489 list_for_each_entry(res, &resources->iomem, list) {
490 if (res == res_bak) 490 if (res == res_bak)
491 break; 491 break;
492 release_region(res->start, res->end - res->start); 492 release_mem_region(res->start, res->end - res->start);
493 } 493 }
494 return -EINVAL; 494 return -EINVAL;
495} 495}
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c
new file mode 100644
index 000000000000..5281ddda2777
--- /dev/null
+++ b/drivers/acpi/apei/erst-dbg.c
@@ -0,0 +1,207 @@
1/*
2 * APEI Error Record Serialization Table debug support
3 *
4 * ERST is a way provided by APEI to save and retrieve hardware error
5 * infomation to and from a persistent store. This file provide the
6 * debugging/testing support for ERST kernel support and firmware
7 * implementation.
8 *
9 * Copyright 2010 Intel Corp.
10 * Author: Huang Ying <ying.huang@intel.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License version
14 * 2 as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/uaccess.h>
29#include <acpi/apei.h>
30#include <linux/miscdevice.h>
31
32#include "apei-internal.h"
33
34#define ERST_DBG_PFX "ERST DBG: "
35
36#define ERST_DBG_RECORD_LEN_MAX 4096
37
38static void *erst_dbg_buf;
39static unsigned int erst_dbg_buf_len;
40
41/* Prevent erst_dbg_read/write from being invoked concurrently */
42static DEFINE_MUTEX(erst_dbg_mutex);
43
44static int erst_dbg_open(struct inode *inode, struct file *file)
45{
46 if (erst_disable)
47 return -ENODEV;
48
49 return nonseekable_open(inode, file);
50}
51
52static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
53{
54 int rc;
55 u64 record_id;
56 u32 record_count;
57
58 switch (cmd) {
59 case APEI_ERST_CLEAR_RECORD:
60 rc = copy_from_user(&record_id, (void __user *)arg,
61 sizeof(record_id));
62 if (rc)
63 return -EFAULT;
64 return erst_clear(record_id);
65 case APEI_ERST_GET_RECORD_COUNT:
66 rc = erst_get_record_count();
67 if (rc < 0)
68 return rc;
69 record_count = rc;
70 rc = put_user(record_count, (u32 __user *)arg);
71 if (rc)
72 return rc;
73 return 0;
74 default:
75 return -ENOTTY;
76 }
77}
78
79static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf,
80 size_t usize, loff_t *off)
81{
82 int rc;
83 ssize_t len = 0;
84 u64 id;
85
86 if (*off != 0)
87 return -EINVAL;
88
89 if (mutex_lock_interruptible(&erst_dbg_mutex) != 0)
90 return -EINTR;
91
92retry_next:
93 rc = erst_get_next_record_id(&id);
94 if (rc)
95 goto out;
96 /* no more record */
97 if (id == APEI_ERST_INVALID_RECORD_ID)
98 goto out;
99retry:
100 rc = len = erst_read(id, erst_dbg_buf, erst_dbg_buf_len);
101 /* The record may be cleared by others, try read next record */
102 if (rc == -ENOENT)
103 goto retry_next;
104 if (rc < 0)
105 goto out;
106