Author: mav
Date: Wed Aug 14 16:12:03 2019
New Revision: 351028
URL: https://svnweb.freebsd.org/changeset/base/351028

Log:
  Report NOIOB and NPWG fields as stripe size.
  
  Namespace Optimal I/O Boundary field added in NVMe 1.3 and Namespace
  Preferred Write Granularity added in 1.4 allow upper layers to align
  I/Os for improved SSD performance and endurance.
  
  I don't have hardware reportig those yet, but NPWG could probably be
  reported by bhyve.
  
  MFC after:    2 weeks
  Sponsored by: iXsystems, Inc.

Modified:
  head/sys/dev/nvme/nvme_ns.c
  head/sys/dev/nvme/nvme_private.h

Modified: head/sys/dev/nvme/nvme_ns.c
==============================================================================
--- head/sys/dev/nvme/nvme_ns.c Wed Aug 14 14:31:17 2019        (r351027)
+++ head/sys/dev/nvme/nvme_ns.c Wed Aug 14 16:12:03 2019        (r351028)
@@ -231,7 +231,11 @@ uint32_t
 nvme_ns_get_stripesize(struct nvme_namespace *ns)
 {
 
-       return (ns->stripesize);
+       if (((ns->data.nsfeat >> NVME_NS_DATA_NSFEAT_NPVALID_SHIFT) &
+           NVME_NS_DATA_NSFEAT_NPVALID_MASK) != 0 && ns->data.npwg != 0) {
+               return ((ns->data.npwg + 1) * nvme_ns_get_sector_size(ns));
+       }
+       return (ns->boundary);
 }
 
 static void
@@ -447,12 +451,12 @@ nvme_ns_bio_process(struct nvme_namespace *ns, struct 
 
        bp->bio_driver1 = cb_fn;
 
-       if (ns->stripesize > 0 &&
+       if (ns->boundary > 0 &&
            (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE)) {
                num_bios = nvme_get_num_segments(bp->bio_offset,
-                   bp->bio_bcount, ns->stripesize);
+                   bp->bio_bcount, ns->boundary);
                if (num_bios > 1)
-                       return (nvme_ns_split_bio(ns, bp, ns->stripesize));
+                       return (nvme_ns_split_bio(ns, bp, ns->boundary));
        }
 
        switch (bp->bio_cmd) {
@@ -511,27 +515,8 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t 
 
        ns->ctrlr = ctrlr;
        ns->id = id;
-       ns->stripesize = 0;
 
        /*
-        * Older Intel devices advertise in vendor specific space an alignment
-        * that improves performance.  If present use for the stripe size.  NVMe
-        * 1.3 standardized this as NOIOB, and newer Intel drives use that.
-        */
-       switch (pci_get_devid(ctrlr->dev)) {
-       case 0x09538086:                /* Intel DC PC3500 */
-       case 0x0a538086:                /* Intel DC PC3520 */
-       case 0x0a548086:                /* Intel DC PC4500 */
-       case 0x0a558086:                /* Dell Intel P4600 */
-               if (ctrlr->cdata.vs[3] != 0)
-                       ns->stripesize =
-                           (1 << ctrlr->cdata.vs[3]) * ctrlr->min_page_size;
-               break;
-       default:
-               break;
-       }
-
-       /*
         * Namespaces are reconstructed after a controller reset, so check
         *  to make sure we only call mtx_init once on each mtx.
         *
@@ -574,6 +559,27 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t 
                printf("lba format %d exceeds number supported (%d)\n",
                    flbas_fmt, ns->data.nlbaf + 1);
                return (ENXIO);
+       }
+
+       /*
+        * Older Intel devices advertise in vendor specific space an alignment
+        * that improves performance.  If present use for the stripe size.  NVMe
+        * 1.3 standardized this as NOIOB, and newer Intel drives use that.
+        */
+       switch (pci_get_devid(ctrlr->dev)) {
+       case 0x09538086:                /* Intel DC PC3500 */
+       case 0x0a538086:                /* Intel DC PC3520 */
+       case 0x0a548086:                /* Intel DC PC4500 */
+       case 0x0a558086:                /* Dell Intel P4600 */
+               if (ctrlr->cdata.vs[3] != 0)
+                       ns->boundary =
+                           (1 << ctrlr->cdata.vs[3]) * ctrlr->min_page_size;
+               else
+                       ns->boundary = 0;
+               break;
+       default:
+               ns->boundary = ns->data.noiob * nvme_ns_get_sector_size(ns);
+               break;
        }
 
        if (nvme_ctrlr_has_dataset_mgmt(&ctrlr->cdata))

Modified: head/sys/dev/nvme/nvme_private.h
==============================================================================
--- head/sys/dev/nvme/nvme_private.h    Wed Aug 14 14:31:17 2019        
(r351027)
+++ head/sys/dev/nvme/nvme_private.h    Wed Aug 14 16:12:03 2019        
(r351028)
@@ -223,7 +223,7 @@ struct nvme_namespace {
        uint32_t                        flags;
        struct cdev                     *cdev;
        void                            *cons_cookie[NVME_MAX_CONSUMERS];
-       uint32_t                        stripesize;
+       uint32_t                        boundary;
        struct mtx                      lock;
 };
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to