android_kernel_xiaomi_sm8350/drivers/pci/pcie/aer/aerdrv.h
Zhang, Yanmin 3d5505c56d PCI AER: multiple error support
When a root port receives the same errors more than once before the
kernel process them, the Multiple Error Messages Received flags are set
by hardware. Because the root port could only save one kind of
correctable error source id and another uncorrectable error source id at
the same time, the second message sender id is lost if the 2 messages
are sent from 2 different devices. This patch makes the kernel search
all devices under the root port when multiple messages are received.

Reviewed-by: Andrew Patterson <andrew.patterson@hp.com>
Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
2009-06-16 14:30:14 -07:00

140 lines
3.4 KiB
C

/*
* Copyright (C) 2006 Intel Corp.
* Tom Long Nguyen (tom.l.nguyen@intel.com)
* Zhang Yanmin (yanmin.zhang@intel.com)
*
*/
#ifndef _AERDRV_H_
#define _AERDRV_H_
#include <linux/workqueue.h>
#include <linux/pcieport_if.h>
#include <linux/aer.h>
#include <linux/interrupt.h>
#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 SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
PCI_EXP_RTCTL_SENFEE| \
PCI_EXP_RTCTL_SEFEE)
#define ROOT_PORT_INTR_ON_MESG_MASK (PCI_ERR_ROOT_CMD_COR_EN| \
PCI_ERR_ROOT_CMD_NONFATAL_EN| \
PCI_ERR_ROOT_CMD_FATAL_EN)
#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| \
PCI_ERR_UNC_ECRC| \
PCI_ERR_UNC_UNSUP| \
PCI_ERR_UNC_COMP_ABORT| \
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;
unsigned int dw2;
unsigned int dw3;
};
#define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */
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 status; /* COR/UNCOR Error Status */
struct header_log_regs tlp; /* TLP Header */
};
struct aer_err_source {
unsigned int status;
unsigned int id;
};
struct aer_rpc {
struct pcie_device *rpd; /* Root Port device */
struct work_struct dpc_handler;
struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
unsigned short prod_idx; /* Error Producer Index */
unsigned short cons_idx; /* Error Consumer Index */
int isr;
spinlock_t e_lock; /*
* Lock access to Error Status/ID Regs
* and error producer/consumer index
*/
struct mutex rpc_mutex; /*
* only one thread could do
* recovery on the same
* root port hierarchy
*/
wait_queue_head_t wait_release;
};
struct aer_broadcast_data {
enum pci_channel_state state;
enum pci_ers_result result;
};
static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
enum pci_ers_result new)
{
if (new == PCI_ERS_RESULT_NONE)
return orig;
switch (orig) {
case PCI_ERS_RESULT_CAN_RECOVER:
case PCI_ERS_RESULT_RECOVERED:
orig = new;
break;
case PCI_ERS_RESULT_DISCONNECT:
if (new == PCI_ERS_RESULT_NEED_RESET)
orig = new;
break;
default:
break;
}
return orig;
}
extern struct bus_type pcie_port_bus_type;
extern void aer_enable_rootport(struct aer_rpc *rpc);
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 irqreturn_t aer_irq(int irq, void *context);
#ifdef CONFIG_ACPI
extern int aer_osc_setup(struct pcie_device *pciedev);
#else
static inline int aer_osc_setup(struct pcie_device *pciedev)
{
return 0;
}
#endif
#endif //_AERDRV_H_