1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#ifndef _POWERPC_EEH_H
21#define _POWERPC_EEH_H
22#ifdef __KERNEL__
23
24#include <linux/init.h>
25#include <linux/list.h>
26#include <linux/string.h>
27#include <linux/time.h>
28
29struct pci_dev;
30struct pci_bus;
31struct device_node;
32
33#ifdef CONFIG_EEH
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49#define EEH_PE_INVALID (1 << 0)
50#define EEH_PE_PHB (1 << 1)
51#define EEH_PE_DEVICE (1 << 2)
52#define EEH_PE_BUS (1 << 3)
53
54#define EEH_PE_ISOLATED (1 << 0)
55#define EEH_PE_RECOVERING (1 << 1)
56#define EEH_PE_PHB_DEAD (1 << 2)
57
58#define EEH_PE_KEEP (1 << 8)
59
60struct eeh_pe {
61 int type;
62 int state;
63 int config_addr;
64 int addr;
65 struct pci_controller *phb;
66 struct pci_bus *bus;
67 int check_count;
68 int freeze_count;
69 struct timeval tstamp;
70 int false_positives;
71 struct eeh_pe *parent;
72 struct list_head child_list;
73 struct list_head edevs;
74 struct list_head child;
75};
76
77#define eeh_pe_for_each_dev(pe, edev, tmp) \
78 list_for_each_entry_safe(edev, tmp, &pe->edevs, list)
79
80
81
82
83
84
85
86
87#define EEH_DEV_BRIDGE (1 << 0)
88#define EEH_DEV_ROOT_PORT (1 << 1)
89#define EEH_DEV_DS_PORT (1 << 2)
90#define EEH_DEV_IRQ_DISABLED (1 << 3)
91#define EEH_DEV_DISCONNECTED (1 << 4)
92
93#define EEH_DEV_SYSFS (1 << 8)
94
95struct eeh_dev {
96 int mode;
97 int class_code;
98 int config_addr;
99 int pe_config_addr;
100 u32 config_space[16];
101 u8 pcie_cap;
102 struct eeh_pe *pe;
103 struct list_head list;
104 struct pci_controller *phb;
105 struct device_node *dn;
106 struct pci_dev *pdev;
107 struct pci_bus *bus;
108};
109
110static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev)
111{
112 return edev ? edev->dn : NULL;
113}
114
115static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
116{
117 return edev ? edev->pdev : NULL;
118}
119
120
121
122
123
124
125
126
127#define EEH_OPT_DISABLE 0
128#define EEH_OPT_ENABLE 1
129#define EEH_OPT_THAW_MMIO 2
130#define EEH_OPT_THAW_DMA 3
131#define EEH_STATE_UNAVAILABLE (1 << 0)
132#define EEH_STATE_NOT_SUPPORT (1 << 1)
133#define EEH_STATE_RESET_ACTIVE (1 << 2)
134#define EEH_STATE_MMIO_ACTIVE (1 << 3)
135#define EEH_STATE_DMA_ACTIVE (1 << 4)
136#define EEH_STATE_MMIO_ENABLED (1 << 5)
137#define EEH_STATE_DMA_ENABLED (1 << 6)
138#define EEH_RESET_DEACTIVATE 0
139#define EEH_RESET_HOT 1
140#define EEH_RESET_FUNDAMENTAL 3
141#define EEH_LOG_TEMP 1
142#define EEH_LOG_PERM 2
143
144struct eeh_ops {
145 char *name;
146 int (*init)(void);
147 int (*post_init)(void);
148 void* (*of_probe)(struct device_node *dn, void *flag);
149 int (*dev_probe)(struct pci_dev *dev, void *flag);
150 int (*set_option)(struct eeh_pe *pe, int option);
151 int (*get_pe_addr)(struct eeh_pe *pe);
152 int (*get_state)(struct eeh_pe *pe, int *state);
153 int (*reset)(struct eeh_pe *pe, int option);
154 int (*wait_state)(struct eeh_pe *pe, int max_wait);
155 int (*get_log)(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len);
156 int (*configure_bridge)(struct eeh_pe *pe);
157 int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
158 int (*write_config)(struct device_node *dn, int where, int size, u32 val);
159 int (*next_error)(struct eeh_pe **pe);
160};
161
162extern struct eeh_ops *eeh_ops;
163extern int eeh_subsystem_enabled;
164extern raw_spinlock_t confirm_error_lock;
165extern int eeh_probe_mode;
166
167#define EEH_PROBE_MODE_DEV (1<<0)
168#define EEH_PROBE_MODE_DEVTREE (1<<1)
169
170static inline void eeh_probe_mode_set(int flag)
171{
172 eeh_probe_mode = flag;
173}
174
175static inline int eeh_probe_mode_devtree(void)
176{
177 return (eeh_probe_mode == EEH_PROBE_MODE_DEVTREE);
178}
179
180static inline int eeh_probe_mode_dev(void)
181{
182 return (eeh_probe_mode == EEH_PROBE_MODE_DEV);
183}
184
185static inline void eeh_serialize_lock(unsigned long *flags)
186{
187 raw_spin_lock_irqsave(&confirm_error_lock, *flags);
188}
189
190static inline void eeh_serialize_unlock(unsigned long flags)
191{
192 raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
193}
194
195
196
197
198
199#define EEH_MAX_ALLOWED_FREEZES 5
200
201typedef void *(*eeh_traverse_func)(void *data, void *flag);
202int eeh_phb_pe_create(struct pci_controller *phb);
203struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb);
204struct eeh_pe *eeh_pe_get(struct eeh_dev *edev);
205int eeh_add_to_parent_pe(struct eeh_dev *edev);
206int eeh_rmv_from_parent_pe(struct eeh_dev *edev);
207void eeh_pe_update_time_stamp(struct eeh_pe *pe);
208void *eeh_pe_traverse(struct eeh_pe *root,
209 eeh_traverse_func fn, void *flag);
210void *eeh_pe_dev_traverse(struct eeh_pe *root,
211 eeh_traverse_func fn, void *flag);
212void eeh_pe_restore_bars(struct eeh_pe *pe);
213struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
214
215void *eeh_dev_init(struct device_node *dn, void *data);
216void eeh_dev_phb_init_dynamic(struct pci_controller *phb);
217int eeh_init(void);
218int __init eeh_ops_register(struct eeh_ops *ops);
219int __exit eeh_ops_unregister(const char *name);
220unsigned long eeh_check_failure(const volatile void __iomem *token,
221 unsigned long val);
222int eeh_dev_check_failure(struct eeh_dev *edev);
223void eeh_addr_cache_build(void);
224void eeh_add_device_early(struct device_node *);
225void eeh_add_device_tree_early(struct device_node *);
226void eeh_add_device_late(struct pci_dev *);
227void eeh_add_device_tree_late(struct pci_bus *);
228void eeh_add_sysfs_files(struct pci_bus *);
229void eeh_remove_device(struct pci_dev *);
230
231
232
233
234
235
236
237#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0 && eeh_subsystem_enabled)
238
239
240
241
242
243
244#define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8))
245
246#else
247
248static inline int eeh_init(void)
249{
250 return 0;
251}
252
253static inline void *eeh_dev_init(struct device_node *dn, void *data)
254{
255 return NULL;
256}
257
258static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { }
259
260static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
261{
262 return val;
263}
264
265#define eeh_dev_check_failure(x) (0)
266
267static inline void eeh_addr_cache_build(void) { }
268
269static inline void eeh_add_device_early(struct device_node *dn) { }
270
271static inline void eeh_add_device_tree_early(struct device_node *dn) { }
272
273static inline void eeh_add_device_late(struct pci_dev *dev) { }
274
275static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
276
277static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
278
279static inline void eeh_remove_device(struct pci_dev *dev) { }
280
281#define EEH_POSSIBLE_ERROR(val, type) (0)
282#define EEH_IO_ERROR_VALUE(size) (-1UL)
283#endif
284
285#ifdef CONFIG_PPC64
286
287
288
289static inline u8 eeh_readb(const volatile void __iomem *addr)
290{
291 u8 val = in_8(addr);
292 if (EEH_POSSIBLE_ERROR(val, u8))
293 return eeh_check_failure(addr, val);
294 return val;
295}
296
297static inline u16 eeh_readw(const volatile void __iomem *addr)
298{
299 u16 val = in_le16(addr);
300 if (EEH_POSSIBLE_ERROR(val, u16))
301 return eeh_check_failure(addr, val);
302 return val;
303}
304
305static inline u32 eeh_readl(const volatile void __iomem *addr)
306{
307 u32 val = in_le32(addr);
308 if (EEH_POSSIBLE_ERROR(val, u32))
309 return eeh_check_failure(addr, val);
310 return val;
311}
312
313static inline u64 eeh_readq(const volatile void __iomem *addr)
314{
315 u64 val = in_le64(addr);
316 if (EEH_POSSIBLE_ERROR(val, u64))
317 return eeh_check_failure(addr, val);
318 return val;
319}
320
321static inline u16 eeh_readw_be(const volatile void __iomem *addr)
322{
323 u16 val = in_be16(addr);
324 if (EEH_POSSIBLE_ERROR(val, u16))
325 return eeh_check_failure(addr, val);
326 return val;
327}
328
329static inline u32 eeh_readl_be(const volatile void __iomem *addr)
330{
331 u32 val = in_be32(addr);
332 if (EEH_POSSIBLE_ERROR(val, u32))
333 return eeh_check_failure(addr, val);
334 return val;
335}
336
337static inline u64 eeh_readq_be(const volatile void __iomem *addr)
338{
339 u64 val = in_be64(addr);
340 if (EEH_POSSIBLE_ERROR(val, u64))
341 return eeh_check_failure(addr, val);
342 return val;
343}
344
345static inline void eeh_memcpy_fromio(void *dest, const
346 volatile void __iomem *src,
347 unsigned long n)
348{
349 _memcpy_fromio(dest, src, n);
350
351
352
353
354 if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32))
355 eeh_check_failure(src, *((u32 *)(dest + n - 4)));
356}
357
358
359static inline void eeh_readsb(const volatile void __iomem *addr, void * buf,
360 int ns)
361{
362 _insb(addr, buf, ns);
363 if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
364 eeh_check_failure(addr, *(u8*)buf);
365}
366
367static inline void eeh_readsw(const volatile void __iomem *addr, void * buf,
368 int ns)
369{
370 _insw(addr, buf, ns);
371 if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
372 eeh_check_failure(addr, *(u16*)buf);
373}
374
375static inline void eeh_readsl(const volatile void __iomem *addr, void * buf,
376 int nl)
377{
378 _insl(addr, buf, nl);
379 if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
380 eeh_check_failure(addr, *(u32*)buf);
381}
382
383#endif
384#endif
385#endif
386