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