nvme-pci: implement the HMB entry number and size limitations
authorChristoph Hellwig <hch@lst.de>
Mon, 11 Sep 2017 16:09:28 +0000 (12:09 -0400)
committerChristoph Hellwig <hch@lst.de>
Mon, 11 Sep 2017 16:29:40 +0000 (12:29 -0400)
Adds support for the new Host Memory Buffer Minimum Descriptor Entry Size
and Host Memory Maximum Descriptors Entries field that were added in
TP 4002 HMB Enhancements.  These allow the controller to advertise
limits for the usual number of segments in the host memory buffer, as
well as a minimum usable per-segment size.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Keith Busch <keith.busch@intel.com>
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
include/linux/nvme.h

index 8040fc14fd1568ddacdb6b949f8a923cfa4dfa94..acc816b67582f30524ad19f66843b071dfcef6ae 100644 (file)
@@ -1897,6 +1897,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                ctrl->cntlid = le16_to_cpu(id->cntlid);
                ctrl->hmpre = le32_to_cpu(id->hmpre);
                ctrl->hmmin = le32_to_cpu(id->hmmin);
+               ctrl->hmminds = le32_to_cpu(id->hmminds);
+               ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
        }
 
        kfree(id);
index b8ba7c85e61b71823b8bde2e6e02f091a1d71fcc..d3f3c4447515703a26683580071bd6fd160cd102 100644 (file)
@@ -181,8 +181,11 @@ struct nvme_ctrl {
        u64 ps_max_latency_us;
        bool apst_enabled;
 
+       /* PCIe only: */
        u32 hmpre;
        u32 hmmin;
+       u32 hmminds;
+       u16 hmmaxd;
 
        /* Fabrics only */
        u16 sqsize;
index 5ed12fbfaad60f29b6e5595acffa58f916a56950..4a2121335f48a0b4af31b413e04af8f9a6a52a2e 100644 (file)
@@ -1625,6 +1625,10 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
        tmp = (preferred + chunk_size - 1);
        do_div(tmp, chunk_size);
        max_entries = tmp;
+
+       if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
+               max_entries = dev->ctrl.hmmaxd;
+
        descs = dma_zalloc_coherent(dev->dev, max_entries * sizeof(*descs),
                        &descs_dma, GFP_KERNEL);
        if (!descs)
@@ -1681,7 +1685,7 @@ static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
 
        /* start big and work our way down */
        for (chunk_size = min_t(u64, preferred, PAGE_SIZE * MAX_ORDER_NR_PAGES);
-            chunk_size >= PAGE_SIZE * 2;
+            chunk_size >= max_t(u32, dev->ctrl.hmminds * 4096, PAGE_SIZE * 2);
             chunk_size /= 2) {
                if (!__nvme_alloc_host_mem(dev, preferred, chunk_size)) {
                        if (!min || dev->host_mem_size >= min)
index 5144f9103723e85662fa2581c44bf90756048e4d..87723c86f136f0e48c64a4c39fa9f0dcb3ad979d 100644 (file)
@@ -226,7 +226,9 @@ struct nvme_id_ctrl {
        __le16                  mntmt;
        __le16                  mxtmt;
        __le32                  sanicap;
-       __u8                    rsvd332[180];
+       __le32                  hmminds;
+       __le16                  hmmaxd;
+       __u8                    rsvd338[174];
        __u8                    sqes;
        __u8                    cqes;
        __le16                  maxcmd;