aerdrv.h 3.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*
 * 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_

A
Alexey Dobriyan 已提交
11
#include <linux/workqueue.h>
12 13
#include <linux/pcieport_if.h>
#include <linux/aer.h>
H
Huang Ying 已提交
14
#include <linux/interrupt.h>
15 16 17 18 19 20 21 22 23

#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 */
24
#define ROOT_ERR_STATUS_MASKS		0x0f
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

#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;
};

Z
Zhang, Yanmin 已提交
60
#define AER_MAX_MULTI_ERR_DEVICES	5	/* Not likely to have more */
61
struct aer_err_info {
Z
Zhang, Yanmin 已提交
62 63
	struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
	int error_dev_num;
64
	u16 id;
65 66 67
	int severity;			/* 0:NONFATAL | 1:FATAL | 2:COR */
	int flags;
	unsigned int status;		/* COR/UNCOR Error Status */
68
	struct header_log_regs tlp;	/* TLP Header */
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
};

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
90
					 * root port hierarchy
91 92 93 94 95 96 97 98 99 100 101 102
					 */
	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)
{
103 104 105
	if (new == PCI_ERS_RESULT_NONE)
		return orig;

106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	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);
126
extern void aer_isr(struct work_struct *work);
127
extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
H
Huang Ying 已提交
128
extern irqreturn_t aer_irq(int irq, void *context);
129 130 131 132 133 134 135 136 137

#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
138

139
#endif /* _AERDRV_H_ */