/*
 *  c 2001 PPC 64 Team, 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.
 *
 * scan-log-data driver for PPC64  Todd Inglett <tinglett@vnet.ibm.com>
 *
 * When ppc64 hardware fails the service processor dumps internal state
 * of the system.  After a reboot the operating system can access a dump
 * of this data using this driver.  A dump exists if the device-tree
 * /chosen/ibm,scan-log-data property exists.
 *
 * This driver exports /proc/ppc64/scan-log-dump which can be read.
 * The driver supports only sequential reads.
 *
 * The driver looks at a write to the driver for the single word "reset".
 * If given, the driver will reset the scanlog so the platform can free it.
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
#include <asm/prom.h>

#define MODULE_VERS "1.0"
#define MODULE_NAME "scanlog"

/* Status returns from ibm,scan-log-dump */
#define SCANLOG_COMPLETE 0
#define SCANLOG_HWERROR -1
#define SCANLOG_CONTINUE 1

#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0)

static int scanlog_debug;
static unsigned int ibm_scan_log_dump;			/* RTAS token */
static struct proc_dir_entry *proc_ppc64_scan_log_dump;	/* The proc file */

static ssize_t scanlog_read(struct file *file, char __user *buf,
			    size_t count, loff_t *ppos)
{
        struct inode * inode = file->f_dentry->d_inode;
	struct proc_dir_entry *dp;
	unsigned int *data;
	int status;
	unsigned long len, off;
	unsigned int wait_time;

        dp = PDE(inode);
 	data = (unsigned int *)dp->data;

	if (!data) {
		printk(KERN_ERR "scanlog: read failed no data\n");
		return -EIO;
	}

	if (count > RTAS_DATA_BUF_SIZE)
		count = RTAS_DATA_BUF_SIZE;

	if (count < 1024) {
		/* This is the min supported by this RTAS call.  Rather
		 * than do all the buffering we insist the user code handle
		 * larger reads.  As long as cp works... :)
		 */
		printk(KERN_ERR "scanlog: cannot perform a small read (%ld)\n", count);
		return -EINVAL;
	}

	if (!access_ok(VERIFY_WRITE, buf, count))
		return -EFAULT;

	for (;;) {
		wait_time = HZ/2;	/* default wait if no data */
		spin_lock(&rtas_data_buf_lock);
		memcpy(rtas_data_buf, data, RTAS_DATA_BUF_SIZE);
		status = rtas_call(ibm_scan_log_dump, 2, 1, NULL,
				   (u32) __pa(rtas_data_buf), (u32) count);
		memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE);
		spin_unlock(&rtas_data_buf_lock);

		DEBUG("status=%d, data[0]=%x, data[1]=%x, data[2]=%x\n",
		      status, data[0], data[1], data[2]);
		switch (status) {
		    case SCANLOG_COMPLETE:
			DEBUG("hit eof\n");
			return 0;
		    case SCANLOG_HWERROR:
			DEBUG("hardware error reading scan log data\n");
			return -EIO;
		    case SCANLOG_CONTINUE:
			/* We may or may not have data yet */
			len = data[1];
			off = data[2];
			if (len > 0) {
				if (copy_to_user(buf, ((char *)data)+off, len))
					return -EFAULT;
				return len;
			}
			/* Break to sleep default time */
			break;
		    default:
			if (status > 9900 && status <= 9905) {
				/* No data.  RTAS is hinting at a delay required
				 * between 1-100000 milliseconds
				 */
				int ms = 1;
				for (; status > 9900; status--)
					ms = ms * 10;
				/* Use microseconds for reasonable accuracy */
				ms *= 1000;
				wait_time = ms / (1000000/HZ); /* round down is fine */
				/* Fall through to sleep */
			} else {
				printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
				return -EIO;
			}
		}
		/* Apparently no data yet.  Wait and try again. */
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(wait_time);
	}
	/*NOTREACHED*/
}

static ssize_t scanlog_write(struct file * file, const char __user * buf,
			     size_t count, loff_t *ppos)
{
	char stkbuf[20];
	int status;

	if (count > 19) count = 19;
	if (copy_from_user (stkbuf, buf, count)) {
		return -EFAULT;
	}
	stkbuf[count] = 0;

	if (buf) {
		if (strncmp(stkbuf, "reset", 5) == 0) {
			DEBUG("reset scanlog\n");
			status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0);
			DEBUG("rtas returns %d\n", status);
		} else if (strncmp(stkbuf, "debugon", 7) == 0) {
			printk(KERN_ERR "scanlog: debug on\n");
			scanlog_debug = 1;
		} else if (strncmp(stkbuf, "debugoff", 8) == 0) {
			printk(KERN_ERR "scanlog: debug off\n");
			scanlog_debug = 0;
		}
	}
	return count;
}

static int scanlog_open(struct inode * inode, struct file * file)
{
	struct proc_dir_entry *dp = PDE(inode);
	unsigned int *data = (unsigned int *)dp->data;

	if (!data) {
		printk(KERN_ERR "scanlog: open failed no data\n");
		return -EIO;
	}

	if (data[0] != 0) {
		/* This imperfect test stops a second copy of the
		 * data (or a reset while data is being copied)
		 */
		return -EBUSY;
	}

	data[0] = 0;	/* re-init so we restart the scan */

	return 0;
}

static int scanlog_release(struct inode * inode, struct file * file)
{
	struct proc_dir_entry *dp = PDE(inode);
	unsigned int *data = (unsigned int *)dp->data;

	if (!data) {
		printk(KERN_ERR "scanlog: release failed no data\n");
		return -EIO;
	}
	data[0] = 0;

	return 0;
}

struct file_operations scanlog_fops = {
	.owner		= THIS_MODULE,
	.read		= scanlog_read,
	.write		= scanlog_write,
	.open		= scanlog_open,
	.release	= scanlog_release,
};

int __init scanlog_init(void)
{
	struct proc_dir_entry *ent;

	ibm_scan_log_dump = rtas_token("ibm,scan-log-dump");
	if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE) {
		printk(KERN_ERR "scan-log-dump not implemented on this system\n");
		return -EIO;
	}

        ent = create_proc_entry("ppc64/rtas/scan-log-dump",  S_IRUSR, NULL);
	if (ent) {
		ent->proc_fops = &scanlog_fops;
		/* Ideally we could allocate a buffer < 4G */
		ent->data = kmalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
		if (!ent->data) {
			printk(KERN_ERR "Failed to allocate a buffer\n");
			remove_proc_entry("scan-log-dump", ent->parent);
			return -ENOMEM;
		}
		((unsigned int *)ent->data)[0] = 0;
	} else {
		printk(KERN_ERR "Failed to create ppc64/scan-log-dump proc entry\n");
		return -EIO;
	}
	proc_ppc64_scan_log_dump = ent;

	return 0;
}

void __exit scanlog_cleanup(void)
{
	if (proc_ppc64_scan_log_dump) {
		if (proc_ppc64_scan_log_dump->data)
			kfree(proc_ppc64_scan_log_dump->data);
		remove_proc_entry("scan-log-dump", proc_ppc64_scan_log_dump->parent);
	}
}

module_init(scanlog_init);
module_exit(scanlog_cleanup);
MODULE_LICENSE("GPL");
