aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-11-29 13:22:53 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-12-07 02:04:02 -0500
commitcee72d5bb48952f2e50acd2610d52ea82f7092c9 (patch)
treef4e29eb7e997e29a333750a241c99e282ffda8c8 /arch
parentf11fe5524aa7427ae8f23dbede8a29fc4f613a71 (diff)
powerpc/powernv: Display diag data on p7ioc EEH errors
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c25
-rw-r--r--arch/powerpc/platforms/powernv/pci-p5ioc2.c1
-rw-r--r--arch/powerpc/platforms/powernv/pci.c117
-rw-r--r--arch/powerpc/platforms/powernv/pci.h16
4 files changed, 140 insertions, 19 deletions
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 425c2b297945..f31162cfdaa9 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -9,7 +9,7 @@
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11 11
12#define DEBUG 12#undef DEBUG
13 13
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/pci.h> 15#include <linux/pci.h>
@@ -467,14 +467,13 @@ static void __devinit pnv_ioda_update_resources(struct pci_bus *bus)
467 struct pci_bus *cbus; 467 struct pci_bus *cbus;
468 struct pci_dev *cdev; 468 struct pci_dev *cdev;
469 unsigned int i; 469 unsigned int i;
470 u16 cmd;
471 470
472 /* Clear all device enables */ 471 /* We used to clear all device enables here. However it looks like
473 list_for_each_entry(cdev, &bus->devices, bus_list) { 472 * clearing MEM enable causes Obsidian (IPR SCS) to go bonkers,
474 pci_read_config_word(cdev, PCI_COMMAND, &cmd); 473 * and shoot fatal errors to the PHB which in turns fences itself
475 cmd &= ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER); 474 * and we can't recover from that ... yet. So for now, let's leave
476 pci_write_config_word(cdev, PCI_COMMAND, cmd); 475 * the enables as-is and hope for the best.
477 } 476 */
478 477
479 /* Check if bus resources fit in our IO or M32 range */ 478 /* Check if bus resources fit in our IO or M32 range */
480 for (i = 0; bus->self && (i < 2); i++) { 479 for (i = 0; bus->self && (i < 2); i++) {
@@ -618,7 +617,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
618 struct pci_dn *pdn = pnv_ioda_get_pdn(parent); 617 struct pci_dn *pdn = pnv_ioda_get_pdn(parent);
619 if (pdn && pdn->pe_number != IODA_INVALID_PE) { 618 if (pdn && pdn->pe_number != IODA_INVALID_PE) {
620 rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, 619 rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
621 pe->pe_number, 1); 620 pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
622 /* XXX What to do in case of error ? */ 621 /* XXX What to do in case of error ? */
623 } 622 }
624 parent = parent->bus->self; 623 parent = parent->bus->self;
@@ -638,7 +637,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
638 pe->mve_number = -1; 637 pe->mve_number = -1;
639 } else { 638 } else {
640 rc = opal_pci_set_mve_enable(phb->opal_id, 639 rc = opal_pci_set_mve_enable(phb->opal_id,
641 pe->mve_number, 1); 640 pe->mve_number, OPAL_ENABLE_MVE);
642 if (rc) { 641 if (rc) {
643 pe_err(pe, "OPAL error %ld enabling MVE %d\n", 642 pe_err(pe, "OPAL error %ld enabling MVE %d\n",
644 rc, pe->mve_number); 643 rc, pe->mve_number);
@@ -1187,6 +1186,12 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
1187 phb->opal_id = phb_id; 1186 phb->opal_id = phb_id;
1188 phb->type = PNV_PHB_IODA1; 1187 phb->type = PNV_PHB_IODA1;
1189 1188
1189 /* Detect specific models for error handling */
1190 if (of_device_is_compatible(np, "ibm,p7ioc-pciex"))
1191 phb->model = PNV_PHB_MODEL_P7IOC;
1192 else
1193 phb->model = PNV_PHB_MODEL_UNKNOWN;
1194
1190 /* We parse "ranges" now since we need to deduce the register base 1195 /* We parse "ranges" now since we need to deduce the register base
1191 * from the IO base 1196 * from the IO base
1192 */ 1197 */
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
index 4c80f7c77d56..264967770c3a 100644
--- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c
+++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
@@ -137,6 +137,7 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np,
137 phb->hose->private_data = phb; 137 phb->hose->private_data = phb;
138 phb->opal_id = phb_id; 138 phb->opal_id = phb_id;
139 phb->type = PNV_PHB_P5IOC2; 139 phb->type = PNV_PHB_P5IOC2;
140 phb->model = PNV_PHB_MODEL_P5IOC2;
140 141
141 phb->regs = of_iomap(np, 0); 142 phb->regs = of_iomap(np, 0);
142 143
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index c0ed379498a0..a70bc1e385eb 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -144,6 +144,112 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
144} 144}
145#endif /* CONFIG_PCI_MSI */ 145#endif /* CONFIG_PCI_MSI */
146 146
147static void pnv_pci_dump_p7ioc_diag_data(struct pnv_phb *phb)
148{
149 struct OpalIoP7IOCPhbErrorData *data = &phb->diag.p7ioc;
150 int i;
151
152 pr_info("PHB %d diagnostic data:\n", phb->hose->global_number);
153
154 pr_info(" brdgCtl = 0x%08x\n", data->brdgCtl);
155
156 pr_info(" portStatusReg = 0x%08x\n", data->portStatusReg);
157 pr_info(" rootCmplxStatus = 0x%08x\n", data->rootCmplxStatus);
158 pr_info(" busAgentStatus = 0x%08x\n", data->busAgentStatus);
159
160 pr_info(" deviceStatus = 0x%08x\n", data->deviceStatus);
161 pr_info(" slotStatus = 0x%08x\n", data->slotStatus);
162 pr_info(" linkStatus = 0x%08x\n", data->linkStatus);
163 pr_info(" devCmdStatus = 0x%08x\n", data->devCmdStatus);
164 pr_info(" devSecStatus = 0x%08x\n", data->devSecStatus);
165
166 pr_info(" rootErrorStatus = 0x%08x\n", data->rootErrorStatus);
167 pr_info(" uncorrErrorStatus = 0x%08x\n", data->uncorrErrorStatus);
168 pr_info(" corrErrorStatus = 0x%08x\n", data->corrErrorStatus);
169 pr_info(" tlpHdr1 = 0x%08x\n", data->tlpHdr1);
170 pr_info(" tlpHdr2 = 0x%08x\n", data->tlpHdr2);
171 pr_info(" tlpHdr3 = 0x%08x\n", data->tlpHdr3);
172 pr_info(" tlpHdr4 = 0x%08x\n", data->tlpHdr4);
173 pr_info(" sourceId = 0x%08x\n", data->sourceId);
174
175 pr_info(" errorClass = 0x%016llx\n", data->errorClass);
176 pr_info(" correlator = 0x%016llx\n", data->correlator);
177
178 pr_info(" p7iocPlssr = 0x%016llx\n", data->p7iocPlssr);
179 pr_info(" p7iocCsr = 0x%016llx\n", data->p7iocCsr);
180 pr_info(" lemFir = 0x%016llx\n", data->lemFir);
181 pr_info(" lemErrorMask = 0x%016llx\n", data->lemErrorMask);
182 pr_info(" lemWOF = 0x%016llx\n", data->lemWOF);
183 pr_info(" phbErrorStatus = 0x%016llx\n", data->phbErrorStatus);
184 pr_info(" phbFirstErrorStatus = 0x%016llx\n", data->phbFirstErrorStatus);
185 pr_info(" phbErrorLog0 = 0x%016llx\n", data->phbErrorLog0);
186 pr_info(" phbErrorLog1 = 0x%016llx\n", data->phbErrorLog1);
187 pr_info(" mmioErrorStatus = 0x%016llx\n", data->mmioErrorStatus);
188 pr_info(" mmioFirstErrorStatus = 0x%016llx\n", data->mmioFirstErrorStatus);
189 pr_info(" mmioErrorLog0 = 0x%016llx\n", data->mmioErrorLog0);
190 pr_info(" mmioErrorLog1 = 0x%016llx\n", data->mmioErrorLog1);
191 pr_info(" dma0ErrorStatus = 0x%016llx\n", data->dma0ErrorStatus);
192 pr_info(" dma0FirstErrorStatus = 0x%016llx\n", data->dma0FirstErrorStatus);
193 pr_info(" dma0ErrorLog0 = 0x%016llx\n", data->dma0ErrorLog0);
194 pr_info(" dma0ErrorLog1 = 0x%016llx\n", data->dma0ErrorLog1);
195 pr_info(" dma1ErrorStatus = 0x%016llx\n", data->dma1ErrorStatus);
196 pr_info(" dma1FirstErrorStatus = 0x%016llx\n", data->dma1FirstErrorStatus);
197 pr_info(" dma1ErrorLog0 = 0x%016llx\n", data->dma1ErrorLog0);
198 pr_info(" dma1ErrorLog1 = 0x%016llx\n", data->dma1ErrorLog1);
199
200 for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
201 if ((data->pestA[i] >> 63) == 0 &&
202 (data->pestB[i] >> 63) == 0)
203 continue;
204 pr_info(" PE[%3d] PESTA = 0x%016llx\n", i, data->pestA[i]);
205 pr_info(" PESTB = 0x%016llx\n", data->pestB[i]);
206 }
207}
208
209static void pnv_pci_dump_phb_diag_data(struct pnv_phb *phb)
210{
211 switch(phb->model) {
212 case PNV_PHB_MODEL_P7IOC:
213 pnv_pci_dump_p7ioc_diag_data(phb);
214 break;
215 default:
216 pr_warning("PCI %d: Can't decode this PHB diag data\n",
217 phb->hose->global_number);
218 }
219}
220
221static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
222{
223 unsigned long flags, rc;
224 int has_diag;
225
226 spin_lock_irqsave(&phb->lock, flags);
227
228 rc = opal_pci_get_phb_diag_data(phb->opal_id, phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
229 has_diag = (rc == OPAL_SUCCESS);
230
231 rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
232 OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
233 if (rc) {
234 pr_warning("PCI %d: Failed to clear EEH freeze state"
235 " for PE#%d, err %ld\n",
236 phb->hose->global_number, pe_no, rc);
237
238 /* For now, let's only display the diag buffer when we fail to clear
239 * the EEH status. We'll do more sensible things later when we have
240 * proper EEH support. We need to make sure we don't pollute ourselves
241 * with the normal errors generated when probing empty slots
242 */
243 if (has_diag)
244 pnv_pci_dump_phb_diag_data(phb);
245 else
246 pr_warning("PCI %d: No diag data available\n",
247 phb->hose->global_number);
248 }
249
250 spin_unlock_irqrestore(&phb->lock, flags);
251}
252
147static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus, 253static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
148 u32 bdfn) 254 u32 bdfn)
149{ 255{
@@ -165,15 +271,8 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
165 } 271 }
166 cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n", 272 cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n",
167 bdfn, pe_no, fstate); 273 bdfn, pe_no, fstate);
168 if (fstate != 0) { 274 if (fstate != 0)
169 rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, 275 pnv_pci_handle_eeh_config(phb, pe_no);
170 OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
171 if (rc) {
172 pr_warning("PCI %d: Failed to clear EEH freeze state"
173 " for PE#%d, err %lld\n",
174 phb->hose->global_number, pe_no, rc);
175 }
176 }
177} 276}
178 277
179static int pnv_pci_read_config(struct pci_bus *bus, 278static int pnv_pci_read_config(struct pci_bus *bus,
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 28ae4ca512c4..8bc479634643 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -9,6 +9,15 @@ enum pnv_phb_type {
9 PNV_PHB_IODA2, 9 PNV_PHB_IODA2,
10}; 10};
11 11
12/* Precise PHB model for error management */
13enum pnv_phb_model {
14 PNV_PHB_MODEL_UNKNOWN,
15 PNV_PHB_MODEL_P5IOC2,
16 PNV_PHB_MODEL_P7IOC,
17};
18
19#define PNV_PCI_DIAG_BUF_SIZE 4096
20
12/* Data associated with a PE, including IOMMU tracking etc.. */ 21/* Data associated with a PE, including IOMMU tracking etc.. */
13struct pnv_ioda_pe { 22struct pnv_ioda_pe {
14 /* A PE can be associated with a single device or an 23 /* A PE can be associated with a single device or an
@@ -56,6 +65,7 @@ struct pnv_ioda_pe {
56struct pnv_phb { 65struct pnv_phb {
57 struct pci_controller *hose; 66 struct pci_controller *hose;
58 enum pnv_phb_type type; 67 enum pnv_phb_type type;
68 enum pnv_phb_model model;
59 u64 opal_id; 69 u64 opal_id;
60 void __iomem *regs; 70 void __iomem *regs;
61 spinlock_t lock; 71 spinlock_t lock;
@@ -118,6 +128,12 @@ struct pnv_phb {
118 struct list_head pe_list; 128 struct list_head pe_list;
119 } ioda; 129 } ioda;
120 }; 130 };
131
132 /* PHB status structure */
133 union {
134 unsigned char blob[PNV_PCI_DIAG_BUF_SIZE];
135 struct OpalIoP7IOCPhbErrorData p7ioc;
136 } diag;
121}; 137};
122 138
123extern struct pci_ops pnv_pci_ops; 139extern struct pci_ops pnv_pci_ops;