1/* 2 * drivers/pci/pcie/aer/aerdrv_core.c 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file "COPYING" in the main directory of this archive 6 * for more details. 7 * 8 * This file implements the core part of PCI-Express AER. When an pci-express 9 * error is delivered, an error message will be collected and printed to 10 * console, then, an error recovery procedure will be executed by following 11 * the pci error recovery rules. 12 * 13 * Copyright (C) 2006 Intel Corp. 14 * Tom Long Nguyen (tom.l.nguyen@intel.com) 15 * Zhang Yanmin (yanmin.zhang@intel.com) 16 * 17 */ 18 19#include <linux/module.h> 20#include <linux/pci.h> 21#include <linux/kernel.h> 22#include <linux/errno.h> 23#include <linux/pm.h> 24#include <linux/suspend.h> 25#include <linux/delay.h> 26#include <linux/slab.h> 27#include <linux/kfifo.h> 28#include "aerdrv.h" 29 30static bool forceload; 31static bool nosourceid; 32module_param(forceload, bool, 0); 33module_param(nosourceid, bool, 0); 34 35#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ 36 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) 37 38int pci_enable_pcie_error_reporting(struct pci_dev *dev) 39{ 40 if (pcie_aer_get_firmware_first(dev)) 41 return -EIO; 42 43 if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) 44 return -EIO; 45 46 return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); 47} 48EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting); 49 50int pci_disable_pcie_error_reporting(struct pci_dev *dev) 51{ 52 if (pcie_aer_get_firmware_first(dev)) 53 return -EIO; 54 55 return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL, 56 PCI_EXP_AER_FLAGS); 57} 58EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); 59 60int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) 61{ 62 int pos; 63 u32 status; 64 65 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 66 if (!pos) 67 return -EIO; 68 69 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); 70 if (status) 71 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); 72 73 return 0; 74} 75EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); 76 77/** 78 * add_error_device - list device to be handled 79 * @e_info: pointer to error info 80 * @dev: pointer to pci_dev to be added 81 */ 82static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev) 83{ 84 if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) { 85 e_info->dev[e_info->error_dev_num] = dev; 86 e_info->error_dev_num++; 87 return 0; 88 } 89 return -ENOSPC; 90} 91 92/** 93 * is_error_source - check whether the device is source of reported error 94 * @dev: pointer to pci_dev to be checked 95 * @e_info: pointer to reported error info 96 */ 97static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) 98{ 99 int pos; 100 u32 status, mask; 101 u16 reg16; 102 103 /* 104 * When bus id is equal to 0, it might be a bad id 105 * reported by root port. 106 */ 107 if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) { 108 /* Device ID match? */ 109 if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) 110 return true; 111 112 /* Continue id comparing if there is no multiple error */ 113 if (!e_info->multi_error_valid) 114 return false; 115 } 116 117 /* 118 * When either 119 * 1) nosourceid==y; 120 * 2) bus id is equal to 0. Some ports might lose the bus 121 * id of error source id; 122 * 3) There are multiple errors and prior id comparing fails; 123 * We check AER status registers to find possible reporter. 124 */ 125 if (atomic_read(&dev->enable_cnt) == 0) 126 return false; 127 128 /* Check if AER is enabled */ 129 pcie_capability_read_word(dev, PCI_EXP_DEVCTL, ®16); 130 if (!(reg16 & PCI_EXP_AER_FLAGS)) 131 return false; 132 133 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 134 if (!pos) 135 return false; 136 137 /* Check if error is recorded */ 138 if (e_info->severity == AER_CORRECTABLE) { 139 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); 140 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask); 141 } else { 142 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); 143 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask); 144 } 145 if (status & ~mask) 146 return true; 147 148 return false; 149} 150 151static int find_device_iter(struct pci_dev *dev, void *data) 152{ 153 struct aer_err_info *e_info = (struct aer_err_info *)data; 154 155 if (is_error_source(dev, e_info)) { 156 /* List this device */ 157 if (add_error_device(e_info, dev)) { 158 /* We cannot handle more... Stop iteration */ 159 /* TODO: Should print error message here? */ 160 return 1; 161 } 162 163 /* If there is only a single error, stop iteration */ 164 if (!e_info->multi_error_valid) 165 return 1; 166 } 167 return 0; 168} 169 170/** 171 * find_source_device - search through device hierarchy for source device 172 * @parent: pointer to Root Port pci_dev data structure 173 * @e_info: including detailed error information such like id 174 * 175 * Return true if found. 176 * 177 * Invoked by DPC when error is detected at the Root Port. 178 * Caller of this function must set id, severity, and multi_error_valid of 179 * struct aer_err_info pointed by @e_info properly. This function must fill 180 * e_info->error_dev_num and e_info->dev[], based on the given information. 181 */ 182static bool find_source_device(struct pci_dev *parent, 183 struct aer_err_info *e_info) 184{ 185 struct pci_dev *dev = parent; 186 int result; 187 188 /* Must reset in this function */ 189 e_info->error_dev_num = 0; 190 191 /* Is Root Port an agent that sends error message? */ 192 result = find_device_iter(dev, e_info); 193 if (result) 194 return true; 195 196 pci_walk_bus(parent->subordinate, find_device_iter, e_info); 197 198 if (!e_info->error_dev_num) { 199 dev_printk(KERN_DEBUG, &parent->dev, 200 "can't find device of ID%04x\n", 201 e_info->id); 202 return false; 203 } 204 return true; 205} 206 207static int report_error_detected(struct pci_dev *dev, void *data) 208{ 209 pci_ers_result_t vote; 210 const struct pci_error_handlers *err_handler; 211 struct aer_broadcast_data *result_data; 212 result_data = (struct aer_broadcast_data *) data; 213 214 device_lock(&dev->dev); 215 dev->error_state = result_data->state; 216 217 if (!dev->driver || 218 !dev->driver->err_handler || 219 !dev->driver->err_handler->error_detected) { 220 if (result_data->state == pci_channel_io_frozen && 221 !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) { 222 /* 223 * In case of fatal recovery, if one of down- 224 * stream device has no driver. We might be 225 * unable to recover because a later insmod 226 * of a driver for this device is unaware of 227 * its hw state. 228 */ 229 dev_printk(KERN_DEBUG, &dev->dev, "device has %s\n", 230 dev->driver ? 231 "no AER-aware driver" : "no driver"); 232 } 233 234 /* 235 * If there's any device in the subtree that does not 236 * have an error_detected callback, returning 237 * PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of 238 * the subsequent mmio_enabled/slot_reset/resume 239 * callbacks of "any" device in the subtree. All the 240 * devices in the subtree are left in the error state 241 * without recovery. 242 */ 243 244 if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) 245 vote = PCI_ERS_RESULT_NO_AER_DRIVER; 246 else 247 vote = PCI_ERS_RESULT_NONE; 248 } else { 249 err_handler = dev->driver->err_handler; 250 vote = err_handler->error_detected(dev, result_data->state); 251 } 252 253 result_data->result = merge_result(result_data->result, vote); 254 device_unlock(&dev->dev); 255 return 0; 256} 257 258static int report_mmio_enabled(struct pci_dev *dev, void *data) 259{ 260 pci_ers_result_t vote; 261 const struct pci_error_handlers *err_handler; 262 struct aer_broadcast_data *result_data; 263 result_data = (struct aer_broadcast_data *) data; 264 265 device_lock(&dev->dev); 266 if (!dev->driver || 267 !dev->driver->err_handler || 268 !dev->driver->err_handler->mmio_enabled) 269 goto out; 270 271 err_handler = dev->driver->err_handler; 272 vote = err_handler->mmio_enabled(dev); 273 result_data->result = merge_result(result_data->result, vote); 274out: 275 device_unlock(&dev->dev); 276 return 0; 277} 278 279static int report_slot_reset(struct pci_dev *dev, void *data) 280{ 281 pci_ers_result_t vote; 282 const struct pci_error_handlers *err_handler; 283 struct aer_broadcast_data *result_data; 284 result_data = (struct aer_broadcast_data *) data; 285 286 device_lock(&dev->dev); 287 if (!dev->driver || 288 !dev->driver->err_handler || 289 !dev->driver->err_handler->slot_reset) 290 goto out; 291 292 err_handler = dev->driver->err_handler; 293 vote = err_handler->slot_reset(dev); 294 result_data->result = merge_result(result_data->result, vote); 295out: 296 device_unlock(&dev->dev); 297 return 0; 298} 299 300static int report_resume(struct pci_dev *dev, void *data) 301{ 302 const struct pci_error_handlers *err_handler; 303 304 device_lock(&dev->dev); 305 dev->error_state = pci_channel_io_normal; 306 307 if (!dev->driver || 308 !dev->driver->err_handler || 309 !dev->driver->err_handler->resume) 310 goto out; 311 312 err_handler = dev->driver->err_handler; 313 err_handler->resume(dev); 314out: 315 device_unlock(&dev->dev); 316 return 0; 317} 318 319/** 320 * broadcast_error_message - handle message broadcast to downstream drivers 321 * @dev: pointer to from where in a hierarchy message is broadcasted down 322 * @state: error state 323 * @error_mesg: message to print 324 * @cb: callback to be broadcasted 325 * 326 * Invoked during error recovery process. Once being invoked, the content 327 * of error severity will be broadcasted to all downstream drivers in a 328 * hierarchy in question. 329 */ 330static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, 331 enum pci_channel_state state, 332 char *error_mesg, 333 int (*cb)(struct pci_dev *, void *)) 334{ 335 struct aer_broadcast_data result_data; 336 337 dev_printk(KERN_DEBUG, &dev->dev, "broadcast %s message\n", error_mesg); 338 result_data.state = state; 339 if (cb == report_error_detected) 340 result_data.result = PCI_ERS_RESULT_CAN_RECOVER; 341 else 342 result_data.result = PCI_ERS_RESULT_RECOVERED; 343 344 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { 345 /* 346 * If the error is reported by a bridge, we think this error 347 * is related to the downstream link of the bridge, so we 348 * do error recovery on all subordinates of the bridge instead 349 * of the bridge and clear the error status of the bridge. 350 */ 351 if (cb == report_error_detected) 352 dev->error_state = state; 353 pci_walk_bus(dev->subordinate, cb, &result_data); 354 if (cb == report_resume) { 355 pci_cleanup_aer_uncorrect_error_status(dev); 356 dev->error_state = pci_channel_io_normal; 357 } 358 } else { 359 /* 360 * If the error is reported by an end point, we think this 361 * error is related to the upstream link of the end point. 362 */ 363 pci_walk_bus(dev->bus, cb, &result_data); 364 } 365 366 return result_data.result; 367} 368 369/** 370 * default_reset_link - default reset function 371 * @dev: pointer to pci_dev data structure 372 * 373 * Invoked when performing link reset on a Downstream Port or a 374 * Root Port with no aer driver. 375 */ 376static pci_ers_result_t default_reset_link(struct pci_dev *dev) 377{ 378 pci_reset_bridge_secondary_bus(dev); 379 dev_printk(KERN_DEBUG, &dev->dev, "downstream link has been reset\n"); 380 return PCI_ERS_RESULT_RECOVERED; 381} 382 383static int find_aer_service_iter(struct device *device, void *data) 384{ 385 struct pcie_port_service_driver *service_driver, **drv; 386 387 drv = (struct pcie_port_service_driver **) data; 388 389 if (device->bus == &pcie_port_bus_type && device->driver) { 390 service_driver = to_service_driver(device->driver); 391 if (service_driver->service == PCIE_PORT_SERVICE_AER) { 392 *drv = service_driver; 393 return 1; 394 } 395 } 396 397 return 0; 398} 399 400static struct pcie_port_service_driver *find_aer_service(struct pci_dev *dev) 401{ 402 struct pcie_port_service_driver *drv = NULL; 403 404 device_for_each_child(&dev->dev, &drv, find_aer_service_iter); 405 406 return drv; 407} 408 409static pci_ers_result_t reset_link(struct pci_dev *dev) 410{ 411 struct pci_dev *udev; 412 pci_ers_result_t status; 413 struct pcie_port_service_driver *driver; 414 415 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { 416 /* Reset this port for all subordinates */ 417 udev = dev; 418 } else { 419 /* Reset the upstream component (likely downstream port) */ 420 udev = dev->bus->self; 421 } 422 423 /* Use the aer driver of the component firstly */ 424 driver = find_aer_service(udev); 425 426 if (driver && driver->reset_link) { 427 status = driver->reset_link(udev); 428 } else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM || 429 pci_pcie_type(udev) == PCI_EXP_TYPE_ROOT_PORT) { 430 status = default_reset_link(udev); 431 } else { 432 dev_printk(KERN_DEBUG, &dev->dev, 433 "no link-reset support at upstream device %s\n", 434 pci_name(udev)); 435 return PCI_ERS_RESULT_DISCONNECT; 436 } 437 438 if (status != PCI_ERS_RESULT_RECOVERED) { 439 dev_printk(KERN_DEBUG, &dev->dev, 440 "link reset at upstream device %s failed\n", 441 pci_name(udev)); 442 return PCI_ERS_RESULT_DISCONNECT; 443 } 444 445 return status; 446} 447 448/** 449 * do_recovery - handle nonfatal/fatal error recovery process 450 * @dev: pointer to a pci_dev data structure of agent detecting an error 451 * @severity: error severity type 452 * 453 * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast 454 * error detected message to all downstream drivers within a hierarchy in 455 * question and return the returned code. 456 */ 457static void do_recovery(struct pci_dev *dev, int severity) 458{ 459 pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED; 460 enum pci_channel_state state; 461 462 if (severity == AER_FATAL) 463 state = pci_channel_io_frozen; 464 else 465 state = pci_channel_io_normal; 466 467 status = broadcast_error_message(dev, 468 state, 469 "error_detected", 470 report_error_detected); 471 472 if (severity == AER_FATAL) { 473 result = reset_link(dev); 474 if (result != PCI_ERS_RESULT_RECOVERED) 475 goto failed; 476 } 477 478 if (status == PCI_ERS_RESULT_CAN_RECOVER) 479 status = broadcast_error_message(dev, 480 state, 481 "mmio_enabled", 482 report_mmio_enabled); 483 484 if (status == PCI_ERS_RESULT_NEED_RESET) { 485 /* 486 * TODO: Should call platform-specific 487 * functions to reset slot before calling 488 * drivers' slot_reset callbacks? 489 */ 490 status = broadcast_error_message(dev, 491 state, 492 "slot_reset", 493 report_slot_reset); 494 } 495 496 if (status != PCI_ERS_RESULT_RECOVERED) 497 goto failed; 498 499 broadcast_error_message(dev, 500 state, 501 "resume", 502 report_resume); 503 504 dev_info(&dev->dev, "AER: Device recovery successful\n"); 505 return; 506 507failed: 508 /* TODO: Should kernel panic here? */ 509 dev_info(&dev->dev, "AER: Device recovery failed\n"); 510} 511 512/** 513 * handle_error_source - handle logging error into an event log 514 * @aerdev: pointer to pcie_device data structure of the root port 515 * @dev: pointer to pci_dev data structure of error source device 516 * @info: comprehensive error information 517 * 518 * Invoked when an error being detected by Root Port. 519 */ 520static void handle_error_source(struct pcie_device *aerdev, 521 struct pci_dev *dev, 522 struct aer_err_info *info) 523{ 524 int pos; 525 526 if (info->severity == AER_CORRECTABLE) { 527 /* 528 * Correctable error does not need software intervention. 529 * No need to go through error recovery process. 530 */ 531 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 532 if (pos) 533 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, 534 info->status); 535 } else 536 do_recovery(dev, info->severity); 537} 538 539#ifdef CONFIG_ACPI_APEI_PCIEAER 540static void aer_recover_work_func(struct work_struct *work); 541 542#define AER_RECOVER_RING_ORDER 4 543#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER) 544 545struct aer_recover_entry { 546 u8 bus; 547 u8 devfn; 548 u16 domain; 549 int severity; 550 struct aer_capability_regs *regs; 551}; 552 553static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry, 554 AER_RECOVER_RING_SIZE); 555/* 556 * Mutual exclusion for writers of aer_recover_ring, reader side don't 557 * need lock, because there is only one reader and lock is not needed 558 * between reader and writer. 559 */ 560static DEFINE_SPINLOCK(aer_recover_ring_lock); 561static DECLARE_WORK(aer_recover_work, aer_recover_work_func); 562 563void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, 564 int severity, struct aer_capability_regs *aer_regs) 565{ 566 unsigned long flags; 567 struct aer_recover_entry entry = { 568 .bus = bus, 569 .devfn = devfn, 570 .domain = domain, 571 .severity = severity, 572 .regs = aer_regs, 573 }; 574 575 spin_lock_irqsave(&aer_recover_ring_lock, flags); 576 if (kfifo_put(&aer_recover_ring, entry)) 577 schedule_work(&aer_recover_work); 578 else 579 pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n", 580 domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 581 spin_unlock_irqrestore(&aer_recover_ring_lock, flags); 582} 583EXPORT_SYMBOL_GPL(aer_recover_queue); 584 585static void aer_recover_work_func(struct work_struct *work) 586{ 587 struct aer_recover_entry entry; 588 struct pci_dev *pdev; 589 590 while (kfifo_get(&aer_recover_ring, &entry)) { 591 pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus, 592 entry.devfn); 593 if (!pdev) { 594 pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n", 595 entry.domain, entry.bus, 596 PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn)); 597 continue; 598 } 599 cper_print_aer(pdev, entry.severity, entry.regs); 600 do_recovery(pdev, entry.severity); 601 pci_dev_put(pdev); 602 } 603} 604#endif 605 606/** 607 * get_device_error_info - read error status from dev and store it to info 608 * @dev: pointer to the device expected to have a error record 609 * @info: pointer to structure to store the error record 610 * 611 * Return 1 on success, 0 on error. 612 * 613 * Note that @info is reused among all error devices. Clear fields properly. 614 */ 615static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) 616{ 617 int pos, temp; 618 619 /* Must reset in this function */ 620 info->status = 0; 621 info->tlp_header_valid = 0; 622 623 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 624 625 /* The device might not support AER */ 626 if (!pos) 627 return 1; 628 629 if (info->severity == AER_CORRECTABLE) { 630 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, 631 &info->status); 632 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, 633 &info->mask); 634 if (!(info->status & ~info->mask)) 635 return 0; 636 } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE || 637 info->severity == AER_NONFATAL) { 638 639 /* Link is still healthy for IO reads */ 640 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, 641 &info->status); 642 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 643 &info->mask); 644 if (!(info->status & ~info->mask)) 645 return 0; 646 647 /* Get First Error Pointer */ 648 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &temp); 649 info->first_error = PCI_ERR_CAP_FEP(temp); 650 651 if (info->status & AER_LOG_TLP_MASKS) { 652 info->tlp_header_valid = 1; 653 pci_read_config_dword(dev, 654 pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0); 655 pci_read_config_dword(dev, 656 pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1); 657 pci_read_config_dword(dev, 658 pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2); 659 pci_read_config_dword(dev, 660 pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3); 661 } 662 } 663 664 return 1; 665} 666 667static inline void aer_process_err_devices(struct pcie_device *p_device, 668 struct aer_err_info *e_info) 669{ 670 int i; 671 672 /* Report all before handle them, not to lost records by reset etc. */ 673 for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { 674 if (get_device_error_info(e_info->dev[i], e_info)) 675 aer_print_error(e_info->dev[i], e_info); 676 } 677 for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { 678 if (get_device_error_info(e_info->dev[i], e_info)) 679 handle_error_source(p_device, e_info->dev[i], e_info); 680 } 681} 682 683/** 684 * aer_isr_one_error - consume an error detected by root port 685 * @p_device: pointer to error root port service device 686 * @e_src: pointer to an error source 687 */ 688static void aer_isr_one_error(struct pcie_device *p_device, 689 struct aer_err_source *e_src) 690{ 691 struct aer_err_info *e_info; 692 693 /* struct aer_err_info might be big, so we allocate it with slab */ 694 e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL); 695 if (!e_info) { 696 dev_printk(KERN_DEBUG, &p_device->port->dev, 697 "Can't allocate mem when processing AER errors\n"); 698 return; 699 } 700 701 /* 702 * There is a possibility that both correctable error and 703 * uncorrectable error being logged. Report correctable error first. 704 */ 705 if (e_src->status & PCI_ERR_ROOT_COR_RCV) { 706 e_info->id = ERR_COR_ID(e_src->id); 707 e_info->severity = AER_CORRECTABLE; 708 709 if (e_src->status & PCI_ERR_ROOT_MULTI_COR_RCV) 710 e_info->multi_error_valid = 1; 711 else 712 e_info->multi_error_valid = 0; 713 714 aer_print_port_info(p_device->port, e_info); 715 716 if (find_source_device(p_device->port, e_info)) 717 aer_process_err_devices(p_device, e_info); 718 } 719 720 if (e_src->status & PCI_ERR_ROOT_UNCOR_RCV) { 721 e_info->id = ERR_UNCOR_ID(e_src->id); 722 723 if (e_src->status & PCI_ERR_ROOT_FATAL_RCV) 724 e_info->severity = AER_FATAL; 725 else 726 e_info->severity = AER_NONFATAL; 727 728 if (e_src->status & PCI_ERR_ROOT_MULTI_UNCOR_RCV) 729 e_info->multi_error_valid = 1; 730 else 731 e_info->multi_error_valid = 0; 732 733 aer_print_port_info(p_device->port, e_info); 734 735 if (find_source_device(p_device->port, e_info)) 736 aer_process_err_devices(p_device, e_info); 737 } 738 739 kfree(e_info); 740} 741 742/** 743 * get_e_source - retrieve an error source 744 * @rpc: pointer to the root port which holds an error 745 * @e_src: pointer to store retrieved error source 746 * 747 * Return 1 if an error source is retrieved, otherwise 0. 748 * 749 * Invoked by DPC handler to consume an error. 750 */ 751static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src) 752{ 753 unsigned long flags; 754 755 /* Lock access to Root error producer/consumer index */ 756 spin_lock_irqsave(&rpc->e_lock, flags); 757 if (rpc->prod_idx == rpc->cons_idx) { 758 spin_unlock_irqrestore(&rpc->e_lock, flags); 759 return 0; 760 } 761 762 *e_src = rpc->e_sources[rpc->cons_idx]; 763 rpc->cons_idx++; 764 if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) 765 rpc->cons_idx = 0; 766 spin_unlock_irqrestore(&rpc->e_lock, flags); 767 768 return 1; 769} 770 771/** 772 * aer_isr - consume errors detected by root port 773 * @work: definition of this work item 774 * 775 * Invoked, as DPC, when root port records new detected error 776 */ 777void aer_isr(struct work_struct *work) 778{ 779 struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); 780 struct pcie_device *p_device = rpc->rpd; 781 struct aer_err_source uninitialized_var(e_src); 782 783 mutex_lock(&rpc->rpc_mutex); 784 while (get_e_source(rpc, &e_src)) 785 aer_isr_one_error(p_device, &e_src); 786 mutex_unlock(&rpc->rpc_mutex); 787} 788 789/** 790 * aer_init - provide AER initialization 791 * @dev: pointer to AER pcie device 792 * 793 * Invoked when AER service driver is loaded. 794 */ 795int aer_init(struct pcie_device *dev) 796{ 797 if (forceload) { 798 dev_printk(KERN_DEBUG, &dev->device, 799 "aerdrv forceload requested.\n"); 800 pcie_aer_force_firmware_first(dev->port, 0); 801 } 802 return 0; 803} 804