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