diff options
Diffstat (limited to 'drivers/pci/pcie/aer')
-rw-r--r-- | drivers/pci/pcie/aer/aer_inject.c | 25 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.c | 22 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.h | 34 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 107 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_errprint.c | 190 |
5 files changed, 181 insertions, 197 deletions
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index d92ae21a59d8..62d15f652bb6 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -22,11 +22,10 @@ #include <linux/miscdevice.h> #include <linux/pci.h> #include <linux/fs.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "aerdrv.h" -struct aer_error_inj -{ +struct aer_error_inj { u8 bus; u8 dev; u8 fn; @@ -38,8 +37,7 @@ struct aer_error_inj u32 header_log3; }; -struct aer_error -{ +struct aer_error { struct list_head list; unsigned int bus; unsigned int devfn; @@ -55,8 +53,7 @@ struct aer_error u32 source_id; }; -struct pci_bus_ops -{ +struct pci_bus_ops { struct list_head list; struct pci_bus *bus; struct pci_ops *ops; @@ -150,7 +147,7 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where, target = &err->header_log1; break; case PCI_ERR_HEADER_LOG+8: - target = &err->header_log2; + target = &err->header_log2; break; case PCI_ERR_HEADER_LOG+12: target = &err->header_log3; @@ -258,8 +255,7 @@ static int pci_bus_set_aer_ops(struct pci_bus *bus) bus_ops = NULL; out: spin_unlock_irqrestore(&inject_lock, flags); - if (bus_ops) - kfree(bus_ops); + kfree(bus_ops); return 0; } @@ -401,10 +397,8 @@ static int aer_inject(struct aer_error_inj *einj) else ret = -EINVAL; out_put: - if (err_alloc) - kfree(err_alloc); - if (rperr_alloc) - kfree(rperr_alloc); + kfree(err_alloc); + kfree(rperr_alloc); pci_dev_put(dev); return ret; } @@ -458,8 +452,7 @@ static void __exit aer_inject_exit(void) } spin_lock_irqsave(&inject_lock, flags); - list_for_each_entry_safe(err, err_next, - &pci_bus_ops_list, list) { + list_for_each_entry_safe(err, err_next, &pci_bus_ops_list, list) { list_del(&err->list); kfree(err); } diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 4770f13b3ca1..10c0e62bd5a8 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -38,7 +38,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -static int __devinit aer_probe (struct pcie_device *dev); +static int __devinit aer_probe(struct pcie_device *dev); static void aer_remove(struct pcie_device *dev); static pci_ers_result_t aer_error_detected(struct pci_dev *dev, enum pci_channel_state error); @@ -47,7 +47,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev); static struct pci_error_handlers aer_error_handlers = { .error_detected = aer_error_detected, - .resume = aer_error_resume, + .resume = aer_error_resume, }; static struct pcie_port_service_driver aerdriver = { @@ -134,12 +134,12 @@ EXPORT_SYMBOL_GPL(aer_irq); * * Invoked when Root Port's AER service is loaded. **/ -static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev) +static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) { struct aer_rpc *rpc; - if (!(rpc = kzalloc(sizeof(struct aer_rpc), - GFP_KERNEL))) + rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL); + if (!rpc) return NULL; /* @@ -189,26 +189,28 @@ static void aer_remove(struct pcie_device *dev) * * Invoked when PCI Express bus loads AER service driver. **/ -static int __devinit aer_probe (struct pcie_device *dev) +static int __devinit aer_probe(struct pcie_device *dev) { int status; struct aer_rpc *rpc; struct device *device = &dev->device; /* Init */ - if ((status = aer_init(dev))) + status = aer_init(dev); + if (status) return status; /* Alloc rpc data structure */ - if (!(rpc = aer_alloc_rpc(dev))) { + rpc = aer_alloc_rpc(dev); + if (!rpc) { dev_printk(KERN_DEBUG, device, "alloc rpc failed\n"); aer_remove(dev); return -ENOMEM; } /* Request IRQ ISR */ - if ((status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", - dev))) { + status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev); + if (status) { dev_printk(KERN_DEBUG, device, "request IRQ failed\n"); aer_remove(dev); return status; diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index bbd7428ca2d0..bd833ea3ba49 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -16,12 +16,9 @@ #define AER_NONFATAL 0 #define AER_FATAL 1 #define AER_CORRECTABLE 2 -#define AER_UNCORRECTABLE 4 -#define AER_ERROR_MASK 0x001fffff -#define AER_ERROR(d) (d & AER_ERROR_MASK) /* Root Error Status Register Bits */ -#define ROOT_ERR_STATUS_MASKS 0x0f +#define ROOT_ERR_STATUS_MASKS 0x0f #define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \ PCI_EXP_RTCTL_SENFEE| \ @@ -32,8 +29,6 @@ #define ERR_COR_ID(d) (d & 0xffff) #define ERR_UNCOR_ID(d) (d >> 16) -#define AER_SUCCESS 0 -#define AER_UNSUCCESS 1 #define AER_ERROR_SOURCES_MAX 100 #define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \ @@ -43,13 +38,6 @@ PCI_ERR_UNC_UNX_COMP| \ PCI_ERR_UNC_MALF_TLP) -/* AER Error Info Flags */ -#define AER_TLP_HEADER_VALID_FLAG 0x00000001 -#define AER_MULTI_ERROR_VALID_FLAG 0x00000002 - -#define ERR_CORRECTABLE_ERROR_MASK 0x000031c1 -#define ERR_UNCORRECTABLE_ERROR_MASK 0x001ff010 - struct header_log_regs { unsigned int dw0; unsigned int dw1; @@ -61,11 +49,20 @@ struct header_log_regs { struct aer_err_info { struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES]; int error_dev_num; - u16 id; - int severity; /* 0:NONFATAL | 1:FATAL | 2:COR */ - int flags; + + unsigned int id:16; + + unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */ + unsigned int __pad1:5; + unsigned int multi_error_valid:1; + + unsigned int first_error:5; + unsigned int __pad2:2; + unsigned int tlp_header_valid:1; + unsigned int status; /* COR/UNCOR Error Status */ - struct header_log_regs tlp; /* TLP Header */ + unsigned int mask; /* COR/UNCOR Error Mask */ + struct header_log_regs tlp; /* TLP Header */ }; struct aer_err_source { @@ -125,6 +122,7 @@ extern void aer_delete_rootport(struct aer_rpc *rpc); extern int aer_init(struct pcie_device *dev); extern void aer_isr(struct work_struct *work); extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); +extern void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); extern irqreturn_t aer_irq(int irq, void *context); #ifdef CONFIG_ACPI @@ -136,4 +134,4 @@ static inline int aer_osc_setup(struct pcie_device *pciedev) } #endif -#endif //_AERDRV_H_ +#endif /* _AERDRV_H_ */ diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 3d8872704a58..9f5ccbeb4fa5 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -49,10 +49,11 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE; - pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, - reg16); + pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, reg16); + return 0; } +EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting); int pci_disable_pcie_error_reporting(struct pci_dev *dev) { @@ -68,10 +69,11 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev) PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); - pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, - reg16); + pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, reg16); + return 0; } +EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) { @@ -92,6 +94,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) return 0; } +EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); #if 0 int pci_cleanup_aer_correct_error_status(struct pci_dev *dev) @@ -110,7 +113,6 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev) } #endif /* 0 */ - static int set_device_error_reporting(struct pci_dev *dev, void *data) { bool enable = *((bool *)data); @@ -164,8 +166,9 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev) e_info->dev[e_info->error_dev_num] = dev; e_info->error_dev_num++; return 1; - } else - return 0; + } + + return 0; } @@ -193,7 +196,7 @@ static int find_device_iter(struct pci_dev *dev, void *data) * If there is no multiple error, we stop * or continue based on the id comparing. */ - if (!(e_info->flags & AER_MULTI_ERROR_VALID_FLAG)) + if (!e_info->multi_error_valid) return result; /* @@ -233,24 +236,16 @@ static int find_device_iter(struct pci_dev *dev, void *data) status = 0; mask = 0; if (e_info->severity == AER_CORRECTABLE) { - pci_read_config_dword(dev, - pos + PCI_ERR_COR_STATUS, - &status); - pci_read_config_dword(dev, - pos + PCI_ERR_COR_MASK, - &mask); - if (status & ERR_CORRECTABLE_ERROR_MASK & ~mask) { + pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); + pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask); + if (status & ~mask) { add_error_device(e_info, dev); goto added; } } else { - pci_read_config_dword(dev, - pos + PCI_ERR_UNCOR_STATUS, - &status); - pci_read_config_dword(dev, - pos + PCI_ERR_UNCOR_MASK, - &mask); - if (status & ERR_UNCORRECTABLE_ERROR_MASK & ~mask) { + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask); + if (status & ~mask) { add_error_device(e_info, dev); goto added; } @@ -259,7 +254,7 @@ static int find_device_iter(struct pci_dev *dev, void *data) return 0; added: - if (e_info->flags & AER_MULTI_ERROR_VALID_FLAG) + if (e_info->multi_error_valid) return 0; else return 1; @@ -411,8 +406,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, pci_cleanup_aer_uncorrect_error_status(dev); dev->error_state = pci_channel_io_normal; } - } - else { + } else { /* * If the error is reported by an end point, we think this * error is related to the upstream link of the end point. @@ -473,7 +467,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev, if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) udev = dev; else - udev= dev->bus->self; + udev = dev->bus->self; data.is_downstream = 0; data.aer_driver = NULL; @@ -576,7 +570,7 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev, * * Invoked when an error being detected by Root Port. */ -static void handle_error_source(struct pcie_device * aerdev, +static void handle_error_source(struct pcie_device *aerdev, struct pci_dev *dev, struct aer_err_info *info) { @@ -682,7 +676,7 @@ static void disable_root_aer(struct aer_rpc *rpc) * * Invoked by DPC handler to consume an error. */ -static struct aer_err_source* get_e_source(struct aer_rpc *rpc) +static struct aer_err_source *get_e_source(struct aer_rpc *rpc) { struct aer_err_source *e_source; unsigned long flags; @@ -702,32 +696,50 @@ static struct aer_err_source* get_e_source(struct aer_rpc *rpc) return e_source; } +/** + * get_device_error_info - read error status from dev and store it to info + * @dev: pointer to the device expected to have a error record + * @info: pointer to structure to store the error record + * + * Return 1 on success, 0 on error. + */ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) { - int pos; + int pos, temp; + + info->status = 0; + info->tlp_header_valid = 0; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); /* The device might not support AER */ if (!pos) - return AER_SUCCESS; + return 1; if (info->severity == AER_CORRECTABLE) { pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &info->status); - if (!(info->status & ERR_CORRECTABLE_ERROR_MASK)) - return AER_UNSUCCESS; + pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, + &info->mask); + if (!(info->status & ~info->mask)) + return 0; } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE || info->severity == AER_NONFATAL) { /* Link is still healthy for IO reads */ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &info->status); - if (!(info->status & ERR_UNCORRECTABLE_ERROR_MASK)) - return AER_UNSUCCESS; + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, + &info->mask); + if (!(info->status & ~info->mask)) + return 0; + + /* Get First Error Pointer */ + pci_read_config_dword(dev, pos + PCI_ERR_CAP, &temp); + info->first_error = PCI_ERR_CAP_FEP(temp); if (info->status & AER_LOG_TLP_MASKS) { - info->flags |= AER_TLP_HEADER_VALID_FLAG; + info->tlp_header_valid = 1; pci_read_config_dword(dev, pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0); pci_read_config_dword(dev, @@ -739,7 +751,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) } } - return AER_SUCCESS; + return 1; } static inline void aer_process_err_devices(struct pcie_device *p_device, @@ -753,14 +765,14 @@ static inline void aer_process_err_devices(struct pcie_device *p_device, e_info->id); } + /* Report all before handle them, not to lost records by reset etc. */ for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { - if (get_device_error_info(e_info->dev[i], e_info) == - AER_SUCCESS) { + if (get_device_error_info(e_info->dev[i], e_info)) aer_print_error(e_info->dev[i], e_info); - handle_error_source(p_device, - e_info->dev[i], - e_info); - } + } + for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { + if (get_device_error_info(e_info->dev[i], e_info)) + handle_error_source(p_device, e_info->dev[i], e_info); } } @@ -806,7 +818,9 @@ static void aer_isr_one_error(struct pcie_device *p_device, if (e_src->status & (PCI_ERR_ROOT_MULTI_COR_RCV | PCI_ERR_ROOT_MULTI_UNCOR_RCV)) - e_info->flags |= AER_MULTI_ERROR_VALID_FLAG; + e_info->multi_error_valid = 1; + + aer_print_port_info(p_device->port, e_info); find_source_device(p_device->port, e_info); aer_process_err_devices(p_device, e_info); @@ -863,10 +877,5 @@ int aer_init(struct pcie_device *dev) if (aer_osc_setup(dev) && !forceload) return -ENXIO; - return AER_SUCCESS; + return 0; } - -EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting); -EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); -EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); - diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 0fc29ae80df8..44acde72294f 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -27,69 +27,70 @@ #define AER_AGENT_COMPLETER 2 #define AER_AGENT_TRANSMITTER 3 -#define AER_AGENT_REQUESTER_MASK (PCI_ERR_UNC_COMP_TIME| \ - PCI_ERR_UNC_UNSUP) - -#define AER_AGENT_COMPLETER_MASK PCI_ERR_UNC_COMP_ABORT - -#define AER_AGENT_TRANSMITTER_MASK(t, e) (e & (PCI_ERR_COR_REP_ROLL| \ - ((t == AER_CORRECTABLE) ? PCI_ERR_COR_REP_TIMER: 0))) +#define AER_AGENT_REQUESTER_MASK(t) ((t == AER_CORRECTABLE) ? \ + 0 : (PCI_ERR_UNC_COMP_TIME|PCI_ERR_UNC_UNSUP)) +#define AER_AGENT_COMPLETER_MASK(t) ((t == AER_CORRECTABLE) ? \ + 0 : PCI_ERR_UNC_COMP_ABORT) +#define AER_AGENT_TRANSMITTER_MASK(t) ((t == AER_CORRECTABLE) ? \ + (PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : 0) #define AER_GET_AGENT(t, e) \ - ((e & AER_AGENT_COMPLETER_MASK) ? AER_AGENT_COMPLETER : \ - (e & AER_AGENT_REQUESTER_MASK) ? AER_AGENT_REQUESTER : \ - (AER_AGENT_TRANSMITTER_MASK(t, e)) ? AER_AGENT_TRANSMITTER : \ + ((e & AER_AGENT_COMPLETER_MASK(t)) ? AER_AGENT_COMPLETER : \ + (e & AER_AGENT_REQUESTER_MASK(t)) ? AER_AGENT_REQUESTER : \ + (e & AER_AGENT_TRANSMITTER_MASK(t)) ? AER_AGENT_TRANSMITTER : \ AER_AGENT_RECEIVER) -#define AER_PHYSICAL_LAYER_ERROR_MASK PCI_ERR_COR_RCVR -#define AER_DATA_LINK_LAYER_ERROR_MASK(t, e) \ - (PCI_ERR_UNC_DLP| \ - PCI_ERR_COR_BAD_TLP| \ - PCI_ERR_COR_BAD_DLLP| \ - PCI_ERR_COR_REP_ROLL| \ - ((t == AER_CORRECTABLE) ? \ - PCI_ERR_COR_REP_TIMER: 0)) - #define AER_PHYSICAL_LAYER_ERROR 0 #define AER_DATA_LINK_LAYER_ERROR 1 #define AER_TRANSACTION_LAYER_ERROR 2 -#define AER_GET_LAYER_ERROR(t, e) \ - ((e & AER_PHYSICAL_LAYER_ERROR_MASK) ? \ - AER_PHYSICAL_LAYER_ERROR : \ - (e & AER_DATA_LINK_LAYER_ERROR_MASK(t, e)) ? \ - AER_DATA_LINK_LAYER_ERROR : \ - AER_TRANSACTION_LAYER_ERROR) +#define AER_PHYSICAL_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \ + PCI_ERR_COR_RCVR : 0) +#define AER_DATA_LINK_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \ + (PCI_ERR_COR_BAD_TLP| \ + PCI_ERR_COR_BAD_DLLP| \ + PCI_ERR_COR_REP_ROLL| \ + PCI_ERR_COR_REP_TIMER) : PCI_ERR_UNC_DLP) + +#define AER_GET_LAYER_ERROR(t, e) \ + ((e & AER_PHYSICAL_LAYER_ERROR_MASK(t)) ? AER_PHYSICAL_LAYER_ERROR : \ + (e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \ + AER_TRANSACTION_LAYER_ERROR) + +#define AER_PR(info, pdev, fmt, args...) \ + printk("%s%s %s: " fmt, (info->severity == AER_CORRECTABLE) ? \ + KERN_WARNING : KERN_ERR, dev_driver_string(&pdev->dev), \ + dev_name(&pdev->dev), ## args) /* * AER error strings */ -static char* aer_error_severity_string[] = { +static char *aer_error_severity_string[] = { "Uncorrected (Non-Fatal)", "Uncorrected (Fatal)", "Corrected" }; -static char* aer_error_layer[] = { +static char *aer_error_layer[] = { "Physical Layer", "Data Link Layer", "Transaction Layer" }; -static char* aer_correctable_error_string[] = { - "Receiver Error ", /* Bit Position 0 */ +static char *aer_correctable_error_string[] = { + "Receiver Error ", /* Bit Position 0 */ NULL, NULL, NULL, NULL, NULL, - "Bad TLP ", /* Bit Position 6 */ - "Bad DLLP ", /* Bit Position 7 */ - "RELAY_NUM Rollover ", /* Bit Position 8 */ + "Bad TLP ", /* Bit Position 6 */ + "Bad DLLP ", /* Bit Position 7 */ + "RELAY_NUM Rollover ", /* Bit Position 8 */ NULL, NULL, NULL, - "Replay Timer Timeout ", /* Bit Position 12 */ - "Advisory Non-Fatal ", /* Bit Position 13 */ + "Replay Timer Timeout ", /* Bit Position 12 */ + "Advisory Non-Fatal ", /* Bit Position 13 */ NULL, NULL, NULL, @@ -110,7 +111,7 @@ static char* aer_correctable_error_string[] = { NULL, }; -static char* aer_uncorrectable_error_string[] = { +static char *aer_uncorrectable_error_string[] = { NULL, NULL, NULL, @@ -123,10 +124,10 @@ static char* aer_uncorrectable_error_string[] = { NULL, NULL, NULL, - "Poisoned TLP ", /* Bit Position 12 */ + "Poisoned TLP ", /* Bit Position 12 */ "Flow Control Protocol ", /* Bit Position 13 */ - "Completion Timeout ", /* Bit Position 14 */ - "Completer Abort ", /* Bit Position 15 */ + "Completion Timeout ", /* Bit Position 14 */ + "Completer Abort ", /* Bit Position 15 */ "Unexpected Completion ", /* Bit Position 16 */ "Receiver Overflow ", /* Bit Position 17 */ "Malformed TLP ", /* Bit Position 18 */ @@ -145,98 +146,69 @@ static char* aer_uncorrectable_error_string[] = { NULL, }; -static char* aer_agent_string[] = { +static char *aer_agent_string[] = { "Receiver ID", "Requester ID", "Completer ID", "Transmitter ID" }; -static char * aer_get_error_source_name(int severity, - unsigned int status, - char errmsg_buff[]) +static void __aer_print_error(struct aer_err_info *info, struct pci_dev *dev) { - int i; - char * errmsg = NULL; + int i, status; + char *errmsg = NULL; + + status = (info->status & ~info->mask); for (i = 0; i < 32; i++) { if (!(status & (1 << i))) continue; - if (severity == AER_CORRECTABLE) + if (info->severity == AER_CORRECTABLE) errmsg = aer_correctable_error_string[i]; else errmsg = aer_uncorrectable_error_string[i]; - if (!errmsg) { - sprintf(errmsg_buff, "Unknown Error Bit %2d ", i); - errmsg = errmsg_buff; - } - - break; + if (errmsg) + AER_PR(info, dev, " [%2d] %s%s\n", i, errmsg, + info->first_error == i ? " (First)" : ""); + else + AER_PR(info, dev, " [%2d] Unknown Error Bit%s\n", i, + info->first_error == i ? " (First)" : ""); } - - return errmsg; } -static DEFINE_SPINLOCK(logbuf_lock); -static char errmsg_buff[100]; void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) { - char * errmsg; - int err_layer, agent; - char * loglevel; - - if (info->severity == AER_CORRECTABLE) - loglevel = KERN_WARNING; - else - loglevel = KERN_ERR; - - printk("%s+------ PCI-Express Device Error ------+\n", loglevel); - printk("%sError Severity\t\t: %s\n", loglevel, - aer_error_severity_string[info->severity]); - - if ( info->status == 0) { - printk("%sPCIE Bus Error type\t: (Unaccessible)\n", loglevel); - printk("%sUnaccessible Received\t: %s\n", loglevel, - info->flags & AER_MULTI_ERROR_VALID_FLAG ? - "Multiple" : "First"); - printk("%sUnregistered Agent ID\t: %04x\n", loglevel, - (dev->bus->number << 8) | dev->devfn); + int id = ((dev->bus->number << 8) | dev->devfn); + + if (info->status == 0) { + AER_PR(info, dev, + "PCIE Bus Error: severity=%s, type=Unaccessible, " + "id=%04x(Unregistered Agent ID)\n", + aer_error_severity_string[info->severity], id); } else { - err_layer = AER_GET_LAYER_ERROR(info->severity, info->status); - printk("%sPCIE Bus Error type\t: %s\n", loglevel, - aer_error_layer[err_layer]); - - spin_lock(&logbuf_lock); - errmsg = aer_get_error_source_name(info->severity, - info->status, - errmsg_buff); - printk("%s%s\t: %s\n", loglevel, errmsg, - info->flags & AER_MULTI_ERROR_VALID_FLAG ? - "Multiple" : "First"); - spin_unlock(&logbuf_lock); + int layer, agent; + layer = AER_GET_LAYER_ERROR(info->severity, info->status); agent = AER_GET_AGENT(info->severity, info->status); - printk("%s%s\t\t: %04x\n", loglevel, - aer_agent_string[agent], - (dev->bus->number << 8) | dev->devfn); - - printk("%sVendorID=%04xh, DeviceID=%04xh," - " Bus=%02xh, Device=%02xh, Function=%02xh\n", - loglevel, - dev->vendor, - dev->device, - dev->bus->number, - PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - - if (info->flags & AER_TLP_HEADER_VALID_FLAG) { + + AER_PR(info, dev, + "PCIE Bus Error: severity=%s, type=%s, id=%04x(%s)\n", + aer_error_severity_string[info->severity], + aer_error_layer[layer], id, aer_agent_string[agent]); + + AER_PR(info, dev, + " device [%04x:%04x] error status/mask=%08x/%08x\n", + dev->vendor, dev->device, info->status, info->mask); + + __aer_print_error(info, dev); + + if (info->tlp_header_valid) { unsigned char *tlp = (unsigned char *) &info->tlp; - printk("%sTLP Header:\n", loglevel); - printk("%s%02x%02x%02x%02x %02x%02x%02x%02x" + AER_PR(info, dev, " TLP Header:" + " %02x%02x%02x%02x %02x%02x%02x%02x" " %02x%02x%02x%02x %02x%02x%02x%02x\n", - loglevel, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), *(tlp + 11), *(tlp + 10), *(tlp + 9), @@ -244,5 +216,15 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) *(tlp + 13), *(tlp + 12)); } } + + if (info->id && info->error_dev_num > 1 && info->id == id) + AER_PR(info, dev, + " Error of this Agent(%04x) is reported first\n", id); } +void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) +{ + dev_info(&dev->dev, "AER: %s%s error received: id=%04x\n", + info->multi_error_valid ? "Multiple " : "", + aer_error_severity_string[info->severity], info->id); +} |