]> err.no Git - linux-2.6/blob - include/asm-powerpc/eeh.h
[PATCH] powerpc: sanitize header files for user space includes
[linux-2.6] / include / asm-powerpc / eeh.h
1 /*
2  * eeh.h
3  * Copyright (C) 2001  Dave Engebretsen & Todd Inglett IBM Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18  */
19
20 #ifndef _PPC64_EEH_H
21 #define _PPC64_EEH_H
22 #ifdef __KERNEL__
23
24 #include <linux/config.h>
25 #include <linux/init.h>
26 #include <linux/list.h>
27 #include <linux/string.h>
28
29 struct pci_dev;
30 struct device_node;
31
32 #ifdef CONFIG_EEH
33
34 extern int eeh_subsystem_enabled;
35
36 /* Values for eeh_mode bits in device_node */
37 #define EEH_MODE_SUPPORTED      (1<<0)
38 #define EEH_MODE_NOCHECK        (1<<1)
39 #define EEH_MODE_ISOLATED       (1<<2)
40
41 /* Max number of EEH freezes allowed before we consider the device
42  * to be permanently disabled. */
43 #define EEH_MAX_ALLOWED_FREEZES 5
44
45 void __init eeh_init(void);
46 unsigned long eeh_check_failure(const volatile void __iomem *token,
47                                 unsigned long val);
48 int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev);
49 void __init pci_addr_cache_build(void);
50
51 /**
52  * eeh_add_device_early
53  * eeh_add_device_late
54  *
55  * Perform eeh initialization for devices added after boot.
56  * Call eeh_add_device_early before doing any i/o to the
57  * device (including config space i/o).  Call eeh_add_device_late
58  * to finish the eeh setup for this device.
59  */
60 void eeh_add_device_early(struct device_node *);
61 void eeh_add_device_tree_early(struct device_node *);
62 void eeh_add_device_late(struct pci_dev *);
63
64 /**
65  * eeh_remove_device - undo EEH setup for the indicated pci device
66  * @dev: pci device to be removed
67  *
68  * This routine should be called when a device is removed from
69  * a running system (e.g. by hotplug or dlpar).  It unregisters
70  * the PCI device from the EEH subsystem.  I/O errors affecting
71  * this device will no longer be detected after this call; thus,
72  * i/o errors affecting this slot may leave this device unusable.
73  */
74 void eeh_remove_device(struct pci_dev *);
75
76 /**
77  * eeh_remove_device_recursive - undo EEH for device & children.
78  * @dev: pci device to be removed
79  *
80  * As above, this removes the device; it also removes child
81  * pci devices as well.
82  */
83 void eeh_remove_bus_device(struct pci_dev *);
84
85 /**
86  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
87  *
88  * If this macro yields TRUE, the caller relays to eeh_check_failure()
89  * which does further tests out of line.
90  */
91 #define EEH_POSSIBLE_ERROR(val, type)   ((val) == (type)~0 && eeh_subsystem_enabled)
92
93 /*
94  * Reads from a device which has been isolated by EEH will return
95  * all 1s.  This macro gives an all-1s value of the given size (in
96  * bytes: 1, 2, or 4) for comparing with the result of a read.
97  */
98 #define EEH_IO_ERROR_VALUE(size)        (~0U >> ((4 - (size)) * 8))
99
100 #else /* !CONFIG_EEH */
101 static inline void eeh_init(void) { }
102
103 static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
104 {
105         return val;
106 }
107
108 static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
109 {
110         return 0;
111 }
112
113 static inline void pci_addr_cache_build(void) { }
114
115 static inline void eeh_add_device_early(struct device_node *dn) { }
116
117 static inline void eeh_add_device_late(struct pci_dev *dev) { }
118
119 static inline void eeh_remove_device(struct pci_dev *dev) { }
120
121 #define EEH_POSSIBLE_ERROR(val, type) (0)
122 #define EEH_IO_ERROR_VALUE(size) (-1UL)
123 #endif /* CONFIG_EEH */
124
125 /*
126  * MMIO read/write operations with EEH support.
127  */
128 static inline u8 eeh_readb(const volatile void __iomem *addr)
129 {
130         u8 val = in_8(addr);
131         if (EEH_POSSIBLE_ERROR(val, u8))
132                 return eeh_check_failure(addr, val);
133         return val;
134 }
135 static inline void eeh_writeb(u8 val, volatile void __iomem *addr)
136 {
137         out_8(addr, val);
138 }
139
140 static inline u16 eeh_readw(const volatile void __iomem *addr)
141 {
142         u16 val = in_le16(addr);
143         if (EEH_POSSIBLE_ERROR(val, u16))
144                 return eeh_check_failure(addr, val);
145         return val;
146 }
147 static inline void eeh_writew(u16 val, volatile void __iomem *addr)
148 {
149         out_le16(addr, val);
150 }
151 static inline u16 eeh_raw_readw(const volatile void __iomem *addr)
152 {
153         u16 val = in_be16(addr);
154         if (EEH_POSSIBLE_ERROR(val, u16))
155                 return eeh_check_failure(addr, val);
156         return val;
157 }
158 static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) {
159         volatile u16 __iomem *vaddr = (volatile u16 __iomem *) addr;
160         out_be16(vaddr, val);
161 }
162
163 static inline u32 eeh_readl(const volatile void __iomem *addr)
164 {
165         u32 val = in_le32(addr);
166         if (EEH_POSSIBLE_ERROR(val, u32))
167                 return eeh_check_failure(addr, val);
168         return val;
169 }
170 static inline void eeh_writel(u32 val, volatile void __iomem *addr)
171 {
172         out_le32(addr, val);
173 }
174 static inline u32 eeh_raw_readl(const volatile void __iomem *addr)
175 {
176         u32 val = in_be32(addr);
177         if (EEH_POSSIBLE_ERROR(val, u32))
178                 return eeh_check_failure(addr, val);
179         return val;
180 }
181 static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr)
182 {
183         out_be32(addr, val);
184 }
185
186 static inline u64 eeh_readq(const volatile void __iomem *addr)
187 {
188         u64 val = in_le64(addr);
189         if (EEH_POSSIBLE_ERROR(val, u64))
190                 return eeh_check_failure(addr, val);
191         return val;
192 }
193 static inline void eeh_writeq(u64 val, volatile void __iomem *addr)
194 {
195         out_le64(addr, val);
196 }
197 static inline u64 eeh_raw_readq(const volatile void __iomem *addr)
198 {
199         u64 val = in_be64(addr);
200         if (EEH_POSSIBLE_ERROR(val, u64))
201                 return eeh_check_failure(addr, val);
202         return val;
203 }
204 static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr)
205 {
206         out_be64(addr, val);
207 }
208
209 #define EEH_CHECK_ALIGN(v,a) \
210         ((((unsigned long)(v)) & ((a) - 1)) == 0)
211
212 static inline void eeh_memset_io(volatile void __iomem *addr, int c,
213                                  unsigned long n)
214 {
215         void *p = (void __force *)addr;
216         u32 lc = c;
217         lc |= lc << 8;
218         lc |= lc << 16;
219
220         while(n && !EEH_CHECK_ALIGN(p, 4)) {
221                 *((volatile u8 *)p) = c;
222                 p++;
223                 n--;
224         }
225         while(n >= 4) {
226                 *((volatile u32 *)p) = lc;
227                 p += 4;
228                 n -= 4;
229         }
230         while(n) {
231                 *((volatile u8 *)p) = c;
232                 p++;
233                 n--;
234         }
235         __asm__ __volatile__ ("sync" : : : "memory");
236 }
237 static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src,
238                                      unsigned long n)
239 {
240         void *vsrc = (void __force *) src;
241         void *destsave = dest;
242         unsigned long nsave = n;
243
244         while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) {
245                 *((u8 *)dest) = *((volatile u8 *)vsrc);
246                 __asm__ __volatile__ ("eieio" : : : "memory");
247                 vsrc++;
248                 dest++;
249                 n--;
250         }
251         while(n > 4) {
252                 *((u32 *)dest) = *((volatile u32 *)vsrc);
253                 __asm__ __volatile__ ("eieio" : : : "memory");
254                 vsrc += 4;
255                 dest += 4;
256                 n -= 4;
257         }
258         while(n) {
259                 *((u8 *)dest) = *((volatile u8 *)vsrc);
260                 __asm__ __volatile__ ("eieio" : : : "memory");
261                 vsrc++;
262                 dest++;
263                 n--;
264         }
265         __asm__ __volatile__ ("sync" : : : "memory");
266
267         /* Look for ffff's here at dest[n].  Assume that at least 4 bytes
268          * were copied. Check all four bytes.
269          */
270         if ((nsave >= 4) &&
271                 (EEH_POSSIBLE_ERROR((*((u32 *) destsave+nsave-4)), u32))) {
272                 eeh_check_failure(src, (*((u32 *) destsave+nsave-4)));
273         }
274 }
275
276 static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src,
277                                    unsigned long n)
278 {
279         void *vdest = (void __force *) dest;
280
281         while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) {
282                 *((volatile u8 *)vdest) = *((u8 *)src);
283                 src++;
284                 vdest++;
285                 n--;
286         }
287         while(n > 4) {
288                 *((volatile u32 *)vdest) = *((volatile u32 *)src);
289                 src += 4;
290                 vdest += 4;
291                 n-=4;
292         }
293         while(n) {
294                 *((volatile u8 *)vdest) = *((u8 *)src);
295                 src++;
296                 vdest++;
297                 n--;
298         }
299         __asm__ __volatile__ ("sync" : : : "memory");
300 }
301
302 #undef EEH_CHECK_ALIGN
303
304 static inline u8 eeh_inb(unsigned long port)
305 {
306         u8 val;
307         if (!_IO_IS_VALID(port))
308                 return ~0;
309         val = in_8((u8 __iomem *)(port+pci_io_base));
310         if (EEH_POSSIBLE_ERROR(val, u8))
311                 return eeh_check_failure((void __iomem *)(port), val);
312         return val;
313 }
314
315 static inline void eeh_outb(u8 val, unsigned long port)
316 {
317         if (_IO_IS_VALID(port))
318                 out_8((u8 __iomem *)(port+pci_io_base), val);
319 }
320
321 static inline u16 eeh_inw(unsigned long port)
322 {
323         u16 val;
324         if (!_IO_IS_VALID(port))
325                 return ~0;
326         val = in_le16((u16 __iomem *)(port+pci_io_base));
327         if (EEH_POSSIBLE_ERROR(val, u16))
328                 return eeh_check_failure((void __iomem *)(port), val);
329         return val;
330 }
331
332 static inline void eeh_outw(u16 val, unsigned long port)
333 {
334         if (_IO_IS_VALID(port))
335                 out_le16((u16 __iomem *)(port+pci_io_base), val);
336 }
337
338 static inline u32 eeh_inl(unsigned long port)
339 {
340         u32 val;
341         if (!_IO_IS_VALID(port))
342                 return ~0;
343         val = in_le32((u32 __iomem *)(port+pci_io_base));
344         if (EEH_POSSIBLE_ERROR(val, u32))
345                 return eeh_check_failure((void __iomem *)(port), val);
346         return val;
347 }
348
349 static inline void eeh_outl(u32 val, unsigned long port)
350 {
351         if (_IO_IS_VALID(port))
352                 out_le32((u32 __iomem *)(port+pci_io_base), val);
353 }
354
355 /* in-string eeh macros */
356 static inline void eeh_insb(unsigned long port, void * buf, int ns)
357 {
358         _insb((u8 __iomem *)(port+pci_io_base), buf, ns);
359         if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
360                 eeh_check_failure((void __iomem *)(port), *(u8*)buf);
361 }
362
363 static inline void eeh_insw_ns(unsigned long port, void * buf, int ns)
364 {
365         _insw_ns((u16 __iomem *)(port+pci_io_base), buf, ns);
366         if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
367                 eeh_check_failure((void __iomem *)(port), *(u16*)buf);
368 }
369
370 static inline void eeh_insl_ns(unsigned long port, void * buf, int nl)
371 {
372         _insl_ns((u32 __iomem *)(port+pci_io_base), buf, nl);
373         if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
374                 eeh_check_failure((void __iomem *)(port), *(u32*)buf);
375 }
376
377 #endif /* __KERNEL__ */
378 #endif /* _PPC64_EEH_H */