svn commit: r330790 - head/usr.sbin/mpsutil

Scott Long scottl at FreeBSD.org
Mon Mar 12 05:03:34 UTC 2018


Author: scottl
Date: Mon Mar 12 05:03:32 2018
New Revision: 330790
URL: https://svnweb.freebsd.org/changeset/base/330790

Log:
  Add a new 'debug' command tree and 'dump_reqs' command to grab and parse
  command and chain frames of in-flight I/O from the driver.
  
  Sponsored by:	Netflix

Added:
  head/usr.sbin/mpsutil/mps_debug.c   (contents, props changed)
Modified:
  head/usr.sbin/mpsutil/Makefile
  head/usr.sbin/mpsutil/mps_show.c
  head/usr.sbin/mpsutil/mpsutil.c
  head/usr.sbin/mpsutil/mpsutil.h

Modified: head/usr.sbin/mpsutil/Makefile
==============================================================================
--- head/usr.sbin/mpsutil/Makefile	Mon Mar 12 05:02:22 2018	(r330789)
+++ head/usr.sbin/mpsutil/Makefile	Mon Mar 12 05:03:32 2018	(r330790)
@@ -1,7 +1,7 @@
 # $FreeBSD$
 
 PROG=	mpsutil
-SRCS=	mps_cmd.c mps_flash.c mps_show.c mpsutil.c
+SRCS=	mps_cmd.c mps_debug.c mps_flash.c mps_show.c mpsutil.c
 MAN=	mpsutil.8
 
 WARNS?= 3

Added: head/usr.sbin/mpsutil/mps_debug.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/mpsutil/mps_debug.c	Mon Mar 12 05:03:32 2018	(r330790)
@@ -0,0 +1,190 @@
+/*-
+ * Copyright (c) 2018 Netflix, Inc.
+ * All rights reserved.
+ * Written by: Scott Long <scottl at freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <err.h>
+#include <libutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "mpsutil.h"
+
+MPS_TABLE(top, debug);
+
+struct mps_dumpreq_hdr {
+	uint32_t	smid;
+	uint32_t	state;
+	uint32_t	numframes;
+	uint32_t	deschi;
+	uint32_t	desclo;
+};
+
+static int find_sgl(char *);
+static void print_sgl(char *, int, int);
+
+#define MPS_FRAME_LEN 128
+
+static int
+debug_dumpreqs(int ac, char **av)
+{
+	struct mps_dumpreq_hdr *hdr;
+	char *buf, sysctlbuf[128];
+	size_t len;
+	int numframes, error, offset;
+
+	len = 0;
+	buf = NULL;
+	snprintf(sysctlbuf, sizeof(sysctlbuf), "dev.%s.%d.dump_reqs",
+	    is_mps ? "mps" : "mpr", mps_unit);
+
+	error = sysctlbyname(sysctlbuf, NULL, &len, NULL, 0);
+	if (error)
+		return (error);
+
+	if (len == 0)
+		return (0);
+
+	buf = malloc(len);
+	if (buf == NULL)
+		return (ENOMEM);
+
+	error = sysctlbyname(sysctlbuf, buf, &len, NULL, 0);
+	if (error) {
+		printf("len= %zd, error= %d errno= %d\n", len, error, errno);
+		return (error);
+	}
+
+	while (len >= MPS_FRAME_LEN) {
+		hdr = (struct mps_dumpreq_hdr *)buf;
+		numframes = hdr->numframes;
+
+		printf("SMID= %d state= %#x numframes= %d desc.hi= %#08x "
+		    "desc.lo= %#08x\n", hdr->smid, hdr->state,
+		    hdr->numframes, hdr->deschi, hdr->desclo);
+
+		buf += sizeof(struct mps_dumpreq_hdr);
+		len -= sizeof(struct mps_dumpreq_hdr);
+
+		if ((offset = find_sgl(buf)) != -1)
+			print_sgl(buf, offset, numframes);
+
+		buf += MPS_FRAME_LEN * numframes;
+		len -= MPS_FRAME_LEN * numframes;
+	}
+
+	return (error);
+}
+
+static int
+find_sgl(char *buf)
+{
+	MPI2_REQUEST_HEADER *req;
+	MPI2_SCSI_IO_REQUEST *scsi;
+	int offset = 0;
+
+	req = (MPI2_REQUEST_HEADER *)buf;
+
+	switch (req->Function) {
+	case MPI2_FUNCTION_SCSI_IO_REQUEST:
+		scsi = (MPI2_SCSI_IO_REQUEST *)buf;
+		offset = scsi->SGLOffset0;
+		break;
+	default:
+		offset = -1;
+	}
+
+	return (offset);
+}
+
+#define SGL_FLAGS "\10LastElement\7EndOfBuffer\4Local\3Host2IOC\2Addr64\1EndOfList"
+
+static void
+print_sgl(char *buf, int offset, int numframes)
+{
+	MPI2_SGE_SIMPLE64 *sge;
+	MPI2_SGE_CHAIN_UNION *sgc;
+	MPI2_REQUEST_HEADER *req;
+	u_int i = 0, flags;
+	char *frame, tmpbuf[128];
+
+	req = (MPI2_REQUEST_HEADER *)buf;
+	frame = (char *)buf;
+	sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4];
+	printf("SGL for command\n");
+
+	hexdump(frame, MPS_FRAME_LEN, NULL, 0);
+	while (frame != NULL) {
+		flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT;
+		bzero(tmpbuf, sizeof(tmpbuf));
+		mps_parse_flags(flags, SGL_FLAGS, tmpbuf, sizeof(tmpbuf));
+		printf("seg%d flags=%x %s len= 0x%06x addr=0x%016jx\n", i,
+		    flags, tmpbuf, sge->FlagsLength & 0xffffff,
+		    mps_to_u64(&sge->Address));
+		if (flags & (MPI2_SGE_FLAGS_END_OF_LIST |
+		    MPI2_SGE_FLAGS_END_OF_BUFFER))
+			break;
+		sge++;
+		i++;
+		if (flags & MPI2_SGE_FLAGS_LAST_ELEMENT) {
+			sgc = (MPI2_SGE_CHAIN_UNION *)sge;
+			if ((sgc->Flags & MPI2_SGE_FLAGS_CHAIN_ELEMENT) == 0) {
+				printf("Invalid chain element\n");
+				break;
+			}
+			bzero(tmpbuf, sizeof(tmpbuf));
+			mps_parse_flags(sgc->Flags, SGL_FLAGS, tmpbuf,
+			    sizeof(tmpbuf));
+			if (sgc->Flags & MPI2_SGE_FLAGS_64_BIT_ADDRESSING)
+				printf("chain64 flags=0x%x %s len=0x%x "
+				    "Offset=0x%x addr=0x%016jx\n", sgc->Flags,
+				    tmpbuf, sgc->Length, sgc->NextChainOffset,
+				    mps_to_u64(&sgc->u.Address64));
+			else
+				printf("chain32 flags=0x%x %s len=0x%x "
+				    "Offset=0x%x addr=0x%08x\n", sgc->Flags,
+				    tmpbuf, sgc->Length, sgc->NextChainOffset,
+				    sgc->u.Address32);
+			if (--numframes <= 0)
+				break;
+			frame += MPS_FRAME_LEN;
+			sge = (MPI2_SGE_SIMPLE64 *)frame;
+			hexdump(frame, MPS_FRAME_LEN, NULL, 0);
+		}
+	}
+}
+
+MPS_COMMAND(debug, dumpreqs, debug_dumpreqs, "", "Dump the active request queue")

Modified: head/usr.sbin/mpsutil/mps_show.c
==============================================================================
--- head/usr.sbin/mpsutil/mps_show.c	Mon Mar 12 05:02:22 2018	(r330789)
+++ head/usr.sbin/mpsutil/mps_show.c	Mon Mar 12 05:03:32 2018	(r330790)
@@ -202,6 +202,7 @@ static int
 show_iocfacts(int ac, char **av)
 {
 	MPI2_IOC_FACTS_REPLY *facts;
+	char tmpbuf[128];
 	int error, fd;
 
 	fd = mps_open(mps_unit);
@@ -217,6 +218,14 @@ show_iocfacts(int ac, char **av)
 		return (errno);
 	}
 
+#define IOCCAP "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf" \
+    "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR" \
+    "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc" \
+    "\22FastPath" "\23RDPQArray" "\24AtomicReqDesc" "\25PCIeSRIOV"
+
+	bzero(tmpbuf, sizeof(tmpbuf));
+	mps_parse_flags(facts->IOCCapabilities, IOCCAP, tmpbuf, sizeof(tmpbuf));
+
 	printf("          MsgVersion: %02d.%02d\n",
 	    facts->MsgVersion >> 8, facts->MsgVersion & 0xff);
 	printf("           MsgLength: %d\n", facts->MsgLength);
@@ -236,14 +245,19 @@ show_iocfacts(int ac, char **av)
 	printf("      MaxMSIxVectors: %d\n", facts->MaxMSIxVectors);
 	printf("       RequestCredit: %d\n", facts->RequestCredit);
 	printf("           ProductID: 0x%x\n", facts->ProductID);
-	printf("     IOCCapabilities: 0x%x\n", facts->IOCCapabilities);
+	printf("     IOCCapabilities: 0x%x %s\n", facts->IOCCapabilities,
+	    tmpbuf);
 	printf("           FWVersion: 0x%08x\n", facts->FWVersion.Word);
 	printf(" IOCRequestFrameSize: %d\n", facts->IOCRequestFrameSize);
 	printf("       MaxInitiators: %d\n", facts->MaxInitiators);
 	printf("          MaxTargets: %d\n", facts->MaxTargets);
 	printf("     MaxSasExpanders: %d\n", facts->MaxSasExpanders);
 	printf("       MaxEnclosures: %d\n", facts->MaxEnclosures);
-	printf("       ProtocolFlags: 0x%x\n", facts->ProtocolFlags);
+
+	bzero(tmpbuf, sizeof(tmpbuf));
+	mps_parse_flags(facts->ProtocolFlags,
+	    "\4NvmeDevices\2ScsiTarget\1ScsiInitiator", tmpbuf, sizeof(tmpbuf));
+	printf("       ProtocolFlags: 0x%x %s\n", facts->ProtocolFlags, tmpbuf);
 	printf("  HighPriorityCredit: %d\n", facts->HighPriorityCredit);
 	printf("MaxRepDescPostQDepth: %d\n",
 	    facts->MaxReplyDescriptorPostQueueDepth);

Modified: head/usr.sbin/mpsutil/mpsutil.c
==============================================================================
--- head/usr.sbin/mpsutil/mpsutil.c	Mon Mar 12 05:02:22 2018	(r330789)
+++ head/usr.sbin/mpsutil/mpsutil.c	Mon Mar 12 05:03:32 2018	(r330790)
@@ -205,3 +205,32 @@ hexdump(const void *ptr, int length, const char *hdr, 
 		printf("\n");
 	}
 }
+
+#define PCHAR(c) { if (retval < tmpsz) { *outbuf++ = (c); retval++; } }
+
+int
+mps_parse_flags(uintmax_t num, const char *q, char *outbuf, int tmpsz)
+{
+	int n, tmp, retval = 0;
+
+	if (num == 0)
+		return (retval);
+
+	/* %b conversion flag format. */
+	tmp = retval;
+	while (*q) {
+		n = *q++;
+		if (num & (1 << (n - 1))) {
+			PCHAR(retval != tmp ?  ',' : '<');
+			for (; (n = *q) > ' '; ++q)
+				PCHAR(n);
+		} else
+			for (; *q > ' '; ++q)
+				continue;
+	}
+	if (retval != tmp)
+		PCHAR('>');
+
+	return (retval);
+}
+

Modified: head/usr.sbin/mpsutil/mpsutil.h
==============================================================================
--- head/usr.sbin/mpsutil/mpsutil.h	Mon Mar 12 05:02:22 2018	(r330789)
+++ head/usr.sbin/mpsutil/mpsutil.h	Mon Mar 12 05:03:32 2018	(r330790)
@@ -42,6 +42,8 @@
 #include <dev/mps/mpi/mpi2_cnfg.h>
 #include <dev/mps/mpi/mpi2_raid.h>
 #include <dev/mps/mpi/mpi2_ioc.h>
+#include <dev/mps/mpi/mpi2_init.h>
+#include <dev/mps/mpi/mpi2_tool.h>
 
 #define MPSUTIL_VERSION	"1.0.0"
 
@@ -102,6 +104,7 @@ void	hexdump(const void *ptr, int length, const char *
 #define	HD_OMIT_HEX	(1 << 17)
 #define	HD_OMIT_CHARS	(1 << 18)
 #define HD_REVERSED	(1 << 19)
+int	mps_parse_flags(uintmax_t, const char *, char *, int);
 
 int	mps_open(int unit);
 int	mps_table_handler(struct mpsutil_command **start,
@@ -140,6 +143,13 @@ mps_read_ioc_page(int fd, U8 PageNumber, U16 *IOCStatu
 
 	return (mps_read_config_page(fd, MPI2_CONFIG_PAGETYPE_IOC, PageNumber,
 	    0, IOCStatus));
+}
+
+static __inline uint64_t
+mps_to_u64(U64 *data)
+{
+
+	return (((uint64_t)(data->High) << 32 ) | data->Low);
 }
 
 MPI2_IOC_FACTS_REPLY * mps_get_iocfacts(int fd);


More information about the svn-src-all mailing list