]> Git Repo - linux.git/blobdiff - drivers/nvme/host/pci.c
Merge branch 'for-4.5/core' of git://git.kernel.dk/linux-block
[linux.git] / drivers / nvme / host / pci.c
index b8a02221233cdb27b94191744dd5d7d8f277447c..f5c0e2613c7cc87fa04ec3bc30f51b14aa1c8278 100644 (file)
@@ -2541,8 +2541,17 @@ static void nvme_ns_remove(struct nvme_ns *ns)
 {
        bool kill = nvme_io_incapable(ns->dev) && !blk_queue_dying(ns->queue);
 
-       if (kill)
+       if (kill) {
                blk_set_queue_dying(ns->queue);
+
+               /*
+                * The controller was shutdown first if we got here through
+                * device removal. The shutdown may requeue outstanding
+                * requests. These need to be aborted immediately so
+                * del_gendisk doesn't block indefinitely for their completion.
+                */
+               blk_mq_abort_requeue_list(ns->queue);
+       }
        if (ns->disk->flags & GENHD_FL_UP)
                del_gendisk(ns->disk);
        if (kill || !blk_queue_dying(ns->queue)) {
@@ -2709,6 +2718,18 @@ static int nvme_dev_map(struct nvme_dev *dev)
        dev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH);
        dev->db_stride = 1 << NVME_CAP_STRIDE(cap);
        dev->dbs = ((void __iomem *)dev->bar) + 4096;
+
+       /*
+        * Temporary fix for the Apple controller found in the MacBook8,1 and
+        * some MacBook7,1 to avoid controller resets and data loss.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_APPLE && pdev->device == 0x2001) {
+               dev->q_depth = 2;
+               dev_warn(dev->dev, "detected Apple NVMe controller, set "
+                       "queue depth=%u to work around controller resets\n",
+                       dev->q_depth);
+       }
+
        if (readl(&dev->bar->vs) >= NVME_VS(1, 2))
                dev->cmb = nvme_map_cmb(dev);
 
@@ -2966,6 +2987,15 @@ static void nvme_dev_remove(struct nvme_dev *dev)
 {
        struct nvme_ns *ns, *next;
 
+       if (nvme_io_incapable(dev)) {
+               /*
+                * If the device is not capable of IO (surprise hot-removal,
+                * for example), we need to quiesce prior to deleting the
+                * namespaces. This will end outstanding requests and prevent
+                * attempts to sync dirty data.
+                */
+               nvme_dev_shutdown(dev);
+       }
        list_for_each_entry_safe(ns, next, &dev->namespaces, list)
                nvme_ns_remove(ns);
 }
This page took 0.029815 seconds and 4 git commands to generate.