upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / include / asm-ppc64 / 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
23 #include <linux/init.h>
24 #include <linux/list.h>
25 #include <linux/string.h>
26 #include <linux/notifier.h>
27
28 struct pci_dev;
29 struct device_node;
30
31 /* Values for eeh_mode bits in device_node */
32 #define EEH_MODE_SUPPORTED      (1<<0)
33 #define EEH_MODE_NOCHECK        (1<<1)
34 #define EEH_MODE_ISOLATED       (1<<2)
35
36 #ifdef CONFIG_PPC_PSERIES
37 extern void __init eeh_init(void);
38 unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val);
39 int eeh_dn_check_failure (struct device_node *dn, struct pci_dev *dev);
40 void __iomem *eeh_ioremap(unsigned long addr, void __iomem *vaddr);
41 void __init pci_addr_cache_build(void);
42 #else
43 #define eeh_check_failure(token, val) (val)
44 #endif
45
46 /**
47  * eeh_add_device_early
48  * eeh_add_device_late
49  *
50  * Perform eeh initialization for devices added after boot.
51  * Call eeh_add_device_early before doing any i/o to the
52  * device (including config space i/o).  Call eeh_add_device_late
53  * to finish the eeh setup for this device.
54  */
55 struct device_node;
56 void eeh_add_device_early(struct device_node *);
57 void eeh_add_device_late(struct pci_dev *);
58
59 /**
60  * eeh_remove_device - undo EEH setup for the indicated pci device
61  * @dev: pci device to be removed
62  *
63  * This routine should be when a device is removed from a running
64  * system (e.g. by hotplug or dlpar).
65  */
66 void eeh_remove_device(struct pci_dev *);
67
68 #define EEH_DISABLE             0
69 #define EEH_ENABLE              1
70 #define EEH_RELEASE_LOADSTORE   2
71 #define EEH_RELEASE_DMA         3
72 int eeh_set_option(struct pci_dev *dev, int options);
73
74
75 /**
76  * Notifier event flags.
77  */
78 #define EEH_NOTIFY_FREEZE  1
79
80 /** EEH event -- structure holding pci slot data that describes
81  *  a change in the isolation status of a PCI slot.  A pointer
82  *  to this struct is passed as the data pointer in a notify callback.
83  */
84 struct eeh_event {
85         struct list_head     list;
86         struct pci_dev       *dev;
87         struct device_node   *dn;
88         int                  reset_state;
89 };
90
91 /** Register to find out about EEH events. */
92 int eeh_register_notifier(struct notifier_block *nb);
93 int eeh_unregister_notifier(struct notifier_block *nb);
94
95 /**
96  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
97  *
98  * If this macro yields TRUE, the caller relays to eeh_check_failure()
99  * which does further tests out of line.
100  */
101 #define EEH_POSSIBLE_ERROR(val, type)   ((val) == (type)~0)
102
103 /*
104  * Reads from a device which has been isolated by EEH will return
105  * all 1s.  This macro gives an all-1s value of the given size (in
106  * bytes: 1, 2, or 4) for comparing with the result of a read.
107  */
108 #define EEH_IO_ERROR_VALUE(size)        (~0U >> ((4 - (size)) * 8))
109
110 /* 
111  * MMIO read/write operations with EEH support.
112  */
113 static inline u8 eeh_readb(const volatile void __iomem *addr)
114 {
115         u8 val = in_8(addr);
116         if (EEH_POSSIBLE_ERROR(val, u8))
117                 return eeh_check_failure(addr, val);
118         return val;
119 }
120 static inline void eeh_writeb(u8 val, volatile void __iomem *addr)
121 {
122         out_8(addr, val);
123 }
124
125 static inline u16 eeh_readw(const volatile void __iomem *addr)
126 {
127         u16 val = in_le16(addr);
128         if (EEH_POSSIBLE_ERROR(val, u16))
129                 return eeh_check_failure(addr, val);
130         return val;
131 }
132 static inline void eeh_writew(u16 val, volatile void __iomem *addr)
133 {
134         out_le16(addr, val);
135 }
136 static inline u16 eeh_raw_readw(const volatile void __iomem *addr)
137 {
138         u16 val = in_be16(addr);
139         if (EEH_POSSIBLE_ERROR(val, u16))
140                 return eeh_check_failure(addr, val);
141         return val;
142 }
143 static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) {
144         volatile u16 __iomem *vaddr = (volatile u16 __iomem *) addr;
145         out_be16(vaddr, val);
146 }
147
148 static inline u32 eeh_readl(const volatile void __iomem *addr)
149 {
150         u32 val = in_le32(addr);
151         if (EEH_POSSIBLE_ERROR(val, u32))
152                 return eeh_check_failure(addr, val);
153         return val;
154 }
155 static inline void eeh_writel(u32 val, volatile void __iomem *addr)
156 {
157         out_le32(addr, val);
158 }
159 static inline u32 eeh_raw_readl(const volatile void __iomem *addr)
160 {
161         u32 val = in_be32(addr);
162         if (EEH_POSSIBLE_ERROR(val, u32))
163                 return eeh_check_failure(addr, val);
164         return val;
165 }
166 static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr)
167 {
168         out_be32(addr, val);
169 }
170
171 static inline u64 eeh_readq(const volatile void __iomem *addr)
172 {
173         u64 val = in_le64(addr);
174         if (EEH_POSSIBLE_ERROR(val, u64))
175                 return eeh_check_failure(addr, val);
176         return val;
177 }
178 static inline void eeh_writeq(u64 val, volatile void __iomem *addr)
179 {
180         out_le64(addr, val);
181 }
182 static inline u64 eeh_raw_readq(const volatile void __iomem *addr)
183 {
184         u64 val = in_be64(addr);
185         if (EEH_POSSIBLE_ERROR(val, u64))
186                 return eeh_check_failure(addr, val);
187         return val;
188 }
189 static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr)
190 {
191         out_be64(addr, val);
192 }
193
194 #define EEH_CHECK_ALIGN(v,a) \
195         ((((unsigned long)(v)) & ((a) - 1)) == 0)
196
197 static inline void eeh_memset_io(volatile void __iomem *addr, int c, unsigned long n)
198 {
199         u32 lc = c;
200         lc |= lc << 8;
201         lc |= lc << 16;
202
203         while(n && !EEH_CHECK_ALIGN(addr, 4)) {
204                 *((volatile u8 *)addr) = c;
205                 addr = (void *)((unsigned long)addr + 1);
206                 n--;
207         }
208         while(n >= 4) {
209                 *((volatile u32 *)addr) = lc;
210                 addr = (void *)((unsigned long)addr + 4);
211                 n -= 4;
212         }
213         while(n) {
214                 *((volatile u8 *)addr) = c;
215                 addr = (void *)((unsigned long)addr + 1);
216                 n--;
217         }
218         __asm__ __volatile__ ("sync" : : : "memory");
219 }
220 static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src,
221                                      unsigned long n)
222 {
223         void *vsrc = (void __force *) src;
224         void *destsave = dest;
225         unsigned long nsave = n;
226
227         while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) {
228                 *((u8 *)dest) = *((volatile u8 *)vsrc);
229                 __asm__ __volatile__ ("eieio" : : : "memory");
230                 vsrc = (void *)((unsigned long)vsrc + 1);
231                 dest = (void *)((unsigned long)dest + 1);                       
232                 n--;
233         }
234         while(n > 4) {
235                 *((u32 *)dest) = *((volatile u32 *)vsrc);
236                 __asm__ __volatile__ ("eieio" : : : "memory");
237                 vsrc = (void *)((unsigned long)vsrc + 4);
238                 dest = (void *)((unsigned long)dest + 4);                       
239                 n -= 4;
240         }
241         while(n) {
242                 *((u8 *)dest) = *((volatile u8 *)vsrc);
243                 __asm__ __volatile__ ("eieio" : : : "memory");
244                 vsrc = (void *)((unsigned long)vsrc + 1);
245                 dest = (void *)((unsigned long)dest + 1);                       
246                 n--;
247         }
248         __asm__ __volatile__ ("sync" : : : "memory");
249
250         /* Look for ffff's here at dest[n].  Assume that at least 4 bytes
251          * were copied. Check all four bytes.
252          */
253         if ((nsave >= 4) &&
254                 (EEH_POSSIBLE_ERROR((*((u32 *) destsave+nsave-4)), u32))) {
255                 eeh_check_failure(src, (*((u32 *) destsave+nsave-4)));
256         }
257 }
258
259 static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src,
260                                    unsigned long n)
261 {
262         void *vdest = (void __force *) dest;
263
264         while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) {
265                 *((volatile u8 *)vdest) = *((u8 *)src);
266                 src = (void *)((unsigned long)src + 1);
267                 vdest = (void *)((unsigned long)vdest + 1);                     
268                 n--;
269         }
270         while(n > 4) {
271                 *((volatile u32 *)vdest) = *((volatile u32 *)src);
272                 src = (void *)((unsigned long)src + 4);
273                 vdest = (void *)((unsigned long)vdest + 4);                     
274                 n-=4;
275         }
276         while(n) {
277                 *((volatile u8 *)vdest) = *((u8 *)src);
278                 src = (void *)((unsigned long)src + 1);
279                 vdest = (void *)((unsigned long)vdest + 1);                     
280                 n--;
281         }
282         __asm__ __volatile__ ("sync" : : : "memory");
283 }
284
285 #undef EEH_CHECK_ALIGN
286
287 static inline u8 eeh_inb(unsigned long port)
288 {
289         u8 val;
290         if (!_IO_IS_VALID(port))
291                 return ~0;
292         val = in_8((u8 __iomem *)(port+pci_io_base));
293         if (EEH_POSSIBLE_ERROR(val, u8))
294                 return eeh_check_failure((void __iomem *)(port), val);
295         return val;
296 }
297
298 static inline void eeh_outb(u8 val, unsigned long port)
299 {
300         if (_IO_IS_VALID(port))
301                 out_8((u8 __iomem *)(port+pci_io_base), val);
302 }
303
304 static inline u16 eeh_inw(unsigned long port)
305 {
306         u16 val;
307         if (!_IO_IS_VALID(port))
308                 return ~0;
309         val = in_le16((u16 __iomem *)(port+pci_io_base));
310         if (EEH_POSSIBLE_ERROR(val, u16))
311                 return eeh_check_failure((void __iomem *)(port), val);
312         return val;
313 }
314
315 static inline void eeh_outw(u16 val, unsigned long port)
316 {
317         if (_IO_IS_VALID(port))
318                 out_le16((u16 __iomem *)(port+pci_io_base), val);
319 }
320
321 static inline u32 eeh_inl(unsigned long port)
322 {
323         u32 val;
324         if (!_IO_IS_VALID(port))
325                 return ~0;
326         val = in_le32((u32 __iomem *)(port+pci_io_base));
327         if (EEH_POSSIBLE_ERROR(val, u32))
328                 return eeh_check_failure((void __iomem *)(port), val);
329         return val;
330 }
331
332 static inline void eeh_outl(u32 val, unsigned long port)
333 {
334         if (_IO_IS_VALID(port))
335                 out_le32((u32 __iomem *)(port+pci_io_base), val);
336 }
337
338 /* in-string eeh macros */
339 static inline void eeh_insb(unsigned long port, void * buf, int ns)
340 {
341         _insb((u8 __iomem *)(port+pci_io_base), buf, ns);
342         if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
343                 eeh_check_failure((void __iomem *)(port), *(u8*)buf);
344 }
345
346 static inline void eeh_insw_ns(unsigned long port, void * buf, int ns)
347 {
348         _insw_ns((u16 __iomem *)(port+pci_io_base), buf, ns);
349         if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
350                 eeh_check_failure((void __iomem *)(port), *(u16*)buf);
351 }
352
353 static inline void eeh_insl_ns(unsigned long port, void * buf, int nl)
354 {
355         _insl_ns((u32 __iomem *)(port+pci_io_base), buf, nl);
356         if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
357                 eeh_check_failure((void __iomem *)(port), *(u32*)buf);
358 }
359
360 #endif /* _PPC64_EEH_H */