aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/eeh.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh.c')
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c87
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];
100static DEFINE_SPINLOCK(slot_errbuf_lock); 100static DEFINE_SPINLOCK(slot_errbuf_lock);
101static int eeh_error_buf_size; 101static int eeh_error_buf_size;
102 102
103#define EEH_PCI_REGS_LOG_LEN 4096
104static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];
105
103/* System monitoring statistics */ 106/* System monitoring statistics */
104static unsigned long no_device; 107static unsigned long no_device;
105static unsigned long no_dn; 108static 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
118void eeh_slot_error_detail (struct pci_dn *pdn, int severity) 121static 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 */
160static 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
218void 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