• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  c 2001 PPC 64 Team, IBM Corp
4  *
5  * scan-log-data driver for PPC64  Todd Inglett <tinglett@vnet.ibm.com>
6  *
7  * When ppc64 hardware fails the service processor dumps internal state
8  * of the system.  After a reboot the operating system can access a dump
9  * of this data using this driver.  A dump exists if the device-tree
10  * /chosen/ibm,scan-log-data property exists.
11  *
12  * This driver exports /proc/powerpc/scan-log-dump which can be read.
13  * The driver supports only sequential reads.
14  *
15  * The driver looks at a write to the driver for the single word "reset".
16  * If given, the driver will reset the scanlog so the platform can free it.
17  */
18 
19 #include <linux/module.h>
20 #include <linux/types.h>
21 #include <linux/errno.h>
22 #include <linux/proc_fs.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/slab.h>
26 #include <linux/uaccess.h>
27 #include <asm/rtas.h>
28 #include <asm/prom.h>
29 
30 #define MODULE_VERS "1.0"
31 #define MODULE_NAME "scanlog"
32 
33 /* Status returns from ibm,scan-log-dump */
34 #define SCANLOG_COMPLETE 0
35 #define SCANLOG_HWERROR -1
36 #define SCANLOG_CONTINUE 1
37 
38 
39 static unsigned int ibm_scan_log_dump;			/* RTAS token */
40 static unsigned int *scanlog_buffer;			/* The data buffer */
41 
scanlog_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)42 static ssize_t scanlog_read(struct file *file, char __user *buf,
43 			    size_t count, loff_t *ppos)
44 {
45 	unsigned int *data = scanlog_buffer;
46 	int status;
47 	unsigned long len, off;
48 	unsigned int wait_time;
49 
50 	if (count > RTAS_DATA_BUF_SIZE)
51 		count = RTAS_DATA_BUF_SIZE;
52 
53 	if (count < 1024) {
54 		/* This is the min supported by this RTAS call.  Rather
55 		 * than do all the buffering we insist the user code handle
56 		 * larger reads.  As long as cp works... :)
57 		 */
58 		printk(KERN_ERR "scanlog: cannot perform a small read (%ld)\n", count);
59 		return -EINVAL;
60 	}
61 
62 	if (!access_ok(buf, count))
63 		return -EFAULT;
64 
65 	for (;;) {
66 		wait_time = 500;	/* default wait if no data */
67 		spin_lock(&rtas_data_buf_lock);
68 		memcpy(rtas_data_buf, data, RTAS_DATA_BUF_SIZE);
69 		status = rtas_call(ibm_scan_log_dump, 2, 1, NULL,
70 				   (u32) __pa(rtas_data_buf), (u32) count);
71 		memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE);
72 		spin_unlock(&rtas_data_buf_lock);
73 
74 		pr_debug("scanlog: status=%d, data[0]=%x, data[1]=%x, " \
75 			 "data[2]=%x\n", status, data[0], data[1], data[2]);
76 		switch (status) {
77 		    case SCANLOG_COMPLETE:
78 			pr_debug("scanlog: hit eof\n");
79 			return 0;
80 		    case SCANLOG_HWERROR:
81 			pr_debug("scanlog: hardware error reading data\n");
82 			return -EIO;
83 		    case SCANLOG_CONTINUE:
84 			/* We may or may not have data yet */
85 			len = data[1];
86 			off = data[2];
87 			if (len > 0) {
88 				if (copy_to_user(buf, ((char *)data)+off, len))
89 					return -EFAULT;
90 				return len;
91 			}
92 			/* Break to sleep default time */
93 			break;
94 		    default:
95 			/* Assume extended busy */
96 			wait_time = rtas_busy_delay_time(status);
97 			if (!wait_time) {
98 				printk(KERN_ERR "scanlog: unknown error " \
99 				       "from rtas: %d\n", status);
100 				return -EIO;
101 			}
102 		}
103 		/* Apparently no data yet.  Wait and try again. */
104 		msleep_interruptible(wait_time);
105 	}
106 	/*NOTREACHED*/
107 }
108 
scanlog_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)109 static ssize_t scanlog_write(struct file * file, const char __user * buf,
110 			     size_t count, loff_t *ppos)
111 {
112 	char stkbuf[20];
113 	int status;
114 
115 	if (count > 19) count = 19;
116 	if (copy_from_user (stkbuf, buf, count)) {
117 		return -EFAULT;
118 	}
119 	stkbuf[count] = 0;
120 
121 	if (buf) {
122 		if (strncmp(stkbuf, "reset", 5) == 0) {
123 			pr_debug("scanlog: reset scanlog\n");
124 			status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0);
125 			pr_debug("scanlog: rtas returns %d\n", status);
126 		}
127 	}
128 	return count;
129 }
130 
scanlog_open(struct inode * inode,struct file * file)131 static int scanlog_open(struct inode * inode, struct file * file)
132 {
133 	unsigned int *data = scanlog_buffer;
134 
135 	if (data[0] != 0) {
136 		/* This imperfect test stops a second copy of the
137 		 * data (or a reset while data is being copied)
138 		 */
139 		return -EBUSY;
140 	}
141 
142 	data[0] = 0;	/* re-init so we restart the scan */
143 
144 	return 0;
145 }
146 
scanlog_release(struct inode * inode,struct file * file)147 static int scanlog_release(struct inode * inode, struct file * file)
148 {
149 	unsigned int *data = scanlog_buffer;
150 
151 	data[0] = 0;
152 	return 0;
153 }
154 
155 static const struct proc_ops scanlog_proc_ops = {
156 	.proc_read	= scanlog_read,
157 	.proc_write	= scanlog_write,
158 	.proc_open	= scanlog_open,
159 	.proc_release	= scanlog_release,
160 	.proc_lseek	= noop_llseek,
161 };
162 
scanlog_init(void)163 static int __init scanlog_init(void)
164 {
165 	struct proc_dir_entry *ent;
166 	int err = -ENOMEM;
167 
168 	ibm_scan_log_dump = rtas_token("ibm,scan-log-dump");
169 	if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE)
170 		return -ENODEV;
171 
172 	/* Ideally we could allocate a buffer < 4G */
173 	scanlog_buffer = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
174 	if (!scanlog_buffer)
175 		goto err;
176 
177 	ent = proc_create("powerpc/rtas/scan-log-dump", 0400, NULL,
178 			  &scanlog_proc_ops);
179 	if (!ent)
180 		goto err;
181 	return 0;
182 err:
183 	kfree(scanlog_buffer);
184 	return err;
185 }
186 
scanlog_cleanup(void)187 static void __exit scanlog_cleanup(void)
188 {
189 	remove_proc_entry("powerpc/rtas/scan-log-dump", NULL);
190 	kfree(scanlog_buffer);
191 }
192 
193 module_init(scanlog_init);
194 module_exit(scanlog_cleanup);
195 MODULE_LICENSE("GPL");
196