aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-06-09 21:41:56 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-05 01:28:48 -0400
commit212d16cdca2d0f7708c9c1d284a845c22bfc90c4 (patch)
tree04d38ee81e32b9c1a06292ee5f07de0a53fdc324
parent05ec424e38fbba43829820b8f3634154f812e67e (diff)
powerpc/eeh: EEH support for VFIO PCI device
The patch exports functions to be used by new VFIO ioctl command, which will be introduced in subsequent patch, to support EEH functinality for VFIO PCI devices. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Acked-by: Alexander Graf <agraf@suse.de> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/eeh.h12
-rw-r--r--arch/powerpc/kernel/eeh.c268
2 files changed, 280 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 9537d83b8320..6e4789418233 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -172,6 +172,11 @@ enum {
172#define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */ 172#define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */
173#define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */ 173#define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */
174#define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */ 174#define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */
175#define EEH_PE_STATE_NORMAL 0 /* Normal state */
176#define EEH_PE_STATE_RESET 1 /* PE reset asserted */
177#define EEH_PE_STATE_STOPPED_IO_DMA 2 /* Frozen PE */
178#define EEH_PE_STATE_STOPPED_DMA 4 /* Stopped DMA, Enabled IO */
179#define EEH_PE_STATE_UNAVAIL 5 /* Unavailable */
175#define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */ 180#define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */
176#define EEH_RESET_HOT 1 /* Hot reset */ 181#define EEH_RESET_HOT 1 /* Hot reset */
177#define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */ 182#define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */
@@ -279,6 +284,13 @@ void eeh_add_device_late(struct pci_dev *);
279void eeh_add_device_tree_late(struct pci_bus *); 284void eeh_add_device_tree_late(struct pci_bus *);
280void eeh_add_sysfs_files(struct pci_bus *); 285void eeh_add_sysfs_files(struct pci_bus *);
281void eeh_remove_device(struct pci_dev *); 286void eeh_remove_device(struct pci_dev *);
287int eeh_dev_open(struct pci_dev *pdev);
288void eeh_dev_release(struct pci_dev *pdev);
289struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group);
290int eeh_pe_set_option(struct eeh_pe *pe, int option);
291int eeh_pe_get_state(struct eeh_pe *pe);
292int eeh_pe_reset(struct eeh_pe *pe, int option);
293int eeh_pe_configure(struct eeh_pe *pe);
282 294
283/** 295/**
284 * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. 296 * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index c8f1a9d2a67b..18c40fd1e62a 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -40,6 +40,7 @@
40#include <asm/eeh.h> 40#include <asm/eeh.h>
41#include <asm/eeh_event.h> 41#include <asm/eeh_event.h>
42#include <asm/io.h> 42#include <asm/io.h>
43#include <asm/iommu.h>
43#include <asm/machdep.h> 44#include <asm/machdep.h>
44#include <asm/ppc-pci.h> 45#include <asm/ppc-pci.h>
45#include <asm/rtas.h> 46#include <asm/rtas.h>
@@ -108,6 +109,9 @@ struct eeh_ops *eeh_ops = NULL;
108/* Lock to avoid races due to multiple reports of an error */ 109/* Lock to avoid races due to multiple reports of an error */
109DEFINE_RAW_SPINLOCK(confirm_error_lock); 110DEFINE_RAW_SPINLOCK(confirm_error_lock);
110 111
112/* Lock to protect passed flags */
113static DEFINE_MUTEX(eeh_dev_mutex);
114
111/* Buffer for reporting pci register dumps. Its here in BSS, and 115/* Buffer for reporting pci register dumps. Its here in BSS, and
112 * not dynamically alloced, so that it ends up in RMO where RTAS 116 * not dynamically alloced, so that it ends up in RMO where RTAS
113 * can access it. 117 * can access it.
@@ -1108,6 +1112,270 @@ void eeh_remove_device(struct pci_dev *dev)
1108 edev->mode &= ~EEH_DEV_SYSFS; 1112 edev->mode &= ~EEH_DEV_SYSFS;
1109} 1113}
1110 1114
1115/**
1116 * eeh_dev_open - Increase count of pass through devices for PE
1117 * @pdev: PCI device
1118 *
1119 * Increase count of passed through devices for the indicated
1120 * PE. In the result, the EEH errors detected on the PE won't be
1121 * reported. The PE owner will be responsible for detection
1122 * and recovery.
1123 */
1124int eeh_dev_open(struct pci_dev *pdev)
1125{
1126 struct eeh_dev *edev;
1127
1128 mutex_lock(&eeh_dev_mutex);
1129
1130 /* No PCI device ? */
1131 if (!pdev)
1132 goto out;
1133
1134 /* No EEH device or PE ? */
1135 edev = pci_dev_to_eeh_dev(pdev);
1136 if (!edev || !edev->pe)
1137 goto out;
1138
1139 /* Increase PE's pass through count */
1140 atomic_inc(&edev->pe->pass_dev_cnt);
1141 mutex_unlock(&eeh_dev_mutex);
1142
1143 return 0;
1144out:
1145 mutex_unlock(&eeh_dev_mutex);
1146 return -ENODEV;
1147}
1148EXPORT_SYMBOL_GPL(eeh_dev_open);
1149
1150/**
1151 * eeh_dev_release - Decrease count of pass through devices for PE
1152 * @pdev: PCI device
1153 *
1154 * Decrease count of pass through devices for the indicated PE. If
1155 * there is no passed through device in PE, the EEH errors detected
1156 * on the PE will be reported and handled as usual.
1157 */
1158void eeh_dev_release(struct pci_dev *pdev)
1159{
1160 struct eeh_dev *edev;
1161
1162 mutex_lock(&eeh_dev_mutex);
1163
1164 /* No PCI device ? */
1165 if (!pdev)
1166 goto out;
1167
1168 /* No EEH device ? */
1169 edev = pci_dev_to_eeh_dev(pdev);
1170 if (!edev || !edev->pe || !eeh_pe_passed(edev->pe))
1171 goto out;
1172
1173 /* Decrease PE's pass through count */
1174 atomic_dec(&edev->pe->pass_dev_cnt);
1175 WARN_ON(atomic_read(&edev->pe->pass_dev_cnt) < 0);
1176out:
1177 mutex_unlock(&eeh_dev_mutex);
1178}
1179EXPORT_SYMBOL(eeh_dev_release);
1180
1181/**
1182 * eeh_iommu_group_to_pe - Convert IOMMU group to EEH PE
1183 * @group: IOMMU group
1184 *
1185 * The routine is called to convert IOMMU group to EEH PE.
1186 */
1187struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group)
1188{
1189 struct iommu_table *tbl;
1190 struct pci_dev *pdev = NULL;
1191 struct eeh_dev *edev;
1192 bool found = false;
1193
1194 /* No IOMMU group ? */
1195 if (!group)
1196 return NULL;
1197
1198 /* No PCI device ? */
1199 for_each_pci_dev(pdev) {
1200 tbl = get_iommu_table_base(&pdev->dev);
1201 if (tbl && tbl->it_group == group) {
1202 found = true;
1203 break;
1204 }
1205 }
1206 if (!found)
1207 return NULL;
1208
1209 /* No EEH device or PE ? */
1210 edev = pci_dev_to_eeh_dev(pdev);
1211 if (!edev || !edev->pe)
1212 return NULL;
1213
1214 return edev->pe;
1215}
1216
1217/**
1218 * eeh_pe_set_option - Set options for the indicated PE
1219 * @pe: EEH PE
1220 * @option: requested option
1221 *
1222 * The routine is called to enable or disable EEH functionality
1223 * on the indicated PE, to enable IO or DMA for the frozen PE.
1224 */
1225int eeh_pe_set_option(struct eeh_pe *pe, int option)
1226{
1227 int ret = 0;
1228
1229 /* Invalid PE ? */
1230 if (!pe)
1231 return -ENODEV;
1232
1233 /*
1234 * EEH functionality could possibly be disabled, just
1235 * return error for the case. And the EEH functinality
1236 * isn't expected to be disabled on one specific PE.
1237 */
1238 switch (option) {
1239 case EEH_OPT_ENABLE:
1240 if (eeh_enabled())
1241 break;
1242 ret = -EIO;
1243 break;
1244 case EEH_OPT_DISABLE:
1245 break;
1246 case EEH_OPT_THAW_MMIO:
1247 case EEH_OPT_THAW_DMA:
1248 if (!eeh_ops || !eeh_ops->set_option) {
1249 ret = -ENOENT;
1250 break;
1251 }
1252
1253 ret = eeh_ops->set_option(pe, option);
1254 break;
1255 default:
1256 pr_debug("%s: Option %d out of range (%d, %d)\n",
1257 __func__, option, EEH_OPT_DISABLE, EEH_OPT_THAW_DMA);
1258 ret = -EINVAL;
1259 }
1260
1261 return ret;
1262}
1263EXPORT_SYMBOL_GPL(eeh_pe_set_option);
1264
1265/**
1266 * eeh_pe_get_state - Retrieve PE's state
1267 * @pe: EEH PE
1268 *
1269 * Retrieve the PE's state, which includes 3 aspects: enabled
1270 * DMA, enabled IO and asserted reset.
1271 */
1272int eeh_pe_get_state(struct eeh_pe *pe)
1273{
1274 int result, ret = 0;
1275 bool rst_active, dma_en, mmio_en;
1276
1277 /* Existing PE ? */
1278 if (!pe)
1279 return -ENODEV;
1280
1281 if (!eeh_ops || !eeh_ops->get_state)
1282 return -ENOENT;
1283
1284 result = eeh_ops->get_state(pe, NULL);
1285 rst_active = !!(result & EEH_STATE_RESET_ACTIVE);
1286 dma_en = !!(result & EEH_STATE_DMA_ENABLED);
1287 mmio_en = !!(result & EEH_STATE_MMIO_ENABLED);
1288
1289 if (rst_active)
1290 ret = EEH_PE_STATE_RESET;
1291 else if (dma_en && mmio_en)
1292 ret = EEH_PE_STATE_NORMAL;
1293 else if (!dma_en && !mmio_en)
1294 ret = EEH_PE_STATE_STOPPED_IO_DMA;
1295 else if (!dma_en && mmio_en)
1296 ret = EEH_PE_STATE_STOPPED_DMA;
1297 else
1298 ret = EEH_PE_STATE_UNAVAIL;
1299
1300 return ret;
1301}
1302EXPORT_SYMBOL_GPL(eeh_pe_get_state);
1303
1304/**
1305 * eeh_pe_reset - Issue PE reset according to specified type
1306 * @pe: EEH PE
1307 * @option: reset type
1308 *
1309 * The routine is called to reset the specified PE with the
1310 * indicated type, either fundamental reset or hot reset.
1311 * PE reset is the most important part for error recovery.
1312 */
1313int eeh_pe_reset(struct eeh_pe *pe, int option)
1314{
1315 int ret = 0;
1316
1317 /* Invalid PE ? */
1318 if (!pe)
1319 return -ENODEV;
1320
1321 if (!eeh_ops || !eeh_ops->set_option || !eeh_ops->reset)
1322 return -ENOENT;
1323
1324 switch (option) {
1325 case EEH_RESET_DEACTIVATE:
1326 ret = eeh_ops->reset(pe, option);
1327 if (ret)
1328 break;
1329
1330 /*
1331 * The PE is still in frozen state and we need to clear
1332 * that. It's good to clear frozen state after deassert
1333 * to avoid messy IO access during reset, which might
1334 * cause recursive frozen PE.
1335 */
1336 ret = eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO);
1337 if (!ret)
1338 ret = eeh_ops->set_option(pe, EEH_OPT_THAW_DMA);
1339 if (!ret)
1340 eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
1341 break;
1342 case EEH_RESET_HOT:
1343 case EEH_RESET_FUNDAMENTAL:
1344 ret = eeh_ops->reset(pe, option);
1345 break;
1346 default:
1347 pr_debug("%s: Unsupported option %d\n",
1348 __func__, option);
1349 ret = -EINVAL;
1350 }
1351
1352 return ret;
1353}
1354EXPORT_SYMBOL_GPL(eeh_pe_reset);
1355
1356/**
1357 * eeh_pe_configure - Configure PCI bridges after PE reset
1358 * @pe: EEH PE
1359 *
1360 * The routine is called to restore the PCI config space for
1361 * those PCI devices, especially PCI bridges affected by PE
1362 * reset issued previously.
1363 */
1364int eeh_pe_configure(struct eeh_pe *pe)
1365{
1366 int ret = 0;
1367
1368 /* Invalid PE ? */
1369 if (!pe)
1370 return -ENODEV;
1371
1372 /* Restore config space for the affected devices */
1373 eeh_pe_restore_bars(pe);
1374
1375 return ret;
1376}
1377EXPORT_SYMBOL_GPL(eeh_pe_configure);
1378
1111static int proc_eeh_show(struct seq_file *m, void *v) 1379static int proc_eeh_show(struct seq_file *m, void *v)
1112{ 1380{
1113 if (!eeh_enabled()) { 1381 if (!eeh_enabled()) {