* [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.