Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Apr 2013 17:56:48 +0000 (UTC)
From:      Jim Harris <jimharris@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r249422 - in head: sbin/nvmecontrol sys/dev/nvme
Message-ID:  <201304121756.r3CHumDp095933@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jimharris
Date: Fri Apr 12 17:56:47 2013
New Revision: 249422
URL: http://svnweb.freebsd.org/changeset/base/249422

Log:
  Remove the NVME_IDENTIFY_CONTROLLER and NVME_IDENTIFY_NAMESPACE IOCTLs and replace
  them with the NVMe passthrough equivalent.
  
  Sponsored by:	Intel

Modified:
  head/sbin/nvmecontrol/nvmecontrol.c
  head/sys/dev/nvme/nvme.h
  head/sys/dev/nvme/nvme_ctrlr.c
  head/sys/dev/nvme/nvme_ns.c

Modified: head/sbin/nvmecontrol/nvmecontrol.c
==============================================================================
--- head/sbin/nvmecontrol/nvmecontrol.c	Fri Apr 12 17:52:17 2013	(r249421)
+++ head/sbin/nvmecontrol/nvmecontrol.c	Fri Apr 12 17:56:47 2013	(r249422)
@@ -210,6 +210,53 @@ ns_get_sector_size(struct nvme_namespace
 	return (1 << nsdata->lbaf[0].lbads);
 }
 
+static void
+read_controller_data(int fd, struct nvme_controller_data *cdata)
+{
+	struct nvme_pt_command	pt;
+
+	memset(&pt, 0, sizeof(pt));
+	pt.cmd.opc = NVME_OPC_IDENTIFY;
+	pt.cmd.cdw10 = 1;
+	pt.buf = cdata;
+	pt.len = sizeof(*cdata);
+	pt.is_read = 1;
+
+	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) {
+		printf("Identify request failed. errno=%d (%s)\n",
+		    errno, strerror(errno));
+		exit(EX_IOERR);
+	}
+
+	if (nvme_completion_is_error(&pt.cpl)) {
+		printf("Passthrough command returned error.\n");
+		exit(EX_IOERR);
+	}
+}
+
+static void
+read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata)
+{
+	struct nvme_pt_command	pt;
+
+	memset(&pt, 0, sizeof(pt));
+	pt.cmd.opc = NVME_OPC_IDENTIFY;
+	pt.cmd.nsid = nsid;
+	pt.buf = nsdata;
+	pt.len = sizeof(*nsdata);
+	pt.is_read = 1;
+
+	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) {
+		printf("Identify request failed. errno=%d (%s)\n",
+		    errno, strerror(errno));
+		exit(EX_IOERR);
+	}
+
+	if (nvme_completion_is_error(&pt.cpl)) {
+		printf("Passthrough command returned error.\n");
+		exit(EX_IOERR);
+	}
+}
 
 static void
 devlist(int argc, char *argv[])
@@ -251,33 +298,12 @@ devlist(int argc, char *argv[])
 			continue;
 		}
 
-		if (ioctl(fd, NVME_IDENTIFY_CONTROLLER, &cdata) < 0) {
-			printf("Identify request to %s failed. errno=%d (%s)\n",
-			    path, errno, strerror(errno));
-			exit_code = EX_IOERR;
-			continue;
-		}
-
+		read_controller_data(fd, &cdata);
 		printf("%6s: %s\n", name, cdata.mn);
 
 		for (i = 0; i < cdata.nn; i++) {
 			sprintf(name, "nvme%dns%d", ctrlr, i+1);
-			sprintf(path, "/dev/%s", name);
-
-			fd = open(path, O_RDWR);
-			if (fd < 0) {
-				printf("Could not open %s. errno=%d (%s)\n",
-				    path, errno, strerror(errno));
-				exit_code = EX_NOPERM;
-				continue;
-			}
-			if (ioctl(fd, NVME_IDENTIFY_NAMESPACE, &nsdata) < 0) {
-				printf("Identify request to %s failed. "
-				    "errno=%d (%s)\n", path, errno,
-				    strerror(errno));
-				exit_code = EX_IOERR;
-				continue;
-			}
+			read_namespace_data(fd, i+1, &nsdata);
 			printf("  %10s (%lldGB)\n",
 				name,
 				nsdata.nsze *
@@ -329,11 +355,7 @@ identify_ctrlr(int argc, char *argv[])
 		exit(EX_NOPERM);
 	}
 
-	if (ioctl(fd, NVME_IDENTIFY_CONTROLLER, &cdata) < 0) {
-		printf("Identify request to %s failed. errno=%d (%s)\n", path,
-		    errno, strerror(errno));
-		exit(EX_IOERR);
-	}
+	read_controller_data(fd, &cdata);
 
 	if (hexflag == 1) {
 		if (verboseflag == 1)
@@ -360,7 +382,8 @@ identify_ns(int argc, char *argv[])
 	struct nvme_namespace_data	nsdata;
 	struct stat			devstat;
 	char				path[64];
-	int				ch, fd, hexflag = 0, hexlength;
+	char				*nsloc;
+	int				ch, fd, hexflag = 0, hexlength, nsid;
 	int				verboseflag = 0;
 
 	while ((ch = getopt(argc, argv, "vx")) != -1) {
@@ -376,8 +399,41 @@ identify_ns(int argc, char *argv[])
 		}
 	}
 
+	/*
+	 * Check if the specified device node exists before continuing.
+	 *  This is a cleaner check for cases where the correct controller
+	 *  is specified, but an invalid namespace on that controller.
+	 */
 	sprintf(path, "/dev/%s", argv[optind]);
+	if (stat(path, &devstat) < 0) {
+		printf("Invalid device node %s. errno=%d (%s)\n", path, errno,
+		    strerror(errno));
+		exit(EX_IOERR);
+	}
 
+	nsloc = strstr(argv[optind], "ns");
+	if (nsloc == NULL) {
+		printf("Invalid namepsace %s.\n", argv[optind]);
+		exit(EX_IOERR);
+	}
+
+	/*
+	 * Pull the namespace id from the string. +2 skips past the "ns" part
+	 *  of the string.
+	 */
+	nsid = strtol(nsloc + 2, NULL, 10);
+	if (nsid == 0 && errno != 0) {
+		printf("Invalid namespace ID %s.\n", argv[optind]);
+		exit(EX_IOERR);
+	}
+
+	/*
+	 * We send IDENTIFY commands to the controller, not the namespace,
+	 *  since it is an admin cmd.  So the path should only include the
+	 *  nvmeX part of the nvmeXnsY string.
+	 */
+	sprintf(path, "/dev/");
+	strncat(path, argv[optind], nsloc - argv[optind]);
 	if (stat(path, &devstat) < 0) {
 		printf("Invalid device node %s. errno=%d (%s)\n", path, errno,
 		    strerror(errno));
@@ -391,11 +447,7 @@ identify_ns(int argc, char *argv[])
 		exit(EX_NOPERM);
 	}
 
-	if (ioctl(fd, NVME_IDENTIFY_NAMESPACE, &nsdata) < 0) {
-		printf("Identify request to %s failed. errno=%d (%s)\n", path,
-		    errno, strerror(errno));
-		exit(EX_IOERR);
-	}
+	read_namespace_data(fd, nsid, &nsdata);
 
 	if (hexflag == 1) {
 		if (verboseflag == 1)

Modified: head/sys/dev/nvme/nvme.h
==============================================================================
--- head/sys/dev/nvme/nvme.h	Fri Apr 12 17:52:17 2013	(r249421)
+++ head/sys/dev/nvme/nvme.h	Fri Apr 12 17:56:47 2013	(r249422)
@@ -33,12 +33,11 @@
 #include <sys/types.h>
 #endif
 
-#define	NVME_IDENTIFY_CONTROLLER	_IOR('n', 0, struct nvme_controller_data)
-#define	NVME_IDENTIFY_NAMESPACE		_IOR('n', 1, struct nvme_namespace_data)
-#define	NVME_IO_TEST			_IOWR('n', 2, struct nvme_io_test)
-#define	NVME_BIO_TEST			_IOWR('n', 4, struct nvme_io_test)
-#define	NVME_RESET_CONTROLLER		_IO('n', 5)
-#define	NVME_PASSTHROUGH_CMD		_IOWR('n', 6, struct nvme_pt_command)
+#define	NVME_PASSTHROUGH_CMD		_IOWR('n', 0, struct nvme_pt_command)
+#define	NVME_RESET_CONTROLLER		_IO('n', 1)
+
+#define	NVME_IO_TEST			_IOWR('n', 100, struct nvme_io_test)
+#define	NVME_BIO_TEST			_IOWR('n', 101, struct nvme_io_test)
 
 /*
  * Use to mark a command to apply to all namespaces, or to retrieve global

Modified: head/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- head/sys/dev/nvme/nvme_ctrlr.c	Fri Apr 12 17:52:17 2013	(r249421)
+++ head/sys/dev/nvme/nvme_ctrlr.c	Fri Apr 12 17:56:47 2013	(r249422)
@@ -976,34 +976,12 @@ static int
 nvme_ctrlr_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
     struct thread *td)
 {
-	struct nvme_completion_poll_status	status;
 	struct nvme_controller			*ctrlr;
 	struct nvme_pt_command			*pt;
 
 	ctrlr = cdev->si_drv1;
 
 	switch (cmd) {
-	case NVME_IDENTIFY_CONTROLLER:
-#ifdef CHATHAM2
-		/*
-		 * Don't refresh data on Chatham, since Chatham returns
-		 *  garbage on IDENTIFY anyways.
-		 */
-		if (pci_get_devid(ctrlr->dev) == CHATHAM_PCI_ID) {
-			memcpy(arg, &ctrlr->cdata, sizeof(ctrlr->cdata));
-			break;
-		}
-#endif
-		/* Refresh data before returning to user. */
-		status.done = FALSE;
-		nvme_ctrlr_cmd_identify_controller(ctrlr, &ctrlr->cdata,
-		    nvme_completion_poll_cb, &status);
-		while (status.done == FALSE)
-			DELAY(5);
-		if (nvme_completion_is_error(&status.cpl))
-			return (ENXIO);
-		memcpy(arg, &ctrlr->cdata, sizeof(ctrlr->cdata));
-		break;
 	case NVME_RESET_CONTROLLER:
 		nvme_ctrlr_reset(ctrlr);
 		break;

Modified: head/sys/dev/nvme/nvme_ns.c
==============================================================================
--- head/sys/dev/nvme/nvme_ns.c	Fri Apr 12 17:52:17 2013	(r249421)
+++ head/sys/dev/nvme/nvme_ns.c	Fri Apr 12 17:56:47 2013	(r249422)
@@ -45,7 +45,6 @@ static int
 nvme_ns_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
     struct thread *td)
 {
-	struct nvme_completion_poll_status	status;
 	struct nvme_namespace			*ns;
 	struct nvme_controller			*ctrlr;
 	struct nvme_pt_command			*pt;
@@ -54,27 +53,6 @@ nvme_ns_ioctl(struct cdev *cdev, u_long 
 	ctrlr = ns->ctrlr;
 
 	switch (cmd) {
-	case NVME_IDENTIFY_NAMESPACE:
-#ifdef CHATHAM2
-		/*
-		 * Don't refresh data on Chatham, since Chatham returns
-		 *  garbage on IDENTIFY anyways.
-		 */
-		if (pci_get_devid(ctrlr->dev) == CHATHAM_PCI_ID) {
-			memcpy(arg, &ns->data, sizeof(ns->data));
-			break;
-		}
-#endif
-		/* Refresh data before returning to user. */
-		status.done = FALSE;
-		nvme_ctrlr_cmd_identify_namespace(ctrlr, ns->id, &ns->data,
-		    nvme_completion_poll_cb, &status);
-		while (status.done == FALSE)
-			DELAY(5);
-		if (nvme_completion_is_error(&status.cpl))
-			return (ENXIO);
-		memcpy(arg, &ns->data, sizeof(ns->data));
-		break;
 	case NVME_IO_TEST:
 	case NVME_BIO_TEST:
 		nvme_ns_test(ns, cmd, arg);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201304121756.r3CHumDp095933>