aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-07-21 00:42:34 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-05 02:33:34 -0400
commit5828790931901329c5e2c5ec0baf1c3c2b74967f (patch)
treee6970df2f470326fbd2c33323c820f41a042b9c1
parent49dec9222f14a01b2de7b11e3de5adc204a74302 (diff)
powerpc/powernv: Handle compound PE for EEH
The patch handles compound PE for EEH backend. If one specific PE in compound group has been frozen, we enforces to freeze all PEs in the group. If we're enable DMA or MMIO for one PE in compound group, DMA or MMIO of all PEs in the group will be enabled. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c125
1 files changed, 78 insertions, 47 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 09cf80be462c..c945bed4dc9e 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -187,10 +187,10 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
187 */ 187 */
188static int ioda_eeh_set_option(struct eeh_pe *pe, int option) 188static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
189{ 189{
190 s64 ret;
191 u32 pe_no;
192 struct pci_controller *hose = pe->phb; 190 struct pci_controller *hose = pe->phb;
193 struct pnv_phb *phb = hose->private_data; 191 struct pnv_phb *phb = hose->private_data;
192 int enable, ret = 0;
193 s64 rc;
194 194
195 /* Check on PE number */ 195 /* Check on PE number */
196 if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { 196 if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) {
@@ -201,41 +201,38 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
201 return -EINVAL; 201 return -EINVAL;
202 } 202 }
203 203
204 pe_no = pe->addr;
205 switch (option) { 204 switch (option) {
206 case EEH_OPT_DISABLE: 205 case EEH_OPT_DISABLE:
207 ret = -EEXIST; 206 return -EPERM;
208 break;
209 case EEH_OPT_ENABLE: 207 case EEH_OPT_ENABLE:
210 ret = 0; 208 return 0;
211 break;
212 case EEH_OPT_THAW_MMIO: 209 case EEH_OPT_THAW_MMIO:
213 ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, 210 enable = OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO;
214 OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO);
215 if (ret) {
216 pr_warning("%s: Failed to enable MMIO for "
217 "PHB#%x-PE#%x, err=%lld\n",
218 __func__, hose->global_number, pe_no, ret);
219 return -EIO;
220 }
221
222 break; 211 break;
223 case EEH_OPT_THAW_DMA: 212 case EEH_OPT_THAW_DMA:
224 ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, 213 enable = OPAL_EEH_ACTION_CLEAR_FREEZE_DMA;
225 OPAL_EEH_ACTION_CLEAR_FREEZE_DMA);
226 if (ret) {
227 pr_warning("%s: Failed to enable DMA for "
228 "PHB#%x-PE#%x, err=%lld\n",
229 __func__, hose->global_number, pe_no, ret);
230 return -EIO;
231 }
232
233 break; 214 break;
234 default: 215 default:
235 pr_warning("%s: Invalid option %d\n", __func__, option); 216 pr_warn("%s: Invalid option %d\n",
217 __func__, option);
236 return -EINVAL; 218 return -EINVAL;
237 } 219 }
238 220
221 /* If PHB supports compound PE, to handle it */
222 if (phb->unfreeze_pe) {
223 ret = phb->unfreeze_pe(phb, pe->addr, enable);
224 } else {
225 rc = opal_pci_eeh_freeze_clear(phb->opal_id,
226 pe->addr,
227 enable);
228 if (rc != OPAL_SUCCESS) {
229 pr_warn("%s: Failure %lld enable %d for PHB#%x-PE#%x\n",
230 __func__, rc, option, phb->hose->global_number,
231 pe->addr);
232 ret = -EIO;
233 }
234 }
235
239 return ret; 236 return ret;
240} 237}
241 238
@@ -309,16 +306,23 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
309 return result; 306 return result;
310 } 307 }
311 308
312 /* Fetch state from hardware */ 309 /*
313 rc = opal_pci_eeh_freeze_status(phb->opal_id, 310 * Fetch PE state from hardware. If the PHB
314 pe->addr, 311 * supports compound PE, let it handle that.
315 &fstate, 312 */
316 &pcierr, 313 if (phb->get_pe_state) {
317 NULL); 314 fstate = phb->get_pe_state(phb, pe->addr);
318 if (rc != OPAL_SUCCESS) { 315 } else {
319 pr_warn("%s: Failure %lld getting PHB#%x-PE%x state\n", 316 rc = opal_pci_eeh_freeze_status(phb->opal_id,
320 __func__, rc, phb->hose->global_number, pe->addr); 317 pe->addr,
321 return EEH_STATE_NOT_SUPPORT; 318 &fstate,
319 &pcierr,
320 NULL);
321 if (rc != OPAL_SUCCESS) {
322 pr_warn("%s: Failure %lld getting PHB#%x-PE%x state\n",
323 __func__, rc, phb->hose->global_number, pe->addr);
324 return EEH_STATE_NOT_SUPPORT;
325 }
322 } 326 }
323 327
324 /* Figure out state */ 328 /* Figure out state */
@@ -357,6 +361,9 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
357 } 361 }
358 362
359 /* 363 /*
364 * If PHB supports compound PE, to freeze all
365 * slave PEs for consistency.
366 *
360 * If the PE is switching to frozen state for the 367 * If the PE is switching to frozen state for the
361 * first time, to dump the PHB diag-data. 368 * first time, to dump the PHB diag-data.
362 */ 369 */
@@ -365,6 +372,9 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
365 !(result & EEH_STATE_MMIO_ACTIVE) && 372 !(result & EEH_STATE_MMIO_ACTIVE) &&
366 !(result & EEH_STATE_DMA_ACTIVE) && 373 !(result & EEH_STATE_DMA_ACTIVE) &&
367 !(pe->state & EEH_PE_ISOLATED)) { 374 !(pe->state & EEH_PE_ISOLATED)) {
375 if (phb->freeze_pe)
376 phb->freeze_pe(phb, pe->addr);
377
368 eeh_pe_state_mark(pe, EEH_PE_ISOLATED); 378 eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
369 ioda_eeh_phb_diag(pe); 379 ioda_eeh_phb_diag(pe);
370 } 380 }
@@ -723,22 +733,43 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
723static int ioda_eeh_get_pe(struct pci_controller *hose, 733static int ioda_eeh_get_pe(struct pci_controller *hose,
724 u16 pe_no, struct eeh_pe **pe) 734 u16 pe_no, struct eeh_pe **pe)
725{ 735{
726 struct eeh_pe *phb_pe, *dev_pe; 736 struct pnv_phb *phb = hose->private_data;
727 struct eeh_dev dev; 737 struct pnv_ioda_pe *pnv_pe;
738 struct eeh_pe *dev_pe;
739 struct eeh_dev edev;
728 740
729 /* Find the PHB PE */ 741 /*
730 phb_pe = eeh_phb_pe_get(hose); 742 * If PHB supports compound PE, to fetch
731 if (!phb_pe) 743 * the master PE because slave PE is invisible
732 return -EEXIST; 744 * to EEH core.
745 */
746 if (phb->get_pe_state) {
747 pnv_pe = &phb->ioda.pe_array[pe_no];
748 if (pnv_pe->flags & PNV_IODA_PE_SLAVE) {
749 pnv_pe = pnv_pe->master;
750 WARN_ON(!pnv_pe ||
751 !(pnv_pe->flags & PNV_IODA_PE_MASTER));
752 pe_no = pnv_pe->pe_number;
753 }
754 }
733 755
734 /* Find the PE according to PE# */ 756 /* Find the PE according to PE# */
735 memset(&dev, 0, sizeof(struct eeh_dev)); 757 memset(&edev, 0, sizeof(struct eeh_dev));
736 dev.phb = hose; 758 edev.phb = hose;
737 dev.pe_config_addr = pe_no; 759 edev.pe_config_addr = pe_no;
738 dev_pe = eeh_pe_get(&dev); 760 dev_pe = eeh_pe_get(&edev);
739 if (!dev_pe) return -EEXIST; 761 if (!dev_pe)
762 return -EEXIST;
740 763
764 /*
765 * At this point, we're sure the compound PE should
766 * be put into frozen state.
767 */
741 *pe = dev_pe; 768 *pe = dev_pe;
769 if (phb->freeze_pe &&
770 !(dev_pe->state & EEH_PE_ISOLATED))
771 phb->freeze_pe(phb, pe_no);
772
742 return 0; 773 return 0;
743} 774}
744 775