| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2006 Intel Corp. | 
 | 3 |  *	Tom Long Nguyen (tom.l.nguyen@intel.com) | 
 | 4 |  *	Zhang Yanmin (yanmin.zhang@intel.com) | 
 | 5 |  * | 
 | 6 |  */ | 
 | 7 |  | 
 | 8 | #ifndef _AERDRV_H_ | 
 | 9 | #define _AERDRV_H_ | 
 | 10 |  | 
| Alexey Dobriyan | e8edc6e | 2007-05-21 01:22:52 +0400 | [diff] [blame] | 11 | #include <linux/workqueue.h> | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 12 | #include <linux/pcieport_if.h> | 
 | 13 | #include <linux/aer.h> | 
| Huang Ying | 634deb0 | 2009-04-24 10:45:23 +0800 | [diff] [blame] | 14 | #include <linux/interrupt.h> | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 15 |  | 
 | 16 | #define AER_NONFATAL			0 | 
 | 17 | #define AER_FATAL			1 | 
 | 18 | #define AER_CORRECTABLE			2 | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 19 |  | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 20 | #define SYSTEM_ERROR_INTR_ON_MESG_MASK	(PCI_EXP_RTCTL_SECEE|	\ | 
 | 21 | 					PCI_EXP_RTCTL_SENFEE|	\ | 
 | 22 | 					PCI_EXP_RTCTL_SEFEE) | 
 | 23 | #define ROOT_PORT_INTR_ON_MESG_MASK	(PCI_ERR_ROOT_CMD_COR_EN|	\ | 
 | 24 | 					PCI_ERR_ROOT_CMD_NONFATAL_EN|	\ | 
 | 25 | 					PCI_ERR_ROOT_CMD_FATAL_EN) | 
 | 26 | #define ERR_COR_ID(d)			(d & 0xffff) | 
 | 27 | #define ERR_UNCOR_ID(d)			(d >> 16) | 
 | 28 |  | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 29 | #define AER_ERROR_SOURCES_MAX		100 | 
 | 30 |  | 
 | 31 | #define AER_LOG_TLP_MASKS		(PCI_ERR_UNC_POISON_TLP|	\ | 
 | 32 | 					PCI_ERR_UNC_ECRC|		\ | 
 | 33 | 					PCI_ERR_UNC_UNSUP|		\ | 
 | 34 | 					PCI_ERR_UNC_COMP_ABORT|		\ | 
 | 35 | 					PCI_ERR_UNC_UNX_COMP|		\ | 
 | 36 | 					PCI_ERR_UNC_MALF_TLP) | 
 | 37 |  | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 38 | struct header_log_regs { | 
 | 39 | 	unsigned int dw0; | 
 | 40 | 	unsigned int dw1; | 
 | 41 | 	unsigned int dw2; | 
 | 42 | 	unsigned int dw3; | 
 | 43 | }; | 
 | 44 |  | 
| Zhang, Yanmin | 3d5505c | 2009-06-16 13:35:16 +0800 | [diff] [blame] | 45 | #define AER_MAX_MULTI_ERR_DEVICES	5	/* Not likely to have more */ | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 46 | struct aer_err_info { | 
| Zhang, Yanmin | 3d5505c | 2009-06-16 13:35:16 +0800 | [diff] [blame] | 47 | 	struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES]; | 
 | 48 | 	int error_dev_num; | 
| Hidetoshi Seto | 273024d | 2009-09-07 17:16:20 +0900 | [diff] [blame] | 49 |  | 
 | 50 | 	unsigned int id:16; | 
 | 51 |  | 
 | 52 | 	unsigned int severity:2;	/* 0:NONFATAL | 1:FATAL | 2:COR */ | 
 | 53 | 	unsigned int __pad1:5; | 
 | 54 | 	unsigned int multi_error_valid:1; | 
 | 55 |  | 
 | 56 | 	unsigned int first_error:5; | 
 | 57 | 	unsigned int __pad2:2; | 
 | 58 | 	unsigned int tlp_header_valid:1; | 
 | 59 |  | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 60 | 	unsigned int status;		/* COR/UNCOR Error Status */ | 
| Hidetoshi Seto | 0d90c3a | 2009-09-07 17:12:25 +0900 | [diff] [blame] | 61 | 	unsigned int mask;		/* COR/UNCOR Error Mask */ | 
| Hidetoshi Seto | c9a9188 | 2009-09-07 17:07:29 +0900 | [diff] [blame] | 62 | 	struct header_log_regs tlp;	/* TLP Header */ | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 63 | }; | 
 | 64 |  | 
 | 65 | struct aer_err_source { | 
 | 66 | 	unsigned int status; | 
 | 67 | 	unsigned int id; | 
 | 68 | }; | 
 | 69 |  | 
 | 70 | struct aer_rpc { | 
 | 71 | 	struct pcie_device *rpd;	/* Root Port device */ | 
 | 72 | 	struct work_struct dpc_handler; | 
 | 73 | 	struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX]; | 
 | 74 | 	unsigned short prod_idx;	/* Error Producer Index */ | 
 | 75 | 	unsigned short cons_idx;	/* Error Consumer Index */ | 
 | 76 | 	int isr; | 
 | 77 | 	spinlock_t e_lock;		/* | 
 | 78 | 					 * Lock access to Error Status/ID Regs | 
 | 79 | 					 * and error producer/consumer index | 
 | 80 | 					 */ | 
 | 81 | 	struct mutex rpc_mutex;		/* | 
 | 82 | 					 * only one thread could do | 
 | 83 | 					 * recovery on the same | 
| Uwe Kleine-König | 1b3c371 | 2007-02-17 19:23:03 +0100 | [diff] [blame] | 84 | 					 * root port hierarchy | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 85 | 					 */ | 
 | 86 | 	wait_queue_head_t wait_release; | 
 | 87 | }; | 
 | 88 |  | 
 | 89 | struct aer_broadcast_data { | 
 | 90 | 	enum pci_channel_state state; | 
 | 91 | 	enum pci_ers_result result; | 
 | 92 | }; | 
 | 93 |  | 
 | 94 | static inline pci_ers_result_t merge_result(enum pci_ers_result orig, | 
 | 95 | 		enum pci_ers_result new) | 
 | 96 | { | 
| Zhang, Yanmin | 029091d | 2009-04-30 14:48:29 +0800 | [diff] [blame] | 97 | 	if (new == PCI_ERS_RESULT_NONE) | 
 | 98 | 		return orig; | 
 | 99 |  | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 100 | 	switch (orig) { | 
 | 101 | 	case PCI_ERS_RESULT_CAN_RECOVER: | 
 | 102 | 	case PCI_ERS_RESULT_RECOVERED: | 
 | 103 | 		orig = new; | 
 | 104 | 		break; | 
 | 105 | 	case PCI_ERS_RESULT_DISCONNECT: | 
 | 106 | 		if (new == PCI_ERS_RESULT_NEED_RESET) | 
 | 107 | 			orig = new; | 
 | 108 | 		break; | 
 | 109 | 	default: | 
 | 110 | 		break; | 
 | 111 | 	} | 
 | 112 |  | 
 | 113 | 	return orig; | 
 | 114 | } | 
 | 115 |  | 
 | 116 | extern struct bus_type pcie_port_bus_type; | 
| Hidetoshi Seto | 8971342 | 2010-04-15 13:21:27 +0900 | [diff] [blame] | 117 | extern void aer_do_secondary_bus_reset(struct pci_dev *dev); | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 118 | extern int aer_init(struct pcie_device *dev); | 
| David Howells | 65f27f3 | 2006-11-22 14:55:48 +0000 | [diff] [blame] | 119 | extern void aer_isr(struct work_struct *work); | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 120 | extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); | 
| Hidetoshi Seto | 79e4b89 | 2009-09-07 17:16:45 +0900 | [diff] [blame] | 121 | extern void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); | 
| Huang Ying | 634deb0 | 2009-04-24 10:45:23 +0800 | [diff] [blame] | 122 | extern irqreturn_t aer_irq(int irq, void *context); | 
| Zhang, Yanmin | 8d29bfb | 2007-06-06 11:44:16 +0800 | [diff] [blame] | 123 |  | 
 | 124 | #ifdef CONFIG_ACPI | 
 | 125 | extern int aer_osc_setup(struct pcie_device *pciedev); | 
 | 126 | #else | 
 | 127 | static inline int aer_osc_setup(struct pcie_device *pciedev) | 
 | 128 | { | 
 | 129 | 	return 0; | 
 | 130 | } | 
 | 131 | #endif | 
| Zhang, Yanmin | 6c2b374 | 2006-07-31 15:21:33 +0800 | [diff] [blame] | 132 |  | 
| Huang Ying | affb72c | 2010-05-18 14:35:16 +0800 | [diff] [blame] | 133 | #ifdef CONFIG_ACPI_APEI | 
 | 134 | extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); | 
 | 135 | #else | 
 | 136 | static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) | 
 | 137 | { | 
 | 138 | 	if (pci_dev->__aer_firmware_first_valid) | 
 | 139 | 		return pci_dev->__aer_firmware_first; | 
 | 140 | 	return 0; | 
 | 141 | } | 
 | 142 | #endif | 
 | 143 |  | 
 | 144 | static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, | 
 | 145 | 						 int enable) | 
 | 146 | { | 
 | 147 | 	pci_dev->__aer_firmware_first = !!enable; | 
 | 148 | 	pci_dev->__aer_firmware_first_valid = 1; | 
 | 149 | } | 
| Hidetoshi Seto | c9a9188 | 2009-09-07 17:07:29 +0900 | [diff] [blame] | 150 | #endif /* _AERDRV_H_ */ |