svn commit: r366213 - in releng/12.2/sys: cam cam/nvme dev/nvme

Colin Percival cperciva at FreeBSD.org
Mon Sep 28 00:53:46 UTC 2020


Author: cperciva
Date: Mon Sep 28 00:53:45 2020
New Revision: 366213
URL: https://svnweb.freebsd.org/changeset/base/366213

Log:
  MFS r366179: Make nvmecontrol work with nda like it does with nvd, and
  associated bits.
  
  Approved by:	re (delphij)
  Sponsored by:	https://www.patreon.com/cperciva

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

Modified: releng/12.2/sys/cam/cam_ccb.h
==============================================================================
--- releng/12.2/sys/cam/cam_ccb.h	Mon Sep 28 00:52:16 2020	(r366212)
+++ releng/12.2/sys/cam/cam_ccb.h	Mon Sep 28 00:53:45 2020	(r366213)
@@ -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: releng/12.2/sys/cam/nvme/nvme_da.c
==============================================================================
--- releng/12.2/sys/cam/nvme/nvme_da.c	Mon Sep 28 00:52:16 2020	(r366212)
+++ releng/12.2/sys/cam/nvme/nvme_da.c	Mon Sep 28 00:53:45 2020	(r366213)
@@ -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: releng/12.2/sys/dev/nvme/nvme_sim.c
==============================================================================
--- releng/12.2/sys/dev/nvme/nvme_sim.c	Mon Sep 28 00:52:16 2020	(r366212)
+++ releng/12.2/sys/dev/nvme/nvme_sim.c	Mon Sep 28 00:53:45 2020	(r366213)
@@ -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-all mailing list