All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/3] Add a method to expand tracers for pstore easily
@ 2014-05-06  5:03 Liu ShuoX
  2014-05-06  5:03 ` [PATCH v5 1/3] pstore: restructure ramoops to support more trace Liu ShuoX
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Liu ShuoX @ 2014-05-06  5:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: yanmin_zhang, Liu ShuoX

Hi,
Here are the v5 of this series. The intention is to add a framework to ramoops
and make expanding tracers for pstore easily. Comments are welcome.

Changelog v5:
  1) Document fix

Changelog v4:
  1) Fix record zone traversing lost when get old buffer.
  2) Add dump records to printk log buf function at runtime by code.
  3) Fix some minor issues.

Changelog v3: 
  1) Fix compiling errors when CONFIG_PSTORE_RAM=m.

Changelog v2: 
  1) Fix compiling errors when CONFIG_PSTORE_RAM is disabled.
  2) Add some protection in the code in case we disable CONFIG_PSTORE_RAM.

---
Liu ShuoX (2):
  pstore: add seq_ops for norm zone
  pstore: support current records dump in ramoops

Zhang Yanmin (1):
  pstore: restructure ramoops to support more trace

 Documentation/ramoops.txt                 |  71 +++++++++++-
 arch/x86/kernel/vmlinux.lds.S             |   9 ++
 drivers/platform/chrome/chromeos_pstore.c |   2 +-
 fs/pstore/inode.c                         | 126 +++++++++++++++++++--
 fs/pstore/internal.h                      |   4 +-
 fs/pstore/platform.c                      |  77 +++++++++++--
 fs/pstore/ram.c                           | 177 +++++++++++++++++++++++++-----
 fs/pstore/ram_core.c                      |  30 +++++
 include/linux/pstore.h                    |   4 +
 include/linux/pstore_ram.h                |  23 ++--
 include/linux/pstore_ramoops.h            |  85 ++++++++++++++
 11 files changed, 543 insertions(+), 65 deletions(-)
 create mode 100644 include/linux/pstore_ramoops.h

-- 
1.8.3.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v5 1/3] pstore: restructure ramoops to support more trace
  2014-05-06  5:03 [PATCH v5 0/3] Add a method to expand tracers for pstore easily Liu ShuoX
@ 2014-05-06  5:03 ` Liu ShuoX
  2014-05-06  5:03 ` [PATCH v5 2/3] pstore: add seq_ops for norm zone Liu ShuoX
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Liu ShuoX @ 2014-05-06  5:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: yanmin_zhang, Zhang Yanmin, Liu ShuoX, Randy Dunlap,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	maintainer:X86 ARCHITECTURE...,
	Olof Johansson, Anton Vorontsov, Colin Cross, Kees Cook,
	Tony Luck, Stefani Seibold, Andy Lutomirski, David Cohen,
	open list:DOCUMENTATION

From: Zhang Yanmin <yanmin.zhang@intel.com>

The patch restructure ramoops of pstore a little to support more user-defined
tracers through ramoops. Here is reason we enhance ramoops:
pstore ramoops is a very import debug feature for mobile development. At present,
ramoops has supported kdump, console and ftrace tracer. Sometimes, we need some
special tracers such as recording cmd and data when driver send/receive. But now,
it's hard to add new tracers into ramoops without touching the pstore core codes.
So we restructure ramoops to let it more flexiable, more eailier to extend.

With this, we split the pstore codes and new tracers which are based on ramoops.
Developer could add a new tracer based on ramoops standalone and pstore detects
it automatically.

Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com>
Signed-off-by: Liu ShuoX <shuox.liu@intel.com>
---
 Documentation/ramoops.txt                 |  71 ++++++++++++-
 arch/x86/kernel/vmlinux.lds.S             |   9 ++
 drivers/platform/chrome/chromeos_pstore.c |   2 +-
 fs/pstore/inode.c                         |  85 +++++++++++++++-
 fs/pstore/internal.h                      |   1 +
 fs/pstore/platform.c                      |  38 +++++++
 fs/pstore/ram.c                           | 159 ++++++++++++++++++++++++------
 fs/pstore/ram_core.c                      |  20 ++++
 include/linux/pstore.h                    |   2 +
 include/linux/pstore_ram.h                |  21 +---
 include/linux/pstore_ramoops.h            |  84 ++++++++++++++++
 11 files changed, 443 insertions(+), 49 deletions(-)
 create mode 100644 include/linux/pstore_ramoops.h

diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 69b3cac..9d37cd4 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -49,7 +49,7 @@ Setting the ramoops parameters can be done in 2 different manners:
  2. Use a platform device and set the platform data. The parameters can then
  be set through that platform data. An example of doing that is:
 
-#include <linux/pstore_ram.h>
+#include <linux/pstore_ramoops.h>
 [...]
 
 static struct ramoops_platform_data ramoops_data = {
@@ -117,3 +117,72 @@ file. Here is an example of usage:
  0 ffffffff811d9c54  ffffffff8101a7a0  __const_udelay <- native_machine_emergency_restart+0x110/0x1e0
  0 ffffffff811d9c34  ffffffff811d9c80  __delay <- __const_udelay+0x30/0x40
  0 ffffffff811d9d14  ffffffff811d9c3f  delay_tsc <- __delay+0xf/0x20
+
+6. Persistent record tracing
+
+Persistent record tracing is useful for debugging software and hardware
+related hang issues. Its flexible usage allows developers to record data in
+a self-defined record structure at tracepoints where they want. After
+rebooting or reset, kernel saves the old records and provides "NAME-ramoops"
+file for applications/users to access.
+Here is an example of usage:
+
+#include <linux/pstore_ramoops.h>
+[...]
+
+struct norm_zone_test_record {
+	unsigned long val;
+	char str[32];
+};
+
+static void print_record(struct seq_file *s, void *rec)
+{
+	struct norm_zone_test_record *record = rec;
+	pstore_print(s, "%s: %ld\n",
+		record->str, record->val);
+}
+
+DEFINE_PSTORE_RAMZONE(test_zone) = {
+	.size = 4096,
+	.name = "test_zone",
+	.item_size = sizeof(struct norm_zone_test_record),
+	.print_record = print_record,
+};
+
+static void add_test_record(char *str, unsigned long val)
+{
+	struct norm_zone_test_record *record;
+	record = ramoops_get_new_record(&test_zone);
+	if (record) {
+		record->val = val;
+		strcpy(record->str, str);
+	}
+}
+
+static int test_cpufreq_transition(struct notifier_block *nb,
+		unsigned long event, void *data)
+{
+	add_test_record("cpufreq transition", event);
+	return 0;
+}
+
+static struct notifier_block freq_transition = {
+	.notifier_call = test_cpufreq_transition,
+};
+
+static int __init norm_zone_test_init(void)
+{
+	cpufreq_register_notifier(&freq_transition,
+			CPUFREQ_TRANSITION_NOTIFIER);
+	return 0;
+}
+module_init(norm_zone_test_init);
+
+Developers could put a call to the memblock_reserve() function (below) in
+setup_arch to reserve memory and implement a ramoops platform device.
+
+#include <linux/memblock.h>
+#include <linux/pstore_ramoops.h>
+
+memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size +
+					pstore_norm_zones_size(NULL));
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 49edf2d..2422622 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -304,6 +304,15 @@ SECTIONS
 		NOSAVE_DATA
 	}
 #endif
+#ifdef CONFIG_PSTORE
+	/* ramoops zone */
+	. = ALIGN(8);
+	.ram_zone : AT(ADDR(.ram_zone) - LOAD_OFFSET) {
+		__ramoops_zone_start = .;
+		*(.ram_zone)
+		__ramoops_zone_end = .;
+	}
+#endif
 
 	/* BSS */
 	. = ALIGN(PAGE_SIZE);
diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c
index e0e0e65..59e102f 100644
--- a/drivers/platform/chrome/chromeos_pstore.c
+++ b/drivers/platform/chrome/chromeos_pstore.c
@@ -11,7 +11,7 @@
 #include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/pstore_ram.h>
+#include <linux/pstore_ramoops.h>
 
 static struct dmi_system_id chromeos_pstore_dmi_table[] __initdata = {
 	{
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 192297b..d463481 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -54,6 +54,78 @@ struct pstore_private {
 	char	data[];
 };
 
+struct pstore_seq_data {
+	size_t off;
+};
+
+static void *pstore_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct pstore_private *ps = s->private;
+	struct ramoops_context *cxt = ps->psi->data;
+	struct ramoops_zone    *zones = cxt->zones;
+	int size = zones[ps->id].item_size;
+	struct pstore_seq_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return NULL;
+
+	data->off = 0;
+	data->off += *pos * size;
+	if (data->off + size > ps->size) {
+		kfree(data);
+		return NULL;
+	}
+
+	return data;
+}
+
+static void pstore_seq_stop(struct seq_file *s, void *v)
+{
+	kfree(v);
+}
+
+static void *pstore_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct pstore_private *ps = s->private;
+	struct pstore_seq_data *data = v;
+	struct ramoops_context *cxt = ps->psi->data;
+	struct ramoops_zone    *zones = cxt->zones;
+	int size = zones[ps->id].item_size;
+
+	data->off += size;
+	if (data->off + size > ps->size)
+		return NULL;
+
+	(*pos)++;
+	return data;
+}
+
+static int pstore_seq_show(struct seq_file *s, void *v)
+{
+	struct pstore_private *ps = s->private;
+	struct pstore_seq_data *data = v;
+	void *record = (void *)(ps->data + data->off);
+	struct ramoops_context *cxt = ps->psi->data;
+	struct ramoops_zone    *zones = cxt->zones;
+
+	if (zones[ps->id].print_record)
+		zones[ps->id].print_record(s, record);
+	else {
+		seq_printf(s, "zone %s doesn't support print_record\n",
+			zones[ps->id].name);
+	}
+
+	return 0;
+}
+
+static const struct seq_operations pstore_seq_ops = {
+	.start	= pstore_seq_start,
+	.next	= pstore_seq_next,
+	.stop	= pstore_seq_stop,
+	.show	= pstore_seq_show,
+};
+
 struct pstore_ftrace_seq_data {
 	const void *ptr;
 	size_t off;
@@ -126,7 +198,8 @@ static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
 	struct seq_file *sf = file->private_data;
 	struct pstore_private *ps = sf->private;
 
-	if (ps->type == PSTORE_TYPE_FTRACE)
+	if (ps->type == PSTORE_TYPE_FTRACE ||
+		ps->type == PSTORE_TYPE_NORM)
 		return seq_read(file, userbuf, count, ppos);
 	return simple_read_from_buffer(userbuf, count, ppos, ps->data, ps->size);
 }
@@ -140,6 +213,8 @@ static int pstore_file_open(struct inode *inode, struct file *file)
 
 	if (ps->type == PSTORE_TYPE_FTRACE)
 		sops = &pstore_ftrace_seq_ops;
+	if (ps->type == PSTORE_TYPE_NORM)
+		sops = &pstore_seq_ops;
 
 	err = seq_open(file, sops);
 	if (err < 0)
@@ -286,6 +361,8 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
 	char			name[PSTORE_NAMELEN];
 	struct pstore_private	*private, *pos;
 	unsigned long		flags;
+	struct ramoops_context	*cxt = psi->data;
+	struct ramoops_zone	*zones = cxt ? cxt->zones : NULL;
 
 	spin_lock_irqsave(&allpstore_lock, flags);
 	list_for_each_entry(pos, &allpstore, list) {
@@ -337,6 +414,12 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
 	case PSTORE_TYPE_PPC_COMMON:
 		sprintf(name, "powerpc-common-%s-%lld", psname, id);
 		break;
+	case PSTORE_TYPE_NORM:
+		/* if zones NULL, it's unknown */
+		if (zones) {
+			sprintf(name, "%s-%s", zones[id].name, psname);
+			break;
+		}
 	case PSTORE_TYPE_UNKNOWN:
 		sprintf(name, "unknown-%s-%lld", psname, id);
 		break;
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 3b3d305..86623ee 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -4,6 +4,7 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/pstore.h>
+#include <linux/pstore_ramoops.h>
 
 #if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB)
 #define PSTORE_CPU_IN_IP 0x1
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 46d269e..f208c2b 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -353,6 +353,44 @@ static struct kmsg_dumper pstore_dumper = {
 	.dump = pstore_dump,
 };
 
+
+struct ramoops_zone *pstore_norm_zones(void)
+{
+	return (struct ramoops_zone *)&__ramoops_zone_start;
+}
+EXPORT_SYMBOL_GPL(pstore_norm_zones);
+
+/* calculate norm zone number and size if they exist */
+unsigned long pstore_norm_zones_size(int *zone_count)
+{
+	unsigned long mem_size = 0;
+	struct ramoops_zone *zones;
+	struct ramoops_zone *zone_end;
+	int i;
+	int count;
+
+	zones = (struct ramoops_zone *)&__ramoops_zone_start;
+	zone_end = (struct ramoops_zone *)&__ramoops_zone_end;
+
+	if (zones > zone_end)
+		return 0;
+	count = zone_end - zones;
+	if (zone_count)
+		*zone_count = count > 0 ? count : 0;
+	if (count <= 0)
+		return 0;
+
+	for (i = 0; i < count; i++) {
+		/*Roundup in case buffer is overflown*/
+		if (zones[i].size && !is_power_of_2(zones[i].size))
+			zones[i].size = roundup_pow_of_two(zones[i].size);
+		mem_size += zones[i].size;
+	}
+
+	return mem_size;
+}
+EXPORT_SYMBOL_GPL(pstore_norm_zones_size);
+
 #ifdef CONFIG_PSTORE_CONSOLE
 static void pstore_console_write(struct console *con, const char *s, unsigned c)
 {
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 3b57443..eb10ce5 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -33,7 +33,9 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/compiler.h>
-#include <linux/pstore_ram.h>
+#include <linux/seq_file.h>
+#include <linux/pstore_ramoops.h>
+#include <linux/sched.h>
 
 #define RAMOOPS_KERNMSG_HDR "===="
 #define MIN_MEM_SIZE 4096UL
@@ -73,26 +75,6 @@ MODULE_PARM_DESC(ramoops_ecc,
 		"ECC buffer size in bytes (1 is a special value, means 16 "
 		"bytes ECC)");
 
-struct ramoops_context {
-	struct persistent_ram_zone **przs;
-	struct persistent_ram_zone *cprz;
-	struct persistent_ram_zone *fprz;
-	phys_addr_t phys_addr;
-	unsigned long size;
-	size_t record_size;
-	size_t console_size;
-	size_t ftrace_size;
-	int dump_oops;
-	struct persistent_ram_ecc_info ecc_info;
-	unsigned int max_dump_cnt;
-	unsigned int dump_write_cnt;
-	/* _read_cnt need clear on ramoops_pstore_open */
-	unsigned int dump_read_cnt;
-	unsigned int console_read_cnt;
-	unsigned int ftrace_read_cnt;
-	struct pstore_info pstore;
-};
-
 static struct platform_device *dummy;
 static struct ramoops_platform_data *dummy_data;
 
@@ -103,6 +85,7 @@ static int ramoops_pstore_open(struct pstore_info *psi)
 	cxt->dump_read_cnt = 0;
 	cxt->console_read_cnt = 0;
 	cxt->ftrace_read_cnt = 0;
+	cxt->norm_read_cnt = 0;
 	return 0;
 }
 
@@ -156,6 +139,47 @@ static void ramoops_read_kmsg_hdr(char *buffer, struct timespec *time,
 	}
 }
 
+/* Norm ram zone user should use it to output instead of seq_pritnf */
+int pstore_print(struct seq_file *m, const char *f, ...)
+{
+	int ret;
+	va_list args;
+
+	va_start(args, f);
+	if (m)
+		ret = seq_vprintf(m, f, args);
+	else
+		ret = vprintk(f, args);
+	va_end(args);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pstore_print);
+
+/* Dump runtime records into printk buffer */
+void pstore_dump_records(struct ramoops_zone *zone)
+{
+	size_t size, off = 0;
+	char *buf;
+	struct persistent_ram_zone *prz;
+	int item_size = zone->item_size;
+	int i;
+
+	prz = zone->prz;
+	if (!prz)
+		return;
+	buf = persistent_ram_buffer(prz);
+	size = persistent_ram_size(prz);
+	if (zone->print_record) {
+		for (i = 0; off < size; off += item_size, i++) {
+			zone->print_record(NULL, (void *)(buf + off));
+			if (!(i % 20))
+				cond_resched();
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(pstore_dump_records);
+
 static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 				   int *count, struct timespec *time,
 				   char **buf, bool *compressed,
@@ -176,6 +200,16 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 		prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt,
 					   1, id, type, PSTORE_TYPE_FTRACE, 0);
 	if (!prz)
+		while (cxt->norm_read_cnt < cxt->norm_num) {
+			prz = ramoops_get_next_prz(cxt->norm_przs,
+					&cxt->norm_read_cnt, cxt->norm_num,
+					id, type, PSTORE_TYPE_NORM, 0);
+			if (!prz)
+				continue;
+			else
+				break;
+		}
+	if (!prz)
 		return 0;
 
 	size = persistent_ram_old_size(prz);
@@ -295,6 +329,11 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
 	case PSTORE_TYPE_FTRACE:
 		prz = cxt->fprz;
 		break;
+	case PSTORE_TYPE_NORM:
+		if (id >= cxt->norm_num)
+			return -EINVAL;
+		prz = cxt->norm_przs[id];
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -329,6 +368,20 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
 	kfree(cxt->przs);
 }
 
+static void ramoops_free_norm_przs(struct ramoops_context *cxt)
+{
+	int i;
+
+	cxt->norm_num = 0;
+	if (!cxt->norm_przs)
+		return;
+
+	for (i = 0; i < cxt->norm_num &&
+			!IS_ERR_OR_NULL(cxt->norm_przs[i]); i++)
+		persistent_ram_free(cxt->norm_przs[i]);
+	kfree(cxt->norm_przs);
+}
+
 static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
 			     phys_addr_t *paddr, size_t dump_mem_sz)
 {
@@ -376,7 +429,7 @@ fail_prz:
 
 static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 			    struct persistent_ram_zone **prz,
-			    phys_addr_t *paddr, size_t sz, u32 sig)
+			    phys_addr_t *paddr, size_t sz, u32 sig, bool ecc)
 {
 	if (!sz)
 		return 0;
@@ -388,7 +441,7 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 		return -ENOMEM;
 	}
 
-	*prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info);
+	*prz = persistent_ram_new(*paddr, sz, sig, ecc ? &cxt->ecc_info : NULL);
 	if (IS_ERR(*prz)) {
 		int err = PTR_ERR(*prz);
 
@@ -404,12 +457,47 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 	return 0;
 }
 
+static int ramoops_init_norm_przs(struct device *dev,
+			struct ramoops_context *cxt,
+			phys_addr_t *paddr)
+{
+	int err = -ENOMEM;
+	struct ramoops_zone *zones = cxt->zones;
+	int i;
+
+	cxt->norm_przs = kzalloc(sizeof(*cxt->przs) * cxt->norm_num,
+			GFP_KERNEL);
+	if (!cxt->norm_przs) {
+		dev_err(dev, "failed to initialize a prz array for dumps\n");
+		goto fail_prz;
+	}
+
+	for (i = 0; i < cxt->norm_num; i++) {
+		err = ramoops_init_prz(dev, cxt, &zones[i].prz,
+				paddr, zones[i].size, 0, false);
+		if (err)
+			goto fail_prz;
+		persistent_ram_set_record_size(zones[i].prz,
+						zones[i].item_size);
+		zones[i].get_new_record = persistent_ram_new_record;
+		zones[i].prz->buffer_size -=
+			(zones[i].prz->buffer_size % zones[i].item_size);
+		cxt->norm_przs[i] = zones[i].prz;
+	}
+
+	return 0;
+fail_prz:
+	ramoops_free_norm_przs(cxt);
+	return err;
+}
+
 static int ramoops_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ramoops_platform_data *pdata = pdev->dev.platform_data;
 	struct ramoops_context *cxt = &oops_cxt;
 	size_t dump_mem_sz;
+	size_t norm_mem_size;
 	phys_addr_t paddr;
 	int err = -EINVAL;
 
@@ -419,8 +507,11 @@ static int ramoops_probe(struct platform_device *pdev)
 	if (cxt->max_dump_cnt)
 		goto fail_out;
 
+	cxt->norm_zone_size = norm_mem_size =
+		pstore_norm_zones_size(&cxt->norm_num);
+
 	if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size &&
-			!pdata->ftrace_size)) {
+			!pdata->ftrace_size && !norm_mem_size)) {
 		pr_err("The memory size and the record/console size must be "
 			"non-zero\n");
 		goto fail_out;
@@ -433,6 +524,8 @@ static int ramoops_probe(struct platform_device *pdev)
 	if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size))
 		pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
 
+	if (cxt->norm_num)
+		cxt->zones = pstore_norm_zones();
 	cxt->size = pdata->mem_size;
 	cxt->phys_addr = pdata->mem_address;
 	cxt->record_size = pdata->record_size;
@@ -443,25 +536,29 @@ static int ramoops_probe(struct platform_device *pdev)
 
 	paddr = cxt->phys_addr;
 
-	dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size;
+	dump_mem_sz = cxt->size - cxt->console_size -
+		cxt->ftrace_size - norm_mem_size;
 	err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz);
 	if (err)
 		goto fail_out;
+	err = ramoops_init_norm_przs(dev, cxt, &paddr);
+	if (err)
+		goto fail_norm_przs;
 
 	err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr,
-			       cxt->console_size, 0);
+			       cxt->console_size, 0, true);
 	if (err)
 		goto fail_init_cprz;
 
-	err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
-			       LINUX_VERSION_CODE);
+	err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr,
+				cxt->ftrace_size, 0, true);
 	if (err)
 		goto fail_init_fprz;
 
-	if (!cxt->przs && !cxt->cprz && !cxt->fprz) {
+	if (!cxt->przs && !cxt->cprz && !cxt->fprz && !cxt->norm_przs) {
 		pr_err("memory size too small, minimum is %zu\n",
 			cxt->console_size + cxt->record_size +
-			cxt->ftrace_size);
+			cxt->ftrace_size + cxt->norm_zone_size);
 		err = -EINVAL;
 		goto fail_cnt;
 	}
@@ -514,6 +611,8 @@ fail_cnt:
 fail_init_fprz:
 	kfree(cxt->cprz);
 fail_init_cprz:
+	ramoops_free_norm_przs(cxt);
+fail_norm_przs:
 	ramoops_free_przs(cxt);
 fail_out:
 	return err;
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index ff7e3d4..9c25a0f 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -30,6 +30,7 @@ struct persistent_ram_buffer {
 	uint32_t    sig;
 	atomic_t    start;
 	atomic_t    size;
+	uint32_t    record_size;
 	uint8_t     data[0];
 };
 
@@ -356,6 +357,19 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
 	return count;
 }
 
+notrace void *persistent_ram_new_record(struct persistent_ram_zone *prz)
+{
+	size_t record_size;
+
+	if (!prz)
+		return NULL;
+
+	record_size = prz->buffer->record_size;
+	buffer_size_add(prz, record_size);
+	return (void *)(prz->buffer->data +
+			buffer_start_add(prz, record_size));
+}
+
 size_t persistent_ram_old_size(struct persistent_ram_zone *prz)
 {
 	return prz->old_log_size;
@@ -380,6 +394,12 @@ void persistent_ram_zap(struct persistent_ram_zone *prz)
 	persistent_ram_update_header_ecc(prz);
 }
 
+void persistent_ram_set_record_size(struct persistent_ram_zone *prz,
+			uint32_t record_size)
+{
+	prz->buffer->record_size = record_size;
+}
+
 static void *persistent_ram_vmap(phys_addr_t start, size_t size)
 {
 	struct page **pages;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index ece0c6b..9936859 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -39,6 +39,8 @@ enum pstore_type_id {
 	PSTORE_TYPE_PPC_RTAS	= 4,
 	PSTORE_TYPE_PPC_OF	= 5,
 	PSTORE_TYPE_PPC_COMMON	= 6,
+	/* normal ram zones */
+	PSTORE_TYPE_NORM	= 7,
 	PSTORE_TYPE_UNKNOWN	= 255
 };
 
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 9974975..d7d0b7a 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/pstore.h>
 
 struct persistent_ram_buffer;
 struct rs_control;
@@ -59,6 +60,10 @@ void persistent_ram_zap(struct persistent_ram_zone *prz);
 
 int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
 	unsigned int count);
+void persistent_ram_set_record_size(struct persistent_ram_zone *prz,
+		uint32_t record_size);
+
+void *persistent_ram_new_record(struct persistent_ram_zone *prz);
 
 void persistent_ram_save_old(struct persistent_ram_zone *prz);
 size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
@@ -67,20 +72,4 @@ void persistent_ram_free_old(struct persistent_ram_zone *prz);
 ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
 	char *str, size_t len);
 
-/*
- * Ramoops platform data
- * @mem_size	memory size for ramoops
- * @mem_address	physical memory address to contain ramoops
- */
-
-struct ramoops_platform_data {
-	unsigned long	mem_size;
-	unsigned long	mem_address;
-	unsigned long	record_size;
-	unsigned long	console_size;
-	unsigned long	ftrace_size;
-	int		dump_oops;
-	struct persistent_ram_ecc_info ecc_info;
-};
-
 #endif
diff --git a/include/linux/pstore_ramoops.h b/include/linux/pstore_ramoops.h
new file mode 100644
index 0000000..28f47a9
--- /dev/null
+++ b/include/linux/pstore_ramoops.h
@@ -0,0 +1,84 @@
+#ifndef __LINUX_PSTORE_RAMOOPS_H__
+#define __LINUX_PSTORE_RAMOOPS_H__
+#include <linux/pstore_ram.h>
+
+struct ramoops_context {
+	struct persistent_ram_zone **przs;
+	struct persistent_ram_zone *cprz;
+	struct persistent_ram_zone *fprz;
+	phys_addr_t phys_addr;
+	unsigned long size;
+	size_t record_size;
+	size_t console_size;
+	size_t ftrace_size;
+	int dump_oops;
+	struct persistent_ram_ecc_info ecc_info;
+	unsigned int max_dump_cnt;
+	unsigned int dump_write_cnt;
+	unsigned int dump_read_cnt;
+	unsigned int console_read_cnt;
+	unsigned int ftrace_read_cnt;
+	struct pstore_info pstore;
+	struct ramoops_zone *zones;
+	struct persistent_ram_zone **norm_przs;
+	size_t norm_zone_size;
+	unsigned int norm_num;
+	unsigned int norm_read_cnt;
+};
+
+struct ramoops_zone {
+	char		name[16];
+	unsigned long	size;
+	struct persistent_ram_zone *prz;
+	int		item_size;
+	void (*print_record)(struct seq_file *s, void *record);
+	void *(*get_new_record)(struct persistent_ram_zone *prz);
+};
+
+/*
+ * Ramoops platform data
+ * @mem_size	memory size for ramoops
+ * @mem_address	physical memory address to contain ramoops
+ */
+
+struct ramoops_platform_data {
+	unsigned long	mem_size;
+	unsigned long	mem_address;
+	unsigned long	record_size;
+	unsigned long	console_size;
+	unsigned long	ftrace_size;
+	int		dump_oops;
+	struct persistent_ram_ecc_info ecc_info;
+};
+
+extern void *__ramoops_zone_start __weak;
+extern void *__ramoops_zone_end __weak;
+/*
+ * define a ram_zone for ramoops
+ * Refer to Documentation/ramoops.txt
+ */
+#ifdef MODULE
+#define DEFINE_PSTORE_RAMZONE(zone) \
+	struct ramoops_zone zone
+#else
+#define DEFINE_PSTORE_RAMZONE(zone) \
+	struct ramoops_zone zone \
+	__attribute__((__section__(".ram_zone"))) \
+	__aligned(sizeof(void *))
+#endif
+
+/* calculate norm zone number and size if they exist */
+unsigned long pstore_norm_zones_size(int *zone_count);
+struct ramoops_zone *pstore_norm_zones(void);
+__printf(2, 3) int pstore_print(struct seq_file *m,
+		const char *f, ...);
+void pstore_dump_records(struct ramoops_zone *zone);
+
+static inline void *ramoops_get_new_record(struct ramoops_zone *zone)
+{
+	if (zone && zone->get_new_record)
+		return zone->get_new_record(zone->prz);
+	return NULL;
+}
+
+#endif
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 2/3] pstore: add seq_ops for norm zone
  2014-05-06  5:03 [PATCH v5 0/3] Add a method to expand tracers for pstore easily Liu ShuoX
  2014-05-06  5:03 ` [PATCH v5 1/3] pstore: restructure ramoops to support more trace Liu ShuoX
@ 2014-05-06  5:03 ` Liu ShuoX
  2014-05-06  5:03 ` [PATCH v5 3/3] pstore: support current records dump in ramoops Liu ShuoX
  2014-05-06  5:03 ` [PATCH] [NOMERGE] reserved ram for pstore on PC (applied on top of new pstore patch) Liu ShuoX
  3 siblings, 0 replies; 7+ messages in thread
From: Liu ShuoX @ 2014-05-06  5:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: yanmin_zhang, Liu ShuoX, Zhang Yanmin, Anton Vorontsov,
	Colin Cross, Kees Cook, Tony Luck

Some developers want to output the pstore record trace flexible.
So add seq_ops into ramoops_zone in case users would make private output
format.

Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com>
Signed-off-by: Liu ShuoX <shuox.liu@intel.com>
---
 fs/pstore/inode.c              | 10 ++++++++--
 include/linux/pstore_ramoops.h |  1 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index d463481..a9c9782 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -207,14 +207,20 @@ static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
 static int pstore_file_open(struct inode *inode, struct file *file)
 {
 	struct pstore_private *ps = inode->i_private;
+	struct ramoops_context *cxt = ps->psi->data;
+	struct ramoops_zone    *zones = cxt ? cxt->zones : NULL;
 	struct seq_file *sf;
 	int err;
 	const struct seq_operations *sops = NULL;
 
 	if (ps->type == PSTORE_TYPE_FTRACE)
 		sops = &pstore_ftrace_seq_ops;
-	if (ps->type == PSTORE_TYPE_NORM)
-		sops = &pstore_seq_ops;
+	if (ps->type == PSTORE_TYPE_NORM && zones) {
+		if (zones[ps->id].seq_ops)
+			sops = zones[ps->id].seq_ops;
+		else
+			sops = &pstore_seq_ops;
+	}
 
 	err = seq_open(file, sops);
 	if (err < 0)
diff --git a/include/linux/pstore_ramoops.h b/include/linux/pstore_ramoops.h
index 28f47a9..b8da964 100644
--- a/include/linux/pstore_ramoops.h
+++ b/include/linux/pstore_ramoops.h
@@ -33,6 +33,7 @@ struct ramoops_zone {
 	int		item_size;
 	void (*print_record)(struct seq_file *s, void *record);
 	void *(*get_new_record)(struct persistent_ram_zone *prz);
+	const struct seq_operations *seq_ops;
 };
 
 /*
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 3/3] pstore: support current records dump in ramoops
  2014-05-06  5:03 [PATCH v5 0/3] Add a method to expand tracers for pstore easily Liu ShuoX
  2014-05-06  5:03 ` [PATCH v5 1/3] pstore: restructure ramoops to support more trace Liu ShuoX
  2014-05-06  5:03 ` [PATCH v5 2/3] pstore: add seq_ops for norm zone Liu ShuoX
@ 2014-05-06  5:03 ` Liu ShuoX
  2014-05-06  5:03 ` [PATCH] [NOMERGE] reserved ram for pstore on PC (applied on top of new pstore patch) Liu ShuoX
  3 siblings, 0 replies; 7+ messages in thread
From: Liu ShuoX @ 2014-05-06  5:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: yanmin_zhang, Liu ShuoX, Zhang Yanmin, Anton Vorontsov,
	Colin Cross, Kees Cook, Tony Luck

dump the records in runtime is useful sometime. We could check the
records and understand driver's and device's status.

Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com>
Signed-off-by: Liu ShuoX <shuox.liu@intel.com>
---
 fs/pstore/inode.c          | 39 +++++++++++++++++++++++++++++++--------
 fs/pstore/internal.h       |  3 ++-
 fs/pstore/platform.c       | 39 ++++++++++++++++++++++++++++++---------
 fs/pstore/ram.c            | 18 ++++++++++++++++++
 fs/pstore/ram_core.c       | 10 ++++++++++
 include/linux/pstore.h     |  2 ++
 include/linux/pstore_ram.h |  2 ++
 7 files changed, 95 insertions(+), 18 deletions(-)

diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index a9c9782..a3b817c15df 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -48,10 +48,11 @@ struct pstore_private {
 	struct list_head list;
 	struct pstore_info *psi;
 	enum pstore_type_id type;
+	int	curr;
 	u64	id;
 	int	count;
 	ssize_t	size;
-	char	data[];
+	char	*data;
 };
 
 struct pstore_seq_data {
@@ -210,16 +211,27 @@ static int pstore_file_open(struct inode *inode, struct file *file)
 	struct ramoops_context *cxt = ps->psi->data;
 	struct ramoops_zone    *zones = cxt ? cxt->zones : NULL;
 	struct seq_file *sf;
+	char *buf = NULL;
 	int err;
+	u64 id = ps->id;
 	const struct seq_operations *sops = NULL;
 
 	if (ps->type == PSTORE_TYPE_FTRACE)
 		sops = &pstore_ftrace_seq_ops;
 	if (ps->type == PSTORE_TYPE_NORM && zones) {
-		if (zones[ps->id].seq_ops)
-			sops = zones[ps->id].seq_ops;
+		if (zones[id].seq_ops)
+			sops = zones[id].seq_ops;
 		else
 			sops = &pstore_seq_ops;
+		if (ps->curr) {
+			/*
+			 * Update size again as current buffer
+			 * size might be changed.
+			 */
+			inode->i_size = ps->size =
+				ps->psi->read_curr(&id, PSTORE_TYPE_NORM,
+						&buf, ps->psi);
+		}
 	}
 
 	err = seq_open(file, sops);
@@ -256,12 +268,16 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct pstore_private *p = dentry->d_inode->i_private;
 
+	if (p->curr)
+		goto unlink;
 	if (p->psi->erase)
 		p->psi->erase(p->type, p->id, p->count,
 			      dentry->d_inode->i_ctime, p->psi);
 	else
 		return -EPERM;
 
+	kfree(p->data);
+unlink:
 	return simple_unlink(dir, dentry);
 }
 
@@ -358,7 +374,7 @@ int pstore_is_mounted(void)
  */
 int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
 		  char *data, bool compressed, size_t size,
-		  struct timespec time, struct pstore_info *psi)
+		  struct timespec time, struct pstore_info *psi, bool curr)
 {
 	struct dentry		*root = pstore_sb->s_root;
 	struct dentry		*dentry;
@@ -374,14 +390,15 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
 	list_for_each_entry(pos, &allpstore, list) {
 		if (pos->type == type &&
 		    pos->id == id &&
-		    pos->psi == psi) {
+		    pos->psi == psi &&
+		    pos->curr == curr) {
 			rc = -EEXIST;
 			break;
 		}
 	}
 	spin_unlock_irqrestore(&allpstore_lock, flags);
 	if (rc)
-		return rc;
+		goto fail;
 
 	rc = -ENOMEM;
 	inode = pstore_get_inode(pstore_sb);
@@ -389,13 +406,15 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
 		goto fail;
 	inode->i_mode = S_IFREG | 0444;
 	inode->i_fop = &pstore_file_operations;
-	private = kmalloc(sizeof *private + size, GFP_KERNEL);
+	private = kmalloc(sizeof(*private), GFP_KERNEL);
 	if (!private)
 		goto fail_alloc;
 	private->type = type;
 	private->id = id;
 	private->count = count;
 	private->psi = psi;
+	private->curr = curr;
+	private->data = data;
 
 	switch (type) {
 	case PSTORE_TYPE_DMESG:
@@ -434,13 +453,15 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
 		break;
 	}
 
+	if (curr)
+		strcat(name, "_cur");
+
 	mutex_lock(&root->d_inode->i_mutex);
 
 	dentry = d_alloc_name(root, name);
 	if (!dentry)
 		goto fail_lockedalloc;
 
-	memcpy(private->data, data, size);
 	inode->i_size = private->size = size;
 
 	inode->i_private = private;
@@ -465,6 +486,7 @@ fail_alloc:
 	iput(inode);
 
 fail:
+	kfree(data);
 	return rc;
 }
 
@@ -497,6 +519,7 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
 		return -ENOMEM;
 
 	pstore_get_records(0);
+	pstore_get_cur_records();
 
 	return 0;
 }
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 86623ee..ccc0f35 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -50,10 +50,11 @@ extern struct pstore_info *psinfo;
 
 extern void	pstore_set_kmsg_bytes(int);
 extern void	pstore_get_records(int);
+extern void	pstore_get_cur_records(void);
 extern int	pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
 			      int count, char *data, bool compressed,
 			      size_t size, struct timespec time,
-			      struct pstore_info *psi);
+			      struct pstore_info *psi, bool curr);
 extern int	pstore_is_mounted(void);
 
 #endif
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index f208c2b..1f4ec47 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -477,8 +477,10 @@ int pstore_register(struct pstore_info *psi)
 
 	allocate_buf_for_compression();
 
-	if (pstore_is_mounted())
+	if (pstore_is_mounted()) {
 		pstore_get_records(0);
+		pstore_get_cur_records();
+	}
 
 	kmsg_dump_register(&pstore_dumper);
 
@@ -536,7 +538,13 @@ void pstore_get_records(int quiet)
 
 			if (unzipped_len > 0) {
 				kfree(buf);
-				buf = big_oops_buf;
+				buf = kmalloc(unzipped_len, GFP_KERNEL);
+				if (!buf) {
+					if (!quiet)
+						failed++;
+					continue;
+				}
+				memcpy(buf, big_oops_buf, unzipped_len);
 				size = unzipped_len;
 				compressed = false;
 			} else {
@@ -546,15 +554,10 @@ void pstore_get_records(int quiet)
 			}
 		}
 		rc = pstore_mkfile(type, psi->name, id, count, buf,
-				  compressed, (size_t)size, time, psi);
-		if (unzipped_len < 0) {
-			/* Free buffer other than big oops */
-			kfree(buf);
-			buf = NULL;
-		} else
-			unzipped_len = -1;
+				  compressed, (size_t)size, time, psi, false);
 		if (rc && (rc != -EEXIST || !quiet))
 			failed++;
+		unzipped_len = -1;
 	}
 	if (psi->close)
 		psi->close(psi);
@@ -566,6 +569,24 @@ out:
 		       failed, psi->name);
 }
 
+void pstore_get_cur_records(void)
+{
+	struct pstore_info *psi = psinfo;
+	ssize_t		size;
+	char		*buf = NULL;
+	struct timespec time = {0};
+	u64		id = 0;
+	int		rc;
+
+	if (!psi || !psi->read_curr)
+		return;
+
+	while (size = psi->read_curr(&id, PSTORE_TYPE_NORM, &buf, psi), buf) {
+		rc = pstore_mkfile(PSTORE_TYPE_NORM, psi->name, id - 1, 0, buf,
+				0, (size_t)size, time, psi, true);
+	}
+}
+
 static void pstore_dowork(struct work_struct *work)
 {
 	pstore_get_records(1);
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index eb10ce5..8fadca3 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -180,6 +180,23 @@ void pstore_dump_records(struct ramoops_zone *zone)
 }
 EXPORT_SYMBOL_GPL(pstore_dump_records);
 
+/* only support PSTORE_TYPE_NORM type ram zone */
+static ssize_t ramoops_pstore_read_current(u64 *id, enum pstore_type_id type,
+		char **buf, struct pstore_info *psi)
+{
+	struct ramoops_context *cxt = psi->data;
+	struct persistent_ram_zone *prz;
+
+	if (type != PSTORE_TYPE_NORM || (*id >= cxt->norm_num)) {
+		*buf = NULL;
+		return 0;
+	}
+	prz = cxt->norm_przs[(*id)++];
+	*buf = persistent_ram_buffer(prz);
+
+	return persistent_ram_size(prz);
+}
+
 static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 				   int *count, struct timespec *time,
 				   char **buf, bool *compressed,
@@ -350,6 +367,7 @@ static struct ramoops_context oops_cxt = {
 		.name	= "ramoops",
 		.open	= ramoops_pstore_open,
 		.read	= ramoops_pstore_read,
+		.read_curr	= ramoops_pstore_read_current,
 		.write_buf	= ramoops_pstore_write_buf,
 		.erase	= ramoops_pstore_erase,
 	},
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 9c25a0f..72a34b5 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -46,6 +46,11 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
 	return atomic_read(&prz->buffer->start);
 }
 
+void *persistent_ram_buffer(struct persistent_ram_zone *prz)
+{
+	return prz->buffer->data;
+}
+
 /* increase and wrap the start pointer, returning the old value */
 static size_t buffer_start_add_atomic(struct persistent_ram_zone *prz, size_t a)
 {
@@ -370,6 +375,11 @@ notrace void *persistent_ram_new_record(struct persistent_ram_zone *prz)
 			buffer_start_add(prz, record_size));
 }
 
+size_t persistent_ram_size(struct persistent_ram_zone *prz)
+{
+	return buffer_size(prz);
+}
+
 size_t persistent_ram_old_size(struct persistent_ram_zone *prz)
 {
 	return prz->old_log_size;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 9936859..31a6ec1 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -59,6 +59,8 @@ struct pstore_info {
 	ssize_t		(*read)(u64 *id, enum pstore_type_id *type,
 			int *count, struct timespec *time, char **buf,
 			bool *compressed, struct pstore_info *psi);
+	ssize_t		(*read_curr)(u64 *id, enum pstore_type_id type,
+			char **buf, struct pstore_info *psi);
 	int		(*write)(enum pstore_type_id type,
 			enum kmsg_dump_reason reason, u64 *id,
 			unsigned int part, int count, bool compressed,
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index d7d0b7a..9e383eb 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -71,5 +71,7 @@ void *persistent_ram_old(struct persistent_ram_zone *prz);
 void persistent_ram_free_old(struct persistent_ram_zone *prz);
 ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
 	char *str, size_t len);
+void *persistent_ram_buffer(struct persistent_ram_zone *prz);
+size_t persistent_ram_size(struct persistent_ram_zone *prz);
 
 #endif
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH] [NOMERGE] reserved ram for pstore on PC (applied on top of new pstore patch)
  2014-05-06  5:03 [PATCH v5 0/3] Add a method to expand tracers for pstore easily Liu ShuoX
                   ` (2 preceding siblings ...)
  2014-05-06  5:03 ` [PATCH v5 3/3] pstore: support current records dump in ramoops Liu ShuoX
@ 2014-05-06  5:03 ` Liu ShuoX
  2014-05-06 14:48   ` Paul Gortmaker
  3 siblings, 1 reply; 7+ messages in thread
From: Liu ShuoX @ 2014-05-06  5:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: yanmin_zhang, Liu ShuoX, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, maintainer:X86 ARCHITECTURE...,
	Anton Vorontsov, Colin Cross, Kees Cook, Tony Luck, Matt Fleming,
	Andrew Morton, Borislav Petkov, Yinghai Lu, Dave Young,
	Tang Chen, Paul Gortmaker, Linn Crosetto

for pstore record test.

Signed-off-by: Liu ShuoX <shuox.liu@intel.com>
---
 arch/x86/kernel/setup.c |   2 +
 fs/pstore/Makefile      |   2 +-
 fs/pstore/test.c        | 170 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 173 insertions(+), 1 deletion(-)
 create mode 100644 fs/pstore/test.c

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 09c76d2..021b17a 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -854,6 +854,7 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
  * Note: On x86_64, fixmaps are ready for use even before this is called.
  */
 
+extern void pstore_ram_reserved_memory(void);
 void __init setup_arch(char **cmdline_p)
 {
 	memblock_reserve(__pa_symbol(_text),
@@ -1217,6 +1218,7 @@ void __init setup_arch(char **cmdline_p)
 
 	x86_init.resources.reserve_resources();
 
+	pstore_ram_reserved_memory();
 	e820_setup_gap();
 
 #ifdef CONFIG_VT
diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile
index 4c9095c..b2a961b 100644
--- a/fs/pstore/Makefile
+++ b/fs/pstore/Makefile
@@ -7,5 +7,5 @@ obj-y += pstore.o
 pstore-objs += inode.o platform.o
 obj-$(CONFIG_PSTORE_FTRACE)	+= ftrace.o
 
-ramoops-objs += ram.o ram_core.o
+ramoops-objs += ram.o ram_core.o test.o
 obj-$(CONFIG_PSTORE_RAM)	+= ramoops.o
diff --git a/fs/pstore/test.c b/fs/pstore/test.c
new file mode 100644
index 0000000..109c5a8
--- /dev/null
+++ b/fs/pstore/test.c
@@ -0,0 +1,170 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/cpufreq.h>
+#include <linux/seq_file.h>
+#include <linux/pstore_ramoops.h>
+#include <linux/platform_device.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/debugfs.h>
+
+struct norm_zone_test_record {
+	unsigned long val;
+	char str[32];
+};
+
+static void print_record(struct seq_file *s, void *rec)
+{
+	struct norm_zone_test_record *record = rec;
+	pstore_print(s, "%s: %ld\n",
+		record->str, record->val);
+}
+
+DEFINE_PSTORE_RAMZONE(test_zone) = {
+	.size = 4096,
+	.name = "test_zone",
+	.item_size = sizeof(struct norm_zone_test_record),
+	.print_record = print_record,
+};
+
+DEFINE_PSTORE_RAMZONE(test_zone1) = {
+	.size = 4096,
+	.name = "test_zone1",
+	.item_size = sizeof(struct norm_zone_test_record),
+	.print_record = print_record,
+};
+
+static void add_test_record(char *str, unsigned long val)
+{
+	struct norm_zone_test_record *record;
+	record = persistent_ram_new_record(test_zone.prz);
+	if (record) {
+		record->val = val;
+		strcpy(record->str, str);
+	}
+	record = persistent_ram_new_record(test_zone1.prz);
+	if (record) {
+		record->val = val;
+		strcpy(record->str, str);
+	}
+}
+
+static int test_cpufreq_transition(struct notifier_block *nb,
+		unsigned long event, void *data)
+{
+	add_test_record("cpufreq transition", event);
+	return 0;
+}
+
+static struct notifier_block freq_transition = {
+	.notifier_call = test_cpufreq_transition,
+};
+
+#define SZ_4K   0x00001000
+#define SZ_2M   0x00200000
+#define SZ_2_1M 0x00219000
+#define SZ_16M  0x01000000
+
+#define PSTORE_RAM_START_DEFAULT        SZ_16M
+#define PSTORE_RAM_SIZE_DEFAULT         SZ_2_1M
+
+#ifdef CONFIG_X86_32
+#define RAM_MAX_MEM (max_low_pfn << PAGE_SHIFT)
+#else
+#define RAM_MAX_MEM (1 << 28)
+#endif
+
+static struct ramoops_platform_data pstore_ram_data = { 
+	.mem_size       = PSTORE_RAM_SIZE_DEFAULT,
+	.mem_address    = PSTORE_RAM_START_DEFAULT,
+	.record_size    = SZ_4K,
+	.console_size   = SZ_2M,
+	.dump_oops      = 1,
+};
+
+static struct platform_device pstore_ram_dev = { 
+	.name = "ramoops",
+	.dev = { 
+		.platform_data = &pstore_ram_data,
+	},  
+};
+
+static int __init pstore_ram_register(void)
+{
+	int ret;
+
+	ret = platform_device_register(&pstore_ram_dev);
+	if (ret) {
+		pr_err("%s: unable to register pstore_ram device: "
+			"start=0x%llx, size=0x%lx, ret=%d\n", __func__,
+			(unsigned long long)pstore_ram_data.mem_address,
+			pstore_ram_data.mem_size, ret);
+	}
+
+	return ret;
+}
+postcore_initcall(pstore_ram_register);
+
+void __init pstore_ram_reserved_memory(void)
+{
+	phys_addr_t mem;
+	size_t size;
+	int ret;
+
+	size = PSTORE_RAM_SIZE_DEFAULT;
+	size += pstore_norm_zones_size(NULL);
+	size = ALIGN(size, PAGE_SIZE);
+	mem = memblock_find_in_range(0, RAM_MAX_MEM, size, PAGE_SIZE);
+	if (!mem) {
+		pr_err("Cannot find memblock range for pstore_ram\n");
+		return;
+	}
+
+	ret = memblock_reserve(mem, size);
+	if (ret) {
+		pr_err("Failed to reserve memory from 0x%llx-0x%llx\n",
+				(unsigned long long)mem,
+				(unsigned long long)(mem + size - 1));
+		return;
+	}
+
+	pstore_ram_data.mem_address = mem;
+	pstore_ram_data.mem_size = size;
+
+	pr_info("reserved RAM buffer (0x%zx@0x%llx)\n",
+			size, (unsigned long long)mem);
+}
+
+static ssize_t pstore_ramoops_write(struct file *f, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static ssize_t pstore_ramoops_read(struct file *f, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct ramoops_zone *zone = (struct ramoops_zone *)f->private_data;
+
+	pstore_dump_records(zone);
+	return 0;
+}
+
+static const struct file_operations pstore_ramoops_fops = { 
+	.open   = simple_open,
+	.read   = pstore_ramoops_read,
+	.write  = pstore_ramoops_write,
+};
+
+
+static int __init norm_zone_test_init(void)
+{
+	cpufreq_register_notifier(&freq_transition,
+			CPUFREQ_TRANSITION_NOTIFIER);
+	debugfs_create_file("zone_dump", 0660, NULL, (void *)&test_zone, &pstore_ramoops_fops);
+	debugfs_create_file("zone1_dump", 0660, NULL, (void *)&test_zone1, &pstore_ramoops_fops);
+
+	return 0;
+}
+module_init(norm_zone_test_init);
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] [NOMERGE] reserved ram for pstore on PC (applied on top of new pstore patch)
  2014-05-06  5:03 ` [PATCH] [NOMERGE] reserved ram for pstore on PC (applied on top of new pstore patch) Liu ShuoX
@ 2014-05-06 14:48   ` Paul Gortmaker
  2014-05-07  1:30     ` Liu ShuoX
  0 siblings, 1 reply; 7+ messages in thread
From: Paul Gortmaker @ 2014-05-06 14:48 UTC (permalink / raw)
  To: Liu ShuoX, linux-kernel
  Cc: yanmin_zhang, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	maintainer:X86 ARCHITECTURE...,
	Anton Vorontsov, Colin Cross, Kees Cook, Tony Luck, Matt Fleming,
	Andrew Morton, Borislav Petkov, Yinghai Lu, Dave Young,
	Tang Chen, Linn Crosetto

On 14-05-06 01:03 AM, Liu ShuoX wrote:
> for pstore record test.

I don't know what kind of cc mechanism you were manually deploying
when using git send-email here, but it is customary to actually
ensure that the 0/N summary also appears in the inbox of anyone
who is cc'd on any of the patches, so they have some context.

Not writing a four line commit log is also a good way to add
extra context too.

Paul.
--

> 
> Signed-off-by: Liu ShuoX <shuox.liu@intel.com>
> ---
>  arch/x86/kernel/setup.c |   2 +
>  fs/pstore/Makefile      |   2 +-
>  fs/pstore/test.c        | 170 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 173 insertions(+), 1 deletion(-)
>  create mode 100644 fs/pstore/test.c
> 
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 09c76d2..021b17a 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -854,6 +854,7 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
>   * Note: On x86_64, fixmaps are ready for use even before this is called.
>   */
>  
> +extern void pstore_ram_reserved_memory(void);
>  void __init setup_arch(char **cmdline_p)
>  {
>  	memblock_reserve(__pa_symbol(_text),
> @@ -1217,6 +1218,7 @@ void __init setup_arch(char **cmdline_p)
>  
>  	x86_init.resources.reserve_resources();
>  
> +	pstore_ram_reserved_memory();
>  	e820_setup_gap();
>  
>  #ifdef CONFIG_VT
> diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile
> index 4c9095c..b2a961b 100644
> --- a/fs/pstore/Makefile
> +++ b/fs/pstore/Makefile
> @@ -7,5 +7,5 @@ obj-y += pstore.o
>  pstore-objs += inode.o platform.o
>  obj-$(CONFIG_PSTORE_FTRACE)	+= ftrace.o
>  
> -ramoops-objs += ram.o ram_core.o
> +ramoops-objs += ram.o ram_core.o test.o
>  obj-$(CONFIG_PSTORE_RAM)	+= ramoops.o
> diff --git a/fs/pstore/test.c b/fs/pstore/test.c
> new file mode 100644
> index 0000000..109c5a8
> --- /dev/null
> +++ b/fs/pstore/test.c
> @@ -0,0 +1,170 @@
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/string.h>
> +#include <linux/cpufreq.h>
> +#include <linux/seq_file.h>
> +#include <linux/pstore_ramoops.h>
> +#include <linux/platform_device.h>
> +#include <linux/memblock.h>
> +#include <linux/bootmem.h>
> +#include <linux/debugfs.h>
> +
> +struct norm_zone_test_record {
> +	unsigned long val;
> +	char str[32];
> +};
> +
> +static void print_record(struct seq_file *s, void *rec)
> +{
> +	struct norm_zone_test_record *record = rec;
> +	pstore_print(s, "%s: %ld\n",
> +		record->str, record->val);
> +}
> +
> +DEFINE_PSTORE_RAMZONE(test_zone) = {
> +	.size = 4096,
> +	.name = "test_zone",
> +	.item_size = sizeof(struct norm_zone_test_record),
> +	.print_record = print_record,
> +};
> +
> +DEFINE_PSTORE_RAMZONE(test_zone1) = {
> +	.size = 4096,
> +	.name = "test_zone1",
> +	.item_size = sizeof(struct norm_zone_test_record),
> +	.print_record = print_record,
> +};
> +
> +static void add_test_record(char *str, unsigned long val)
> +{
> +	struct norm_zone_test_record *record;
> +	record = persistent_ram_new_record(test_zone.prz);
> +	if (record) {
> +		record->val = val;
> +		strcpy(record->str, str);
> +	}
> +	record = persistent_ram_new_record(test_zone1.prz);
> +	if (record) {
> +		record->val = val;
> +		strcpy(record->str, str);
> +	}
> +}
> +
> +static int test_cpufreq_transition(struct notifier_block *nb,
> +		unsigned long event, void *data)
> +{
> +	add_test_record("cpufreq transition", event);
> +	return 0;
> +}
> +
> +static struct notifier_block freq_transition = {
> +	.notifier_call = test_cpufreq_transition,
> +};
> +
> +#define SZ_4K   0x00001000
> +#define SZ_2M   0x00200000
> +#define SZ_2_1M 0x00219000
> +#define SZ_16M  0x01000000
> +
> +#define PSTORE_RAM_START_DEFAULT        SZ_16M
> +#define PSTORE_RAM_SIZE_DEFAULT         SZ_2_1M
> +
> +#ifdef CONFIG_X86_32
> +#define RAM_MAX_MEM (max_low_pfn << PAGE_SHIFT)
> +#else
> +#define RAM_MAX_MEM (1 << 28)
> +#endif
> +
> +static struct ramoops_platform_data pstore_ram_data = { 
> +	.mem_size       = PSTORE_RAM_SIZE_DEFAULT,
> +	.mem_address    = PSTORE_RAM_START_DEFAULT,
> +	.record_size    = SZ_4K,
> +	.console_size   = SZ_2M,
> +	.dump_oops      = 1,
> +};
> +
> +static struct platform_device pstore_ram_dev = { 
> +	.name = "ramoops",
> +	.dev = { 
> +		.platform_data = &pstore_ram_data,
> +	},  
> +};
> +
> +static int __init pstore_ram_register(void)
> +{
> +	int ret;
> +
> +	ret = platform_device_register(&pstore_ram_dev);
> +	if (ret) {
> +		pr_err("%s: unable to register pstore_ram device: "
> +			"start=0x%llx, size=0x%lx, ret=%d\n", __func__,
> +			(unsigned long long)pstore_ram_data.mem_address,
> +			pstore_ram_data.mem_size, ret);
> +	}
> +
> +	return ret;
> +}
> +postcore_initcall(pstore_ram_register);
> +
> +void __init pstore_ram_reserved_memory(void)
> +{
> +	phys_addr_t mem;
> +	size_t size;
> +	int ret;
> +
> +	size = PSTORE_RAM_SIZE_DEFAULT;
> +	size += pstore_norm_zones_size(NULL);
> +	size = ALIGN(size, PAGE_SIZE);
> +	mem = memblock_find_in_range(0, RAM_MAX_MEM, size, PAGE_SIZE);
> +	if (!mem) {
> +		pr_err("Cannot find memblock range for pstore_ram\n");
> +		return;
> +	}
> +
> +	ret = memblock_reserve(mem, size);
> +	if (ret) {
> +		pr_err("Failed to reserve memory from 0x%llx-0x%llx\n",
> +				(unsigned long long)mem,
> +				(unsigned long long)(mem + size - 1));
> +		return;
> +	}
> +
> +	pstore_ram_data.mem_address = mem;
> +	pstore_ram_data.mem_size = size;
> +
> +	pr_info("reserved RAM buffer (0x%zx@0x%llx)\n",
> +			size, (unsigned long long)mem);
> +}
> +
> +static ssize_t pstore_ramoops_write(struct file *f, const char __user *buf,
> +		size_t count, loff_t *ppos)
> +{
> +	return 0;
> +}
> +
> +static ssize_t pstore_ramoops_read(struct file *f, char __user *buf,
> +		size_t count, loff_t *ppos)
> +{
> +	struct ramoops_zone *zone = (struct ramoops_zone *)f->private_data;
> +
> +	pstore_dump_records(zone);
> +	return 0;
> +}
> +
> +static const struct file_operations pstore_ramoops_fops = { 
> +	.open   = simple_open,
> +	.read   = pstore_ramoops_read,
> +	.write  = pstore_ramoops_write,
> +};
> +
> +
> +static int __init norm_zone_test_init(void)
> +{
> +	cpufreq_register_notifier(&freq_transition,
> +			CPUFREQ_TRANSITION_NOTIFIER);
> +	debugfs_create_file("zone_dump", 0660, NULL, (void *)&test_zone, &pstore_ramoops_fops);
> +	debugfs_create_file("zone1_dump", 0660, NULL, (void *)&test_zone1, &pstore_ramoops_fops);
> +
> +	return 0;
> +}
> +module_init(norm_zone_test_init);
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] [NOMERGE] reserved ram for pstore on PC (applied on top of new pstore patch)
  2014-05-06 14:48   ` Paul Gortmaker
@ 2014-05-07  1:30     ` Liu ShuoX
  0 siblings, 0 replies; 7+ messages in thread
From: Liu ShuoX @ 2014-05-07  1:30 UTC (permalink / raw)
  To: Paul Gortmaker
  Cc: linux-kernel, yanmin_zhang, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, maintainer:X86 ARCHITECTURE...,
	Anton Vorontsov, Colin Cross, Kees Cook, Tony Luck, Matt Fleming,
	Andrew Morton, Borislav Petkov, Yinghai Lu, Dave Young,
	Tang Chen, Linn Crosetto

On Tue  6.May'14 at 10:48:00 -0400, Paul Gortmaker wrote:
>On 14-05-06 01:03 AM, Liu ShuoX wrote:
>> for pstore record test.
>
>I don't know what kind of cc mechanism you were manually deploying
>when using git send-email here, but it is customary to actually
Sorry. This is my first time to send out test patch.
I used --cc-cmd=./scripts/get_maintainer.pl for my
patchset(include this NOMERGE one).
Actually, this one is for testing and verifying. Because of the x86 arch
code changing in the patch, get_maintainer.pl involves more guys.
BTW, what's the right/good approach to send out test patch?
Need i send it by deploying cc-list manually?

Thanks.
>ensure that the 0/N summary also appears in the inbox of anyone
>who is cc'd on any of the patches, so they have some context.
>
>Not writing a four line commit log is also a good way to add
>extra context too.
>
>Paul.
>--
>
>>
>> Signed-off-by: Liu ShuoX <shuox.liu@intel.com>
>> ---
>>  arch/x86/kernel/setup.c |   2 +
>>  fs/pstore/Makefile      |   2 +-
>>  fs/pstore/test.c        | 170 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 173 insertions(+), 1 deletion(-)
>>  create mode 100644 fs/pstore/test.c
>>
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 09c76d2..021b17a 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -854,6 +854,7 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
>>   * Note: On x86_64, fixmaps are ready for use even before this is called.
>>   */
>>
>> +extern void pstore_ram_reserved_memory(void);
>>  void __init setup_arch(char **cmdline_p)
>>  {
>>  	memblock_reserve(__pa_symbol(_text),
>> @@ -1217,6 +1218,7 @@ void __init setup_arch(char **cmdline_p)
>>
>>  	x86_init.resources.reserve_resources();
>>
>> +	pstore_ram_reserved_memory();
>>  	e820_setup_gap();
>>
>>  #ifdef CONFIG_VT
>> diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile
>> index 4c9095c..b2a961b 100644
>> --- a/fs/pstore/Makefile
>> +++ b/fs/pstore/Makefile
>> @@ -7,5 +7,5 @@ obj-y += pstore.o
>>  pstore-objs += inode.o platform.o
>>  obj-$(CONFIG_PSTORE_FTRACE)	+= ftrace.o
>>
>> -ramoops-objs += ram.o ram_core.o
>> +ramoops-objs += ram.o ram_core.o test.o
>>  obj-$(CONFIG_PSTORE_RAM)	+= ramoops.o
>> diff --git a/fs/pstore/test.c b/fs/pstore/test.c
>> new file mode 100644
>> index 0000000..109c5a8
>> --- /dev/null
>> +++ b/fs/pstore/test.c
>> @@ -0,0 +1,170 @@
>> +#include <linux/module.h>
>> +#include <linux/init.h>
>> +#include <linux/string.h>
>> +#include <linux/cpufreq.h>
>> +#include <linux/seq_file.h>
>> +#include <linux/pstore_ramoops.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/memblock.h>
>> +#include <linux/bootmem.h>
>> +#include <linux/debugfs.h>
>> +
>> +struct norm_zone_test_record {
>> +	unsigned long val;
>> +	char str[32];
>> +};
>> +
>> +static void print_record(struct seq_file *s, void *rec)
>> +{
>> +	struct norm_zone_test_record *record = rec;
>> +	pstore_print(s, "%s: %ld\n",
>> +		record->str, record->val);
>> +}
>> +
>> +DEFINE_PSTORE_RAMZONE(test_zone) = {
>> +	.size = 4096,
>> +	.name = "test_zone",
>> +	.item_size = sizeof(struct norm_zone_test_record),
>> +	.print_record = print_record,
>> +};
>> +
>> +DEFINE_PSTORE_RAMZONE(test_zone1) = {
>> +	.size = 4096,
>> +	.name = "test_zone1",
>> +	.item_size = sizeof(struct norm_zone_test_record),
>> +	.print_record = print_record,
>> +};
>> +
>> +static void add_test_record(char *str, unsigned long val)
>> +{
>> +	struct norm_zone_test_record *record;
>> +	record = persistent_ram_new_record(test_zone.prz);
>> +	if (record) {
>> +		record->val = val;
>> +		strcpy(record->str, str);
>> +	}
>> +	record = persistent_ram_new_record(test_zone1.prz);
>> +	if (record) {
>> +		record->val = val;
>> +		strcpy(record->str, str);
>> +	}
>> +}
>> +
>> +static int test_cpufreq_transition(struct notifier_block *nb,
>> +		unsigned long event, void *data)
>> +{
>> +	add_test_record("cpufreq transition", event);
>> +	return 0;
>> +}
>> +
>> +static struct notifier_block freq_transition = {
>> +	.notifier_call = test_cpufreq_transition,
>> +};
>> +
>> +#define SZ_4K   0x00001000
>> +#define SZ_2M   0x00200000
>> +#define SZ_2_1M 0x00219000
>> +#define SZ_16M  0x01000000
>> +
>> +#define PSTORE_RAM_START_DEFAULT        SZ_16M
>> +#define PSTORE_RAM_SIZE_DEFAULT         SZ_2_1M
>> +
>> +#ifdef CONFIG_X86_32
>> +#define RAM_MAX_MEM (max_low_pfn << PAGE_SHIFT)
>> +#else
>> +#define RAM_MAX_MEM (1 << 28)
>> +#endif
>> +
>> +static struct ramoops_platform_data pstore_ram_data = {
>> +	.mem_size       = PSTORE_RAM_SIZE_DEFAULT,
>> +	.mem_address    = PSTORE_RAM_START_DEFAULT,
>> +	.record_size    = SZ_4K,
>> +	.console_size   = SZ_2M,
>> +	.dump_oops      = 1,
>> +};
>> +
>> +static struct platform_device pstore_ram_dev = {
>> +	.name = "ramoops",
>> +	.dev = {
>> +		.platform_data = &pstore_ram_data,
>> +	},
>> +};
>> +
>> +static int __init pstore_ram_register(void)
>> +{
>> +	int ret;
>> +
>> +	ret = platform_device_register(&pstore_ram_dev);
>> +	if (ret) {
>> +		pr_err("%s: unable to register pstore_ram device: "
>> +			"start=0x%llx, size=0x%lx, ret=%d\n", __func__,
>> +			(unsigned long long)pstore_ram_data.mem_address,
>> +			pstore_ram_data.mem_size, ret);
>> +	}
>> +
>> +	return ret;
>> +}
>> +postcore_initcall(pstore_ram_register);
>> +
>> +void __init pstore_ram_reserved_memory(void)
>> +{
>> +	phys_addr_t mem;
>> +	size_t size;
>> +	int ret;
>> +
>> +	size = PSTORE_RAM_SIZE_DEFAULT;
>> +	size += pstore_norm_zones_size(NULL);
>> +	size = ALIGN(size, PAGE_SIZE);
>> +	mem = memblock_find_in_range(0, RAM_MAX_MEM, size, PAGE_SIZE);
>> +	if (!mem) {
>> +		pr_err("Cannot find memblock range for pstore_ram\n");
>> +		return;
>> +	}
>> +
>> +	ret = memblock_reserve(mem, size);
>> +	if (ret) {
>> +		pr_err("Failed to reserve memory from 0x%llx-0x%llx\n",
>> +				(unsigned long long)mem,
>> +				(unsigned long long)(mem + size - 1));
>> +		return;
>> +	}
>> +
>> +	pstore_ram_data.mem_address = mem;
>> +	pstore_ram_data.mem_size = size;
>> +
>> +	pr_info("reserved RAM buffer (0x%zx@0x%llx)\n",
>> +			size, (unsigned long long)mem);
>> +}
>> +
>> +static ssize_t pstore_ramoops_write(struct file *f, const char __user *buf,
>> +		size_t count, loff_t *ppos)
>> +{
>> +	return 0;
>> +}
>> +
>> +static ssize_t pstore_ramoops_read(struct file *f, char __user *buf,
>> +		size_t count, loff_t *ppos)
>> +{
>> +	struct ramoops_zone *zone = (struct ramoops_zone *)f->private_data;
>> +
>> +	pstore_dump_records(zone);
>> +	return 0;
>> +}
>> +
>> +static const struct file_operations pstore_ramoops_fops = {
>> +	.open   = simple_open,
>> +	.read   = pstore_ramoops_read,
>> +	.write  = pstore_ramoops_write,
>> +};
>> +
>> +
>> +static int __init norm_zone_test_init(void)
>> +{
>> +	cpufreq_register_notifier(&freq_transition,
>> +			CPUFREQ_TRANSITION_NOTIFIER);
>> +	debugfs_create_file("zone_dump", 0660, NULL, (void *)&test_zone, &pstore_ramoops_fops);
>> +	debugfs_create_file("zone1_dump", 0660, NULL, (void *)&test_zone1, &pstore_ramoops_fops);
>> +
>> +	return 0;
>> +}
>> +module_init(norm_zone_test_init);
>>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-05-07  1:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-06  5:03 [PATCH v5 0/3] Add a method to expand tracers for pstore easily Liu ShuoX
2014-05-06  5:03 ` [PATCH v5 1/3] pstore: restructure ramoops to support more trace Liu ShuoX
2014-05-06  5:03 ` [PATCH v5 2/3] pstore: add seq_ops for norm zone Liu ShuoX
2014-05-06  5:03 ` [PATCH v5 3/3] pstore: support current records dump in ramoops Liu ShuoX
2014-05-06  5:03 ` [PATCH] [NOMERGE] reserved ram for pstore on PC (applied on top of new pstore patch) Liu ShuoX
2014-05-06 14:48   ` Paul Gortmaker
2014-05-07  1:30     ` Liu ShuoX

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.