All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] powerpc/powernv: Platform dump interface
@ 2014-01-16 12:16 Vasant Hegde
  2014-02-08 21:20 ` Anton Blanchard
  2014-02-21  0:15 ` [PATCH v2] powernv: don't attempt to refetch the FSP dump until the user has explicitly acked it Stewart Smith
  0 siblings, 2 replies; 8+ messages in thread
From: Vasant Hegde @ 2014-01-16 12:16 UTC (permalink / raw)
  To: linuxppc-dev

This patch adds interface to retrieve FSP and Platform dump.

Flow:
  - We register for OPAL notification events.
  - OPAL sends new dump available notification.
  - We retrieve the dump via OPAL interface and send it to debugfs.
  - User copies the dump data and end ACKs via debugfs.
  - We send ACK to OPAL.

OPAL APIs:
  - opal_dump_init()
  - opal_dump_info()
  - opal_dump_read()
  - opal_dump_ack()
  - opal_dump_resend_notification()

debugfs files:
  We create below dump related files under "fsp" directory.
    - dump            : Dump data
    - dump_available  : New dump available notification to userspace
    - dump_control    : ACK dump. Also initiate new FSP dump
    - README          : README

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
Ben,
  I have rebased this patch on top of your next branch.

-Vasant

 arch/powerpc/include/asm/opal.h                |   12 +
 arch/powerpc/platforms/powernv/Makefile        |    2 
 arch/powerpc/platforms/powernv/opal-dump.c     |  436 ++++++++++++++++++++++++
 arch/powerpc/platforms/powernv/opal-wrappers.S |    5 
 arch/powerpc/platforms/powernv/opal.c          |    2 
 5 files changed, 456 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/platforms/powernv/opal-dump.c

diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 9a87b44..0f4c7ff 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -154,8 +154,13 @@ extern int opal_enter_rtas(struct rtas_args *args,
 #define OPAL_FLASH_VALIDATE			76
 #define OPAL_FLASH_MANAGE			77
 #define OPAL_FLASH_UPDATE			78
+#define OPAL_DUMP_INIT				81
+#define OPAL_DUMP_INFO				82
+#define OPAL_DUMP_READ				83
+#define OPAL_DUMP_ACK				84
 #define OPAL_GET_MSG				85
 #define OPAL_CHECK_ASYNC_COMPLETION		86
+#define OPAL_DUMP_RESEND			91
 
 #ifndef __ASSEMBLY__
 
@@ -236,6 +241,7 @@ enum OpalPendingState {
 	OPAL_EVENT_EPOW			= 0x80,
 	OPAL_EVENT_LED_STATUS		= 0x100,
 	OPAL_EVENT_PCI_ERROR		= 0x200,
+	OPAL_EVENT_DUMP_AVAIL		= 0x400,
 	OPAL_EVENT_MSG_PENDING		= 0x800,
 };
 
@@ -825,6 +831,11 @@ int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type,
 int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
 int64_t opal_manage_flash(uint8_t op);
 int64_t opal_update_flash(uint64_t blk_list);
+int64_t opal_dump_init(uint8_t dump_type);
+int64_t opal_dump_info(uint32_t *dump_id, uint32_t *dump_size);
+int64_t opal_dump_read(uint32_t dump_id, uint64_t buffer);
+int64_t opal_dump_ack(uint32_t dump_id);
+int64_t opal_dump_resend_notification(void);
 
 int64_t opal_get_msg(uint64_t buffer, size_t size);
 int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
@@ -859,6 +870,7 @@ extern void opal_get_rtc_time(struct rtc_time *tm);
 extern unsigned long opal_get_boot_time(void);
 extern void opal_nvram_init(void);
 extern void opal_flash_init(void);
+extern void opal_platform_dump_init(void);
 
 extern int opal_machine_check(struct pt_regs *regs);
 
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index 8d767fd..3528c11 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,6 +1,6 @@
 obj-y			+= setup.o opal-takeover.o opal-wrappers.o opal.o
 obj-y			+= opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
-obj-y			+= rng.o
+obj-y			+= rng.o opal-dump.o
 
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_PCI)	+= pci.o pci-p5ioc2.o pci-ioda.o
diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
new file mode 100644
index 0000000..4447027
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-dump.c
@@ -0,0 +1,436 @@
+/*
+ * PowerNV OPAL Dump Interface
+ *
+ * Copyright 2013 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kobject.h>
+#include <linux/debugfs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/delay.h>
+
+#include <asm/opal.h>
+
+/* Dump type */
+#define DUMP_TYPE_FSP	0x01
+
+/* Extract failed */
+#define DUMP_NACK_ID	0x00
+
+/* Dump record */
+struct dump_record {
+	uint8_t		type;
+	uint32_t	id;
+	uint32_t	size;
+	char		*buffer;
+};
+static struct dump_record dump_record;
+
+/* Dump available status */
+static u32 dump_avail;
+
+/* Binary blobs */
+static struct debugfs_blob_wrapper dump_blob;
+static struct debugfs_blob_wrapper readme_blob;
+
+/* Ignore dump notification, if we fail to create debugfs files */
+static bool dump_disarmed = false;
+
+
+static void free_dump_sg_list(struct opal_sg_list *list)
+{
+	struct opal_sg_list *sg1;
+	while (list) {
+		sg1 = list->next;
+		kfree(list);
+		list = sg1;
+	}
+	list = NULL;
+}
+
+/*
+ * Build dump buffer scatter gather list
+ */
+static struct opal_sg_list *dump_data_to_sglist(void)
+{
+	struct opal_sg_list *sg1, *list = NULL;
+	void *addr;
+	int64_t size;
+
+	addr = dump_record.buffer;
+	size = dump_record.size;
+
+	sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!sg1)
+		goto nomem;
+
+	list = sg1;
+	sg1->num_entries = 0;
+	while (size > 0) {
+		/* Translate virtual address to physical address */
+		sg1->entry[sg1->num_entries].data =
+			(void *)(vmalloc_to_pfn(addr) << PAGE_SHIFT);
+
+		if (size > PAGE_SIZE)
+			sg1->entry[sg1->num_entries].length = PAGE_SIZE;
+		else
+			sg1->entry[sg1->num_entries].length = size;
+
+		sg1->num_entries++;
+		if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
+			sg1->next = kzalloc(PAGE_SIZE, GFP_KERNEL);
+			if (!sg1->next)
+				goto nomem;
+
+			sg1 = sg1->next;
+			sg1->num_entries = 0;
+		}
+		addr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	return list;
+
+nomem:
+	pr_err("%s : Failed to allocate memory\n", __func__);
+	free_dump_sg_list(list);
+	return NULL;
+}
+
+/*
+ * Translate sg list address to absolute
+ */
+static void sglist_to_phy_addr(struct opal_sg_list *list)
+{
+	struct opal_sg_list *sg, *next;
+
+	for (sg = list; sg; sg = next) {
+		next = sg->next;
+		/* Don't translate NULL pointer for last entry */
+		if (sg->next)
+			sg->next = (struct opal_sg_list *)__pa(sg->next);
+		else
+			sg->next = NULL;
+
+		/* Convert num_entries to length */
+		sg->num_entries =
+			sg->num_entries * sizeof(struct opal_sg_entry) + 16;
+	}
+}
+
+static void free_dump_data_buf(void)
+{
+	vfree(dump_record.buffer);
+	dump_record.size = 0;
+}
+
+/*
+ * Allocate dump data buffer.
+ */
+static int alloc_dump_data_buf(void)
+{
+	dump_record.buffer = vzalloc(PAGE_ALIGN(dump_record.size));
+	if (!dump_record.buffer) {
+		pr_err("%s : Failed to allocate memory\n", __func__);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+/*
+ * Initiate FipS dump
+ */
+static int64_t dump_fips_init(uint8_t type)
+{
+	int rc;
+
+	rc = opal_dump_init(type);
+	if (rc)
+		pr_warn("%s: Failed to initiate FipS dump (%d)\n",
+			__func__, rc);
+	return rc;
+}
+
+/*
+ * Get dump ID and size.
+ */
+static int64_t dump_read_info(void)
+{
+	int rc;
+
+	rc = opal_dump_info(&dump_record.id, &dump_record.size);
+	if (rc)
+		pr_warn("%s: Failed to get dump info (%d)\n",
+			__func__, rc);
+	return rc;
+}
+
+/*
+ * Send acknowledgement to OPAL
+ */
+static int64_t dump_send_ack(uint32_t dump_id)
+{
+	int rc;
+
+	rc = opal_dump_ack(dump_id);
+	if (rc)
+		pr_warn("%s: Failed to send ack to Dump ID 0x%x (%d)\n",
+			__func__, dump_id, rc);
+	return rc;
+}
+
+/*
+ * Retrieve dump data
+ */
+static int64_t dump_read_data(void)
+{
+	struct opal_sg_list *list;
+	uint64_t addr;
+	int64_t rc;
+
+	/* Allocate memory */
+	rc = alloc_dump_data_buf();
+	if (rc)
+		goto out;
+
+	/* Generate SG list */
+	list = dump_data_to_sglist();
+	if (!list) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Translate sg list addr to real address */
+	sglist_to_phy_addr(list);
+
+	/* First entry address */
+	addr = __pa(list);
+
+	/* Fetch data */
+	rc = OPAL_BUSY_EVENT;
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_dump_read(dump_record.id, addr);
+		if (rc == OPAL_BUSY_EVENT) {
+			opal_poll_events(NULL);
+			msleep(10);
+		}
+	}
+
+	if (rc != OPAL_SUCCESS && rc != OPAL_PARTIAL)
+		pr_warn("%s: Extract dump failed for ID 0x%x\n",
+			__func__, dump_record.id);
+
+	/* Free SG list */
+	free_dump_sg_list(list);
+
+out:
+	return rc;
+}
+
+static int extract_dump(void)
+{
+	int rc;
+
+	/* Get dump ID, size */
+	rc = dump_read_info();
+	if (rc != OPAL_SUCCESS)
+		return rc;
+
+	/* Read dump data */
+	rc = dump_read_data();
+	if (rc != OPAL_SUCCESS && rc != OPAL_PARTIAL) {
+		/*
+		 * Failed to allocate memory to retrieve dump. Lets send
+		 * negative ack so that we get notification again.
+		 */
+		dump_send_ack(DUMP_NACK_ID);
+
+		/* Free dump buffer */
+		free_dump_data_buf();
+
+		return rc;
+	}
+	if (rc == OPAL_PARTIAL)
+		pr_info("%s: Platform dump partially read. ID = 0x%x\n",
+			__func__, dump_record.id);
+	else
+		pr_info("%s: New platform dump available. ID = 0x%x\n",
+			__func__, dump_record.id);
+
+	/* Update dump blob */
+	dump_blob.data = (void *)dump_record.buffer;
+	dump_blob.size = dump_record.size;
+
+	/* Update dump available status */
+	dump_avail = 1;
+
+	return rc;
+}
+
+static void dump_extract_fn(struct work_struct *work)
+{
+	extract_dump();
+}
+
+static DECLARE_WORK(dump_work, dump_extract_fn);
+
+/* Workqueue to extract dump */
+static void schedule_extract_dump(void)
+{
+	schedule_work(&dump_work);
+}
+
+/*
+ * New dump available notification
+ *
+ * Once we get notification, we extract dump via OPAL call
+ * and then pass dump to userspace via debugfs interface.
+ */
+static int dump_event(struct notifier_block *nb,
+		      unsigned long events, void *change)
+{
+	/*
+	 * Don't retrieve dump, if we don't have debugfs
+	 * interface to pass data to userspace.
+	 */
+	if (dump_disarmed)
+		return 0;
+
+	/* Check for dump available notification */
+	if (events & OPAL_EVENT_DUMP_AVAIL)
+		schedule_extract_dump();
+
+	return 0;
+}
+
+static struct notifier_block dump_nb = {
+	.notifier_call  = dump_event,
+	.next           = NULL,
+	.priority       = 0
+};
+
+
+/* debugfs README message */
+static const char readme_msg[] =
+	"Platform dump HOWTO:\n\n"
+	"files:\n"
+	"  dump                  - Binary file, contains actual dump data\n"
+	"  dump_available (r--)  - New dump available notification\n"
+	"                          0 : No dump available\n"
+	"                          1 : New dump available\n"
+	"  dump_control(-w-)     - Dump control file\n"
+	"                          1 : Send acknowledgement (dump copied)\n"
+	"                          2 : Initiate FipS dump\n";
+
+/* debugfs dump_control file operations */
+static ssize_t dump_control_write(struct file *file,
+				  const char __user *user_buf,
+				  size_t count, loff_t *ppos)
+{
+	char buf[4];
+	size_t buf_size;
+
+	buf_size = min(count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+
+	switch (buf[0]) {
+	case '1':	/* Dump send ack */
+		if (dump_avail) {
+			dump_avail = 0;
+			free_dump_data_buf();
+			dump_send_ack(dump_record.id);
+		}
+		break;
+	case '2':	/* Initiate FipS dump */
+		dump_fips_init(DUMP_TYPE_FSP);
+		break;
+	default:
+		break;
+	}
+	return count;
+}
+
+static const struct file_operations dump_control_fops = {
+	.open	= simple_open,
+	.write	= dump_control_write,
+	.llseek	= default_llseek,
+};
+
+/*
+ * Create dump debugfs file
+ */
+static int debugfs_dump_init(void)
+{
+	struct dentry *dir, *file;
+
+	/* FSP dump directory */
+	dir = debugfs_create_dir("fsp", NULL);
+	if (!dir)
+		goto out;
+
+	/* README */
+	readme_blob.data = (void *)readme_msg;
+	readme_blob.size = strlen(readme_msg);
+	file = debugfs_create_blob("README", 0400, dir, &readme_blob);
+	if (!file)
+		goto remove_dir;
+
+	/* Dump available notification */
+	file = debugfs_create_u32("dump_avail", 0400, dir, &dump_avail);
+	if (!file)
+		goto remove_dir;
+
+	/* data file */
+	dump_blob.data = (void *)dump_record.buffer;
+	dump_blob.size = dump_record.size;
+	file = debugfs_create_blob("dump", 0400, dir, &dump_blob);
+	if (!file)
+		goto remove_dir;
+
+	/* Control file */
+	file = debugfs_create_file("dump_control", 0200, dir,
+				   NULL, &dump_control_fops);
+	if (!file)
+		goto remove_dir;
+
+	return 0;
+
+remove_dir:
+	debugfs_remove_recursive(dir);
+
+out:
+	dump_disarmed = true;
+	return -1;
+}
+
+void __init opal_platform_dump_init(void)
+{
+	int rc;
+
+	/* debugfs interface */
+	rc = debugfs_dump_init();
+	if (rc) {
+		pr_warn("%s: Failed to create debugfs interface (%d)\n",
+			__func__, rc);
+		return;
+	}
+
+	/* Register for opal notifier */
+	rc = opal_notifier_register(&dump_nb);
+	if (rc) {
+		pr_warn("%s: Can't register OPAL event notifier (%d)\n",
+			__func__, rc);
+		return;
+	}
+
+	/* Request to resend dump available notification */
+	opal_dump_resend_notification();
+}
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 719aa5c..c1e979b 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -126,5 +126,10 @@ OPAL_CALL(opal_return_cpu,			OPAL_RETURN_CPU);
 OPAL_CALL(opal_validate_flash,			OPAL_FLASH_VALIDATE);
 OPAL_CALL(opal_manage_flash,			OPAL_FLASH_MANAGE);
 OPAL_CALL(opal_update_flash,			OPAL_FLASH_UPDATE);
+OPAL_CALL(opal_dump_init,			OPAL_DUMP_INIT);
+OPAL_CALL(opal_dump_info,			OPAL_DUMP_INFO);
+OPAL_CALL(opal_dump_read,			OPAL_DUMP_READ);
+OPAL_CALL(opal_dump_ack,			OPAL_DUMP_ACK);
 OPAL_CALL(opal_get_msg,				OPAL_GET_MSG);
 OPAL_CALL(opal_check_completion,		OPAL_CHECK_ASYNC_COMPLETION);
+OPAL_CALL(opal_dump_resend_notification,	OPAL_DUMP_RESEND);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 7a184a0..1b00e99 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -473,6 +473,8 @@ static int __init opal_init(void)
 	if (rc == 0) {
 		/* Setup code update interface */
 		opal_flash_init();
+		/* Setup platform dump extract interface */
+		opal_platform_dump_init();
 	}
 
 	return 0;

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

* Re: [PATCH v2] powerpc/powernv: Platform dump interface
  2014-01-16 12:16 [PATCH v2] powerpc/powernv: Platform dump interface Vasant Hegde
@ 2014-02-08 21:20 ` Anton Blanchard
  2014-02-12 15:01   ` Vasant Hegde
  2014-02-21  0:15 ` [PATCH v2] powernv: don't attempt to refetch the FSP dump until the user has explicitly acked it Stewart Smith
  1 sibling, 1 reply; 8+ messages in thread
From: Anton Blanchard @ 2014-02-08 21:20 UTC (permalink / raw)
  To: Vasant Hegde; +Cc: linuxppc-dev


Hi Vasant,

> +static void free_dump_sg_list(struct opal_sg_list *list)
> +{
> +	struct opal_sg_list *sg1;
> +	while (list) {
> +		sg1 = list->next;
> +		kfree(list);
> +		list = sg1;
> +	}
> +	list = NULL;
> +}
> +
> +/*
> + * Build dump buffer scatter gather list
> + */
> +static struct opal_sg_list *dump_data_to_sglist(void)
> +{
> +	struct opal_sg_list *sg1, *list = NULL;
> +	void *addr;
> +	int64_t size;
> +
> +	addr = dump_record.buffer;
> +	size = dump_record.size;
> +
> +	sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
> +	if (!sg1)
> +		goto nomem;
> +
> +	list = sg1;
> +	sg1->num_entries = 0;
> +	while (size > 0) {
> +		/* Translate virtual address to physical address */
> +		sg1->entry[sg1->num_entries].data =
> +			(void *)(vmalloc_to_pfn(addr) << PAGE_SHIFT);
> +
> +		if (size > PAGE_SIZE)
> +			sg1->entry[sg1->num_entries].length =
> PAGE_SIZE;
> +		else
> +			sg1->entry[sg1->num_entries].length = size;
> +
> +		sg1->num_entries++;
> +		if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
> +			sg1->next = kzalloc(PAGE_SIZE, GFP_KERNEL);
> +			if (!sg1->next)
> +				goto nomem;
> +
> +			sg1 = sg1->next;
> +			sg1->num_entries = 0;
> +		}
> +		addr += PAGE_SIZE;
> +		size -= PAGE_SIZE;
> +	}
> +	return list;
> +
> +nomem:
> +	pr_err("%s : Failed to allocate memory\n", __func__);
> +	free_dump_sg_list(list);
> +	return NULL;
> +}
> +
> +/*
> + * Translate sg list address to absolute
> + */
> +static void sglist_to_phy_addr(struct opal_sg_list *list)
> +{
> +	struct opal_sg_list *sg, *next;
> +
> +	for (sg = list; sg; sg = next) {
> +		next = sg->next;
> +		/* Don't translate NULL pointer for last entry */
> +		if (sg->next)
> +			sg->next = (struct opal_sg_list
> *)__pa(sg->next);
> +		else
> +			sg->next = NULL;
> +
> +		/* Convert num_entries to length */
> +		sg->num_entries =
> +			sg->num_entries * sizeof(struct
> opal_sg_entry) + 16;
> +	}
> +}
> +
> +static void free_dump_data_buf(void)
> +{
> +	vfree(dump_record.buffer);
> +	dump_record.size = 0;
> +}

This looks identical to the code in opal-flash.c. Considering how
complicated it is, can we put it somewhere common?

Anton

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

* Re: [PATCH v2] powerpc/powernv: Platform dump interface
  2014-02-08 21:20 ` Anton Blanchard
@ 2014-02-12 15:01   ` Vasant Hegde
  2014-03-25  5:52     ` Anton Blanchard
  0 siblings, 1 reply; 8+ messages in thread
From: Vasant Hegde @ 2014-02-12 15:01 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linuxppc-dev

On 02/09/2014 02:50 AM, Anton Blanchard wrote:
>
> Hi Vasant,
>
>> +static void free_dump_sg_list(struct opal_sg_list *list)
>> +{
>> +	struct opal_sg_list *sg1;
>> +	while (list) {
>> +		sg1 = list->next;
>> +		kfree(list);
>> +		list = sg1;
>> +	}
>> +	list = NULL;
>> +}
>> +
>> +/*
>> + * Build dump buffer scatter gather list
>> + */
>> +static struct opal_sg_list *dump_data_to_sglist(void)
>> +{
>> +	struct opal_sg_list *sg1, *list = NULL;
>> +	void *addr;
>> +	int64_t size;
>> +
>> +	addr = dump_record.buffer;
>> +	size = dump_record.size;
>> +
>> +	sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
>> +	if (!sg1)
>> +		goto nomem;
>> +
>> +	list = sg1;
>> +	sg1->num_entries = 0;
>> +	while (size > 0) {
>> +		/* Translate virtual address to physical address */
>> +		sg1->entry[sg1->num_entries].data =
>> +			(void *)(vmalloc_to_pfn(addr) << PAGE_SHIFT);
>> +
>> +		if (size > PAGE_SIZE)
>> +			sg1->entry[sg1->num_entries].length =
>> PAGE_SIZE;
>> +		else
>> +			sg1->entry[sg1->num_entries].length = size;
>> +
>> +		sg1->num_entries++;
>> +		if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
>> +			sg1->next = kzalloc(PAGE_SIZE, GFP_KERNEL);
>> +			if (!sg1->next)
>> +				goto nomem;
>> +
>> +			sg1 = sg1->next;
>> +			sg1->num_entries = 0;
>> +		}
>> +		addr += PAGE_SIZE;
>> +		size -= PAGE_SIZE;
>> +	}
>> +	return list;
>> +
>> +nomem:
>> +	pr_err("%s : Failed to allocate memory\n", __func__);
>> +	free_dump_sg_list(list);
>> +	return NULL;
>> +}
>> +
>> +/*
>> + * Translate sg list address to absolute
>> + */
>> +static void sglist_to_phy_addr(struct opal_sg_list *list)
>> +{
>> +	struct opal_sg_list *sg, *next;
>> +
>> +	for (sg = list; sg; sg = next) {
>> +		next = sg->next;
>> +		/* Don't translate NULL pointer for last entry */
>> +		if (sg->next)
>> +			sg->next = (struct opal_sg_list
>> *)__pa(sg->next);
>> +		else
>> +			sg->next = NULL;
>> +
>> +		/* Convert num_entries to length */
>> +		sg->num_entries =
>> +			sg->num_entries * sizeof(struct
>> opal_sg_entry) + 16;
>> +	}
>> +}
>> +
>> +static void free_dump_data_buf(void)
>> +{
>> +	vfree(dump_record.buffer);
>> +	dump_record.size = 0;
>> +}
>

Anton,

> This looks identical to the code in opal-flash.c. Considering how
> complicated it is, can we put it somewhere common?

Thanks for the review.. Will look into it next week.

-Vasant

>
> Anton
>

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

* [PATCH v2] powernv: don't attempt to refetch the FSP dump until the user has explicitly acked it.
  2014-01-16 12:16 [PATCH v2] powerpc/powernv: Platform dump interface Vasant Hegde
  2014-02-08 21:20 ` Anton Blanchard
@ 2014-02-21  0:15 ` Stewart Smith
  2014-02-21  2:52   ` Michael Neuling
  1 sibling, 1 reply; 8+ messages in thread
From: Stewart Smith @ 2014-02-21  0:15 UTC (permalink / raw)
  To: linuxppc-dev, hegdevasant; +Cc: Stewart Smith

This fixes a bug where we would get two events from OPAL with DUMP_AVAIL
set (which is valid for OPAL to do) and in the second run of extract_dump()
we would fail to free the memory previously allocated for the dump
(leaking ~6MB+) as well as on the second dump_read_data() call OPAL
would not retrieve the dump, leaving us with a dump in linux that was
the correct size but all zeros.

Changes since v1: fixed typo

Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powernv/opal-dump.c |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
index 4447027..53c2675 100644
--- a/arch/powerpc/platforms/powernv/opal-dump.c
+++ b/arch/powerpc/platforms/powernv/opal-dump.c
@@ -238,6 +238,14 @@ static int extract_dump(void)
 {
 	int rc;
 
+	/* We can get notified that a dump is available multiple times
+	 * (dump_read_info clears the bit in the event from OPAL).
+	 * But we should not re-read the dump from OPAL as we
+	 * don't get the next dump until we've explicitly acked this one.
+	 */
+	if (dump_avail)
+		return OPAL_SUCCESS;
+
 	/* Get dump ID, size */
 	rc = dump_read_info();
 	if (rc != OPAL_SUCCESS)
-- 
1.7.10.4

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

* Re: [PATCH v2] powernv: don't attempt to refetch the FSP dump until the user has explicitly acked it.
  2014-02-21  0:15 ` [PATCH v2] powernv: don't attempt to refetch the FSP dump until the user has explicitly acked it Stewart Smith
@ 2014-02-21  2:52   ` Michael Neuling
  2014-02-21  3:34     ` Stewart Smith
  0 siblings, 1 reply; 8+ messages in thread
From: Michael Neuling @ 2014-02-21  2:52 UTC (permalink / raw)
  To: Stewart Smith; +Cc: hegdevasant, linuxppc-dev

Stewart Smith <stewart@linux.vnet.ibm.com> wrote:

> This fixes a bug where we would get two events from OPAL with DUMP_AVAIL
> set (which is valid for OPAL to do) and in the second run of extract_dump()
> we would fail to free the memory previously allocated for the dump
> (leaking ~6MB+) as well as on the second dump_read_data() call OPAL
> would not retrieve the dump, leaving us with a dump in linux that was
> the correct size but all zeros.
> 
> Changes since v1: fixed typo
> 
> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Should we CC stable on this?

Mikey

> ---
>  arch/powerpc/platforms/powernv/opal-dump.c |    8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
> index 4447027..53c2675 100644
> --- a/arch/powerpc/platforms/powernv/opal-dump.c
> +++ b/arch/powerpc/platforms/powernv/opal-dump.c
> @@ -238,6 +238,14 @@ static int extract_dump(void)
>  {
>  	int rc;
>  
> +	/* We can get notified that a dump is available multiple times
> +	 * (dump_read_info clears the bit in the event from OPAL).
> +	 * But we should not re-read the dump from OPAL as we
> +	 * don't get the next dump until we've explicitly acked this one.
> +	 */
> +	if (dump_avail)
> +		return OPAL_SUCCESS;
> +
>  	/* Get dump ID, size */
>  	rc = dump_read_info();
>  	if (rc != OPAL_SUCCESS)
> -- 
> 1.7.10.4
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

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

* Re: [PATCH v2] powernv: don't attempt to refetch the FSP dump until the user has explicitly acked it.
  2014-02-21  2:52   ` Michael Neuling
@ 2014-02-21  3:34     ` Stewart Smith
  0 siblings, 0 replies; 8+ messages in thread
From: Stewart Smith @ 2014-02-21  3:34 UTC (permalink / raw)
  To: Michael Neuling; +Cc: hegdevasant, linuxppc-dev

Michael Neuling <mikey@neuling.org> writes:
> Stewart Smith <stewart@linux.vnet.ibm.com> wrote:
>
>> This fixes a bug where we would get two events from OPAL with DUMP_AVAIL
>> set (which is valid for OPAL to do) and in the second run of extract_dump()
>> we would fail to free the memory previously allocated for the dump
>> (leaking ~6MB+) as well as on the second dump_read_data() call OPAL
>> would not retrieve the dump, leaving us with a dump in linux that was
>> the correct size but all zeros.
>> 
>> Changes since v1: fixed typo
>> 
>> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
>> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>
> Should we CC stable on this?

we don't need to as the code this patches hasn't made it to stable
yet. Hopefully Vasant resends a version of the patch incorporating my
fix :)

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

* Re: [PATCH v2] powerpc/powernv: Platform dump interface
  2014-02-12 15:01   ` Vasant Hegde
@ 2014-03-25  5:52     ` Anton Blanchard
  2014-03-26 14:14       ` Vasant Hegde
  0 siblings, 1 reply; 8+ messages in thread
From: Anton Blanchard @ 2014-03-25  5:52 UTC (permalink / raw)
  To: Vasant Hegde; +Cc: linuxppc-dev

Hi Vasant,

> On 02/09/2014 02:50 AM, Anton Blanchard wrote:
> >
> > Hi Vasant,
> >
> >> +static void free_dump_sg_list(struct opal_sg_list *list)
> >> +{
> >> +	struct opal_sg_list *sg1;
> >> +	while (list) {
> >> +		sg1 = list->next;
> >> +		kfree(list);
> >> +		list = sg1;
> >> +	}
> >> +	list = NULL;
> >> +}
> >> +
> >> +/*
> >> + * Build dump buffer scatter gather list
> >> + */
> >> +static struct opal_sg_list *dump_data_to_sglist(void)
> >> +{
> >> +	struct opal_sg_list *sg1, *list = NULL;
> >> +	void *addr;
> >> +	int64_t size;
> >> +
> >> +	addr = dump_record.buffer;
> >> +	size = dump_record.size;
> >> +
> >> +	sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
> >> +	if (!sg1)
> >> +		goto nomem;
> >> +
> >> +	list = sg1;
> >> +	sg1->num_entries = 0;
> >> +	while (size > 0) {
> >> +		/* Translate virtual address to physical address
> >> */
> >> +		sg1->entry[sg1->num_entries].data =
> >> +			(void *)(vmalloc_to_pfn(addr) <<
> >> PAGE_SHIFT); +
> >> +		if (size > PAGE_SIZE)
> >> +			sg1->entry[sg1->num_entries].length =
> >> PAGE_SIZE;
> >> +		else
> >> +			sg1->entry[sg1->num_entries].length =
> >> size; +
> >> +		sg1->num_entries++;
> >> +		if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
> >> +			sg1->next = kzalloc(PAGE_SIZE,
> >> GFP_KERNEL);
> >> +			if (!sg1->next)
> >> +				goto nomem;
> >> +
> >> +			sg1 = sg1->next;
> >> +			sg1->num_entries = 0;
> >> +		}
> >> +		addr += PAGE_SIZE;
> >> +		size -= PAGE_SIZE;
> >> +	}
> >> +	return list;
> >> +
> >> +nomem:
> >> +	pr_err("%s : Failed to allocate memory\n", __func__);
> >> +	free_dump_sg_list(list);
> >> +	return NULL;
> >> +}
> >> +
> >> +/*
> >> + * Translate sg list address to absolute
> >> + */
> >> +static void sglist_to_phy_addr(struct opal_sg_list *list)
> >> +{
> >> +	struct opal_sg_list *sg, *next;
> >> +
> >> +	for (sg = list; sg; sg = next) {
> >> +		next = sg->next;
> >> +		/* Don't translate NULL pointer for last entry */
> >> +		if (sg->next)
> >> +			sg->next = (struct opal_sg_list
> >> *)__pa(sg->next);
> >> +		else
> >> +			sg->next = NULL;
> >> +
> >> +		/* Convert num_entries to length */
> >> +		sg->num_entries =
> >> +			sg->num_entries * sizeof(struct
> >> opal_sg_entry) + 16;
> >> +	}
> >> +}
> >> +
> >> +static void free_dump_data_buf(void)
> >> +{
> >> +	vfree(dump_record.buffer);
> >> +	dump_record.size = 0;
> >> +}
> >
> 
> Anton,
> 
> > This looks identical to the code in opal-flash.c. Considering how
> > complicated it is, can we put it somewhere common?
> 
> Thanks for the review.. Will look into it next week.

This doesn't appear to have been fixed in the version that went into
next.

Anton

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

* Re: [PATCH v2] powerpc/powernv: Platform dump interface
  2014-03-25  5:52     ` Anton Blanchard
@ 2014-03-26 14:14       ` Vasant Hegde
  0 siblings, 0 replies; 8+ messages in thread
From: Vasant Hegde @ 2014-03-26 14:14 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linuxppc-dev

On 03/25/2014 11:22 AM, Anton Blanchard wrote:
> Hi Vasant,
>
>> On 02/09/2014 02:50 AM, Anton Blanchard wrote:
>>>
>>> Hi Vasant,
>>>
>>>> +static void free_dump_sg_list(struct opal_sg_list *list)
>>>> +{
>>>> +	struct opal_sg_list *sg1;
>>>> +	while (list) {
>>>> +		sg1 = list->next;
>>>> +		kfree(list);
>>>> +		list = sg1;
>>>> +	}
>>>> +	list = NULL;
>>>> +}
>>>> +
>>>> +/*
>>>> + * Build dump buffer scatter gather list
>>>> + */
>>>> +static struct opal_sg_list *dump_data_to_sglist(void)
>>>> +{
>>>> +	struct opal_sg_list *sg1, *list = NULL;
>>>> +	void *addr;
>>>> +	int64_t size;
>>>> +
>>>> +	addr = dump_record.buffer;
>>>> +	size = dump_record.size;
>>>> +
>>>> +	sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
>>>> +	if (!sg1)
>>>> +		goto nomem;
>>>> +
>>>> +	list = sg1;
>>>> +	sg1->num_entries = 0;
>>>> +	while (size > 0) {
>>>> +		/* Translate virtual address to physical address
>>>> */
>>>> +		sg1->entry[sg1->num_entries].data =
>>>> +			(void *)(vmalloc_to_pfn(addr) <<
>>>> PAGE_SHIFT); +
>>>> +		if (size > PAGE_SIZE)
>>>> +			sg1->entry[sg1->num_entries].length =
>>>> PAGE_SIZE;
>>>> +		else
>>>> +			sg1->entry[sg1->num_entries].length =
>>>> size; +
>>>> +		sg1->num_entries++;
>>>> +		if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
>>>> +			sg1->next = kzalloc(PAGE_SIZE,
>>>> GFP_KERNEL);
>>>> +			if (!sg1->next)
>>>> +				goto nomem;
>>>> +
>>>> +			sg1 = sg1->next;
>>>> +			sg1->num_entries = 0;
>>>> +		}
>>>> +		addr += PAGE_SIZE;
>>>> +		size -= PAGE_SIZE;
>>>> +	}
>>>> +	return list;
>>>> +
>>>> +nomem:
>>>> +	pr_err("%s : Failed to allocate memory\n", __func__);
>>>> +	free_dump_sg_list(list);
>>>> +	return NULL;
>>>> +}
>>>> +
>>>> +/*
>>>> + * Translate sg list address to absolute
>>>> + */
>>>> +static void sglist_to_phy_addr(struct opal_sg_list *list)
>>>> +{
>>>> +	struct opal_sg_list *sg, *next;
>>>> +
>>>> +	for (sg = list; sg; sg = next) {
>>>> +		next = sg->next;
>>>> +		/* Don't translate NULL pointer for last entry */
>>>> +		if (sg->next)
>>>> +			sg->next = (struct opal_sg_list
>>>> *)__pa(sg->next);
>>>> +		else
>>>> +			sg->next = NULL;
>>>> +
>>>> +		/* Convert num_entries to length */
>>>> +		sg->num_entries =
>>>> +			sg->num_entries * sizeof(struct
>>>> opal_sg_entry) + 16;
>>>> +	}
>>>> +}
>>>> +
>>>> +static void free_dump_data_buf(void)
>>>> +{
>>>> +	vfree(dump_record.buffer);
>>>> +	dump_record.size = 0;
>>>> +}
>>>
>>
>> Anton,
>>
>>> This looks identical to the code in opal-flash.c. Considering how
>>> complicated it is, can we put it somewhere common?
>>
>> Thanks for the review.. Will look into it next week.
>

Anton,

> This doesn't appear to have been fixed in the version that went into
> next.
>

Stewart rewrote dump interface.. That set of patch went into next, not my 
original patch..
Yes.. SG list separation is not yet done.. Never got a chance to look into this 
one.. Will try to
do it soon.

-Vasant

> Anton
>

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

end of thread, other threads:[~2014-03-26 14:14 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-16 12:16 [PATCH v2] powerpc/powernv: Platform dump interface Vasant Hegde
2014-02-08 21:20 ` Anton Blanchard
2014-02-12 15:01   ` Vasant Hegde
2014-03-25  5:52     ` Anton Blanchard
2014-03-26 14:14       ` Vasant Hegde
2014-02-21  0:15 ` [PATCH v2] powernv: don't attempt to refetch the FSP dump until the user has explicitly acked it Stewart Smith
2014-02-21  2:52   ` Michael Neuling
2014-02-21  3:34     ` Stewart Smith

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.