aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2015-12-07 17:30:31 -0500
committerJens Axboe <axboe@fb.com>2015-12-22 12:09:06 -0500
commita0a3408ee614848c27b0d36c2fe490da3b387b8d (patch)
tree2b045db6bf91c40535e2d49b3b923d779f60834c
parentbbc758ec04c2f30805ce0fcdfbaa4c3445fafbae (diff)
NVMe: Add pci error handlers
Requests enabling pcie aer support. Shuts down the controller on error detected with io frozen state prior to requesting slot reset; resumes controller after reset completes. Signed-off-by: Keith Busch <keith.busch@intel.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/nvme/host/pci.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index b88708affad8..b82bbea909cd 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -12,6 +12,7 @@
12 * more details. 12 * more details.
13 */ 13 */
14 14
15#include <linux/aer.h>
15#include <linux/bitops.h> 16#include <linux/bitops.h>
16#include <linux/blkdev.h> 17#include <linux/blkdev.h>
17#include <linux/blk-mq.h> 18#include <linux/blk-mq.h>
@@ -1670,6 +1671,8 @@ static int nvme_dev_map(struct nvme_dev *dev)
1670 if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2)) 1671 if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2))
1671 dev->cmb = nvme_map_cmb(dev); 1672 dev->cmb = nvme_map_cmb(dev);
1672 1673
1674 pci_enable_pcie_error_reporting(pdev);
1675 pci_save_state(pdev);
1673 return 0; 1676 return 0;
1674 1677
1675 unmap: 1678 unmap:
@@ -1697,8 +1700,10 @@ static void nvme_dev_unmap(struct nvme_dev *dev)
1697 pci_release_regions(pdev); 1700 pci_release_regions(pdev);
1698 } 1701 }
1699 1702
1700 if (pci_is_enabled(pdev)) 1703 if (pci_is_enabled(pdev)) {
1704 pci_disable_pcie_error_reporting(pdev);
1701 pci_disable_device(pdev); 1705 pci_disable_device(pdev);
1706 }
1702} 1707}
1703 1708
1704struct nvme_delq_ctx { 1709struct nvme_delq_ctx {
@@ -2225,13 +2230,6 @@ static void nvme_remove(struct pci_dev *pdev)
2225 nvme_put_ctrl(&dev->ctrl); 2230 nvme_put_ctrl(&dev->ctrl);
2226} 2231}
2227 2232
2228/* These functions are yet to be implemented */
2229#define nvme_error_detected NULL
2230#define nvme_dump_registers NULL
2231#define nvme_link_reset NULL
2232#define nvme_slot_reset NULL
2233#define nvme_error_resume NULL
2234
2235#ifdef CONFIG_PM_SLEEP 2233#ifdef CONFIG_PM_SLEEP
2236static int nvme_suspend(struct device *dev) 2234static int nvme_suspend(struct device *dev)
2237{ 2235{
@@ -2254,10 +2252,46 @@ static int nvme_resume(struct device *dev)
2254 2252
2255static SIMPLE_DEV_PM_OPS(nvme_dev_pm_ops, nvme_suspend, nvme_resume); 2253static SIMPLE_DEV_PM_OPS(nvme_dev_pm_ops, nvme_suspend, nvme_resume);
2256 2254
2255static pci_ers_result_t nvme_error_detected(struct pci_dev *pdev,
2256 pci_channel_state_t state)
2257{
2258 struct nvme_dev *dev = pci_get_drvdata(pdev);
2259
2260 /*
2261 * A frozen channel requires a reset. When detected, this method will
2262 * shutdown the controller to quiesce. The controller will be restarted
2263 * after the slot reset through driver's slot_reset callback.
2264 */
2265 dev_warn(&pdev->dev, "error detected: state:%d\n", state);
2266 switch (state) {
2267 case pci_channel_io_normal:
2268 return PCI_ERS_RESULT_CAN_RECOVER;
2269 case pci_channel_io_frozen:
2270 nvme_dev_shutdown(dev);
2271 return PCI_ERS_RESULT_NEED_RESET;
2272 case pci_channel_io_perm_failure:
2273 return PCI_ERS_RESULT_DISCONNECT;
2274 }
2275 return PCI_ERS_RESULT_NEED_RESET;
2276}
2277
2278static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)
2279{
2280 struct nvme_dev *dev = pci_get_drvdata(pdev);
2281
2282 dev_info(&pdev->dev, "restart after slot reset\n");
2283 pci_restore_state(pdev);
2284 queue_work(nvme_workq, &dev->reset_work);
2285 return PCI_ERS_RESULT_RECOVERED;
2286}
2287
2288static void nvme_error_resume(struct pci_dev *pdev)
2289{
2290 pci_cleanup_aer_uncorrect_error_status(pdev);
2291}
2292
2257static const struct pci_error_handlers nvme_err_handler = { 2293static const struct pci_error_handlers nvme_err_handler = {
2258 .error_detected = nvme_error_detected, 2294 .error_detected = nvme_error_detected,
2259 .mmio_enabled = nvme_dump_registers,
2260 .link_reset = nvme_link_reset,
2261 .slot_reset = nvme_slot_reset, 2295 .slot_reset = nvme_slot_reset,
2262 .resume = nvme_error_resume, 2296 .resume = nvme_error_resume,
2263 .reset_notify = nvme_reset_notify, 2297 .reset_notify = nvme_reset_notify,