Author: mav
Date: Thu Aug 20 02:54:44 2020
New Revision: 364414
URL: https://svnweb.freebsd.org/changeset/base/364414

Log:
  MFC r364185: Fill device serial_num and device_id in NVMe XPT.
  
  It allows to report GEOM::lunid for nda(4) same as for nvd(4).  Since
  NVMe now allows multiple LUs (namespaces) with multiple paths unique
  LU identification is important.  The serial_num field is filled same
  as before with the controller serial number, while device_id is based
  on namespace GUID and/or EUI64 fields as recommended by "NVM Express:
  SCSI Translation Reference" and matching nvd(4) at the end.

Modified:
  stable/12/sys/cam/nvme/nvme_xpt.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/cam/nvme/nvme_xpt.c
==============================================================================
--- stable/12/sys/cam/nvme/nvme_xpt.c   Thu Aug 20 02:51:18 2020        
(r364413)
+++ stable/12/sys/cam/nvme/nvme_xpt.c   Thu Aug 20 02:54:44 2020        
(r364414)
@@ -311,9 +311,11 @@ nvme_probe_done(struct cam_periph *periph, union ccb *
        struct nvme_controller_data *nvme_cdata;
        nvme_probe_softc *softc;
        struct cam_path *path;
+       struct scsi_vpd_device_id *did;
+       struct scsi_vpd_id_descriptor *idd;
        cam_status status;
        u_int32_t  priority;
-       int found = 1;
+       int found = 1, e, g, len;
 
        CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("nvme_probe_done\n"));
 
@@ -370,6 +372,21 @@ device_fail:       if ((path->device->flags & 
CAM_DEV_UNCONF
                bcopy(&softc->cd, nvme_cdata, sizeof(*nvme_cdata));
                path->device->nvme_cdata = nvme_cdata;
 
+               /* Save/update serial number. */
+               if (path->device->serial_num != NULL) {
+                       free(path->device->serial_num, M_CAMXPT);
+                       path->device->serial_num = NULL;
+                       path->device->serial_num_len = 0;
+               }
+               path->device->serial_num = (u_int8_t *)
+                   malloc(NVME_SERIAL_NUMBER_LENGTH + 1, M_CAMXPT, M_NOWAIT);
+               if (path->device->serial_num != NULL) {
+                       cam_strvis(path->device->serial_num, nvme_cdata->sn,
+                           NVME_SERIAL_NUMBER_LENGTH, 
NVME_SERIAL_NUMBER_LENGTH + 1);
+                       path->device->serial_num_len =
+                           strlen(path->device->serial_num);
+               }
+
 //             nvme_find_quirk(path->device);
                nvme_device_transport(path);
                NVME_PROBE_SET_ACTION(softc, NVME_PROBE_IDENTIFY_NS);
@@ -395,6 +412,53 @@ device_fail:       if ((path->device->flags & 
CAM_DEV_UNCONF
                bcopy(&softc->ns, nvme_data, sizeof(*nvme_data));
                path->device->nvme_data = nvme_data;
 
+               /* Save/update device_id based on NGUID and/or EUI64. */
+               if (path->device->device_id != NULL) {
+                       free(path->device->device_id, M_CAMXPT);
+                       path->device->device_id = NULL;
+                       path->device->device_id_len = 0;
+               }
+               len = 0;
+               for (g = 0; g < sizeof(nvme_data->nguid); g++) {
+                       if (nvme_data->nguid[g] != 0)
+                               break;
+               }
+               if (g < sizeof(nvme_data->nguid))
+                       len += sizeof(struct scsi_vpd_id_descriptor) + 16;
+               for (e = 0; e < sizeof(nvme_data->eui64); e++) {
+                       if (nvme_data->eui64[e] != 0)
+                               break;
+               }
+               if (e < sizeof(nvme_data->eui64))
+                       len += sizeof(struct scsi_vpd_id_descriptor) + 8;
+               if (len > 0) {
+                       path->device->device_id = (u_int8_t *)
+                           malloc(SVPD_DEVICE_ID_HDR_LEN + len,
+                           M_CAMXPT, M_NOWAIT);
+               }
+               if (path->device->device_id != NULL) {
+                       did = (struct scsi_vpd_device_id 
*)path->device->device_id;
+                       did->device = SID_QUAL_LU_CONNECTED | T_DIRECT;
+                       did->page_code = SVPD_DEVICE_ID;
+                       scsi_ulto2b(len, did->length);
+                       idd = (struct scsi_vpd_id_descriptor *)(did + 1);
+                       if (g < sizeof(nvme_data->nguid)) {
+                               idd->proto_codeset = SVPD_ID_CODESET_BINARY;
+                               idd->id_type = SVPD_ID_ASSOC_LUN | 
SVPD_ID_TYPE_EUI64;
+                               idd->length = 16;
+                               bcopy(nvme_data->nguid, idd->identifier, 16);
+                               idd = (struct scsi_vpd_id_descriptor *)
+                                   &idd->identifier[16];
+                       }
+                       if (e < sizeof(nvme_data->eui64)) {
+                               idd->proto_codeset = SVPD_ID_CODESET_BINARY;
+                               idd->id_type = SVPD_ID_ASSOC_LUN | 
SVPD_ID_TYPE_EUI64;
+                               idd->length = 8;
+                               bcopy(nvme_data->eui64, idd->identifier, 8);
+                       }
+                       path->device->device_id_len = SVPD_DEVICE_ID_HDR_LEN + 
len;
+               }
+
                if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
                        path->device->flags &= ~CAM_DEV_UNCONFIGURED;
                        xpt_acquire_device(path->device);
@@ -547,9 +611,9 @@ nvme_alloc_device(struct cam_eb *bus, struct cam_et *t
        device->maxtags = 0;
        device->inq_flags = 0;
        device->queue_flags = 0;
-       device->device_id = NULL;       /* XXX Need to set this somewhere */
+       device->device_id = NULL;
        device->device_id_len = 0;
-       device->serial_num = NULL;      /* XXX Need to set this somewhere */
+       device->serial_num = NULL;
        device->serial_num_len = 0;
        return (device);
 }
_______________________________________________
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