aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-09-29 22:39:01 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2014-09-30 03:15:14 -0400
commit4eeeff0ebcdeabf3f76c4eece0593e98c6619be8 (patch)
treecf0760e5efe03913afa52375b037f50734907124
parent4d4f577e4b5ee1299096438bbcf743bbe14f33ab (diff)
powerpc/eeh: Unfreeze PE on enabling EEH functionality
When passing through PE to guest, that's possibly in frozen state. The driver for the pass-through devices on guest side can't be loaded successfully as reported. We already had one gate in eeh_dev_open() to clear PE frozen state accordingly, but that's not enough because the function is only called at QEMU startup for once. The patch adds another gate in eeh_pe_set_option() so that the PE frozen state can be cleared at QEMU restart time. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/eeh.h1
-rw-r--r--arch/powerpc/kernel/eeh.c60
2 files changed, 33 insertions, 28 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 4fa15796537a..b793fdfb37f3 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -286,6 +286,7 @@ void eeh_add_device_late(struct pci_dev *);
286void eeh_add_device_tree_late(struct pci_bus *); 286void eeh_add_device_tree_late(struct pci_bus *);
287void eeh_add_sysfs_files(struct pci_bus *); 287void eeh_add_sysfs_files(struct pci_bus *);
288void eeh_remove_device(struct pci_dev *); 288void eeh_remove_device(struct pci_dev *);
289int eeh_unfreeze_pe(struct eeh_pe *pe, bool sw_state);
289int eeh_dev_open(struct pci_dev *pdev); 290int eeh_dev_open(struct pci_dev *pdev);
290void eeh_dev_release(struct pci_dev *pdev); 291void eeh_dev_release(struct pci_dev *pdev);
291struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group); 292struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group);
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index b79a8331965f..b569ce2a8037 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -1164,6 +1164,31 @@ void eeh_remove_device(struct pci_dev *dev)
1164 edev->mode &= ~EEH_DEV_SYSFS; 1164 edev->mode &= ~EEH_DEV_SYSFS;
1165} 1165}
1166 1166
1167int eeh_unfreeze_pe(struct eeh_pe *pe, bool sw_state)
1168{
1169 int ret;
1170
1171 ret = eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
1172 if (ret) {
1173 pr_warn("%s: Failure %d enabling IO on PHB#%x-PE#%x\n",
1174 __func__, ret, pe->phb->global_number, pe->addr);
1175 return ret;
1176 }
1177
1178 ret = eeh_pci_enable(pe, EEH_OPT_THAW_DMA);
1179 if (ret) {
1180 pr_warn("%s: Failure %d enabling DMA on PHB#%x-PE#%x\n",
1181 __func__, ret, pe->phb->global_number, pe->addr);
1182 return ret;
1183 }
1184
1185 /* Clear software isolated state */
1186 if (sw_state && (pe->state & EEH_PE_ISOLATED))
1187 eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
1188
1189 return ret;
1190}
1191
1167/** 1192/**
1168 * eeh_dev_open - Increase count of pass through devices for PE 1193 * eeh_dev_open - Increase count of pass through devices for PE
1169 * @pdev: PCI device 1194 * @pdev: PCI device
@@ -1176,7 +1201,6 @@ void eeh_remove_device(struct pci_dev *dev)
1176int eeh_dev_open(struct pci_dev *pdev) 1201int eeh_dev_open(struct pci_dev *pdev)
1177{ 1202{
1178 struct eeh_dev *edev; 1203 struct eeh_dev *edev;
1179 int flag = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
1180 int ret = -ENODEV; 1204 int ret = -ENODEV;
1181 1205
1182 mutex_lock(&eeh_dev_mutex); 1206 mutex_lock(&eeh_dev_mutex);
@@ -1196,31 +1220,9 @@ int eeh_dev_open(struct pci_dev *pdev)
1196 * in frozen PE won't work properly. Clear the frozen state 1220 * in frozen PE won't work properly. Clear the frozen state
1197 * in advance. 1221 * in advance.
1198 */ 1222 */
1199 ret = eeh_ops->get_state(edev->pe, NULL); 1223 ret = eeh_unfreeze_pe(edev->pe, true);
1200 if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT && 1224 if (ret)
1201 (ret & flag) != flag) { 1225 goto out;
1202 ret = eeh_ops->set_option(edev->pe, EEH_OPT_THAW_MMIO);
1203 if (ret) {
1204 pr_warn("%s: Failure %d enabling MMIO "
1205 "for PHB#%x-PE#%x\n",
1206 __func__, ret, edev->phb->global_number,
1207 edev->pe->addr);
1208 goto out;
1209 }
1210
1211 ret = eeh_ops->set_option(edev->pe, EEH_OPT_THAW_DMA);
1212 if (ret) {
1213 pr_warn("%s: Failure %d enabling DMA "
1214 "for PHB#%x-PE#%x\n",
1215 __func__, ret, edev->phb->global_number,
1216 edev->pe->addr);
1217 goto out;
1218 }
1219 }
1220
1221 /* Clear software isolated state */
1222 if (edev->pe->state & EEH_PE_ISOLATED)
1223 eeh_pe_state_clear(edev->pe, EEH_PE_ISOLATED);
1224 1226
1225 /* Increase PE's pass through count */ 1227 /* Increase PE's pass through count */
1226 atomic_inc(&edev->pe->pass_dev_cnt); 1228 atomic_inc(&edev->pe->pass_dev_cnt);
@@ -1338,8 +1340,10 @@ int eeh_pe_set_option(struct eeh_pe *pe, int option)
1338 */ 1340 */
1339 switch (option) { 1341 switch (option) {
1340 case EEH_OPT_ENABLE: 1342 case EEH_OPT_ENABLE:
1341 if (eeh_enabled()) 1343 if (eeh_enabled()) {
1344 ret = eeh_unfreeze_pe(pe, true);
1342 break; 1345 break;
1346 }
1343 ret = -EIO; 1347 ret = -EIO;
1344 break; 1348 break;
1345 case EEH_OPT_DISABLE: 1349 case EEH_OPT_DISABLE:
@@ -1351,7 +1355,7 @@ int eeh_pe_set_option(struct eeh_pe *pe, int option)
1351 break; 1355 break;
1352 } 1356 }
1353 1357
1354 ret = eeh_ops->set_option(pe, option); 1358 ret = eeh_pci_enable(pe, option);
1355 break; 1359 break;
1356 default: 1360 default:
1357 pr_debug("%s: Option %d out of range (%d, %d)\n", 1361 pr_debug("%s: Option %d out of range (%d, %d)\n",