Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Jun 2017 23:15:29 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r320483 - head/sbin/nvmecontrol
Message-ID:  <201706292315.v5TNFTOp060309@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Thu Jun 29 23:15:28 2017
New Revision: 320483
URL: https://svnweb.freebsd.org/changeset/base/320483

Log:
  Improve wdc error log pulling.
  
  After review by the WDC engineers, improve how we pull down the
  so-called 'e6' logs. The 'c6' logs are obsolete and support for them
  has been removed because FreeBSD needed to pull them in chunks, which
  is incompatible with the 0xc6 opcode implementation. Rather than leave
  the code in place that produces bad log pulls, remove it.

Modified:
  head/sbin/nvmecontrol/wdc.c

Modified: head/sbin/nvmecontrol/wdc.c
==============================================================================
--- head/sbin/nvmecontrol/wdc.c	Thu Jun 29 22:09:32 2017	(r320482)
+++ head/sbin/nvmecontrol/wdc.c	Thu Jun 29 23:15:28 2017	(r320483)
@@ -47,36 +47,12 @@ __FBSDID("$FreeBSD$");
 #define WDC_NVME_CAP_DIAG_OPCODE	0xe6
 #define WDC_NVME_CAP_DIAG_CMD		0x0000
 
-#define WDC_NVME_DIAG_OPCODE		0xc6
-#define WDC_NVME_DRIVE_LOG_SIZE_CMD	0x0120
-#define WDC_NVME_DRIVE_LOG_CMD		0x0020
-#define WDC_NVME_CRASH_DUMP_SIZE_CMD	0x0320
-#define WDC_NVME_CRASH_DUMP_CMD		0x0420
-#define WDC_NVME_PFAIL_DUMP_SIZE_CMD	0x0520
-#define WDC_NVME_PFAIL_DUMP_CMD		0x0620
-
-#define WDC_NVME_CLEAR_DUMP_OPCODE	0xff
-#define WDC_NVME_CLEAR_CRASH_DUMP_CMD	0x0503
-#define WDC_NVME_CLEAR_PFAIL_DUMP_CMD	0x0603
-
 static void wdc_cap_diag(int argc, char *argv[]);
-static void wdc_drive_log(int argc, char *argv[]);
-static void wdc_get_crash_dump(int argc, char *argv[]);
-static void wdc_purge(int argc, char *argv[]);
-static void wdc_purge_monitor(int argc, char *argv[]);
 
 #define WDC_CAP_DIAG_USAGE	"\tnvmecontrol wdc cap-diag [-o path-template]\n"
-#define WDC_DRIVE_LOG_USAGE	"\tnvmecontrol wdc drive-log [-o path-template]\n"
-#define WDC_GET_CRASH_DUMP_USAGE "\tnvmecontrol wdc get-crash-dump [-o path-template]\n"
-#define WDC_PURGE_USAGE		"\tnvmecontrol wdc purge [-o path-template]\n"
-#define WDC_PURGE_MONITOR_USAGE	"\tnvmecontrol wdc purge-monitor\n"
 
 static struct nvme_function wdc_funcs[] = {
 	{"cap-diag",		wdc_cap_diag,		WDC_CAP_DIAG_USAGE},
-	{"drive-log",		wdc_drive_log,		WDC_DRIVE_LOG_USAGE},
-	{"get-crash-dump",	wdc_get_crash_dump,	WDC_GET_CRASH_DUMP_USAGE},
-	{"purge",		wdc_purge,		WDC_PURGE_USAGE},
-	{"purge_monitor",	wdc_purge_monitor,	WDC_PURGE_MONITOR_USAGE},
 	{NULL,			NULL,			NULL},
 };
 
@@ -123,8 +99,9 @@ wdc_get_data(int fd, uint32_t opcode, uint32_t len, ui
 
 static void
 wdc_do_dump(int fd, char *tmpl, const char *suffix, uint32_t opcode,
-    uint32_t size_cmd, uint32_t cmd, int len_off)
+    uint32_t cmd, int len_off)
 {
+	int first;
 	int fd2;
 	uint8_t *buf;
 	uint32_t len, offset;
@@ -132,52 +109,49 @@ wdc_do_dump(int fd, char *tmpl, const char *suffix, ui
 
 	wdc_append_serial_name(fd, tmpl, MAXPATHLEN, suffix);
 
-	buf = aligned_alloc(PAGE_SIZE, WDC_NVME_TOC_SIZE);
-	if (buf == NULL)
-		errx(1, "Can't get buffer to get size");
-	wdc_get_data(fd, opcode, WDC_NVME_TOC_SIZE,
-	    0, size_cmd, buf, WDC_NVME_TOC_SIZE);
-	len = be32dec(buf + len_off);
-
-	if (len == 0)
-		errx(1, "No data for %s", suffix);
-
-	printf("Dumping %d bytes to %s\n", len, tmpl);
 	/* XXX overwrite protection? */
-	fd2 = open(tmpl, O_WRONLY | O_CREAT | O_TRUNC);
+	fd2 = open(tmpl, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 	if (fd2 < 0)
 		err(1, "open %s", tmpl);
-	offset = 0;
 	buf = aligned_alloc(PAGE_SIZE, NVME_MAX_XFER_SIZE);
 	if (buf == NULL)
 		errx(1, "Can't get buffer to read dump");
-	while (len > 0) {
+	offset = 0;
+	len = NVME_MAX_XFER_SIZE;
+	first = 1;
+
+	do {
 		resid = len > NVME_MAX_XFER_SIZE ? NVME_MAX_XFER_SIZE : len;
 		wdc_get_data(fd, opcode, resid, offset, cmd, buf, resid);
+
+		if (first) {
+			len = be32dec(buf + len_off);
+			if (len == 0)
+				errx(1, "No data for %s", suffix);
+			if (memcmp("E6LG", buf, 4) != 0)
+				printf("Expected header of E6LG, found '%4.4s' instead\n",
+				    buf);
+			printf("Dumping %d bytes of version %d.%d log to %s\n", len,
+			    buf[8], buf[9], tmpl);
+			/*
+			 * Adjust amount to dump if total dump < 1MB,
+			 * though it likely doesn't matter to the WDC
+			 * analysis tools.
+			 */
+			if (resid > len)
+				resid = len;
+			first = 0;
+		}
 		if (write(fd2, buf, resid) != resid)
 			err(1, "write");
 		offset += resid;
 		len -= resid;
-	}
+	} while (len > 0);
 	free(buf);
 	close(fd2);
 }
 
 static void
-wdc_do_clear_dump(int fd, uint32_t opcode, uint32_t cmd)
-{
-	struct nvme_pt_command	pt;
-
-	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = opcode;
-	pt.cmd.cdw12 = cmd;
-	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
-		err(1, "wdc_do_clear_dump request failed");
-	if (nvme_completion_is_error(&pt.cpl))
-		errx(1, "wdc_do_clear_dump request returned error");
-}
-
-static void
 wdc_cap_diag_usage(void)
 {
 	fprintf(stderr, "usage:\n");
@@ -207,131 +181,11 @@ wdc_cap_diag(int argc, char *argv[])
 	open_dev(argv[optind], &fd, 1, 1);
 
 	wdc_do_dump(fd, path_tmpl, "cap_diag", WDC_NVME_CAP_DIAG_OPCODE,
-	    WDC_NVME_CAP_DIAG_CMD, WDC_NVME_CAP_DIAG_CMD, 4);
+	    WDC_NVME_CAP_DIAG_CMD, 4);
 
 	close(fd);
 
 	exit(1);	
-}
-
-static void
-wdc_drive_log_usage(void)
-{
-	fprintf(stderr, "usage:\n");
-	fprintf(stderr, WDC_DRIVE_LOG_USAGE);
-	exit(1);
-}
-
-static void
-wdc_drive_log(int argc, char *argv[])
-{
-	char path_tmpl[MAXPATHLEN];
-	int ch, fd;
-
-	path_tmpl[0] = '\0';
-	while ((ch = getopt(argc, argv, "o:")) != -1) {
-		switch ((char)ch) {
-		case 'o':
-			strlcpy(path_tmpl, optarg, MAXPATHLEN);
-			break;
-		default:
-			wdc_drive_log_usage();
-		}
-	}
-	/* Check that a controller was specified. */
-	if (optind >= argc)
-		wdc_drive_log_usage();
-	open_dev(argv[optind], &fd, 1, 1);
-
-	wdc_do_dump(fd, path_tmpl, "drive_log", WDC_NVME_DIAG_OPCODE,
-	    WDC_NVME_DRIVE_LOG_SIZE_CMD, WDC_NVME_DRIVE_LOG_CMD, 0);
-
-	close(fd);
-
-	exit(1);
-}
-
-static void
-wdc_get_crash_dump_usage(void)
-{
-	fprintf(stderr, "usage:\n");
-	fprintf(stderr, WDC_CAP_DIAG_USAGE);
-	exit(1);
-}
-
-static void
-wdc_get_crash_dump(int argc, char *argv[])
-{
-	char path_tmpl[MAXPATHLEN];
-	int ch, fd;
-
-	while ((ch = getopt(argc, argv, "o:")) != -1) {
-		switch ((char)ch) {
-		case 'o':
-			strlcpy(path_tmpl, optarg, MAXPATHLEN);
-			break;
-		default:
-			wdc_get_crash_dump_usage();
-		}
-	}
-	/* Check that a controller was specified. */
-	if (optind >= argc)
-		wdc_get_crash_dump_usage();
-	open_dev(argv[optind], &fd, 1, 1);
-
-	wdc_do_dump(fd, path_tmpl, "crash_dump", WDC_NVME_DIAG_OPCODE,
-	    WDC_NVME_CRASH_DUMP_SIZE_CMD, WDC_NVME_CRASH_DUMP_CMD, 0);
-	wdc_do_clear_dump(fd, WDC_NVME_CLEAR_DUMP_OPCODE,
-	    WDC_NVME_CLEAR_CRASH_DUMP_CMD);
-//	wdc_led_beacon_disable(fd);
-	wdc_do_dump(fd, path_tmpl, "pfail_dump", WDC_NVME_DIAG_OPCODE,
-	    WDC_NVME_PFAIL_DUMP_SIZE_CMD, WDC_NVME_PFAIL_DUMP_CMD, 0);
-	wdc_do_clear_dump(fd, WDC_NVME_CLEAR_DUMP_OPCODE,
-		WDC_NVME_CLEAR_PFAIL_DUMP_CMD);
-
-	close(fd);
-
-	exit(1);
-}
-
-static void
-wdc_purge(int argc, char *argv[])
-{
-	char path_tmpl[MAXPATHLEN];
-	int ch;
-
-	while ((ch = getopt(argc, argv, "o:")) != -1) {
-		switch ((char)ch) {
-		case 'o':
-			strlcpy(path_tmpl, optarg, MAXPATHLEN);
-			break;
-		default:
-			wdc_cap_diag_usage();
-		}
-	}
-
-	printf("purge has not been implemented.\n");
-	exit(1);
-}
-
-static void
-wdc_purge_monitor(int argc, char *argv[])
-{
-	char path_tmpl[MAXPATHLEN];
-	int ch;
-
-	while ((ch = getopt(argc, argv, "o:")) != -1) {
-		switch ((char)ch) {
-		case 'o':
-			strlcpy(path_tmpl, optarg, MAXPATHLEN);
-			break;
-		default:
-			wdc_cap_diag_usage();
-		}
-	}
-
-	printf("purge has not been implemented.\n");
-	exit(1);
 }
 
 void



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