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 _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 28 struct pci_dev; 29 struct pci_bus; 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 #define EEH_MODE_RECOVERING (1<<3) 41 #define EEH_MODE_IRQ_DISABLED (1<<4) 42 43 /* Max number of EEH freezes allowed before we consider the device 44 * to be permanently disabled. */ 45 #define EEH_MAX_ALLOWED_FREEZES 5 46 47 void __init eeh_init(void); 48 unsigned long eeh_check_failure(const volatile void __iomem *token, 49 unsigned long val); 50 int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev); 51 void __init pci_addr_cache_build(void); 52 53 /** 54 * eeh_add_device_early 55 * eeh_add_device_late 56 * 57 * Perform eeh initialization for devices added after boot. 58 * Call eeh_add_device_early before doing any i/o to the 59 * device (including config space i/o). Call eeh_add_device_late 60 * to finish the eeh setup for this device. 61 */ 62 void eeh_add_device_tree_early(struct device_node *); 63 void eeh_add_device_tree_late(struct pci_bus *); 64 65 /** 66 * eeh_remove_device_recursive - undo EEH for device & children. 67 * @dev: pci device to be removed 68 * 69 * As above, this removes the device; it also removes child 70 * pci devices as well. 71 */ 72 void eeh_remove_bus_device(struct pci_dev *); 73 74 /** 75 * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. 76 * 77 * If this macro yields TRUE, the caller relays to eeh_check_failure() 78 * which does further tests out of line. 79 */ 80 #define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0 && eeh_subsystem_enabled) 81 82 /* 83 * Reads from a device which has been isolated by EEH will return 84 * all 1s. This macro gives an all-1s value of the given size (in 85 * bytes: 1, 2, or 4) for comparing with the result of a read. 86 */ 87 #define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8)) 88 89 #else /* !CONFIG_EEH */ 90 static inline void eeh_init(void) { } 91 92 static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val) 93 { 94 return val; 95 } 96 97 static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) 98 { 99 return 0; 100 } 101 102 static inline void pci_addr_cache_build(void) { } 103 104 static inline void eeh_add_device_tree_early(struct device_node *dn) { } 105 106 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { } 107 108 static inline void eeh_remove_bus_device(struct pci_dev *dev) { } 109 #define EEH_POSSIBLE_ERROR(val, type) (0) 110 #define EEH_IO_ERROR_VALUE(size) (-1UL) 111 #endif /* CONFIG_EEH */ 112 113 #ifdef CONFIG_PPC64 114 /* 115 * MMIO read/write operations with EEH support. 116 */ 117 static inline u8 eeh_readb(const volatile void __iomem *addr) 118 { 119 u8 val = in_8(addr); 120 if (EEH_POSSIBLE_ERROR(val, u8)) 121 return eeh_check_failure(addr, val); 122 return 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 133 static inline u32 eeh_readl(const volatile void __iomem *addr) 134 { 135 u32 val = in_le32(addr); 136 if (EEH_POSSIBLE_ERROR(val, u32)) 137 return eeh_check_failure(addr, val); 138 return val; 139 } 140 141 static inline u64 eeh_readq(const volatile void __iomem *addr) 142 { 143 u64 val = in_le64(addr); 144 if (EEH_POSSIBLE_ERROR(val, u64)) 145 return eeh_check_failure(addr, val); 146 return val; 147 } 148 149 static inline u16 eeh_readw_be(const volatile void __iomem *addr) 150 { 151 u16 val = in_be16(addr); 152 if (EEH_POSSIBLE_ERROR(val, u16)) 153 return eeh_check_failure(addr, val); 154 return val; 155 } 156 157 static inline u32 eeh_readl_be(const volatile void __iomem *addr) 158 { 159 u32 val = in_be32(addr); 160 if (EEH_POSSIBLE_ERROR(val, u32)) 161 return eeh_check_failure(addr, val); 162 return val; 163 } 164 165 static inline u64 eeh_readq_be(const volatile void __iomem *addr) 166 { 167 u64 val = in_be64(addr); 168 if (EEH_POSSIBLE_ERROR(val, u64)) 169 return eeh_check_failure(addr, val); 170 return val; 171 } 172 173 static inline void eeh_memcpy_fromio(void *dest, const 174 volatile void __iomem *src, 175 unsigned long n) 176 { 177 _memcpy_fromio(dest, src, n); 178 179 /* Look for ffff's here at dest[n]. Assume that at least 4 bytes 180 * were copied. Check all four bytes. 181 */ 182 if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32)) 183 eeh_check_failure(src, *((u32 *)(dest + n - 4))); 184 } 185 186 /* in-string eeh macros */ 187 static inline void eeh_readsb(const volatile void __iomem *addr, void * buf, 188 int ns) 189 { 190 _insb(addr, buf, ns); 191 if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8)) 192 eeh_check_failure(addr, *(u8*)buf); 193 } 194 195 static inline void eeh_readsw(const volatile void __iomem *addr, void * buf, 196 int ns) 197 { 198 _insw(addr, buf, ns); 199 if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16)) 200 eeh_check_failure(addr, *(u16*)buf); 201 } 202 203 static inline void eeh_readsl(const volatile void __iomem *addr, void * buf, 204 int nl) 205 { 206 _insl(addr, buf, nl); 207 if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32)) 208 eeh_check_failure(addr, *(u32*)buf); 209 } 210 211 #endif /* CONFIG_PPC64 */ 212 #endif /* __KERNEL__ */ 213 #endif /* _POWERPC_EEH_H */ 214