Commit 4222a907 authored by Dave Jiang's avatar Dave Jiang Committed by Vinod Koul

dmaengine: ioatdma: add PCIe AER handlers

Adding AER handlers in order to handle any PCIe errors.
Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent ad4a7b50
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/dca.h> #include <linux/dca.h>
#include <linux/aer.h>
#include "dma.h" #include "dma.h"
#include "registers.h" #include "registers.h"
#include "hw.h" #include "hw.h"
...@@ -1211,14 +1212,91 @@ static void ioat_shutdown(struct pci_dev *pdev) ...@@ -1211,14 +1212,91 @@ static void ioat_shutdown(struct pci_dev *pdev)
ioat_disable_interrupts(ioat_dma); ioat_disable_interrupts(ioat_dma);
} }
void ioat_resume(struct ioatdma_device *ioat_dma)
{
struct ioatdma_chan *ioat_chan;
u32 chanerr;
int i;
for (i = 0; i < IOAT_MAX_CHANS; i++) {
ioat_chan = ioat_dma->idx[i];
if (!ioat_chan)
continue;
spin_lock_bh(&ioat_chan->prep_lock);
clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
spin_unlock_bh(&ioat_chan->prep_lock);
chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
/* no need to reset as shutdown already did that */
}
}
#define DRV_NAME "ioatdma" #define DRV_NAME "ioatdma"
static pci_ers_result_t ioat_pcie_error_detected(struct pci_dev *pdev,
enum pci_channel_state error)
{
dev_dbg(&pdev->dev, "%s: PCIe AER error %d\n", DRV_NAME, error);
/* quiesce and block I/O */
ioat_shutdown(pdev);
return PCI_ERS_RESULT_NEED_RESET;
}
static pci_ers_result_t ioat_pcie_error_slot_reset(struct pci_dev *pdev)
{
pci_ers_result_t result = PCI_ERS_RESULT_RECOVERED;
int err;
dev_dbg(&pdev->dev, "%s post reset handling\n", DRV_NAME);
if (pci_enable_device_mem(pdev) < 0) {
dev_err(&pdev->dev,
"Failed to enable PCIe device after reset.\n");
result = PCI_ERS_RESULT_DISCONNECT;
} else {
pci_set_master(pdev);
pci_restore_state(pdev);
pci_save_state(pdev);
pci_wake_from_d3(pdev, false);
}
err = pci_cleanup_aer_uncorrect_error_status(pdev);
if (err) {
dev_err(&pdev->dev,
"AER uncorrect error status clear failed: %#x\n", err);
}
return result;
}
static void ioat_pcie_error_resume(struct pci_dev *pdev)
{
struct ioatdma_device *ioat_dma = pci_get_drvdata(pdev);
dev_dbg(&pdev->dev, "%s: AER handling resuming\n", DRV_NAME);
/* initialize and bring everything back */
ioat_resume(ioat_dma);
}
static const struct pci_error_handlers ioat_err_handler = {
.error_detected = ioat_pcie_error_detected,
.slot_reset = ioat_pcie_error_slot_reset,
.resume = ioat_pcie_error_resume,
};
static struct pci_driver ioat_pci_driver = { static struct pci_driver ioat_pci_driver = {
.name = DRV_NAME, .name = DRV_NAME,
.id_table = ioat_pci_tbl, .id_table = ioat_pci_tbl,
.probe = ioat_pci_probe, .probe = ioat_pci_probe,
.remove = ioat_remove, .remove = ioat_remove,
.shutdown = ioat_shutdown, .shutdown = ioat_shutdown,
.err_handler = &ioat_err_handler,
}; };
static struct ioatdma_device * static struct ioatdma_device *
...@@ -1271,13 +1349,17 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1271,13 +1349,17 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, device); pci_set_drvdata(pdev, device);
device->version = readb(device->reg_base + IOAT_VER_OFFSET); device->version = readb(device->reg_base + IOAT_VER_OFFSET);
if (device->version >= IOAT_VER_3_0) if (device->version >= IOAT_VER_3_0) {
err = ioat3_dma_probe(device, ioat_dca_enabled); err = ioat3_dma_probe(device, ioat_dca_enabled);
else
if (device->version >= IOAT_VER_3_3)
pci_enable_pcie_error_reporting(pdev);
} else
return -ENODEV; return -ENODEV;
if (err) { if (err) {
dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n"); dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n");
pci_disable_pcie_error_reporting(pdev);
return -ENODEV; return -ENODEV;
} }
...@@ -1297,6 +1379,8 @@ static void ioat_remove(struct pci_dev *pdev) ...@@ -1297,6 +1379,8 @@ static void ioat_remove(struct pci_dev *pdev)
free_dca_provider(device->dca); free_dca_provider(device->dca);
device->dca = NULL; device->dca = NULL;
} }
pci_disable_pcie_error_reporting(pdev);
ioat_dma_remove(device); ioat_dma_remove(device);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment