diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh.c')
| -rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 87 |
1 files changed, 85 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 63e23062e982..093438b93bd9 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
| @@ -100,6 +100,9 @@ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; | |||
| 100 | static DEFINE_SPINLOCK(slot_errbuf_lock); | 100 | static DEFINE_SPINLOCK(slot_errbuf_lock); |
| 101 | static int eeh_error_buf_size; | 101 | static int eeh_error_buf_size; |
| 102 | 102 | ||
| 103 | #define EEH_PCI_REGS_LOG_LEN 4096 | ||
| 104 | static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN]; | ||
| 105 | |||
| 103 | /* System monitoring statistics */ | 106 | /* System monitoring statistics */ |
| 104 | static unsigned long no_device; | 107 | static unsigned long no_device; |
| 105 | static unsigned long no_dn; | 108 | static unsigned long no_dn; |
| @@ -115,7 +118,8 @@ static unsigned long slot_resets; | |||
| 115 | /* --------------------------------------------------------------- */ | 118 | /* --------------------------------------------------------------- */ |
| 116 | /* Below lies the EEH event infrastructure */ | 119 | /* Below lies the EEH event infrastructure */ |
| 117 | 120 | ||
| 118 | void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | 121 | static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, |
| 122 | char *driver_log, size_t loglen) | ||
| 119 | { | 123 | { |
| 120 | int config_addr; | 124 | int config_addr; |
| 121 | unsigned long flags; | 125 | unsigned long flags; |
| @@ -133,7 +137,8 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | |||
| 133 | rc = rtas_call(ibm_slot_error_detail, | 137 | rc = rtas_call(ibm_slot_error_detail, |
| 134 | 8, 1, NULL, config_addr, | 138 | 8, 1, NULL, config_addr, |
| 135 | BUID_HI(pdn->phb->buid), | 139 | BUID_HI(pdn->phb->buid), |
| 136 | BUID_LO(pdn->phb->buid), NULL, 0, | 140 | BUID_LO(pdn->phb->buid), |
| 141 | virt_to_phys(driver_log), loglen, | ||
| 137 | virt_to_phys(slot_errbuf), | 142 | virt_to_phys(slot_errbuf), |
| 138 | eeh_error_buf_size, | 143 | eeh_error_buf_size, |
| 139 | severity); | 144 | severity); |
| @@ -144,6 +149,84 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | |||
| 144 | } | 149 | } |
| 145 | 150 | ||
| 146 | /** | 151 | /** |
| 152 | * gather_pci_data - copy assorted PCI config space registers to buff | ||
| 153 | * @pdn: device to report data for | ||
| 154 | * @buf: point to buffer in which to log | ||
| 155 | * @len: amount of room in buffer | ||
| 156 | * | ||
| 157 | * This routine captures assorted PCI configuration space data, | ||
| 158 | * and puts them into a buffer for RTAS error logging. | ||
| 159 | */ | ||
| 160 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | ||
| 161 | { | ||
| 162 | u32 cfg; | ||
| 163 | int cap, i; | ||
| 164 | int n = 0; | ||
| 165 | |||
| 166 | n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name); | ||
| 167 | printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name); | ||
| 168 | |||
| 169 | rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg); | ||
| 170 | n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); | ||
| 171 | printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); | ||
| 172 | |||
| 173 | rtas_read_config(pdn, PCI_COMMAND, 4, &cfg); | ||
| 174 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); | ||
| 175 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); | ||
| 176 | |||
| 177 | /* Dump out the PCI-X command and status regs */ | ||
| 178 | cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX); | ||
| 179 | if (cap) { | ||
| 180 | rtas_read_config(pdn, cap, 4, &cfg); | ||
| 181 | n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); | ||
| 182 | printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); | ||
| 183 | |||
| 184 | rtas_read_config(pdn, cap+4, 4, &cfg); | ||
| 185 | n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); | ||
| 186 | printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); | ||
| 187 | } | ||
| 188 | |||
| 189 | /* If PCI-E capable, dump PCI-E cap 10, and the AER */ | ||
| 190 | cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_EXP); | ||
| 191 | if (cap) { | ||
| 192 | n += scnprintf(buf+n, len-n, "pci-e cap10:\n"); | ||
| 193 | printk(KERN_WARNING | ||
| 194 | "EEH: PCI-E capabilities and status follow:\n"); | ||
| 195 | |||
| 196 | for (i=0; i<=8; i++) { | ||
| 197 | rtas_read_config(pdn, cap+4*i, 4, &cfg); | ||
| 198 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | ||
| 199 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); | ||
| 200 | } | ||
| 201 | |||
| 202 | cap = pci_find_ext_capability(pdn->pcidev,PCI_EXT_CAP_ID_ERR); | ||
| 203 | if (cap) { | ||
| 204 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); | ||
| 205 | printk(KERN_WARNING | ||
| 206 | "EEH: PCI-E AER capability register set follows:\n"); | ||
| 207 | |||
| 208 | for (i=0; i<14; i++) { | ||
| 209 | rtas_read_config(pdn, cap+4*i, 4, &cfg); | ||
| 210 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | ||
| 211 | printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | } | ||
| 215 | return n; | ||
| 216 | } | ||
| 217 | |||
| 218 | void eeh_slot_error_detail(struct pci_dn *pdn, int severity) | ||
| 219 | { | ||
| 220 | size_t loglen = 0; | ||
| 221 | memset(pci_regs_buf, 0, EEH_PCI_REGS_LOG_LEN); | ||
| 222 | |||
| 223 | rtas_pci_enable(pdn, EEH_THAW_MMIO); | ||
| 224 | loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN); | ||
| 225 | |||
| 226 | rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen); | ||
| 227 | } | ||
| 228 | |||
| 229 | /** | ||
| 147 | * read_slot_reset_state - Read the reset state of a device node's slot | 230 | * read_slot_reset_state - Read the reset state of a device node's slot |
| 148 | * @dn: device node to read | 231 | * @dn: device node to read |
| 149 | * @rets: array to return results in | 232 | * @rets: array to return results in |
