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/acpi.h> 26#include <linux/pci-acpi.h> 27#include <linux/delay.h> 28#include "aerdrv.h" 29 30static int forceload; 31module_param(forceload, bool, 0); 32 33#define PCI_CFG_SPACE_SIZE (0x100) 34int pci_find_aer_capability(struct pci_dev *dev) 35{ 36 int pos; 37 u32 reg32 = 0; 38 39 /* Check if it's a pci-express device */ 40 pos = pci_find_capability(dev, PCI_CAP_ID_EXP); 41 if (!pos) 42 return 0; 43 44 /* Check if it supports pci-express AER */ 45 pos = PCI_CFG_SPACE_SIZE; 46 while (pos) { 47 if (pci_read_config_dword(dev, pos, ®32)) 48 return 0; 49 50 /* some broken boards return ~0 */ 51 if (reg32 == 0xffffffff) 52 return 0; 53 54 if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR) 55 break; 56 57 pos = reg32 >> 20; 58 } 59 60 return pos; 61} 62 63int pci_enable_pcie_error_reporting(struct pci_dev *dev) 64{ 65 u16 reg16 = 0; 66 int pos; 67 68 pos = pci_find_capability(dev, PCI_CAP_ID_EXP); 69 if (!pos) 70 return -EIO; 71 72 pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, ®16); 73 reg16 = reg16 | 74 PCI_EXP_DEVCTL_CERE | 75 PCI_EXP_DEVCTL_NFERE | 76 PCI_EXP_DEVCTL_FERE | 77 PCI_EXP_DEVCTL_URRE; 78 pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, 79 reg16); 80 return 0; 81} 82 83int pci_disable_pcie_error_reporting(struct pci_dev *dev) 84{ 85 u16 reg16 = 0; 86 int pos; 87 88 pos = pci_find_capability(dev, PCI_CAP_ID_EXP); 89 if (!pos) 90 return -EIO; 91 92 pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, ®16); 93 reg16 = reg16 & ~(PCI_EXP_DEVCTL_CERE | 94 PCI_EXP_DEVCTL_NFERE | 95 PCI_EXP_DEVCTL_FERE | 96 PCI_EXP_DEVCTL_URRE); 97 pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, 98 reg16); 99 return 0; 100} 101 102int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) 103{ 104 int pos; 105 u32 status, mask; 106 107 pos = pci_find_aer_capability(dev); 108 if (!pos) 109 return -EIO; 110 111 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); 112 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); 113 if (dev->error_state == pci_channel_io_normal) 114 status &= ~mask; /* Clear corresponding nonfatal bits */ 115 else 116 status &= mask; /* Clear corresponding fatal bits */ 117 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); 118 119 return 0; 120} 121 122static int find_device_iter(struct device *device, void *data) 123{ 124 struct pci_dev *dev; 125 u16 id = *(unsigned long *)data; 126 u8 secondary, subordinate, d_bus = id >> 8; 127 128 if (device->bus == &pci_bus_type) { 129 dev = to_pci_dev(device); 130 if (id == ((dev->bus->number << 8) | dev->devfn)) { 131 /* 132 * Device ID match 133 */ 134 *(unsigned long*)data = (unsigned long)device; 135 return 1; 136 } 137 138 /* 139 * If device is P2P, check if it is an upstream? 140 */ 141 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { 142 pci_read_config_byte(dev, PCI_SECONDARY_BUS, 143 &secondary); 144 pci_read_config_byte(dev, PCI_SUBORDINATE_BUS, 145 &subordinate); 146 if (d_bus >= secondary && d_bus <= subordinate) { 147 *(unsigned long*)data = (unsigned long)device; 148 return 1; 149 } 150 } 151 } 152 153 return 0; 154} 155 156/** 157 * find_source_device - search through device hierarchy for source device 158 * @p_dev: pointer to Root Port pci_dev data structure 159 * @id: device ID of agent who sends an error message to this Root Port 160 * 161 * Invoked when error is detected at the Root Port. 162 **/ 163static struct device* find_source_device(struct pci_dev *parent, u16 id) 164{ 165 struct pci_dev *dev = parent; 166 struct device *device; 167 unsigned long device_addr; 168 int status; 169 170 /* Is Root Port an agent that sends error message? */ 171 if (id == ((dev->bus->number << 8) | dev->devfn)) 172 return &dev->dev; 173 174 do { 175 device_addr = id; 176 if ((status = device_for_each_child(&dev->dev, 177 &device_addr, find_device_iter))) { 178 device = (struct device*)device_addr; 179 dev = to_pci_dev(device); 180 if (id == ((dev->bus->number << 8) | dev->devfn)) 181 return device; 182 } 183 }while (status); 184 185 return NULL; 186} 187 188static void report_error_detected(struct pci_dev *dev, void *data) 189{ 190 pci_ers_result_t vote; 191 struct pci_error_handlers *err_handler; 192 struct aer_broadcast_data *result_data; 193 result_data = (struct aer_broadcast_data *) data; 194 195 dev->error_state = result_data->state; 196 197 if (!dev->driver || 198 !dev->driver->err_handler || 199 !dev->driver->err_handler->error_detected) { 200 if (result_data->state == pci_channel_io_frozen && 201 !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) { 202 /* 203 * In case of fatal recovery, if one of down- 204 * stream device has no driver. We might be 205 * unable to recover because a later insmod 206 * of a driver for this device is unaware of 207 * its hw state. 208 */ 209 printk(KERN_DEBUG "Device ID[%s] has %s\n", 210 dev->dev.bus_id, (dev->driver) ? 211 "no AER-aware driver" : "no driver"); 212 } 213 return; 214 } 215 216 err_handler = dev->driver->err_handler; 217 vote = err_handler->error_detected(dev, result_data->state); 218 result_data->result = merge_result(result_data->result, vote); 219 return; 220} 221 222static void report_mmio_enabled(struct pci_dev *dev, void *data) 223{ 224 pci_ers_result_t vote; 225 struct pci_error_handlers *err_handler; 226 struct aer_broadcast_data *result_data; 227 result_data = (struct aer_broadcast_data *) data; 228 229 if (!dev->driver || 230 !dev->driver->err_handler || 231 !dev->driver->err_handler->mmio_enabled) 232 return; 233 234 err_handler = dev->driver->err_handler; 235 vote = err_handler->mmio_enabled(dev); 236 result_data->result = merge_result(result_data->result, vote); 237 return; 238} 239 240static void report_slot_reset(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 if (!dev->driver || 248 !dev->driver->err_handler || 249 !dev->driver->err_handler->slot_reset) 250 return; 251 252 err_handler = dev->driver->err_handler; 253 vote = err_handler->slot_reset(dev); 254 result_data->result = merge_result(result_data->result, vote); 255 return; 256} 257 258static void report_resume(struct pci_dev *dev, void *data) 259{ 260 struct pci_error_handlers *err_handler; 261 262 dev->error_state = pci_channel_io_normal; 263 264 if (!dev->driver || 265 !dev->driver->err_handler || 266 !dev->driver->err_handler->slot_reset) 267 return; 268 269 err_handler = dev->driver->err_handler; 270 err_handler->resume(dev); 271 return; 272} 273 274/** 275 * broadcast_error_message - handle message broadcast to downstream drivers 276 * @device: pointer to from where in a hierarchy message is broadcasted down 277 * @api: callback to be broadcasted 278 * @state: error state 279 * 280 * Invoked during error recovery process. Once being invoked, the content 281 * of error severity will be broadcasted to all downstream drivers in a 282 * hierarchy in question. 283 **/ 284static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, 285 enum pci_channel_state state, 286 char *error_mesg, 287 void (*cb)(struct pci_dev *, void *)) 288{ 289 struct aer_broadcast_data result_data; 290 291 printk(KERN_DEBUG "Broadcast %s message\n", error_mesg); 292 result_data.state = state; 293 if (cb == report_error_detected) 294 result_data.result = PCI_ERS_RESULT_CAN_RECOVER; 295 else 296 result_data.result = PCI_ERS_RESULT_RECOVERED; 297 298 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { 299 /* 300 * If the error is reported by a bridge, we think this error 301 * is related to the downstream link of the bridge, so we 302 * do error recovery on all subordinates of the bridge instead 303 * of the bridge and clear the error status of the bridge. 304 */ 305 if (cb == report_error_detected) 306 dev->error_state = state; 307 pci_walk_bus(dev->subordinate, cb, &result_data); 308 if (cb == report_resume) { 309 pci_cleanup_aer_uncorrect_error_status(dev); 310 dev->error_state = pci_channel_io_normal; 311 } 312 } 313 else { 314 /* 315 * If the error is reported by an end point, we think this 316 * error is related to the upstream link of the end point. 317 */ 318 pci_walk_bus(dev->bus, cb, &result_data); 319 } 320 321 return result_data.result; 322} 323 324struct find_aer_service_data { 325 struct pcie_port_service_driver *aer_driver; 326 int is_downstream; 327}; 328 329static int find_aer_service_iter(struct device *device, void *data) 330{ 331 struct device_driver *driver; 332 struct pcie_port_service_driver *service_driver; 333 struct pcie_device *pcie_dev; 334 struct find_aer_service_data *result; 335 336 result = (struct find_aer_service_data *) data; 337 338 if (device->bus == &pcie_port_bus_type) { 339 pcie_dev = to_pcie_device(device); 340 if (pcie_dev->id.port_type == PCIE_SW_DOWNSTREAM_PORT) 341 result->is_downstream = 1; 342 343 driver = device->driver; 344 if (driver) { 345 service_driver = to_service_driver(driver); 346 if (service_driver->id_table->service_type == 347 PCIE_PORT_SERVICE_AER) { 348 result->aer_driver = service_driver; 349 return 1; 350 } 351 } 352 } 353 354 return 0; 355} 356 357static void find_aer_service(struct pci_dev *dev, 358 struct find_aer_service_data *data) 359{ 360 int retval; 361 retval = device_for_each_child(&dev->dev, data, find_aer_service_iter); 362} 363 364static pci_ers_result_t reset_link(struct pcie_device *aerdev, 365 struct pci_dev *dev) 366{ 367 struct pci_dev *udev; 368 pci_ers_result_t status; 369 struct find_aer_service_data data; 370 371 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) 372 udev = dev; 373 else 374 udev= dev->bus->self; 375 376 data.is_downstream = 0; 377 data.aer_driver = NULL; 378 find_aer_service(udev, &data); 379 380 /* 381 * Use the aer driver of the error agent firstly. 382 * If it hasn't the aer driver, use the root port's 383 */ 384 if (!data.aer_driver || !data.aer_driver->reset_link) { 385 if (data.is_downstream && 386 aerdev->device.driver && 387 to_service_driver(aerdev->device.driver)->reset_link) { 388 data.aer_driver = 389 to_service_driver(aerdev->device.driver); 390 } else { 391 printk(KERN_DEBUG "No link-reset support to Device ID" 392 "[%s]\n", 393 dev->dev.bus_id); 394 return PCI_ERS_RESULT_DISCONNECT; 395 } 396 } 397 398 status = data.aer_driver->reset_link(udev); 399 if (status != PCI_ERS_RESULT_RECOVERED) { 400 printk(KERN_DEBUG "Link reset at upstream Device ID" 401 "[%s] failed\n", 402 udev->dev.bus_id); 403 return PCI_ERS_RESULT_DISCONNECT; 404 } 405 406 return status; 407} 408 409/** 410 * do_recovery - handle nonfatal/fatal error recovery process 411 * @aerdev: pointer to a pcie_device data structure of root port 412 * @dev: pointer to a pci_dev data structure of agent detecting an error 413 * @severity: error severity type 414 * 415 * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast 416 * error detected message to all downstream drivers within a hierarchy in 417 * question and return the returned code. 418 **/ 419static pci_ers_result_t do_recovery(struct pcie_device *aerdev, 420 struct pci_dev *dev, 421 int severity) 422{ 423 pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED; 424 enum pci_channel_state state; 425 426 if (severity == AER_FATAL) 427 state = pci_channel_io_frozen; 428 else 429 state = pci_channel_io_normal; 430 431 status = broadcast_error_message(dev, 432 state, 433 "error_detected", 434 report_error_detected); 435 436 if (severity == AER_FATAL) { 437 result = reset_link(aerdev, dev); 438 if (result != PCI_ERS_RESULT_RECOVERED) { 439 /* TODO: Should panic here? */ 440 return result; 441 } 442 } 443 444 if (status == PCI_ERS_RESULT_CAN_RECOVER) 445 status = broadcast_error_message(dev, 446 state, 447 "mmio_enabled", 448 report_mmio_enabled); 449 450 if (status == PCI_ERS_RESULT_NEED_RESET) { 451 /* 452 * TODO: Should call platform-specific 453 * functions to reset slot before calling 454 * drivers' slot_reset callbacks? 455 */ 456 status = broadcast_error_message(dev, 457 state, 458 "slot_reset", 459 report_slot_reset); 460 } 461 462 if (status == PCI_ERS_RESULT_RECOVERED) 463 broadcast_error_message(dev, 464 state, 465 "resume", 466 report_resume); 467 468 return status; 469} 470 471/** 472 * handle_error_source - handle logging error into an event log 473 * @aerdev: pointer to pcie_device data structure of the root port 474 * @dev: pointer to pci_dev data structure of error source device 475 * @info: comprehensive error information 476 * 477 * Invoked when an error being detected by Root Port. 478 **/ 479static void handle_error_source(struct pcie_device * aerdev, 480 struct pci_dev *dev, 481 struct aer_err_info info) 482{ 483 pci_ers_result_t status = 0; 484 int pos; 485 486 if (info.severity == AER_CORRECTABLE) { 487 /* 488 * Correctable error does not need software intevention. 489 * No need to go through error recovery process. 490 */ 491 pos = pci_find_aer_capability(dev); 492 if (pos) 493 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, 494 info.status); 495 } else { 496 status = do_recovery(aerdev, dev, info.severity); 497 if (status == PCI_ERS_RESULT_RECOVERED) { 498 printk(KERN_DEBUG "AER driver successfully recovered\n"); 499 } else { 500 /* TODO: Should kernel panic here? */ 501 printk(KERN_DEBUG "AER driver didn't recover\n"); 502 } 503 } 504} 505 506/** 507 * aer_enable_rootport - enable Root Port's interrupts when receiving messages 508 * @rpc: pointer to a Root Port data structure 509 * 510 * Invoked when PCIE bus loads AER service driver. 511 **/ 512void aer_enable_rootport(struct aer_rpc *rpc) 513{ 514 struct pci_dev *pdev = rpc->rpd->port; 515 int pos, aer_pos; 516 u16 reg16; 517 u32 reg32; 518 519 pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); 520 /* Clear PCIE Capability's Device Status */ 521 pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, ®16); 522 pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); 523 524 /* Disable system error generation in response to error messages */ 525 pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, ®16); 526 reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK); 527 pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16); 528 529 aer_pos = pci_find_aer_capability(pdev); 530 /* Clear error status */ 531 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); 532 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); 533 pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, ®32); 534 pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32); 535 pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, ®32); 536 pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32); 537 538 /* Enable Root Port device reporting error itself */ 539 pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, ®16); 540 reg16 = reg16 | 541 PCI_EXP_DEVCTL_CERE | 542 PCI_EXP_DEVCTL_NFERE | 543 PCI_EXP_DEVCTL_FERE | 544 PCI_EXP_DEVCTL_URRE; 545 pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL, 546 reg16); 547 548 /* Enable Root Port's interrupt in response to error messages */ 549 pci_write_config_dword(pdev, 550 aer_pos + PCI_ERR_ROOT_COMMAND, 551 ROOT_PORT_INTR_ON_MESG_MASK); 552} 553 554/** 555 * disable_root_aer - disable Root Port's interrupts when receiving messages 556 * @rpc: pointer to a Root Port data structure 557 * 558 * Invoked when PCIE bus unloads AER service driver. 559 **/ 560static void disable_root_aer(struct aer_rpc *rpc) 561{ 562 struct pci_dev *pdev = rpc->rpd->port; 563 u32 reg32; 564 int pos; 565 566 pos = pci_find_aer_capability(pdev); 567 /* Disable Root's interrupt in response to error messages */ 568 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0); 569 570 /* Clear Root's error status reg */ 571 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, ®32); 572 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32); 573} 574 575/** 576 * get_e_source - retrieve an error source 577 * @rpc: pointer to the root port which holds an error 578 * 579 * Invoked by DPC handler to consume an error. 580 **/ 581static struct aer_err_source* get_e_source(struct aer_rpc *rpc) 582{ 583 struct aer_err_source *e_source; 584 unsigned long flags; 585 586 /* Lock access to Root error producer/consumer index */ 587 spin_lock_irqsave(&rpc->e_lock, flags); 588 if (rpc->prod_idx == rpc->cons_idx) { 589 spin_unlock_irqrestore(&rpc->e_lock, flags); 590 return NULL; 591 } 592 e_source = &rpc->e_sources[rpc->cons_idx]; 593 rpc->cons_idx++; 594 if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) 595 rpc->cons_idx = 0; 596 spin_unlock_irqrestore(&rpc->e_lock, flags); 597 598 return e_source; 599} 600 601static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) 602{ 603 int pos; 604 605 pos = pci_find_aer_capability(dev); 606 607 /* The device might not support AER */ 608 if (!pos) 609 return AER_SUCCESS; 610 611 if (info->severity == AER_CORRECTABLE) { 612 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, 613 &info->status); 614 if (!(info->status & ERR_CORRECTABLE_ERROR_MASK)) 615 return AER_UNSUCCESS; 616 } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE || 617 info->severity == AER_NONFATAL) { 618 619 /* Link is still healthy for IO reads */ 620 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, 621 &info->status); 622 if (!(info->status & ERR_UNCORRECTABLE_ERROR_MASK)) 623 return AER_UNSUCCESS; 624 625 if (info->status & AER_LOG_TLP_MASKS) { 626 info->flags |= AER_TLP_HEADER_VALID_FLAG; 627 pci_read_config_dword(dev, 628 pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0); 629 pci_read_config_dword(dev, 630 pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1); 631 pci_read_config_dword(dev, 632 pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2); 633 pci_read_config_dword(dev, 634 pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3); 635 } 636 } 637 638 return AER_SUCCESS; 639} 640 641/** 642 * aer_isr_one_error - consume an error detected by root port 643 * @p_device: pointer to error root port service device 644 * @e_src: pointer to an error source 645 **/ 646static void aer_isr_one_error(struct pcie_device *p_device, 647 struct aer_err_source *e_src) 648{ 649 struct device *s_device; 650 struct aer_err_info e_info = {0, 0, 0,}; 651 int i; 652 u16 id; 653 654 /* 655 * There is a possibility that both correctable error and 656 * uncorrectable error being logged. Report correctable error first. 657 */ 658 for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) { 659 if (i > 4) 660 break; 661 if (!(e_src->status & i)) 662 continue; 663 664 /* Init comprehensive error information */ 665 if (i & PCI_ERR_ROOT_COR_RCV) { 666 id = ERR_COR_ID(e_src->id); 667 e_info.severity = AER_CORRECTABLE; 668 } else { 669 id = ERR_UNCOR_ID(e_src->id); 670 e_info.severity = ((e_src->status >> 6) & 1); 671 } 672 if (e_src->status & 673 (PCI_ERR_ROOT_MULTI_COR_RCV | 674 PCI_ERR_ROOT_MULTI_UNCOR_RCV)) 675 e_info.flags |= AER_MULTI_ERROR_VALID_FLAG; 676 if (!(s_device = find_source_device(p_device->port, id))) { 677 printk(KERN_DEBUG "%s->can't find device of ID%04x\n", 678 __FUNCTION__, id); 679 continue; 680 } 681 if (get_device_error_info(to_pci_dev(s_device), &e_info) == 682 AER_SUCCESS) { 683 aer_print_error(to_pci_dev(s_device), &e_info); 684 handle_error_source(p_device, 685 to_pci_dev(s_device), 686 e_info); 687 } 688 } 689} 690 691/** 692 * aer_isr - consume errors detected by root port 693 * @work: definition of this work item 694 * 695 * Invoked, as DPC, when root port records new detected error 696 **/ 697void aer_isr(struct work_struct *work) 698{ 699 struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); 700 struct pcie_device *p_device = rpc->rpd; 701 struct aer_err_source *e_src; 702 703 mutex_lock(&rpc->rpc_mutex); 704 e_src = get_e_source(rpc); 705 while (e_src) { 706 aer_isr_one_error(p_device, e_src); 707 e_src = get_e_source(rpc); 708 } 709 mutex_unlock(&rpc->rpc_mutex); 710 711 wake_up(&rpc->wait_release); 712} 713 714/** 715 * aer_delete_rootport - disable root port aer and delete service data 716 * @rpc: pointer to a root port device being deleted 717 * 718 * Invoked when AER service unloaded on a specific Root Port 719 **/ 720void aer_delete_rootport(struct aer_rpc *rpc) 721{ 722 /* Disable root port AER itself */ 723 disable_root_aer(rpc); 724 725 kfree(rpc); 726} 727 728/** 729 * aer_init - provide AER initialization 730 * @dev: pointer to AER pcie device 731 * 732 * Invoked when AER service driver is loaded. 733 **/ 734int aer_init(struct pcie_device *dev) 735{ 736 int status; 737 738 /* Run _OSC Method */ 739 status = aer_osc_setup(dev->port); 740 741 if(status != OSC_METHOD_RUN_SUCCESS) { 742 printk(KERN_DEBUG "%s: AER service init fails - %s\n", 743 __FUNCTION__, 744 (status == OSC_METHOD_NOT_SUPPORTED) ? 745 "No ACPI _OSC support" : "Run ACPI _OSC fails"); 746 747 if (!forceload) 748 return status; 749 } 750 751 return AER_SUCCESS; 752} 753 754EXPORT_SYMBOL_GPL(pci_find_aer_capability); 755EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting); 756EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); 757EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); 758