Skip to content

Commit

Permalink
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/aegl/linux-2.6

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6:
  [IA64] tioca: Fix assignment from incompatible pointer warnings
  [IA64] mca.c: Fix cast from integer to pointer warning
  [IA64] setup.c Typo fix "Architechtuallly"
  [IA64] Add CONFIG_MISC_DEVICES=y to configs that need it.
  [IA64] disable interrupts at end of ia64_mca_cpe_int_handler()
  [IA64] Add DMA_ERROR_CODE define.
  pstore: fix build warning for unused return value from sysfs_create_file
  pstore: X86 platform interface using ACPI/APEI/ERST
  pstore: new filesystem interface to platform persistent storage
  • Loading branch information
torvalds committed Mar 17, 2011
2 parents 4c5811b + afe997a commit 242e5d0
Show file tree
Hide file tree
Showing 19 changed files with 766 additions and 3 deletions.
35 changes: 35 additions & 0 deletions Documentation/ABI/testing/pstore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Where: /dev/pstore/...
Date: January 2011
Kernel Version: 2.6.38
Contact: [email protected]
Description: Generic interface to platform dependent persistent storage.

Platforms that provide a mechanism to preserve some data
across system reboots can register with this driver to
provide a generic interface to show records captured in
the dying moments. In the case of a panic the last part
of the console log is captured, but other interesting
data can also be saved.

# mount -t pstore - /dev/pstore

$ ls -l /dev/pstore
total 0
-r--r--r-- 1 root root 7896 Nov 30 15:38 dmesg-erst-1

Different users of this interface will result in different
filename prefixes. Currently two are defined:

"dmesg" - saved console log
"mce" - architecture dependent data from fatal h/w error

Once the information in a file has been read, removing
the file will signal to the underlying persistent storage
device that it can reclaim the space for later re-use.

$ rm /dev/pstore/dmesg-erst-1

The expectation is that all files in /dev/pstore
will be saved elsewhere and erased from persistent store
soon after boot to free up space ready for the next
catastrophe.
7 changes: 7 additions & 0 deletions Documentation/ABI/testing/sysfs-fs-pstore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
What: /sys/fs/pstore/kmsg_bytes
Date: January 2011
Kernel Version: 2.6.38
Contact: "Tony Luck" <[email protected]>
Description:
Controls amount of console log that will be saved
to persistent store on oops/panic.
1 change: 1 addition & 0 deletions arch/ia64/configs/generic_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,4 @@ CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRC_T10DIF=y
CONFIG_MISC_DEVICES=y
1 change: 1 addition & 0 deletions arch/ia64/configs/gensparse_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,4 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_CRYPTO_MD5=y
CONFIG_MISC_DEVICES=y
2 changes: 2 additions & 0 deletions arch/ia64/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#define ARCH_HAS_DMA_GET_REQUIRED_MASK

#define DMA_ERROR_CODE 0

extern struct dma_map_ops *dma_ops;
extern struct ia64_machine_vector ia64_mv;
extern void set_iommu_machvec(void);
Expand Down
5 changes: 4 additions & 1 deletion arch/ia64/kernel/mca.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg)
/* Get the CPE error record and log it */
ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);

local_irq_disable();

return IRQ_HANDLED;
}

Expand Down Expand Up @@ -1859,7 +1861,8 @@ ia64_mca_cpu_init(void *cpu_data)
data = mca_bootmem();
first_time = 0;
} else
data = __get_free_pages(GFP_KERNEL, get_order(sz));
data = (void *)__get_free_pages(GFP_KERNEL,
get_order(sz));
if (!data)
panic("Could not allocate MCA memory for cpu %d\n",
cpu);
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/sn/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ void __cpuinit sn_cpu_init(void)
/*
* Don't check status. The SAL call is not supported on all PROMs
* but a failure is harmless.
* Architechtuallly, cpu_init is always called twice on cpu 0. We
* Architecturally, cpu_init is always called twice on cpu 0. We
* should set cpu_number on cpu 0 once.
*/
if (cpuid == 0) {
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/sn/pci/tioca_provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
* use the GART mapped mode.
*/
static u64
tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
{
u64 mapaddr;

Expand Down
1 change: 1 addition & 0 deletions drivers/acpi/apei/Kconfig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
config ACPI_APEI
bool "ACPI Platform Error Interface (APEI)"
select PSTORE
depends on X86
help
APEI allows to report errors (for example from the chipset)
Expand Down
136 changes: 136 additions & 0 deletions drivers/acpi/apei/erst.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/cper.h>
#include <linux/nmi.h>
#include <linux/hardirq.h>
#include <linux/pstore.h>
#include <acpi/apei.h>

#include "apei-internal.h"
Expand Down Expand Up @@ -781,13 +782,136 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
return 0;
}

static size_t erst_reader(u64 *id, enum pstore_type_id *type,
struct timespec *time);
static u64 erst_writer(enum pstore_type_id type, size_t size);

static struct pstore_info erst_info = {
.owner = THIS_MODULE,
.name = "erst",
.read = erst_reader,
.write = erst_writer,
.erase = erst_clear
};

#define CPER_CREATOR_PSTORE \
UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \
0x64, 0x90, 0xb8, 0x9d)
#define CPER_SECTION_TYPE_DMESG \
UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \
0x94, 0x19, 0xeb, 0x12)
#define CPER_SECTION_TYPE_MCE \
UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \
0x04, 0x4a, 0x38, 0xfc)

struct cper_pstore_record {
struct cper_record_header hdr;
struct cper_section_descriptor sec_hdr;
char data[];
} __packed;

static size_t erst_reader(u64 *id, enum pstore_type_id *type,
struct timespec *time)
{
int rc;
ssize_t len;
unsigned long flags;
u64 record_id;
struct cper_pstore_record *rcd = (struct cper_pstore_record *)
(erst_info.buf - sizeof(*rcd));

if (erst_disable)
return -ENODEV;

raw_spin_lock_irqsave(&erst_lock, flags);
skip:
rc = __erst_get_next_record_id(&record_id);
if (rc) {
raw_spin_unlock_irqrestore(&erst_lock, flags);
return rc;
}
/* no more record */
if (record_id == APEI_ERST_INVALID_RECORD_ID) {
raw_spin_unlock_irqrestore(&erst_lock, flags);
return 0;
}

len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
erst_erange.size);
if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
goto skip;
raw_spin_unlock_irqrestore(&erst_lock, flags);

*id = record_id;
if (uuid_le_cmp(rcd->sec_hdr.section_type,
CPER_SECTION_TYPE_DMESG) == 0)
*type = PSTORE_TYPE_DMESG;
else if (uuid_le_cmp(rcd->sec_hdr.section_type,
CPER_SECTION_TYPE_MCE) == 0)
*type = PSTORE_TYPE_MCE;
else
*type = PSTORE_TYPE_UNKNOWN;

if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP)
time->tv_sec = rcd->hdr.timestamp;
else
time->tv_sec = 0;
time->tv_nsec = 0;

return len - sizeof(*rcd);
}

static u64 erst_writer(enum pstore_type_id type, size_t size)
{
struct cper_pstore_record *rcd = (struct cper_pstore_record *)
(erst_info.buf - sizeof(*rcd));

memset(rcd, 0, sizeof(*rcd));
memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
rcd->hdr.revision = CPER_RECORD_REV;
rcd->hdr.signature_end = CPER_SIG_END;
rcd->hdr.section_count = 1;
rcd->hdr.error_severity = CPER_SEV_FATAL;
/* timestamp valid. platform_id, partition_id are invalid */
rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
rcd->hdr.timestamp = get_seconds();
rcd->hdr.record_length = sizeof(*rcd) + size;
rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
rcd->hdr.notification_type = CPER_NOTIFY_MCE;
rcd->hdr.record_id = cper_next_record_id();
rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR;

rcd->sec_hdr.section_offset = sizeof(*rcd);
rcd->sec_hdr.section_length = size;
rcd->sec_hdr.revision = CPER_SEC_REV;
/* fru_id and fru_text is invalid */
rcd->sec_hdr.validation_bits = 0;
rcd->sec_hdr.flags = CPER_SEC_PRIMARY;
switch (type) {
case PSTORE_TYPE_DMESG:
rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG;
break;
case PSTORE_TYPE_MCE:
rcd->sec_hdr.section_type = CPER_SECTION_TYPE_MCE;
break;
default:
return -EINVAL;
}
rcd->sec_hdr.section_severity = CPER_SEV_FATAL;

erst_write(&rcd->hdr);

return rcd->hdr.record_id;
}

static int __init erst_init(void)
{
int rc = 0;
acpi_status status;
struct apei_exec_context ctx;
struct apei_resources erst_resources;
struct resource *r;
char *buf;

if (acpi_disabled)
goto err;
Expand Down Expand Up @@ -854,6 +978,18 @@ static int __init erst_init(void)
if (!erst_erange.vaddr)
goto err_release_erange;

buf = kmalloc(erst_erange.size, GFP_KERNEL);
mutex_init(&erst_info.buf_mutex);
if (buf) {
erst_info.buf = buf + sizeof(struct cper_pstore_record);
erst_info.bufsize = erst_erange.size -
sizeof(struct cper_pstore_record);
if (pstore_register(&erst_info)) {
pr_info(ERST_PFX "Could not register with persistent store\n");
kfree(buf);
}
}

pr_info(ERST_PFX
"Error Record Serialization Table (ERST) support is initialized.\n");

Expand Down
1 change: 1 addition & 0 deletions fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ source "fs/omfs/Kconfig"
source "fs/hpfs/Kconfig"
source "fs/qnx4/Kconfig"
source "fs/romfs/Kconfig"
source "fs/pstore/Kconfig"
source "fs/sysv/Kconfig"
source "fs/ufs/Kconfig"
source "fs/exofs/Kconfig"
Expand Down
1 change: 1 addition & 0 deletions fs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,4 @@ obj-$(CONFIG_BTRFS_FS) += btrfs/
obj-$(CONFIG_GFS2_FS) += gfs2/
obj-$(CONFIG_EXOFS_FS) += exofs/
obj-$(CONFIG_CEPH_FS) += ceph/
obj-$(CONFIG_PSTORE) += pstore/
13 changes: 13 additions & 0 deletions fs/pstore/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
config PSTORE
bool "Persistant store support"
default n
help
This option enables generic access to platform level
persistent storage via "pstore" filesystem that can
be mounted as /dev/pstore. Only useful if you have
a platform level driver that registers with pstore to
provide the data, so you probably should just go say "Y"
(or "M") to a platform specific persistent store driver
(e.g. ACPI_APEI on X86) which will select this for you.
If you don't have a platform persistent store driver,
say N.
7 changes: 7 additions & 0 deletions fs/pstore/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Makefile for the linux pstorefs routines.
#

obj-y += pstore.o

pstore-objs += inode.o platform.o
Loading

0 comments on commit 242e5d0

Please sign in to comment.