]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
NVMe: reduce admin queue depth as workaround for Samsung EPIC SQ errata
authorAshok Vairavan <ashok.vairavan@oracle.com>
Thu, 8 Dec 2016 00:10:38 +0000 (16:10 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 1 Jun 2017 20:41:29 +0000 (13:41 -0700)
Orabug: 25186219

PCIe analyzer tracing by Oracle and Samsung revealed an errata in Samsung's
firmware for EPIC SSDs where the invalid completion entries in admin queue
and IO queue can occur  when the queues straddle an 8MB DMA address boundary.

This patch limits admin queue depth to 64 for EPIC SSDs.

Signed-off-by: Ashok Vairavan <ashok.vairavan@oracle.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Dhaval Giani <dhaval.giani@oracle.com>
drivers/nvme/host/pci.c

index f0b0b0c97d8e48b1d721f856a6c82bd89eb76bc8..55bac17cb94d920f747e0593d910a34dc4c4bfce 100644 (file)
@@ -1200,6 +1200,7 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev)
                 * condition. See NVM-Express 1.2 specification, section 4.1.2.
                 */
                dev->admin_tagset.queue_depth = NVME_AQ_BLKMQ_DEPTH - 1;
+               dev->admin_tagset.reserved_tags = 1;
                dev->admin_tagset.timeout = ADMIN_TIMEOUT;
                dev->admin_tagset.numa_node = dev_to_node(dev->dev);
                dev->admin_tagset.cmd_size = nvme_cmd_size(dev);
@@ -1244,7 +1245,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
 
        nvmeq = dev->queues[0];
        if (!nvmeq) {
-               nvmeq = nvme_alloc_queue(dev, 0, NVME_AQ_DEPTH);
+               nvmeq = nvme_alloc_queue(dev, 0, dev->admin_tagset.queue_depth + 1);
                if (!nvmeq)
                        return -ENOMEM;
        }
@@ -1696,10 +1697,17 @@ static int nvme_dev_map(struct nvme_dev *dev)
         * size should not span a DMA page (64 x 64B) unless NVME_CAP_MQES(cap) 
         * already restricted it further.
         */
-       if (pdev->vendor == PCI_VENDOR_ID_SAMSUNG && pdev->device == 0xa821 ) {
-               dev->q_depth = min_t(int, dev->q_depth, 64);
-               dev_warn(dev->dev, "detected Samsung NVMe controller, limit "
-                       "queue depth=%u.\n", dev->q_depth);
+
+       dev->admin_tagset.queue_depth = NVME_AQ_DEPTH - 1;
+
+       if (pdev->vendor == PCI_VENDOR_ID_SAMSUNG) {
+               if(pdev->device == 0xa821 || pdev->device == 0xa822) {
+                       dev->q_depth = min_t(int, dev->q_depth, 64);
+                       dev->admin_tagset.queue_depth = min_t(int, NVME_AQ_DEPTH, 64) - 1;
+                       dev_warn(dev->dev, "detected Samsung PM172x controller, limit "
+                               "IO queue depth to %u and admin queue depth to %u.\n", 
+                               dev->q_depth, dev->admin_tagset.queue_depth);
+               }
        }
 
        if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2))