svn commit: r366179 - in stable/12/sys: cam cam/nvme dev/nvme

Colin Percival cperciva at FreeBSD.org
Sat Sep 26 00:58:28 UTC 2020


Author: cperciva
Date: Sat Sep 26 00:58:27 2020
New Revision: 366179
URL: https://svnweb.freebsd.org/changeset/base/366179

Log:
  MFC r360483,360484: Make nvmecontrol work with nda like it does with
  nvd, and associated bits.
  
  This commit changes the size of 'struct ccb_pathinq_settings_nvme', which
  would normally risk breaking kernel ABI; however, that structure is only
  ever used as part of a union with larger structures -- so nothing really
  changes size.
  
  r360483:
    Return the nvmeX device associated with the ndaX device.
  
    Add the nvmeX device to the XPT_PATH_INQ nvme specific
    information. while one could figure this out by looking up the
    domain:bus:slot:function, it's a lot easier to have the SIM set it
    directly since the sim knows this.
  
  r360484:
    Implement the NVME_GET_NSID and NVME_PASSTHROUGH_CMD ioctls
  
    With these two ioctls implemented in the nda driver, nvmecontrol now
    works with nda just like it does with nvd. It eliminates the need to
    jump through odd hoops to get this data.
  
  Discussed with:	imp

Modified:
  stable/12/sys/cam/cam_ccb.h
  stable/12/sys/cam/nvme/nvme_da.c
  stable/12/sys/dev/nvme/nvme_sim.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/cam/cam_ccb.h
==============================================================================
--- stable/12/sys/cam/cam_ccb.h	Sat Sep 26 00:40:56 2020	(r366178)
+++ stable/12/sys/cam/cam_ccb.h	Sat Sep 26 00:58:27 2020	(r366179)
@@ -630,6 +630,7 @@ struct ccb_pathinq_settings_sas {
 	u_int32_t bitrate;	/* Mbps */
 };
 
+#define NVME_DEV_NAME_LEN	52
 struct ccb_pathinq_settings_nvme {
 	uint32_t nsid;		/* Namespace ID for this path */
 	uint32_t domain;
@@ -637,7 +638,10 @@ struct ccb_pathinq_settings_nvme {
 	uint8_t  slot;
 	uint8_t  function;
 	uint8_t  extra;
+	char	 dev_name[NVME_DEV_NAME_LEN]; /* nvme controller dev name for this device */
 };
+_Static_assert(sizeof(struct ccb_pathinq_settings_nvme) == 64,
+    "ccb_pathinq_settings_nvme too big");
 
 #define	PATHINQ_SETTINGS_SIZE	128
 
@@ -1030,6 +1034,7 @@ struct ccb_trans_settings_nvme 
 	uint8_t		speed;		/* PCIe generation for each lane */
 	uint8_t		max_lanes;	/* Number of PCIe lanes */
 	uint8_t		max_speed;	/* PCIe generation for each lane */
+
 };
 
 #include <cam/mmc/mmc_bus.h>

Modified: stable/12/sys/cam/nvme/nvme_da.c
==============================================================================
--- stable/12/sys/cam/nvme/nvme_da.c	Sat Sep 26 00:40:56 2020	(r366178)
+++ stable/12/sys/cam/nvme/nvme_da.c	Sat Sep 26 00:58:27 2020	(r366179)
@@ -88,6 +88,7 @@ typedef enum {
 	NDA_CCB_BUFFER_IO	= 0x01,
 	NDA_CCB_DUMP            = 0x02,
 	NDA_CCB_TRIM            = 0x03,
+	NDA_CCB_PASS            = 0x04,
 	NDA_CCB_TYPE_MASK	= 0x0F,
 } nda_ccb_state;
 
@@ -136,6 +137,7 @@ struct nda_trim_request {
 
 /* Need quirk table */
 
+static	disk_ioctl_t	ndaioctl;
 static	disk_strategy_t	ndastrategy;
 static	dumper_t	ndadump;
 static	periph_init_t	ndainit;
@@ -354,6 +356,91 @@ ndaschedule(struct cam_periph *periph)
 	cam_iosched_schedule(softc->cam_iosched, periph);
 }
 
+static int
+ndaioctl(struct disk *dp, u_long cmd, void *data, int fflag,
+    struct thread *td)
+{
+	struct cam_periph *periph;
+	struct nda_softc *softc;
+
+	periph = (struct cam_periph *)dp->d_drv1;
+	softc = (struct nda_softc *)periph->softc;
+
+	switch (cmd) {
+	case NVME_IO_TEST:
+	case NVME_BIO_TEST:
+		/*
+		 * These don't map well to the underlying CCBs, so
+		 * they are usupported via CAM.
+		 */
+		return (ENOTTY);
+	case NVME_GET_NSID:
+	{
+		struct nvme_get_nsid *gnsid = (struct nvme_get_nsid *)data;
+		struct ccb_pathinq cpi;
+
+		xpt_path_inq(&cpi, periph->path);
+		strncpy(gnsid->cdev, cpi.xport_specific.nvme.dev_name,
+		    sizeof(gnsid->cdev));
+		gnsid->nsid = cpi.xport_specific.nvme.nsid;
+		return (0);
+	}
+	case NVME_PASSTHROUGH_CMD:
+	{
+		struct nvme_pt_command *pt;
+		union ccb *ccb;
+		struct cam_periph_map_info mapinfo;
+		u_int maxmap = MAXPHYS;	/* XXX is this right */
+		int error;
+
+		/*
+		 * Create a NVME_IO CCB to do the passthrough command.
+		 */
+		pt = (struct nvme_pt_command *)data;
+		ccb = xpt_alloc_ccb();
+		xpt_setup_ccb(&ccb->ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+		ccb->ccb_state = NDA_CCB_PASS;
+		cam_fill_nvmeio(&ccb->nvmeio,
+		    0,			/* Retries */
+		    ndadone,
+		    (pt->is_read ? CAM_DIR_IN : CAM_DIR_OUT) | CAM_DATA_VADDR,
+		    pt->buf,
+		    pt->len,
+		    nda_default_timeout * 1000);
+		memcpy(&ccb->nvmeio.cmd, &pt->cmd, sizeof(pt->cmd));
+
+		/*
+		 * Wire the user memory in this request for the I/O
+		 */
+		memset(&mapinfo, 0, sizeof(mapinfo));
+		error = cam_periph_mapmem(ccb, &mapinfo, maxmap);
+		if (error)
+			return (error);
+
+		/*
+		 * Lock the periph and run the command. XXX do we need
+		 * to lock the periph?
+		 */
+		cam_periph_lock(periph);
+		cam_periph_runccb(ccb, NULL, CAM_RETRY_SELTO, SF_RETRY_UA | SF_NO_PRINT,
+		    NULL);
+		cam_periph_unlock(periph);
+
+		/*
+		 * Tear down mapping and return status.
+		 */
+		cam_periph_unmapmem(ccb, &mapinfo);
+		cam_periph_lock(periph);
+		error = (ccb->ccb_h.status == CAM_REQ_CMP) ? 0 : EIO;
+		xpt_release_ccb(ccb);
+		return (error);
+	}
+	default:
+		break;
+	}
+	return (ENOTTY);
+}
+
 /*
  * Actually translate the requested transfer into one the physical driver
  * can understand.  The transfer is described by a buf and will include
@@ -735,11 +822,8 @@ ndaregister(struct cam_periph *periph, void *arg)
 	/* ident_data parsing */
 
 	periph->softc = softc;
-
 	softc->quirks = NDA_Q_NONE;
-
 	xpt_path_inq(&cpi, periph->path);
-
 	TASK_INIT(&softc->sysctl_task, 0, ndasysctlinit, periph);
 
 	/*
@@ -763,6 +847,7 @@ ndaregister(struct cam_periph *periph, void *arg)
 	disk->d_open = ndaopen;
 	disk->d_close = ndaclose;
 	disk->d_strategy = ndastrategy;
+	disk->d_ioctl = ndaioctl;
 	disk->d_getattr = ndagetattr;
 	disk->d_dump = ndadump;
 	disk->d_gone = ndadiskgonecb;
@@ -1108,6 +1193,8 @@ ndadone(struct cam_periph *periph, union ccb *done_ccb
 	}
 	case NDA_CCB_DUMP:
 		/* No-op.  We're polling */
+		return;
+	case NDA_CCB_PASS:
 		return;
 	default:
 		break;

Modified: stable/12/sys/dev/nvme/nvme_sim.c
==============================================================================
--- stable/12/sys/dev/nvme/nvme_sim.c	Sat Sep 26 00:40:56 2020	(r366178)
+++ stable/12/sys/dev/nvme/nvme_sim.c	Sat Sep 26 00:58:27 2020	(r366179)
@@ -197,6 +197,8 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb)
 		cpi->xport_specific.nvme.slot = pci_get_slot(dev);
 		cpi->xport_specific.nvme.function = pci_get_function(dev);
 		cpi->xport_specific.nvme.extra = 0;
+		strncpy(cpi->xport_specific.nvme.dev_name, device_get_nameunit(ctrlr->dev),
+		    sizeof(cpi->xport_specific.nvme.dev_name));
 		cpi->ccb_h.status = CAM_REQ_CMP;
 		break;
 	}


More information about the svn-src-stable-12 mailing list