/* Copyright 2013-2014 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/*
 * Dump support:
 *  We get dump notification from different sources:
 *   - During system initialization via HDAT
 *   - During FSP reset/reload (FipS dump)
 *   - Dump available notification MBOX command (0xCE, 0x78, 0x00)
 *
 *  To avoid complications, we keep list of dumps in a list and fetch
 *  them serially.
 *
 * Dump retrieve process:
 *   - Once we get notification from FSP we enqueue the dump ID and notify
 *     Linux via OPAL event notification.
 *   - Linux reads dump info and allocates required memory to fetch the dump
 *     and makes dump read call.
 *   - Sapphire fetches dump data from FSP.
 *   - Linux writes dump to disk and sends acknowledgement.
 *   - Sapphire acknowledges FSP.
 */

#include <fsp.h>
#include <psi.h>
#include <lock.h>
#include <device.h>
#include <skiboot.h>
#include <errorlog.h>
#include <opal-api.h>

/*
 * Max outstanding dumps to retrieve
 *
 * Note:
 *  Dumps are serialized. We don't get notification for second
 *  dump of given type until we acknowledge first one. But we
 *  may get notification for different dump type. And our dump
 *  retrieval code is serialized. Hence we use list to keep
 *  track of outstanding dumps to be retrieved.
 */
#define MAX_DUMP_RECORD		0x04

/* Max retry */
#define FIPS_DUMP_MAX_RETRY	0x03

/* Dump type */
#define DUMP_TYPE_FSP		0x01
#define DUMP_TYPE_SYS		0x02
#define DUMP_TYPE_SMA		0x03

/* Dump fetch size */
#define DUMP_FETCH_SIZE_FSP	0x500000
#define DUMP_FETCH_SIZE_SYS	0x400000
#define DUMP_FETCH_SIZE_RES	0x200000

/* Params for Fips dump */
#define FSP_DUMP_TOOL_TYPE	"SYS "
#define FSP_DUMP_CLIENT_ID	"SAPPHIRE_CLIENT"

enum dump_state {
	DUMP_STATE_ABSENT,	/* No FSP dump */
	DUMP_STATE_NONE,	/* No dump to retrieve */
	DUMP_STATE_NOTIFY,	/* Notified Linux */
	DUMP_STATE_FETCHING,	/* Dump retrieval is in progress */
	DUMP_STATE_FETCH,	/* Dump retrieve complete */
	DUMP_STATE_PARTIAL,	/* Partial read */
	DUMP_STATE_ABORTING,	/* Aborting due to kexec */
};

/* Pending dump list */
struct dump_record {
	uint8_t	 type;
	uint32_t id;
	uint32_t size;
	struct list_node link;
};

/* List definations */
static LIST_HEAD(dump_pending);
static LIST_HEAD(dump_free);

/* Dump retrieve state */
static enum dump_state dump_state = DUMP_STATE_NONE;

/* Dump buffer SG list */
static struct opal_sg_list *dump_data;
static struct dump_record *dump_entry;
static int64_t dump_offset;
static size_t fetch_remain;

/* FipS dump retry count */
static int retry_cnt;

/* Protect list and dump retrieve state */
static struct lock dump_lock = LOCK_UNLOCKED;

/* Forward declaration */
static int64_t fsp_opal_dump_init(uint8_t dump_type);
static int64_t fsp_dump_read(void);

DEFINE_LOG_ENTRY(OPAL_RC_DUMP_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP,
		 OPAL_PLATFORM_FIRMWARE,
		 OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT,
		 OPAL_NA);

DEFINE_LOG_ENTRY(OPAL_RC_DUMP_LIST, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP,
		 OPAL_PLATFORM_FIRMWARE,
		 OPAL_INFO,
		 OPAL_NA);

DEFINE_LOG_ENTRY(OPAL_RC_DUMP_ACK, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP,
		 OPAL_PLATFORM_FIRMWARE, OPAL_INFO,
		 OPAL_NA);

/*
 * Helper functions
 */
static inline void update_dump_state(enum dump_state state)
{
	dump_state = state;
}

static int64_t check_dump_state(void)
{
	switch (dump_state) {
	case DUMP_STATE_ABSENT:
		return OPAL_HARDWARE;
	case DUMP_STATE_NONE:
	case DUMP_STATE_NOTIFY:
		/* During dump fetch, notify is wrong state */
		return OPAL_WRONG_STATE;
	case DUMP_STATE_FETCHING:
	case DUMP_STATE_ABORTING:
		return OPAL_BUSY_EVENT;
	case DUMP_STATE_FETCH:
		return OPAL_SUCCESS;
	case DUMP_STATE_PARTIAL:
		return OPAL_PARTIAL;
	}
	return OPAL_SUCCESS;
}

static inline void dump_tce_map(uint32_t tce_offset,
				void *buffer, uint32_t size)
{
	uint32_t tlen = ALIGN_UP(size, TCE_PSIZE);
	fsp_tce_map(PSI_DMA_DUMP_DATA + tce_offset, buffer, tlen);
}

static inline void dump_tce_unmap(uint32_t size)
{
	fsp_tce_unmap(PSI_DMA_DUMP_DATA, size);
}

/*
 * Returns Data set ID for the given dump type
 */
static inline uint16_t get_dump_data_set_id(uint8_t type)
{
	switch (type) {
	case DUMP_TYPE_FSP:
		return FSP_DATASET_SP_DUMP;
	case DUMP_TYPE_SYS:
		return FSP_DATASET_HW_DUMP;
	default:
		break;
	}
	return OPAL_INTERNAL_ERROR;
}

/*
 * Returns max data we can fetch from FSP fetch data call
 */
static inline int64_t get_dump_fetch_max_size(uint8_t type)
{
	switch (type) {
	case DUMP_TYPE_FSP:
		return DUMP_FETCH_SIZE_FSP;
	case DUMP_TYPE_SYS:
		return DUMP_FETCH_SIZE_SYS;
	default:
		break;
	}
	return OPAL_INTERNAL_ERROR;
}

/*
 * Get dump record from pending list
 */
static inline struct dump_record *get_dump_rec_from_list(uint32_t id)
{
	struct dump_record *record;

	list_for_each(&dump_pending, record, link) {
		if (record->id == id)
			return record;
	}
	return NULL;
}

/*
 * New dump available notification to Linux
 */
static void update_opal_dump_notify(void)
{
	/*
	 * Wait until current dump retrieval to complete
	 * before notifying again.
	 */
	if (dump_state != DUMP_STATE_NONE)
		return;

	 /* More dump's to retrieve */
	if (!list_empty(&dump_pending)) {
		update_dump_state(DUMP_STATE_NOTIFY);
		opal_update_pending_evt(OPAL_EVENT_DUMP_AVAIL,
					OPAL_EVENT_DUMP_AVAIL);
	}
}

static int64_t remove_dump_id_from_list(uint32_t dump_id)
{
	struct dump_record *record, *nxt_record;
	int rc = OPAL_SUCCESS;
	bool found = false;

	/* Remove record from pending list */
	list_for_each_safe(&dump_pending, record, nxt_record, link) {
		if (record->id != dump_id)
			continue;

		found = true;
		list_del(&record->link);
		list_add(&dump_free, &record->link);
		break;
	}

	/*
	 * Continue update_opal_dump_notify even if it fails
	 * to remove ID. So that we can resend notification
	 * for the same dump ID to Linux.
	 */
	if (!found) { /* List corrupted? */
		log_simple_error(&e_info(OPAL_RC_DUMP_LIST),
				 "DUMP: ID 0x%x not found in list!\n",
				 dump_id);
		rc = OPAL_PARAMETER;
	}

	/* Update state */
	update_dump_state(DUMP_STATE_NONE);
	/* Notify next available dump to retrieve */
	update_opal_dump_notify();

	return rc;
}

static int64_t add_dump_id_to_list(uint8_t dump_type,
				   uint32_t dump_id, uint32_t dump_size)
{
	struct dump_record *record;
	int rc = OPAL_SUCCESS;

	lock(&dump_lock);

	rc = check_dump_state();
	if (rc == OPAL_HARDWARE)
		goto out;

	/* List is full ? */
	if (list_empty(&dump_free)) {
		printf("DUMP: Dump ID 0x%x is not queued.\n", dump_id);
		rc = OPAL_RESOURCE;
		goto out;
	}

	/* Already queued? */
	record = get_dump_rec_from_list(dump_id);
	if (record) {
		rc = OPAL_SUCCESS;
		goto out;
	}

	/* Add to list */
	record = list_pop(&dump_free, struct dump_record, link);
	record->type = dump_type;
	record->id = dump_id;
	record->size = dump_size;
	list_add_tail(&dump_pending, &record->link);

	/* OPAL notification */
	update_opal_dump_notify();
	rc = OPAL_SUCCESS;

out:
	unlock(&dump_lock);
	return rc;
}

static void dump_init_complete(struct fsp_msg *msg)
{
	uint8_t status = (msg->resp->word1 >> 8) & 0xff;

	printf("DUMP: FipS dump init status = 0x%x\n", status);
	fsp_freemsg(msg);

	switch (status) {
	case FSP_STATUS_SUCCESS:
		printf("DUMP: Initiated FipS dump.\n");
		break;
	case FSP_STATUS_BUSY: /* Retry, if FSP is busy */
		if (retry_cnt++ < FIPS_DUMP_MAX_RETRY)
			if (fsp_opal_dump_init(DUMP_TYPE_FSP) == OPAL_SUCCESS)
				return;
		break;
	default:
		break;
	}
	/* Reset max retry count */
	retry_cnt = 0;
}

/*
 * Initiate new FipS dump
 */
static int64_t fsp_opal_dump_init(uint8_t dump_type)
{
	struct fsp_msg *msg;
	int rc = OPAL_SUCCESS;
	uint32_t *tool_type = (void *)FSP_DUMP_TOOL_TYPE;
	uint32_t *client_id = (void *)FSP_DUMP_CLIENT_ID;

	/* Only FipS dump generate request is supported */
	if (dump_type != DUMP_TYPE_FSP)
		return OPAL_PARAMETER;

	msg = fsp_mkmsg(FSP_CMD_FSP_DUMP_INIT, 6, *tool_type,
			sizeof(FSP_DUMP_CLIENT_ID), *client_id,
			*(client_id + 1), *(client_id + 2), *(client_id + 3));

	if (!msg) {
		log_simple_error(&e_info(OPAL_RC_DUMP_INIT),
				 "DUMP: Message allocation failed.\n");
		rc = OPAL_INTERNAL_ERROR;
	} else if (fsp_queue_msg(msg, dump_init_complete)) {
		log_simple_error(&e_info(OPAL_RC_DUMP_INIT),
			"DUMP: Failed to queue FipS dump init request.\n");
		fsp_freemsg(msg);
		rc = OPAL_INTERNAL_ERROR;
	}

	return rc;
}

/*
 * OPAL interface to send dump information to Linux.
 */
static int64_t fsp_opal_dump_info2(uint32_t *dump_id, uint32_t *dump_size,
				   uint32_t *dump_type)
{
	struct dump_record *record;
	int rc = OPAL_SUCCESS;

	lock(&dump_lock);

	/* Clear notification */
	opal_update_pending_evt(OPAL_EVENT_DUMP_AVAIL, 0);

	record = list_top(&dump_pending, struct dump_record, link);
	if (!record) { /* List corrupted? */
		update_dump_state(DUMP_STATE_NONE);
		rc = OPAL_INTERNAL_ERROR;
		goto out;
	}
	*dump_id = record->id;
	*dump_size = record->size;
	*dump_type = record->type;

out:
	unlock(&dump_lock);
	return rc;
}

static int64_t fsp_opal_dump_info(uint32_t *dump_id, uint32_t *dump_size)
{
	uint32_t dump_type;
	return fsp_opal_dump_info2(dump_id, dump_size, &dump_type);
}

static int64_t validate_dump_sglist(struct opal_sg_list *list,
				    int64_t *size)
{
	struct opal_sg_list *sg;
	struct opal_sg_entry *prev_entry, *entry;
	int length, num_entries, i;

	prev_entry = NULL;
	*size = 0;
	for (sg = list; sg; sg = (struct opal_sg_list*)be64_to_cpu(sg->next)) {
		length = be64_to_cpu(sg->length) - 16;
		num_entries = length / sizeof(struct opal_sg_entry);
		if (num_entries <= 0)
			return OPAL_PARAMETER;

		for (i = 0; i < num_entries; i++) {
			entry = &sg->entry[i];
			*size += be64_to_cpu(entry->length);

			/* All entries must be aligned */
			if (((uint64_t)be64_to_cpu(entry->data)) & 0xfff)
				return OPAL_PARAMETER;

			/* All non-terminal entries size must be aligned */
			if (prev_entry && (be64_to_cpu(prev_entry->length) & 0xfff))
				return OPAL_PARAMETER;

			prev_entry = entry;
		}
	}
	return OPAL_SUCCESS;
}

/*
 * Map dump buffer to TCE buffer
 */
static int64_t map_dump_buffer(void)
{
	struct opal_sg_list *sg;
	struct opal_sg_entry *entry;
	int64_t fetch_max;
	int length, num_entries, i;
	int buf_off, fetch_off, tce_off, sg_off;
	bool last = false;

	/* FSP fetch max size */
	fetch_max = get_dump_fetch_max_size(dump_entry->type);
	if (fetch_max > (dump_entry->size - dump_offset))
		fetch_remain = dump_entry->size - dump_offset;
	else
		fetch_remain = fetch_max;

	/* offsets */
	fetch_off = fetch_remain;
	tce_off = sg_off = 0;

	for (sg = dump_data; sg; sg = (struct opal_sg_list*)be64_to_cpu(sg->next)) {
		num_entries = (be64_to_cpu(sg->length) - 16) /
					sizeof(struct opal_sg_entry);
		if (num_entries <= 0)
			return OPAL_PARAMETER;

		for (i = 0; i < num_entries; i++) {
			entry = &sg->entry[i];

			/* Continue until we get offset */
			if ((sg_off + be64_to_cpu(entry->length)) < dump_offset) {
				sg_off += be64_to_cpu(entry->length);
				continue;
			}

			/*
			 * SG list entry size can be more than 4k.
			 * Map only required pages, instead of
			 * mapping entire entry.
			 */
			if (!tce_off) {
				buf_off = (dump_offset - sg_off) & ~0xfff;
				length = be64_to_cpu(entry->length) - buf_off;
			} else {
				buf_off = 0;
				length = be64_to_cpu(entry->length);
			}

			/* Adjust length for last mapping */
			if (fetch_off <= length) {
				length = fetch_off;
				last = true;
			}

			/* Adjust offset */
			sg_off += be64_to_cpu(entry->length);
			fetch_off -= length;

			/* TCE mapping */
			dump_tce_map(tce_off, (void*)(be64_to_cpu(entry->data) + buf_off), length);
			tce_off += length;

			/* TCE mapping complete */
			if (last)
				return OPAL_SUCCESS;
		}
	} /* outer loop */
	return OPAL_PARAMETER;
}

static void dump_read_complete(struct fsp_msg *msg)
{
	void *buffer;
	size_t length, offset;
	int rc;
	uint32_t dump_id;
	uint16_t id;
	uint8_t flags, status;
	bool compl = false;

	status = (msg->resp->word1 >> 8) & 0xff;
	flags = (msg->data.words[0] >> 16) & 0xff;
	id = msg->data.words[0] & 0xffff;
	dump_id = msg->data.words[1];
	offset = msg->resp->data.words[1];
	length = msg->resp->data.words[2];

	fsp_freemsg(msg);

	lock(&dump_lock);

	if (dump_state == DUMP_STATE_ABORTING) {
		printf("DUMP: Fetch dump aborted, ID = 0x%x\n", dump_id);
		dump_tce_unmap(PSI_DMA_DUMP_DATA_SIZE);
		update_dump_state(DUMP_STATE_NONE);
		goto bail;
	}

	switch (status) {
	case FSP_STATUS_SUCCESS: /* Fetch next dump block */
		if (dump_offset < dump_entry->size) {
			dump_tce_unmap(PSI_DMA_DUMP_DATA_SIZE);
			rc = fsp_dump_read();
			if (rc == OPAL_SUCCESS)
				goto bail;
		} else { /* Dump read complete */
			compl = true;
		}
		break;
	case FSP_STATUS_MORE_DATA:	/* More data to read */
		offset += length;
		buffer = (void *)PSI_DMA_DUMP_DATA + offset;
		fetch_remain -= length;

		rc = fsp_fetch_data_queue(flags, id, dump_id, offset, buffer,
					  &fetch_remain, dump_read_complete);
		if (rc == OPAL_SUCCESS)
			goto bail;
		break;
	default:
		break;
	}

	dump_tce_unmap(PSI_DMA_DUMP_DATA_SIZE);

	/* Update state */
	if (compl) {
		printf("DUMP: Fetch dump success. ID = 0x%x\n", dump_id);
		update_dump_state(DUMP_STATE_FETCH);
	} else {
		printf("DUMP: Fetch dump partial. ID = 0x%x\n", dump_id);
		update_dump_state(DUMP_STATE_PARTIAL);
	}
 bail:
	unlock(&dump_lock);
}

/*
 * Fetch dump data from FSP
 */
static int64_t fsp_dump_read(void)
{
	int64_t rc;
	uint16_t data_set;
	uint8_t flags = 0x00;

	/* Get data set ID */
	data_set = get_dump_data_set_id(dump_entry->type);

	/* Map TCE buffer */
	rc = map_dump_buffer();
	if (rc != OPAL_SUCCESS) {
		printf("DUMP: TCE mapping failed\n");
		return rc;
	}

	printf("DUMP: Fetch Dump. ID = %02x, sub ID = %08x, len = %ld\n",
	       data_set, dump_entry->id, fetch_remain);

	/* Fetch data */
	rc = fsp_fetch_data_queue(flags, data_set, dump_entry->id,
				  dump_offset, (void *)PSI_DMA_DUMP_DATA,
				  &fetch_remain, dump_read_complete);

	/* Adjust dump fetch offset */
	dump_offset += fetch_remain;

	return rc;
}

static int64_t fsp_opal_dump_read(uint32_t dump_id,
				  struct opal_sg_list *list)
{
	struct dump_record *record;
	int64_t rc, size;

	lock(&dump_lock);

	/* Check state */
	if (dump_state != DUMP_STATE_NOTIFY) {
		rc = check_dump_state();
		goto out;
	}

	/* Validate dump ID */
	record = get_dump_rec_from_list(dump_id);
	if (!record) { /* List corrupted? */
		rc = OPAL_INTERNAL_ERROR;
		goto out;
	}

	/* Validate dump buffer and size */
	rc = validate_dump_sglist(list, &size);
	if (rc != OPAL_SUCCESS) {
		printf("DUMP: SG list validation failed\n");
		goto out;
	}

	if (size < record->size) { /* Insuffient buffer */
		printf("DUMP: Insufficient buffer\n");
		rc = OPAL_PARAMETER;
		goto out;
	}

	/* Update state */
	update_dump_state(DUMP_STATE_FETCHING);

	/* Fetch dump data */
	dump_entry = record;
	dump_data = list;
	dump_offset = 0;
	rc = fsp_dump_read();
	if (rc != OPAL_SUCCESS)
		goto out;

	/* Check status after initiating fetch data */
	rc = check_dump_state();

out:
	unlock(&dump_lock);
	return rc;
}

static void dump_ack_complete(struct fsp_msg *msg)
{
	uint8_t status = (msg->resp->word1 >> 8) & 0xff;

	if (status)
		log_simple_error(&e_info(OPAL_RC_DUMP_ACK),
				 "DUMP: ACK failed for ID: 0x%x\n",
				 msg->data.words[0]);
	else
		printf("DUMP: ACKed dump ID: 0x%x\n", msg->data.words[0]);

	fsp_freemsg(msg);
}

/*
 * Acknowledge dump
 */
static int64_t fsp_opal_dump_ack(uint32_t dump_id)
{
	struct dump_record *record;
	struct fsp_msg *msg;
	int rc;
	uint32_t cmd;
	uint8_t dump_type = 0;

	/* Get dump type */
	lock(&dump_lock);
	record = get_dump_rec_from_list(dump_id);
	if (record)
		dump_type = record->type;

	/*
	 * Next available dump in pending list will be of different
	 * type. Hence we don't need to wait for ack complete.
	 *
	 * Note:
	 *   This allows us to proceed even if we fail to ACK.
	 *   In the worst case we may get notification for the
	 *   same dump again, which is probably better than
	 *   looping forever.
	 */
	rc = remove_dump_id_from_list(dump_id);
	if (rc != OPAL_SUCCESS) /* Invalid dump id */
		goto out;

	/* Adjust mod value */
	cmd = FSP_CMD_ACK_DUMP | (dump_type & 0xff);
	msg = fsp_mkmsg(cmd, 1, dump_id);
	if (!msg) {
		log_simple_error(&e_info(OPAL_RC_DUMP_ACK),
				 "DUMP: Message allocation failed.!\n");
		rc = OPAL_INTERNAL_ERROR;
	} else if (fsp_queue_msg(msg, dump_ack_complete)) {
		log_simple_error(&e_info(OPAL_RC_DUMP_ACK),
			"DUMP: Failed to queue dump ack message.\n");
		fsp_freemsg(msg);
		rc = OPAL_INTERNAL_ERROR;
	}
out:
	unlock(&dump_lock);
	return rc;
}

/* Resend dump available notification */
static int64_t fsp_opal_dump_resend_notification(void)
{
	lock(&dump_lock);

	if (dump_state != DUMP_STATE_ABSENT)
		update_dump_state(DUMP_STATE_NONE);

	update_opal_dump_notify();

	unlock(&dump_lock);

	return OPAL_SUCCESS;
}

/*
 * Handle FSP R/R event.
 */
static bool fsp_dump_retrieve_rr(uint32_t cmd_sub_mod,
				 struct fsp_msg *msg __unused)
{
	switch (cmd_sub_mod) {
	case FSP_RESET_START:
		lock(&dump_lock);
		/* Reset dump state */
		if (dump_state == DUMP_STATE_FETCHING)
			update_dump_state(DUMP_STATE_ABORTING);
		unlock(&dump_lock);
		return true;
	case FSP_RELOAD_COMPLETE:
		lock(&dump_lock);

		/* Reset TCE mapping */
		dump_tce_unmap(PSI_DMA_DUMP_DATA_SIZE);

		/* Reset dump state */
		update_dump_state(DUMP_STATE_NONE);

		/*
		 * For now keeping R/R handler simple. In the worst case
		 * we may endup resending dump available notification for
		 * same dump ID twice to Linux.
		 */
		update_opal_dump_notify();
		unlock(&dump_lock);
		return true;
	}
	return false;
}

/*
 * Handle host kexec'ing scenarios
 */
static bool opal_kexec_dump_notify(void *data __unused)
{
	bool ready = true;

	lock(&dump_lock);

	/* Dump retrieve is in progress? */
	if (dump_state == DUMP_STATE_FETCHING)
		dump_state = DUMP_STATE_ABORTING;

	/* Not yet safe to kexec */
	if (dump_state == DUMP_STATE_ABORTING)
		ready = false;

	unlock(&dump_lock);

	return ready;
}

/*
 * FipS dump notification
 */
void fsp_fips_dump_notify(uint32_t dump_id, uint32_t dump_size)
{
	printf("DUMP: FipS dump available. ID = 0x%x [size: %d bytes]\n",
	       dump_id, dump_size);
	add_dump_id_to_list(DUMP_TYPE_FSP, dump_id, dump_size);
}

/*
 * System/Platform dump notification
 */
static bool fsp_sys_dump_notify(uint32_t cmd_sub_mod, struct fsp_msg *msg)
{
	/*
	 * Though spec says mod 00 is deprecated we still
	 * seems to get mod 00 notification (at least on
	 * P7 machine).
	 */
	if (cmd_sub_mod != FSP_RSP_SYS_DUMP &&
	    cmd_sub_mod != FSP_RSP_SYS_DUMP_OLD)
		return false;

	printf("DUMP: Platform dump available. ID = 0x%x [size: %d bytes]\n",
	       msg->data.words[0], msg->data.words[1]);

	add_dump_id_to_list(DUMP_TYPE_SYS,
			    msg->data.words[0], msg->data.words[1]);
	return true;
}

/*
 * If platform dump available during IPL time, then we
 * get notification via HDAT. Check for DT for the dump
 * presence.
 */
static void check_ipl_sys_dump(void)
{
	struct dt_node *dump_node;
	uint32_t dump_id, dump_size;

	dump_node = dt_find_by_path(dt_root, "ipl-params/platform-dump");
	if (!dump_node)
		return;

	if (!dt_find_property(dump_node, "dump-id"))
		return;

	dump_id = dt_prop_get_u32(dump_node, "dump-id");
	dump_size = (uint32_t)dt_prop_get_u64(dump_node, "total-size");

	printf("DUMP: Platform dump present during IPL.\n");
	printf("      ID = 0x%x [size: %d bytes]\n", dump_id, dump_size);

	add_dump_id_to_list(DUMP_TYPE_SYS, dump_id, dump_size);
}

/*
 * Allocate and initialize dump list
 */
static int init_dump_free_list(void)
{
	struct dump_record *entry;
	int i;

	entry = zalloc(sizeof(struct dump_record) * MAX_DUMP_RECORD);
	if (!entry) {
		log_simple_error(&e_info(OPAL_RC_DUMP_INIT),
				 "DUMP: Out of memory\n");
		return -ENOMEM;
	}

	for (i = 0; i < MAX_DUMP_RECORD; i++) {
		list_add_tail(&dump_free, &entry->link);
		entry++;
	}
	return 0;
}

static struct fsp_client fsp_sys_dump_client = {
	.message = fsp_sys_dump_notify,
};

static struct fsp_client fsp_dump_client_rr = {
	.message = fsp_dump_retrieve_rr,
};

void fsp_dump_init(void)
{
	if (!fsp_present()) {
		update_dump_state(DUMP_STATE_ABSENT);
		return;
	}

	/* Initialize list */
	if (init_dump_free_list() != 0) {
		update_dump_state(DUMP_STATE_ABSENT);
		return;
	}

	/* Register for Class CE */
	fsp_register_client(&fsp_sys_dump_client, FSP_MCLASS_SERVICE);
	/* Register for Class AA (FSP R/R) */
	fsp_register_client(&fsp_dump_client_rr, FSP_MCLASS_RR_EVENT);

	/* Register for sync on host reboot call */
	opal_add_host_sync_notifier(opal_kexec_dump_notify, NULL);

	/* OPAL interface */
	opal_register(OPAL_DUMP_INIT, fsp_opal_dump_init, 1);
	opal_register(OPAL_DUMP_INFO, fsp_opal_dump_info, 2);
	opal_register(OPAL_DUMP_INFO2, fsp_opal_dump_info2, 3);
	opal_register(OPAL_DUMP_READ, fsp_opal_dump_read, 2);
	opal_register(OPAL_DUMP_ACK, fsp_opal_dump_ack, 1);
	opal_register(OPAL_DUMP_RESEND, fsp_opal_dump_resend_notification, 0);

	/* Check for platform dump presence during IPL time */
	check_ipl_sys_dump();
}
