diff options
author | Dave Jiang <dave.jiang@intel.com> | 2015-08-26 16:17:30 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2015-09-21 11:40:05 -0400 |
commit | 4222a9074339fccc59526cbf30d8d2ec41468574 (patch) | |
tree | 60c072474058d21babc7d7ee86e66efe78844d7b | |
parent | ad4a7b5065c1b4f5176e7d031c3cc2b36f776884 (diff) |
dmaengine: ioatdma: add PCIe AER handlers
Adding AER handlers in order to handle any PCIe errors.
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r-- | drivers/dma/ioat/init.c | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index 793c5dd6a0e7..4ef0c5e07912 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <linux/prefetch.h> | 28 | #include <linux/prefetch.h> |
29 | #include <linux/dca.h> | 29 | #include <linux/dca.h> |
30 | #include <linux/aer.h> | ||
30 | #include "dma.h" | 31 | #include "dma.h" |
31 | #include "registers.h" | 32 | #include "registers.h" |
32 | #include "hw.h" | 33 | #include "hw.h" |
@@ -1211,14 +1212,91 @@ static void ioat_shutdown(struct pci_dev *pdev) | |||
1211 | ioat_disable_interrupts(ioat_dma); | 1212 | ioat_disable_interrupts(ioat_dma); |
1212 | } | 1213 | } |
1213 | 1214 | ||
1215 | void ioat_resume(struct ioatdma_device *ioat_dma) | ||
1216 | { | ||
1217 | struct ioatdma_chan *ioat_chan; | ||
1218 | u32 chanerr; | ||
1219 | int i; | ||
1220 | |||
1221 | for (i = 0; i < IOAT_MAX_CHANS; i++) { | ||
1222 | ioat_chan = ioat_dma->idx[i]; | ||
1223 | if (!ioat_chan) | ||
1224 | continue; | ||
1225 | |||
1226 | spin_lock_bh(&ioat_chan->prep_lock); | ||
1227 | clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state); | ||
1228 | spin_unlock_bh(&ioat_chan->prep_lock); | ||
1229 | |||
1230 | chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); | ||
1231 | writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET); | ||
1232 | |||
1233 | /* no need to reset as shutdown already did that */ | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1214 | #define DRV_NAME "ioatdma" | 1237 | #define DRV_NAME "ioatdma" |
1215 | 1238 | ||
1239 | static pci_ers_result_t ioat_pcie_error_detected(struct pci_dev *pdev, | ||
1240 | enum pci_channel_state error) | ||
1241 | { | ||
1242 | dev_dbg(&pdev->dev, "%s: PCIe AER error %d\n", DRV_NAME, error); | ||
1243 | |||
1244 | /* quiesce and block I/O */ | ||
1245 | ioat_shutdown(pdev); | ||
1246 | |||
1247 | return PCI_ERS_RESULT_NEED_RESET; | ||
1248 | } | ||
1249 | |||
1250 | static pci_ers_result_t ioat_pcie_error_slot_reset(struct pci_dev *pdev) | ||
1251 | { | ||
1252 | pci_ers_result_t result = PCI_ERS_RESULT_RECOVERED; | ||
1253 | int err; | ||
1254 | |||
1255 | dev_dbg(&pdev->dev, "%s post reset handling\n", DRV_NAME); | ||
1256 | |||
1257 | if (pci_enable_device_mem(pdev) < 0) { | ||
1258 | dev_err(&pdev->dev, | ||
1259 | "Failed to enable PCIe device after reset.\n"); | ||
1260 | result = PCI_ERS_RESULT_DISCONNECT; | ||
1261 | } else { | ||
1262 | pci_set_master(pdev); | ||
1263 | pci_restore_state(pdev); | ||
1264 | pci_save_state(pdev); | ||
1265 | pci_wake_from_d3(pdev, false); | ||
1266 | } | ||
1267 | |||
1268 | err = pci_cleanup_aer_uncorrect_error_status(pdev); | ||
1269 | if (err) { | ||
1270 | dev_err(&pdev->dev, | ||
1271 | "AER uncorrect error status clear failed: %#x\n", err); | ||
1272 | } | ||
1273 | |||
1274 | return result; | ||
1275 | } | ||
1276 | |||
1277 | static void ioat_pcie_error_resume(struct pci_dev *pdev) | ||
1278 | { | ||
1279 | struct ioatdma_device *ioat_dma = pci_get_drvdata(pdev); | ||
1280 | |||
1281 | dev_dbg(&pdev->dev, "%s: AER handling resuming\n", DRV_NAME); | ||
1282 | |||
1283 | /* initialize and bring everything back */ | ||
1284 | ioat_resume(ioat_dma); | ||
1285 | } | ||
1286 | |||
1287 | static const struct pci_error_handlers ioat_err_handler = { | ||
1288 | .error_detected = ioat_pcie_error_detected, | ||
1289 | .slot_reset = ioat_pcie_error_slot_reset, | ||
1290 | .resume = ioat_pcie_error_resume, | ||
1291 | }; | ||
1292 | |||
1216 | static struct pci_driver ioat_pci_driver = { | 1293 | static struct pci_driver ioat_pci_driver = { |
1217 | .name = DRV_NAME, | 1294 | .name = DRV_NAME, |
1218 | .id_table = ioat_pci_tbl, | 1295 | .id_table = ioat_pci_tbl, |
1219 | .probe = ioat_pci_probe, | 1296 | .probe = ioat_pci_probe, |
1220 | .remove = ioat_remove, | 1297 | .remove = ioat_remove, |
1221 | .shutdown = ioat_shutdown, | 1298 | .shutdown = ioat_shutdown, |
1299 | .err_handler = &ioat_err_handler, | ||
1222 | }; | 1300 | }; |
1223 | 1301 | ||
1224 | static struct ioatdma_device * | 1302 | static struct ioatdma_device * |
@@ -1271,13 +1349,17 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1271 | pci_set_drvdata(pdev, device); | 1349 | pci_set_drvdata(pdev, device); |
1272 | 1350 | ||
1273 | device->version = readb(device->reg_base + IOAT_VER_OFFSET); | 1351 | device->version = readb(device->reg_base + IOAT_VER_OFFSET); |
1274 | if (device->version >= IOAT_VER_3_0) | 1352 | if (device->version >= IOAT_VER_3_0) { |
1275 | err = ioat3_dma_probe(device, ioat_dca_enabled); | 1353 | err = ioat3_dma_probe(device, ioat_dca_enabled); |
1276 | else | 1354 | |
1355 | if (device->version >= IOAT_VER_3_3) | ||
1356 | pci_enable_pcie_error_reporting(pdev); | ||
1357 | } else | ||
1277 | return -ENODEV; | 1358 | return -ENODEV; |
1278 | 1359 | ||
1279 | if (err) { | 1360 | if (err) { |
1280 | dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n"); | 1361 | dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n"); |
1362 | pci_disable_pcie_error_reporting(pdev); | ||
1281 | return -ENODEV; | 1363 | return -ENODEV; |
1282 | } | 1364 | } |
1283 | 1365 | ||
@@ -1297,6 +1379,8 @@ static void ioat_remove(struct pci_dev *pdev) | |||
1297 | free_dca_provider(device->dca); | 1379 | free_dca_provider(device->dca); |
1298 | device->dca = NULL; | 1380 | device->dca = NULL; |
1299 | } | 1381 | } |
1382 | |||
1383 | pci_disable_pcie_error_reporting(pdev); | ||
1300 | ioat_dma_remove(device); | 1384 | ioat_dma_remove(device); |
1301 | } | 1385 | } |
1302 | 1386 | ||