xref: /openbmc/linux/drivers/acpi/apei/erst.c (revision 58f87ed0)
1 /*
2  * APEI Error Record Serialization Table support
3  *
4  * ERST is a way provided by APEI to save and retrieve hardware error
5  * information to and from a persistent store.
6  *
7  * For more information about ERST, please refer to ACPI Specification
8  * version 4.0, section 17.4.
9  *
10  * Copyright 2010 Intel Corp.
11  *   Author: Huang Ying <ying.huang@intel.com>
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License version
15  * 2 as published by the Free Software Foundation.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26 
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/delay.h>
31 #include <linux/io.h>
32 #include <linux/acpi.h>
33 #include <linux/uaccess.h>
34 #include <linux/cper.h>
35 #include <linux/nmi.h>
36 #include <linux/hardirq.h>
37 #include <acpi/apei.h>
38 
39 #include "apei-internal.h"
40 
41 #define ERST_PFX "ERST: "
42 
43 /* ERST command status */
44 #define ERST_STATUS_SUCCESS			0x0
45 #define ERST_STATUS_NOT_ENOUGH_SPACE		0x1
46 #define ERST_STATUS_HARDWARE_NOT_AVAILABLE	0x2
47 #define ERST_STATUS_FAILED			0x3
48 #define ERST_STATUS_RECORD_STORE_EMPTY		0x4
49 #define ERST_STATUS_RECORD_NOT_FOUND		0x5
50 
51 #define ERST_TAB_ENTRY(tab)						\
52 	((struct acpi_whea_header *)((char *)(tab) +			\
53 				     sizeof(struct acpi_table_erst)))
54 
55 #define SPIN_UNIT		100			/* 100ns */
56 /* Firmware should respond within 1 miliseconds */
57 #define FIRMWARE_TIMEOUT	(1 * NSEC_PER_MSEC)
58 #define FIRMWARE_MAX_STALL	50			/* 50us */
59 
60 int erst_disable;
61 EXPORT_SYMBOL_GPL(erst_disable);
62 
63 static struct acpi_table_erst *erst_tab;
64 
65 /* ERST Error Log Address Range atrributes */
66 #define ERST_RANGE_RESERVED	0x0001
67 #define ERST_RANGE_NVRAM	0x0002
68 #define ERST_RANGE_SLOW		0x0004
69 
70 /*
71  * ERST Error Log Address Range, used as buffer for reading/writing
72  * error records.
73  */
74 static struct erst_erange {
75 	u64 base;
76 	u64 size;
77 	void __iomem *vaddr;
78 	u32 attr;
79 } erst_erange;
80 
81 /*
82  * Prevent ERST interpreter to run simultaneously, because the
83  * corresponding firmware implementation may not work properly when
84  * invoked simultaneously.
85  *
86  * It is used to provide exclusive accessing for ERST Error Log
87  * Address Range too.
88  */
89 static DEFINE_SPINLOCK(erst_lock);
90 
91 static inline int erst_errno(int command_status)
92 {
93 	switch (command_status) {
94 	case ERST_STATUS_SUCCESS:
95 		return 0;
96 	case ERST_STATUS_HARDWARE_NOT_AVAILABLE:
97 		return -ENODEV;
98 	case ERST_STATUS_NOT_ENOUGH_SPACE:
99 		return -ENOSPC;
100 	case ERST_STATUS_RECORD_STORE_EMPTY:
101 	case ERST_STATUS_RECORD_NOT_FOUND:
102 		return -ENOENT;
103 	default:
104 		return -EINVAL;
105 	}
106 }
107 
108 static int erst_timedout(u64 *t, u64 spin_unit)
109 {
110 	if ((s64)*t < spin_unit) {
111 		pr_warning(FW_WARN ERST_PFX
112 			   "Firmware does not respond in time\n");
113 		return 1;
114 	}
115 	*t -= spin_unit;
116 	ndelay(spin_unit);
117 	touch_nmi_watchdog();
118 	return 0;
119 }
120 
121 static int erst_exec_load_var1(struct apei_exec_context *ctx,
122 			       struct acpi_whea_header *entry)
123 {
124 	return __apei_exec_read_register(entry, &ctx->var1);
125 }
126 
127 static int erst_exec_load_var2(struct apei_exec_context *ctx,
128 			       struct acpi_whea_header *entry)
129 {
130 	return __apei_exec_read_register(entry, &ctx->var2);
131 }
132 
133 static int erst_exec_store_var1(struct apei_exec_context *ctx,
134 				struct acpi_whea_header *entry)
135 {
136 	return __apei_exec_write_register(entry, ctx->var1);
137 }
138 
139 static int erst_exec_add(struct apei_exec_context *ctx,
140 			 struct acpi_whea_header *entry)
141 {
142 	ctx->var1 += ctx->var2;
143 	return 0;
144 }
145 
146 static int erst_exec_subtract(struct apei_exec_context *ctx,
147 			      struct acpi_whea_header *entry)
148 {
149 	ctx->var1 -= ctx->var2;
150 	return 0;
151 }
152 
153 static int erst_exec_add_value(struct apei_exec_context *ctx,
154 			       struct acpi_whea_header *entry)
155 {
156 	int rc;
157 	u64 val;
158 
159 	rc = __apei_exec_read_register(entry, &val);
160 	if (rc)
161 		return rc;
162 	val += ctx->value;
163 	rc = __apei_exec_write_register(entry, val);
164 	return rc;
165 }
166 
167 static int erst_exec_subtract_value(struct apei_exec_context *ctx,
168 				    struct acpi_whea_header *entry)
169 {
170 	int rc;
171 	u64 val;
172 
173 	rc = __apei_exec_read_register(entry, &val);
174 	if (rc)
175 		return rc;
176 	val -= ctx->value;
177 	rc = __apei_exec_write_register(entry, val);
178 	return rc;
179 }
180 
181 static int erst_exec_stall(struct apei_exec_context *ctx,
182 			   struct acpi_whea_header *entry)
183 {
184 	u64 stall_time;
185 
186 	if (ctx->value > FIRMWARE_MAX_STALL) {
187 		if (!in_nmi())
188 			pr_warning(FW_WARN ERST_PFX
189 			"Too long stall time for stall instruction: %llx.\n",
190 				   ctx->value);
191 		stall_time = FIRMWARE_MAX_STALL;
192 	} else
193 		stall_time = ctx->value;
194 	udelay(stall_time);
195 	return 0;
196 }
197 
198 static int erst_exec_stall_while_true(struct apei_exec_context *ctx,
199 				      struct acpi_whea_header *entry)
200 {
201 	int rc;
202 	u64 val;
203 	u64 timeout = FIRMWARE_TIMEOUT;
204 	u64 stall_time;
205 
206 	if (ctx->var1 > FIRMWARE_MAX_STALL) {
207 		if (!in_nmi())
208 			pr_warning(FW_WARN ERST_PFX
209 		"Too long stall time for stall while true instruction: %llx.\n",
210 				   ctx->var1);
211 		stall_time = FIRMWARE_MAX_STALL;
212 	} else
213 		stall_time = ctx->var1;
214 
215 	for (;;) {
216 		rc = __apei_exec_read_register(entry, &val);
217 		if (rc)
218 			return rc;
219 		if (val != ctx->value)
220 			break;
221 		if (erst_timedout(&timeout, stall_time * NSEC_PER_USEC))
222 			return -EIO;
223 	}
224 	return 0;
225 }
226 
227 static int erst_exec_skip_next_instruction_if_true(
228 	struct apei_exec_context *ctx,
229 	struct acpi_whea_header *entry)
230 {
231 	int rc;
232 	u64 val;
233 
234 	rc = __apei_exec_read_register(entry, &val);
235 	if (rc)
236 		return rc;
237 	if (val == ctx->value) {
238 		ctx->ip += 2;
239 		return APEI_EXEC_SET_IP;
240 	}
241 
242 	return 0;
243 }
244 
245 static int erst_exec_goto(struct apei_exec_context *ctx,
246 			  struct acpi_whea_header *entry)
247 {
248 	ctx->ip = ctx->value;
249 	return APEI_EXEC_SET_IP;
250 }
251 
252 static int erst_exec_set_src_address_base(struct apei_exec_context *ctx,
253 					  struct acpi_whea_header *entry)
254 {
255 	return __apei_exec_read_register(entry, &ctx->src_base);
256 }
257 
258 static int erst_exec_set_dst_address_base(struct apei_exec_context *ctx,
259 					  struct acpi_whea_header *entry)
260 {
261 	return __apei_exec_read_register(entry, &ctx->dst_base);
262 }
263 
264 static int erst_exec_move_data(struct apei_exec_context *ctx,
265 			       struct acpi_whea_header *entry)
266 {
267 	int rc;
268 	u64 offset;
269 
270 	rc = __apei_exec_read_register(entry, &offset);
271 	if (rc)
272 		return rc;
273 	memmove((void *)ctx->dst_base + offset,
274 		(void *)ctx->src_base + offset,
275 		ctx->var2);
276 
277 	return 0;
278 }
279 
280 static struct apei_exec_ins_type erst_ins_type[] = {
281 	[ACPI_ERST_READ_REGISTER] = {
282 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
283 		.run = apei_exec_read_register,
284 	},
285 	[ACPI_ERST_READ_REGISTER_VALUE] = {
286 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
287 		.run = apei_exec_read_register_value,
288 	},
289 	[ACPI_ERST_WRITE_REGISTER] = {
290 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
291 		.run = apei_exec_write_register,
292 	},
293 	[ACPI_ERST_WRITE_REGISTER_VALUE] = {
294 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
295 		.run = apei_exec_write_register_value,
296 	},
297 	[ACPI_ERST_NOOP] = {
298 		.flags = 0,
299 		.run = apei_exec_noop,
300 	},
301 	[ACPI_ERST_LOAD_VAR1] = {
302 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
303 		.run = erst_exec_load_var1,
304 	},
305 	[ACPI_ERST_LOAD_VAR2] = {
306 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
307 		.run = erst_exec_load_var2,
308 	},
309 	[ACPI_ERST_STORE_VAR1] = {
310 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
311 		.run = erst_exec_store_var1,
312 	},
313 	[ACPI_ERST_ADD] = {
314 		.flags = 0,
315 		.run = erst_exec_add,
316 	},
317 	[ACPI_ERST_SUBTRACT] = {
318 		.flags = 0,
319 		.run = erst_exec_subtract,
320 	},
321 	[ACPI_ERST_ADD_VALUE] = {
322 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
323 		.run = erst_exec_add_value,
324 	},
325 	[ACPI_ERST_SUBTRACT_VALUE] = {
326 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
327 		.run = erst_exec_subtract_value,
328 	},
329 	[ACPI_ERST_STALL] = {
330 		.flags = 0,
331 		.run = erst_exec_stall,
332 	},
333 	[ACPI_ERST_STALL_WHILE_TRUE] = {
334 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
335 		.run = erst_exec_stall_while_true,
336 	},
337 	[ACPI_ERST_SKIP_NEXT_IF_TRUE] = {
338 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
339 		.run = erst_exec_skip_next_instruction_if_true,
340 	},
341 	[ACPI_ERST_GOTO] = {
342 		.flags = 0,
343 		.run = erst_exec_goto,
344 	},
345 	[ACPI_ERST_SET_SRC_ADDRESS_BASE] = {
346 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
347 		.run = erst_exec_set_src_address_base,
348 	},
349 	[ACPI_ERST_SET_DST_ADDRESS_BASE] = {
350 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
351 		.run = erst_exec_set_dst_address_base,
352 	},
353 	[ACPI_ERST_MOVE_DATA] = {
354 		.flags = APEI_EXEC_INS_ACCESS_REGISTER,
355 		.run = erst_exec_move_data,
356 	},
357 };
358 
359 static inline void erst_exec_ctx_init(struct apei_exec_context *ctx)
360 {
361 	apei_exec_ctx_init(ctx, erst_ins_type, ARRAY_SIZE(erst_ins_type),
362 			   ERST_TAB_ENTRY(erst_tab), erst_tab->entries);
363 }
364 
365 static int erst_get_erange(struct erst_erange *range)
366 {
367 	struct apei_exec_context ctx;
368 	int rc;
369 
370 	erst_exec_ctx_init(&ctx);
371 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_RANGE);
372 	if (rc)
373 		return rc;
374 	range->base = apei_exec_ctx_get_output(&ctx);
375 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_LENGTH);
376 	if (rc)
377 		return rc;
378 	range->size = apei_exec_ctx_get_output(&ctx);
379 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_ATTRIBUTES);
380 	if (rc)
381 		return rc;
382 	range->attr = apei_exec_ctx_get_output(&ctx);
383 
384 	return 0;
385 }
386 
387 static ssize_t __erst_get_record_count(void)
388 {
389 	struct apei_exec_context ctx;
390 	int rc;
391 
392 	erst_exec_ctx_init(&ctx);
393 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_COUNT);
394 	if (rc)
395 		return rc;
396 	return apei_exec_ctx_get_output(&ctx);
397 }
398 
399 ssize_t erst_get_record_count(void)
400 {
401 	ssize_t count;
402 	unsigned long flags;
403 
404 	if (erst_disable)
405 		return -ENODEV;
406 
407 	spin_lock_irqsave(&erst_lock, flags);
408 	count = __erst_get_record_count();
409 	spin_unlock_irqrestore(&erst_lock, flags);
410 
411 	return count;
412 }
413 EXPORT_SYMBOL_GPL(erst_get_record_count);
414 
415 static int __erst_get_next_record_id(u64 *record_id)
416 {
417 	struct apei_exec_context ctx;
418 	int rc;
419 
420 	erst_exec_ctx_init(&ctx);
421 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_ID);
422 	if (rc)
423 		return rc;
424 	*record_id = apei_exec_ctx_get_output(&ctx);
425 
426 	return 0;
427 }
428 
429 /*
430  * Get the record ID of an existing error record on the persistent
431  * storage. If there is no error record on the persistent storage, the
432  * returned record_id is APEI_ERST_INVALID_RECORD_ID.
433  */
434 int erst_get_next_record_id(u64 *record_id)
435 {
436 	int rc;
437 	unsigned long flags;
438 
439 	if (erst_disable)
440 		return -ENODEV;
441 
442 	spin_lock_irqsave(&erst_lock, flags);
443 	rc = __erst_get_next_record_id(record_id);
444 	spin_unlock_irqrestore(&erst_lock, flags);
445 
446 	return rc;
447 }
448 EXPORT_SYMBOL_GPL(erst_get_next_record_id);
449 
450 static int __erst_write_to_storage(u64 offset)
451 {
452 	struct apei_exec_context ctx;
453 	u64 timeout = FIRMWARE_TIMEOUT;
454 	u64 val;
455 	int rc;
456 
457 	erst_exec_ctx_init(&ctx);
458 	rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_WRITE);
459 	if (rc)
460 		return rc;
461 	apei_exec_ctx_set_input(&ctx, offset);
462 	rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_OFFSET);
463 	if (rc)
464 		return rc;
465 	rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION);
466 	if (rc)
467 		return rc;
468 	for (;;) {
469 		rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS);
470 		if (rc)
471 			return rc;
472 		val = apei_exec_ctx_get_output(&ctx);
473 		if (!val)
474 			break;
475 		if (erst_timedout(&timeout, SPIN_UNIT))
476 			return -EIO;
477 	}
478 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS);
479 	if (rc)
480 		return rc;
481 	val = apei_exec_ctx_get_output(&ctx);
482 	rc = apei_exec_run(&ctx, ACPI_ERST_END);
483 	if (rc)
484 		return rc;
485 
486 	return erst_errno(val);
487 }
488 
489 static int __erst_read_from_storage(u64 record_id, u64 offset)
490 {
491 	struct apei_exec_context ctx;
492 	u64 timeout = FIRMWARE_TIMEOUT;
493 	u64 val;
494 	int rc;
495 
496 	erst_exec_ctx_init(&ctx);
497 	rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_READ);
498 	if (rc)
499 		return rc;
500 	apei_exec_ctx_set_input(&ctx, offset);
501 	rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_OFFSET);
502 	if (rc)
503 		return rc;
504 	apei_exec_ctx_set_input(&ctx, record_id);
505 	rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_ID);
506 	if (rc)
507 		return rc;
508 	rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION);
509 	if (rc)
510 		return rc;
511 	for (;;) {
512 		rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS);
513 		if (rc)
514 			return rc;
515 		val = apei_exec_ctx_get_output(&ctx);
516 		if (!val)
517 			break;
518 		if (erst_timedout(&timeout, SPIN_UNIT))
519 			return -EIO;
520 	};
521 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS);
522 	if (rc)
523 		return rc;
524 	val = apei_exec_ctx_get_output(&ctx);
525 	rc = apei_exec_run(&ctx, ACPI_ERST_END);
526 	if (rc)
527 		return rc;
528 
529 	return erst_errno(val);
530 }
531 
532 static int __erst_clear_from_storage(u64 record_id)
533 {
534 	struct apei_exec_context ctx;
535 	u64 timeout = FIRMWARE_TIMEOUT;
536 	u64 val;
537 	int rc;
538 
539 	erst_exec_ctx_init(&ctx);
540 	rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_CLEAR);
541 	if (rc)
542 		return rc;
543 	apei_exec_ctx_set_input(&ctx, record_id);
544 	rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_ID);
545 	if (rc)
546 		return rc;
547 	rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION);
548 	if (rc)
549 		return rc;
550 	for (;;) {
551 		rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS);
552 		if (rc)
553 			return rc;
554 		val = apei_exec_ctx_get_output(&ctx);
555 		if (!val)
556 			break;
557 		if (erst_timedout(&timeout, SPIN_UNIT))
558 			return -EIO;
559 	}
560 	rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS);
561 	if (rc)
562 		return rc;
563 	val = apei_exec_ctx_get_output(&ctx);
564 	rc = apei_exec_run(&ctx, ACPI_ERST_END);
565 	if (rc)
566 		return rc;
567 
568 	return erst_errno(val);
569 }
570 
571 /* NVRAM ERST Error Log Address Range is not supported yet */
572 static void pr_unimpl_nvram(void)
573 {
574 	if (printk_ratelimit())
575 		pr_warning(ERST_PFX
576 		"NVRAM ERST Log Address Range is not implemented yet\n");
577 }
578 
579 static int __erst_write_to_nvram(const struct cper_record_header *record)
580 {
581 	/* do not print message, because printk is not safe for NMI */
582 	return -ENOSYS;
583 }
584 
585 static int __erst_read_to_erange_from_nvram(u64 record_id, u64 *offset)
586 {
587 	pr_unimpl_nvram();
588 	return -ENOSYS;
589 }
590 
591 static int __erst_clear_from_nvram(u64 record_id)
592 {
593 	pr_unimpl_nvram();
594 	return -ENOSYS;
595 }
596 
597 int erst_write(const struct cper_record_header *record)
598 {
599 	int rc;
600 	unsigned long flags;
601 	struct cper_record_header *rcd_erange;
602 
603 	if (erst_disable)
604 		return -ENODEV;
605 
606 	if (memcmp(record->signature, CPER_SIG_RECORD, CPER_SIG_SIZE))
607 		return -EINVAL;
608 
609 	if (erst_erange.attr & ERST_RANGE_NVRAM) {
610 		if (!spin_trylock_irqsave(&erst_lock, flags))
611 			return -EBUSY;
612 		rc = __erst_write_to_nvram(record);
613 		spin_unlock_irqrestore(&erst_lock, flags);
614 		return rc;
615 	}
616 
617 	if (record->record_length > erst_erange.size)
618 		return -EINVAL;
619 
620 	if (!spin_trylock_irqsave(&erst_lock, flags))
621 		return -EBUSY;
622 	memcpy(erst_erange.vaddr, record, record->record_length);
623 	rcd_erange = erst_erange.vaddr;
624 	/* signature for serialization system */
625 	memcpy(&rcd_erange->persistence_information, "ER", 2);
626 
627 	rc = __erst_write_to_storage(0);
628 	spin_unlock_irqrestore(&erst_lock, flags);
629 
630 	return rc;
631 }
632 EXPORT_SYMBOL_GPL(erst_write);
633 
634 static int __erst_read_to_erange(u64 record_id, u64 *offset)
635 {
636 	int rc;
637 
638 	if (erst_erange.attr & ERST_RANGE_NVRAM)
639 		return __erst_read_to_erange_from_nvram(
640 			record_id, offset);
641 
642 	rc = __erst_read_from_storage(record_id, 0);
643 	if (rc)
644 		return rc;
645 	*offset = 0;
646 
647 	return 0;
648 }
649 
650 static ssize_t __erst_read(u64 record_id, struct cper_record_header *record,
651 			   size_t buflen)
652 {
653 	int rc;
654 	u64 offset, len = 0;
655 	struct cper_record_header *rcd_tmp;
656 
657 	rc = __erst_read_to_erange(record_id, &offset);
658 	if (rc)
659 		return rc;
660 	rcd_tmp = erst_erange.vaddr + offset;
661 	len = rcd_tmp->record_length;
662 	if (len <= buflen)
663 		memcpy(record, rcd_tmp, len);
664 
665 	return len;
666 }
667 
668 /*
669  * If return value > buflen, the buffer size is not big enough,
670  * else if return value < 0, something goes wrong,
671  * else everything is OK, and return value is record length
672  */
673 ssize_t erst_read(u64 record_id, struct cper_record_header *record,
674 		  size_t buflen)
675 {
676 	ssize_t len;
677 	unsigned long flags;
678 
679 	if (erst_disable)
680 		return -ENODEV;
681 
682 	spin_lock_irqsave(&erst_lock, flags);
683 	len = __erst_read(record_id, record, buflen);
684 	spin_unlock_irqrestore(&erst_lock, flags);
685 	return len;
686 }
687 EXPORT_SYMBOL_GPL(erst_read);
688 
689 /*
690  * If return value > buflen, the buffer size is not big enough,
691  * else if return value = 0, there is no more record to read,
692  * else if return value < 0, something goes wrong,
693  * else everything is OK, and return value is record length
694  */
695 ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
696 {
697 	int rc;
698 	ssize_t len;
699 	unsigned long flags;
700 	u64 record_id;
701 
702 	if (erst_disable)
703 		return -ENODEV;
704 
705 	spin_lock_irqsave(&erst_lock, flags);
706 	rc = __erst_get_next_record_id(&record_id);
707 	if (rc) {
708 		spin_unlock_irqrestore(&erst_lock, flags);
709 		return rc;
710 	}
711 	/* no more record */
712 	if (record_id == APEI_ERST_INVALID_RECORD_ID) {
713 		spin_unlock_irqrestore(&erst_lock, flags);
714 		return 0;
715 	}
716 
717 	len = __erst_read(record_id, record, buflen);
718 	spin_unlock_irqrestore(&erst_lock, flags);
719 
720 	return len;
721 }
722 EXPORT_SYMBOL_GPL(erst_read_next);
723 
724 int erst_clear(u64 record_id)
725 {
726 	int rc;
727 	unsigned long flags;
728 
729 	if (erst_disable)
730 		return -ENODEV;
731 
732 	spin_lock_irqsave(&erst_lock, flags);
733 	if (erst_erange.attr & ERST_RANGE_NVRAM)
734 		rc = __erst_clear_from_nvram(record_id);
735 	else
736 		rc = __erst_clear_from_storage(record_id);
737 	spin_unlock_irqrestore(&erst_lock, flags);
738 
739 	return rc;
740 }
741 EXPORT_SYMBOL_GPL(erst_clear);
742 
743 static int __init setup_erst_disable(char *str)
744 {
745 	erst_disable = 1;
746 	return 0;
747 }
748 
749 __setup("erst_disable", setup_erst_disable);
750 
751 static int erst_check_table(struct acpi_table_erst *erst_tab)
752 {
753 	if (erst_tab->header_length != sizeof(struct acpi_table_erst))
754 		return -EINVAL;
755 	if (erst_tab->header.length < sizeof(struct acpi_table_erst))
756 		return -EINVAL;
757 	if (erst_tab->entries !=
758 	    (erst_tab->header.length - sizeof(struct acpi_table_erst)) /
759 	    sizeof(struct acpi_erst_entry))
760 		return -EINVAL;
761 
762 	return 0;
763 }
764 
765 static int __init erst_init(void)
766 {
767 	int rc = 0;
768 	acpi_status status;
769 	struct apei_exec_context ctx;
770 	struct apei_resources erst_resources;
771 	struct resource *r;
772 
773 	if (acpi_disabled)
774 		goto err;
775 
776 	if (erst_disable) {
777 		pr_info(ERST_PFX
778 	"Error Record Serialization Table (ERST) support is disabled.\n");
779 		goto err;
780 	}
781 
782 	status = acpi_get_table(ACPI_SIG_ERST, 0,
783 				(struct acpi_table_header **)&erst_tab);
784 	if (status == AE_NOT_FOUND) {
785 		pr_info(ERST_PFX "Table is not found!\n");
786 		goto err;
787 	} else if (ACPI_FAILURE(status)) {
788 		const char *msg = acpi_format_exception(status);
789 		pr_err(ERST_PFX "Failed to get table, %s\n", msg);
790 		rc = -EINVAL;
791 		goto err;
792 	}
793 
794 	rc = erst_check_table(erst_tab);
795 	if (rc) {
796 		pr_err(FW_BUG ERST_PFX "ERST table is invalid\n");
797 		goto err;
798 	}
799 
800 	apei_resources_init(&erst_resources);
801 	erst_exec_ctx_init(&ctx);
802 	rc = apei_exec_collect_resources(&ctx, &erst_resources);
803 	if (rc)
804 		goto err_fini;
805 	rc = apei_resources_request(&erst_resources, "APEI ERST");
806 	if (rc)
807 		goto err_fini;
808 	rc = apei_exec_pre_map_gars(&ctx);
809 	if (rc)
810 		goto err_release;
811 	rc = erst_get_erange(&erst_erange);
812 	if (rc) {
813 		if (rc == -ENODEV)
814 			pr_info(ERST_PFX
815 	"The corresponding hardware device or firmware implementation "
816 	"is not available.\n");
817 		else
818 			pr_err(ERST_PFX
819 			       "Failed to get Error Log Address Range.\n");
820 		goto err_unmap_reg;
821 	}
822 
823 	r = request_mem_region(erst_erange.base, erst_erange.size, "APEI ERST");
824 	if (!r) {
825 		pr_err(ERST_PFX
826 		"Can not request iomem region <0x%16llx-0x%16llx> for ERST.\n",
827 		(unsigned long long)erst_erange.base,
828 		(unsigned long long)erst_erange.base + erst_erange.size);
829 		rc = -EIO;
830 		goto err_unmap_reg;
831 	}
832 	rc = -ENOMEM;
833 	erst_erange.vaddr = ioremap_cache(erst_erange.base,
834 					  erst_erange.size);
835 	if (!erst_erange.vaddr)
836 		goto err_release_erange;
837 
838 	pr_info(ERST_PFX
839 	"Error Record Serialization Table (ERST) support is initialized.\n");
840 
841 	return 0;
842 
843 err_release_erange:
844 	release_mem_region(erst_erange.base, erst_erange.size);
845 err_unmap_reg:
846 	apei_exec_post_unmap_gars(&ctx);
847 err_release:
848 	apei_resources_release(&erst_resources);
849 err_fini:
850 	apei_resources_fini(&erst_resources);
851 err:
852 	erst_disable = 1;
853 	return rc;
854 }
855 
856 device_initcall(erst_init);
857