aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-09-29 22:38:54 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2014-09-30 03:15:08 -0400
commit404079c87e2f390611b71c8f03b9f5ddb6241131 (patch)
tree2431314baf03bec6f1d413bd75d6e4af77f41f71 /arch/powerpc/kernel
parent316233ff878451e198e3633fd9165c437007a309 (diff)
powerpc/eeh: Clear frozen state on passing device
When passing through device, its PE might have been put into frozen state. One obvious example would be: the passed PE is forced to be offline because of hitting maximal allowed EEH errors in userland. In that case, the frozen state won't be cleared and then the PE is returned back to host, which might not have chance detecting and recovering from it. The patch adds more check when passing through device and clear the PE frozen state if necessary. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/eeh.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 6b4690f315d3..f5677684429e 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -1150,6 +1150,8 @@ void eeh_remove_device(struct pci_dev *dev)
1150int eeh_dev_open(struct pci_dev *pdev) 1150int eeh_dev_open(struct pci_dev *pdev)
1151{ 1151{
1152 struct eeh_dev *edev; 1152 struct eeh_dev *edev;
1153 int flag = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
1154 int ret = -ENODEV;
1153 1155
1154 mutex_lock(&eeh_dev_mutex); 1156 mutex_lock(&eeh_dev_mutex);
1155 1157
@@ -1162,6 +1164,38 @@ int eeh_dev_open(struct pci_dev *pdev)
1162 if (!edev || !edev->pe) 1164 if (!edev || !edev->pe)
1163 goto out; 1165 goto out;
1164 1166
1167 /*
1168 * The PE might have been put into frozen state, but we
1169 * didn't detect that yet. The passed through PCI devices
1170 * in frozen PE won't work properly. Clear the frozen state
1171 * in advance.
1172 */
1173 ret = eeh_ops->get_state(edev->pe, NULL);
1174 if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT &&
1175 (ret & flag) != flag) {
1176 ret = eeh_ops->set_option(edev->pe, EEH_OPT_THAW_MMIO);
1177 if (ret) {
1178 pr_warn("%s: Failure %d enabling MMIO "
1179 "for PHB#%x-PE#%x\n",
1180 __func__, ret, edev->phb->global_number,
1181 edev->pe->addr);
1182 goto out;
1183 }
1184
1185 ret = eeh_ops->set_option(edev->pe, EEH_OPT_THAW_DMA);
1186 if (ret) {
1187 pr_warn("%s: Failure %d enabling DMA "
1188 "for PHB#%x-PE#%x\n",
1189 __func__, ret, edev->phb->global_number,
1190 edev->pe->addr);
1191 goto out;
1192 }
1193 }
1194
1195 /* Clear software isolated state */
1196 if (edev->pe->state & EEH_PE_ISOLATED)
1197 eeh_pe_state_clear(edev->pe, EEH_PE_ISOLATED);
1198
1165 /* Increase PE's pass through count */ 1199 /* Increase PE's pass through count */
1166 atomic_inc(&edev->pe->pass_dev_cnt); 1200 atomic_inc(&edev->pe->pass_dev_cnt);
1167 mutex_unlock(&eeh_dev_mutex); 1201 mutex_unlock(&eeh_dev_mutex);
@@ -1169,7 +1203,7 @@ int eeh_dev_open(struct pci_dev *pdev)
1169 return 0; 1203 return 0;
1170out: 1204out:
1171 mutex_unlock(&eeh_dev_mutex); 1205 mutex_unlock(&eeh_dev_mutex);
1172 return -ENODEV; 1206 return ret;
1173} 1207}
1174EXPORT_SYMBOL_GPL(eeh_dev_open); 1208EXPORT_SYMBOL_GPL(eeh_dev_open);
1175 1209