--- /dev/null
+'\" t
+.\" Title: persistent-event-log
+.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\" Date: 01/11/2021
+.\" Manual: NVMe Manual
+.\" Source: NVMe
+.\" Language: English
+.\"
+.TH "PERSISTENT\-EVENT\-L" "1" "01/11/2021" "NVMe" "NVMe Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nvme-persistent-event-log \- Send NVMe persistent event log page request, returns result and log
+.SH "SYNOPSIS"
+.sp
+.nf
+\fInvme persistent\-event\-log\fR <device> [\-\-action=<action> | \-a <action>]
+ [\-\-log\-len=<log\-len> | \-l <log\-len>]
+ [\-\-raw\-binary | \-b]
+ [\-\-output\-format=<fmt> | \-o <fmt>]
+.fi
+.SH "DESCRIPTION"
+.sp
+Retrieves the NVMe persistent event log page from an NVMe device and provides the returned structure\&.
+.sp
+The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&.
+.sp
+On success, the returned persistent event log structure may be returned in one of several ways depending on the option flags; the structure may parsed by the program and printed in a readable format or the raw buffer may be printed to stdout for another program to parse\&.
+.SH "OPTIONS"
+.PP
+\-a <action>, \-\-action=<action>
+.RS 4
+While try to retrieve this log action the controller shall take during processing this persistent log page command\&. This mandatory field, based on the value issued it may Read Log Data, Establish Context and Read Log Data or Release Context can occur\&. For More details see NVM Express 1\&.4 Spec\&. Section 5\&.14\&.1\&.13 Persistent Event Log (Log Identifier 0Dh)
+.RE
+.PP
+\-l <log\-len>, \-\-log\-len=<log\-len>
+.RS 4
+Allocates a buffer of <log\-len> bytes size and requests this many bytes be returned in the constructed NVMe command\&. This param is mandatory\&. If <log\-len> given is 0 and action is 0, it will read the Total Log Length(TLL) of the page\&.
+.RE
+.PP
+\-b, \-\-raw\-binary
+.RS 4
+Print the raw persistent event log buffer to stdout\&.
+.RE
+.PP
+\-o <format>, \-\-output\-format=<format>
+.RS 4
+Set the reporting format to
+\fInormal\fR,
+\fIjson\fR, or
+\fIbinary\fR\&. Only one output format can be used at a time\&.
+.RE
+.SH "EXAMPLES"
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Print the persistent event log page in a human readable format:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme persistent\-event\-log /dev/nvme0
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Print the raw persistent event log to a file:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme persistent\-event\-log /dev/nvme0 \-\-raw\-binary > persistent_log\&.raw
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+It is probably a bad idea to not redirect stdout when using this mode\&.
+.RE
+.SH "NVME"
+.sp
+Part of the nvme\-user suite
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.10" />\r
+<title>persistent-event-log(1)</title>\r
+<style type="text/css">\r
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
+\r
+/* Default font. */\r
+body {\r
+ font-family: Georgia,serif;\r
+}\r
+\r
+/* Title font. */\r
+h1, h2, h3, h4, h5, h6,\r
+div.title, caption.title,\r
+thead, p.table.header,\r
+#toctitle,\r
+#author, #revnumber, #revdate, #revremark,\r
+#footer {\r
+ font-family: Arial,Helvetica,sans-serif;\r
+}\r
+\r
+body {\r
+ margin: 1em 5% 1em 5%;\r
+}\r
+\r
+a {\r
+ color: blue;\r
+ text-decoration: underline;\r
+}\r
+a:visited {\r
+ color: fuchsia;\r
+}\r
+\r
+em {\r
+ font-style: italic;\r
+ color: navy;\r
+}\r
+\r
+strong {\r
+ font-weight: bold;\r
+ color: #083194;\r
+}\r
+\r
+h1, h2, h3, h4, h5, h6 {\r
+ color: #527bbd;\r
+ margin-top: 1.2em;\r
+ margin-bottom: 0.5em;\r
+ line-height: 1.3;\r
+}\r
+\r
+h1, h2, h3 {\r
+ border-bottom: 2px solid silver;\r
+}\r
+h2 {\r
+ padding-top: 0.5em;\r
+}\r
+h3 {\r
+ float: left;\r
+}\r
+h3 + * {\r
+ clear: left;\r
+}\r
+h5 {\r
+ font-size: 1.0em;\r
+}\r
+\r
+div.sectionbody {\r
+ margin-left: 0;\r
+}\r
+\r
+hr {\r
+ border: 1px solid silver;\r
+}\r
+\r
+p {\r
+ margin-top: 0.5em;\r
+ margin-bottom: 0.5em;\r
+}\r
+\r
+ul, ol, li > p {\r
+ margin-top: 0;\r
+}\r
+ul > li { color: #aaa; }\r
+ul > li > * { color: black; }\r
+\r
+.monospaced, code, pre {\r
+ font-family: "Courier New", Courier, monospace;\r
+ font-size: inherit;\r
+ color: navy;\r
+ padding: 0;\r
+ margin: 0;\r
+}\r
+pre {\r
+ white-space: pre-wrap;\r
+}\r
+\r
+#author {\r
+ color: #527bbd;\r
+ font-weight: bold;\r
+ font-size: 1.1em;\r
+}\r
+#email {\r
+}\r
+#revnumber, #revdate, #revremark {\r
+}\r
+\r
+#footer {\r
+ font-size: small;\r
+ border-top: 2px solid silver;\r
+ padding-top: 0.5em;\r
+ margin-top: 4.0em;\r
+}\r
+#footer-text {\r
+ float: left;\r
+ padding-bottom: 0.5em;\r
+}\r
+#footer-badges {\r
+ float: right;\r
+ padding-bottom: 0.5em;\r
+}\r
+\r
+#preamble {\r
+ margin-top: 1.5em;\r
+ margin-bottom: 1.5em;\r
+}\r
+div.imageblock, div.exampleblock, div.verseblock,\r
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,\r
+div.admonitionblock {\r
+ margin-top: 1.0em;\r
+ margin-bottom: 1.5em;\r
+}\r
+div.admonitionblock {\r
+ margin-top: 2.0em;\r
+ margin-bottom: 2.0em;\r
+ margin-right: 10%;\r
+ color: #606060;\r
+}\r
+\r
+div.content { /* Block element content. */\r
+ padding: 0;\r
+}\r
+\r
+/* Block element titles. */\r
+div.title, caption.title {\r
+ color: #527bbd;\r
+ font-weight: bold;\r
+ text-align: left;\r
+ margin-top: 1.0em;\r
+ margin-bottom: 0.5em;\r
+}\r
+div.title + * {\r
+ margin-top: 0;\r
+}\r
+\r
+td div.title:first-child {\r
+ margin-top: 0.0em;\r
+}\r
+div.content div.title:first-child {\r
+ margin-top: 0.0em;\r
+}\r
+div.content + div.title {\r
+ margin-top: 0.0em;\r
+}\r
+\r
+div.sidebarblock > div.content {\r
+ background: #ffffee;\r
+ border: 1px solid #dddddd;\r
+ border-left: 4px solid #f0f0f0;\r
+ padding: 0.5em;\r
+}\r
+\r
+div.listingblock > div.content {\r
+ border: 1px solid #dddddd;\r
+ border-left: 5px solid #f0f0f0;\r
+ background: #f8f8f8;\r
+ padding: 0.5em;\r
+}\r
+\r
+div.quoteblock, div.verseblock {\r
+ padding-left: 1.0em;\r
+ margin-left: 1.0em;\r
+ margin-right: 10%;\r
+ border-left: 5px solid #f0f0f0;\r
+ color: #888;\r
+}\r
+\r
+div.quoteblock > div.attribution {\r
+ padding-top: 0.5em;\r
+ text-align: right;\r
+}\r
+\r
+div.verseblock > pre.content {\r
+ font-family: inherit;\r
+ font-size: inherit;\r
+}\r
+div.verseblock > div.attribution {\r
+ padding-top: 0.75em;\r
+ text-align: left;\r
+}\r
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */\r
+div.verseblock + div.attribution {\r
+ text-align: left;\r
+}\r
+\r
+div.admonitionblock .icon {\r
+ vertical-align: top;\r
+ font-size: 1.1em;\r
+ font-weight: bold;\r
+ text-decoration: underline;\r
+ color: #527bbd;\r
+ padding-right: 0.5em;\r
+}\r
+div.admonitionblock td.content {\r
+ padding-left: 0.5em;\r
+ border-left: 3px solid #dddddd;\r
+}\r
+\r
+div.exampleblock > div.content {\r
+ border-left: 3px solid #dddddd;\r
+ padding-left: 0.5em;\r
+}\r
+\r
+div.imageblock div.content { padding-left: 0; }\r
+span.image img { border-style: none; vertical-align: text-bottom; }\r
+a.image:visited { color: white; }\r
+\r
+dl {\r
+ margin-top: 0.8em;\r
+ margin-bottom: 0.8em;\r
+}\r
+dt {\r
+ margin-top: 0.5em;\r
+ margin-bottom: 0;\r
+ font-style: normal;\r
+ color: navy;\r
+}\r
+dd > *:first-child {\r
+ margin-top: 0.1em;\r
+}\r
+\r
+ul, ol {\r
+ list-style-position: outside;\r
+}\r
+ol.arabic {\r
+ list-style-type: decimal;\r
+}\r
+ol.loweralpha {\r
+ list-style-type: lower-alpha;\r
+}\r
+ol.upperalpha {\r
+ list-style-type: upper-alpha;\r
+}\r
+ol.lowerroman {\r
+ list-style-type: lower-roman;\r
+}\r
+ol.upperroman {\r
+ list-style-type: upper-roman;\r
+}\r
+\r
+div.compact ul, div.compact ol,\r
+div.compact p, div.compact p,\r
+div.compact div, div.compact div {\r
+ margin-top: 0.1em;\r
+ margin-bottom: 0.1em;\r
+}\r
+\r
+tfoot {\r
+ font-weight: bold;\r
+}\r
+td > div.verse {\r
+ white-space: pre;\r
+}\r
+\r
+div.hdlist {\r
+ margin-top: 0.8em;\r
+ margin-bottom: 0.8em;\r
+}\r
+div.hdlist tr {\r
+ padding-bottom: 15px;\r
+}\r
+dt.hdlist1.strong, td.hdlist1.strong {\r
+ font-weight: bold;\r
+}\r
+td.hdlist1 {\r
+ vertical-align: top;\r
+ font-style: normal;\r
+ padding-right: 0.8em;\r
+ color: navy;\r
+}\r
+td.hdlist2 {\r
+ vertical-align: top;\r
+}\r
+div.hdlist.compact tr {\r
+ margin: 0;\r
+ padding-bottom: 0;\r
+}\r
+\r
+.comment {\r
+ background: yellow;\r
+}\r
+\r
+.footnote, .footnoteref {\r
+ font-size: 0.8em;\r
+}\r
+\r
+span.footnote, span.footnoteref {\r
+ vertical-align: super;\r
+}\r
+\r
+#footnotes {\r
+ margin: 20px 0 20px 0;\r
+ padding: 7px 0 0 0;\r
+}\r
+\r
+#footnotes div.footnote {\r
+ margin: 0 0 5px 0;\r
+}\r
+\r
+#footnotes hr {\r
+ border: none;\r
+ border-top: 1px solid silver;\r
+ height: 1px;\r
+ text-align: left;\r
+ margin-left: 0;\r
+ width: 20%;\r
+ min-width: 100px;\r
+}\r
+\r
+div.colist td {\r
+ padding-right: 0.5em;\r
+ padding-bottom: 0.3em;\r
+ vertical-align: top;\r
+}\r
+div.colist td img {\r
+ margin-top: 0.3em;\r
+}\r
+\r
+@media print {\r
+ #footer-badges { display: none; }\r
+}\r
+\r
+#toc {\r
+ margin-bottom: 2.5em;\r
+}\r
+\r
+#toctitle {\r
+ color: #527bbd;\r
+ font-size: 1.1em;\r
+ font-weight: bold;\r
+ margin-top: 1.0em;\r
+ margin-bottom: 0.1em;\r
+}\r
+\r
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {\r
+ margin-top: 0;\r
+ margin-bottom: 0;\r
+}\r
+div.toclevel2 {\r
+ margin-left: 2em;\r
+ font-size: 0.9em;\r
+}\r
+div.toclevel3 {\r
+ margin-left: 4em;\r
+ font-size: 0.9em;\r
+}\r
+div.toclevel4 {\r
+ margin-left: 6em;\r
+ font-size: 0.9em;\r
+}\r
+\r
+span.aqua { color: aqua; }\r
+span.black { color: black; }\r
+span.blue { color: blue; }\r
+span.fuchsia { color: fuchsia; }\r
+span.gray { color: gray; }\r
+span.green { color: green; }\r
+span.lime { color: lime; }\r
+span.maroon { color: maroon; }\r
+span.navy { color: navy; }\r
+span.olive { color: olive; }\r
+span.purple { color: purple; }\r
+span.red { color: red; }\r
+span.silver { color: silver; }\r
+span.teal { color: teal; }\r
+span.white { color: white; }\r
+span.yellow { color: yellow; }\r
+\r
+span.aqua-background { background: aqua; }\r
+span.black-background { background: black; }\r
+span.blue-background { background: blue; }\r
+span.fuchsia-background { background: fuchsia; }\r
+span.gray-background { background: gray; }\r
+span.green-background { background: green; }\r
+span.lime-background { background: lime; }\r
+span.maroon-background { background: maroon; }\r
+span.navy-background { background: navy; }\r
+span.olive-background { background: olive; }\r
+span.purple-background { background: purple; }\r
+span.red-background { background: red; }\r
+span.silver-background { background: silver; }\r
+span.teal-background { background: teal; }\r
+span.white-background { background: white; }\r
+span.yellow-background { background: yellow; }\r
+\r
+span.big { font-size: 2em; }\r
+span.small { font-size: 0.6em; }\r
+\r
+span.underline { text-decoration: underline; }\r
+span.overline { text-decoration: overline; }\r
+span.line-through { text-decoration: line-through; }\r
+\r
+div.unbreakable { page-break-inside: avoid; }\r
+\r
+\r
+/*\r
+ * xhtml11 specific\r
+ *\r
+ * */\r
+\r
+div.tableblock {\r
+ margin-top: 1.0em;\r
+ margin-bottom: 1.5em;\r
+}\r
+div.tableblock > table {\r
+ border: 3px solid #527bbd;\r
+}\r
+thead, p.table.header {\r
+ font-weight: bold;\r
+ color: #527bbd;\r
+}\r
+p.table {\r
+ margin-top: 0;\r
+}\r
+/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+div.tableblock > table[frame="void"] {\r
+ border-style: none;\r
+}\r
+div.tableblock > table[frame="hsides"] {\r
+ border-left-style: none;\r
+ border-right-style: none;\r
+}\r
+div.tableblock > table[frame="vsides"] {\r
+ border-top-style: none;\r
+ border-bottom-style: none;\r
+}\r
+\r
+\r
+/*\r
+ * html5 specific\r
+ *\r
+ * */\r
+\r
+table.tableblock {\r
+ margin-top: 1.0em;\r
+ margin-bottom: 1.5em;\r
+}\r
+thead, p.tableblock.header {\r
+ font-weight: bold;\r
+ color: #527bbd;\r
+}\r
+p.tableblock {\r
+ margin-top: 0;\r
+}\r
+table.tableblock {\r
+ border-width: 3px;\r
+ border-spacing: 0px;\r
+ border-style: solid;\r
+ border-color: #527bbd;\r
+ border-collapse: collapse;\r
+}\r
+th.tableblock, td.tableblock {\r
+ border-width: 1px;\r
+ padding: 4px;\r
+ border-style: solid;\r
+ border-color: #527bbd;\r
+}\r
+\r
+table.tableblock.frame-topbot {\r
+ border-left-style: hidden;\r
+ border-right-style: hidden;\r
+}\r
+table.tableblock.frame-sides {\r
+ border-top-style: hidden;\r
+ border-bottom-style: hidden;\r
+}\r
+table.tableblock.frame-none {\r
+ border-style: hidden;\r
+}\r
+\r
+th.tableblock.halign-left, td.tableblock.halign-left {\r
+ text-align: left;\r
+}\r
+th.tableblock.halign-center, td.tableblock.halign-center {\r
+ text-align: center;\r
+}\r
+th.tableblock.halign-right, td.tableblock.halign-right {\r
+ text-align: right;\r
+}\r
+\r
+th.tableblock.valign-top, td.tableblock.valign-top {\r
+ vertical-align: top;\r
+}\r
+th.tableblock.valign-middle, td.tableblock.valign-middle {\r
+ vertical-align: middle;\r
+}\r
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {\r
+ vertical-align: bottom;\r
+}\r
+\r
+\r
+/*\r
+ * manpage specific\r
+ *\r
+ * */\r
+\r
+body.manpage h1 {\r
+ padding-top: 0.5em;\r
+ padding-bottom: 0.5em;\r
+ border-top: 2px solid silver;\r
+ border-bottom: 2px solid silver;\r
+}\r
+body.manpage h2 {\r
+ border-style: none;\r
+}\r
+body.manpage div.sectionbody {\r
+ margin-left: 3em;\r
+}\r
+\r
+@media print {\r
+ body.manpage div#toc { display: none; }\r
+}\r
+\r
+\r
+</style>\r
+<script type="text/javascript">\r
+/*<+'])');\r
+ // Function that scans the DOM tree for header elements (the DOM2\r
+ // nodeIterator API would be a better technique but not supported by all\r
+ // browsers).\r
+ var iterate = function (el) {\r
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {\r
+ var mo = re.exec(i.tagName);\r
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {\r
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);\r
+ }\r
+ iterate(i);\r
+ }\r
+ }\r
+ }\r
+ iterate(el);\r
+ return result;\r
+ }\r
+\r
+ var toc = document.getElementById("toc");\r
+ if (!toc) {\r
+ return;\r
+ }\r
+\r
+ // Delete existing TOC entries in case we're reloading the TOC.\r
+ var tocEntriesToRemove = [];\r
+ var i;\r
+ for (i = 0; i < toc.childNodes.length; i++) {\r
+ var entry = toc.childNodes[i];\r
+ if (entry.nodeName.toLowerCase() == 'div'\r
+ && entry.getAttribute("class")\r
+ && entry.getAttribute("class").match(/^toclevel/))\r
+ tocEntriesToRemove.push(entry);\r
+ }\r
+ for (i = 0; i < tocEntriesToRemove.length; i++) {\r
+ toc.removeChild(tocEntriesToRemove[i]);\r
+ }\r
+\r
+ // Rebuild TOC entries.\r
+ var entries = tocEntries(document.getElementById("content"), toclevels);\r
+ for (var i = 0; i < entries.length; ++i) {\r
+ var entry = entries[i];\r
+ if (entry.element.id == "")\r
+ entry.element.id = "_toc_" + i;\r
+ var a = document.createElement("a");\r
+ a.href = "#" + entry.element.id;\r
+ a.appendChild(document.createTextNode(entry.text));\r
+ var div = document.createElement("div");\r
+ div.appendChild(a);\r
+ div.className = "toclevel" + entry.toclevel;\r
+ toc.appendChild(div);\r
+ }\r
+ if (entries.length == 0)\r
+ toc.parentNode.removeChild(toc);\r
+},\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Footnotes generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Based on footnote generation code from:\r
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html\r
+ */\r
+\r
+footnotes: function () {\r
+ // Delete existing footnote entries in case we're reloading the footnodes.\r
+ var i;\r
+ var noteholder = document.getElementById("footnotes");\r
+ if (!noteholder) {\r
+ return;\r
+ }\r
+ var entriesToRemove = [];\r
+ for (i = 0; i < noteholder.childNodes.length; i++) {\r
+ var entry = noteholder.childNodes[i];\r
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")\r
+ entriesToRemove.push(entry);\r
+ }\r
+ for (i = 0; i < entriesToRemove.length; i++) {\r
+ noteholder.removeChild(entriesToRemove[i]);\r
+ }\r
+\r
+ // Rebuild footnote entries.\r
+ var cont = document.getElementById("content");\r
+ var spans = cont.getElementsByTagName("span");\r
+ var refs = {};\r
+ var n = 0;\r
+ for (i=0; i<spans.length; i++) {\r
+ if (spans[i].className == "footnote") {\r
+ n++;\r
+ var note = spans[i].getAttribute("data-note");\r
+ if (!note) {\r
+ // Use [\s\S] in place of . so multi-line matches work.\r
+ // Because JavaScript has no s (dotall) regex flag.\r
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];\r
+ spans[i].innerHTML =\r
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +\r
+ "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+ spans[i].setAttribute("data-note", note);\r
+ }\r
+ noteholder.innerHTML +=\r
+ "<div class='footnote' id='_footnote_" + n + "'>" +\r
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +\r
+ n + "</a>. " + note + "</div>";\r
+ var id =spans[i].getAttribute("id");\r
+ if (id != null) refs["#"+id] = n;\r
+ }\r
+ }\r
+ if (n == 0)\r
+ noteholder.parentNode.removeChild(noteholder);\r
+ else {\r
+ // Process footnoterefs.\r
+ for (i=0; i<spans.length; i++) {\r
+ if (spans[i].className == "footnoteref") {\r
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");\r
+ href = href.match(/#.*/)[0]; // Because IE return full URL.\r
+ n = refs[href];\r
+ spans[i].innerHTML =\r
+ "[<a href='#_footnote_" + n +\r
+ "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+ }\r
+ }\r
+ }\r
+},\r
+\r
+install: function(toclevels) {\r
+ var timerId;\r
+\r
+ function reinstall() {\r
+ asciidoc.footnotes();\r
+ if (toclevels) {\r
+ asciidoc.toc(toclevels);\r
+ }\r
+ }\r
+\r
+ function reinstallAndRemoveTimer() {\r
+ clearInterval(timerId);\r
+ reinstall();\r
+ }\r
+\r
+ timerId = setInterval(reinstall, 500);\r
+ if (document.addEventListener)\r
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);\r
+ else\r
+ window.onload = reinstallAndRemoveTimer;\r
+}\r
+\r
+}\r
+asciidoc.install();\r
+/*]]>*/\r
+</script>\r
+</head>\r
+<body class="manpage">\r
+<div id="header">\r
+<h1>\r
+persistent-event-log(1) Manual Page\r
+</h1>\r
+<h2>NAME</h2>\r
+<div class="sectionbody">\r
+<p>nvme-persistent-event-log -\r
+ Send NVMe persistent event log page request, returns result and log\r
+</p>\r
+</div>\r
+</div>\r
+<div id="content">\r
+<div class="sect1">\r
+<h2 id="_synopsis">SYNOPSIS</h2>\r
+<div class="sectionbody">\r
+<div class="verseblock">\r
+<pre class="content"><em>nvme persistent-event-log</em> <device> [--action=<action> | -a <action>]\r
+ [--log-len=<log-len> | -l <log-len>]\r
+ [--raw-binary | -b]\r
+ [--output-format=<fmt> | -o <fmt>]</pre>\r
+<div class="attribution">\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_description">DESCRIPTION</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Retrieves the NVMe persistent event log page from an NVMe device\r
+and provides the returned structure.</p></div>\r
+<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character\r
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>\r
+<div class="paragraph"><p>On success, the returned persistent event log structure may be returned\r
+in one of several ways depending on the option flags; the structure may\r
+parsed by the program and printed in a readable format or the raw buffer\r
+may be printed to stdout for another program to parse.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_options">OPTIONS</h2>\r
+<div class="sectionbody">\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+-a <action>\r
+</dt>\r
+<dt class="hdlist1">\r
+--action=<action>\r
+</dt>\r
+<dd>\r
+<p>\r
+ While try to retrieve this log action the controller shall take\r
+ during processing this persistent log page command. This mandatory\r
+ field, based on the value issued it may Read Log Data, Establish\r
+ Context and Read Log Data or Release Context can occur. For More\r
+ details see NVM Express 1.4 Spec. Section 5.14.1.13 Persistent\r
+ Event Log (Log Identifier 0Dh)\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-l <log-len>\r
+</dt>\r
+<dt class="hdlist1">\r
+--log-len=<log-len>\r
+</dt>\r
+<dd>\r
+<p>\r
+ Allocates a buffer of <log-len> bytes size and requests this\r
+ many bytes be returned in the constructed NVMe command. This\r
+ param is mandatory. If <log-len> given is 0 and action is 0,\r
+ it will read the Total Log Length(TLL) of the page.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-b\r
+</dt>\r
+<dt class="hdlist1">\r
+--raw-binary\r
+</dt>\r
+<dd>\r
+<p>\r
+ Print the raw persistent event log buffer to stdout.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-o <format>\r
+</dt>\r
+<dt class="hdlist1">\r
+--output-format=<format>\r
+</dt>\r
+<dd>\r
+<p>\r
+ Set the reporting format to <em>normal</em>, <em>json</em>, or <em>binary</em>.\r
+ Only one output format can be used at a time.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_examples">EXAMPLES</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Print the persistent event log page in a human readable format:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme persistent-event-log /dev/nvme0</code></pre>\r
+</div></div>\r
+</li>\r
+<li>\r
+<p>\r
+Print the raw persistent event log to a file:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme persistent-event-log /dev/nvme0 --raw-binary > persistent_log.raw</code></pre>\r
+</div></div>\r
+<div class="paragraph"><p>It is probably a bad idea to not redirect stdout when using this mode.</p></div>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_nvme">NVME</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated\r
+ 2021-01-11 17:07:01 IST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+persistent-event-log(1)
+=======================
+
+NAME
+----
+nvme-persistent-event-log - Send NVMe persistent event log page request,
+returns result and log
+
+SYNOPSIS
+--------
+[verse]
+'nvme persistent-event-log' <device> [--action=<action> | -a <action>]
+ [--log-len=<log-len> | -l <log-len>]
+ [--raw-binary | -b]
+ [--output-format=<fmt> | -o <fmt>]
+
+DESCRIPTION
+-----------
+Retrieves the NVMe persistent event log page from an NVMe device
+and provides the returned structure.
+
+The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).
+
+On success, the returned persistent event log structure may be returned
+in one of several ways depending on the option flags; the structure may
+parsed by the program and printed in a readable format or the raw buffer
+may be printed to stdout for another program to parse.
+
+OPTIONS
+-------
+-a <action>::
+--action=<action>::
+ While try to retrieve this log action the controller shall take
+ during processing this persistent log page command. This mandatory
+ field, based on the value issued it may Read Log Data, Establish
+ Context and Read Log Data or Release Context can occur. For More
+ details see NVM Express 1.4 Spec. Section 5.14.1.13 Persistent
+ Event Log (Log Identifier 0Dh)
+
+-l <log-len>::
+--log-len=<log-len>::
+ Allocates a buffer of <log-len> bytes size and requests this
+ many bytes be returned in the constructed NVMe command. This
+ param is mandatory. If <log-len> given is 0 and action is 0,
+ it will read the Total Log Length(TLL) of the page.
+
+-b::
+--raw-binary::
+ Print the raw persistent event log buffer to stdout.
+
+-o <format>::
+--output-format=<format>::
+ Set the reporting format to 'normal', 'json', or 'binary'.
+ Only one output format can be used at a time.
+
+EXAMPLES
+--------
+* Print the persistent event log page in a human readable format:
++
+------------
+# nvme persistent-event-log /dev/nvme0
+------------
++
+
+* Print the raw persistent event log to a file:
++
+------------
+# nvme persistent-event-log /dev/nvme0 --raw-binary > persistent_log.raw
+------------
++
+It is probably a bad idea to not redirect stdout when using this mode.
+
+NVME
+----
+Part of the nvme-user suite
'list-ctrl:identify all controller(s) attached'
'get-ns-id:get namespace id of opened block device'
'get-log:retrieve any log in raw format'
+ 'persistent-event-log:retrieve presistent event log'
'fw-log:retrieve fw log'
'smart-log:retrieve SMART log'
'smart-log-add:retrieve additional SMART log'
_arguments '*:: :->subcmds'
_describe -t commands "nvme get-log options" _getlog
;;
+ (persistent-event-log)
+ local _persistenteventlog
+ _persistenteventlog=(
+ /dev/nvme':supply a device to use (required)'
+ --action=': action the controller shall take for this log page'
+ -a':alias to --action'
+ --log-len=':number of bytes to show for requested log'
+ -l':alias of --log-len'
+ --raw-binary':dump infos in binary format'
+ -b':alias of --raw-binary'
+ )
+ _arguments '*:: :->subcmds'
+ _describe -t commands "persistent-event-log options" _persistenteventlog
+ ;;
(fw-log)
local _fwlog
_fwlog=(
list-ctrl get-ns-id get-log fw-log smart-log error-log get-feature
set-feature format fw-activate fw-download admin-passthru io-passthru
security-send security-recv resv-acquire resv-register resv-release
- resv-report flush compare read write copy show-regs
+ resv-report flush compare read write copy show-regs persistent-event-log
)
_arguments '*:: :->subcmds'
_describe -t commands "help: infos on a specific nvme command, or provide no option to see a synopsis of all nvme commands" _h
# Kelly Kaoudis kelly.n.kaoudis at intel.com, Aug. 2015
_cmds="list id-ctrl id-ns list-ns id-iocs create-ns delete-ns \
- attach-ns detach-ns list-ctrl get-ns-id get-log \
+ attach-ns detach-ns list-ctrl get-ns-id get-log persistent-event-log \
fw-log smart-log smart-log-add error-log \
get-feature set-feature format fw-activate \
fw-download admin-passthru io-passthru security-send \
opts+=" --log-id= -i --log-len= -l --namespace-id= -n \
--raw-binary= -b"
;;
+ "persistent-event-log")
+ opts+=" --action= -a --log-len= -l \
+ --raw-binary -b --output-format= -o"
+ ;;
"fw-log")
opts+=" --raw-binary -b --output-format= -o"
;;
__le16 rsvd10[3];
};
+/* persistent event type 02h */
+struct nvme_fw_commit_event {
+ __le64 old_fw_rev;
+ __le64 new_fw_rev;
+ __u8 fw_commit_action;
+ __u8 fw_slot;
+ __u8 sct_fw;
+ __u8 sc_fw;
+ __le16 vndr_assign_fw_commit_rc;
+} __attribute__((packed));
+
+/* persistent event type 03h */
+struct nvme_time_stamp_change_event {
+ __le64 previous_timestamp;
+ __le64 ml_secs_since_reset;
+};
+
+/* persistent event type 04h */
+struct nvme_power_on_reset_info_list {
+ __le16 cid;
+ __u8 fw_act;
+ __u8 op_in_prog;
+ __u8 rsvd4[12];
+ __le32 ctrl_power_cycle;
+ __le64 power_on_ml_seconds;
+ __le64 ctrl_time_stamp;
+} __attribute__((packed));
+
+/* persistent event type 05h */
+struct nvme_nss_hw_err_event {
+ __le16 nss_hw_err_event_code;
+ __u8 rsvd2[2];
+ __u8 *add_hw_err_info;
+};
+
+/* persistent event type 06h */
+struct nvme_change_ns_event {
+ __le32 nsmgt_cdw10;
+ __u8 rsvd4[4];
+ __le64 nsze;
+ __u8 nscap[16];
+ __u8 flbas;
+ __u8 dps;
+ __u8 nmic;
+ __u8 rsvd35;
+ __le32 ana_grp_id;
+ __le16 nvmset_id;
+ __le16 rsvd42;
+ __le32 nsid;
+};
+
+/* persistent event type 07h */
+struct nvme_format_nvm_start_event {
+ __le32 nsid;
+ __u8 fna;
+ __u8 rsvd5[3];
+ __le32 format_nvm_cdw10;
+};
+
+/* persistent event type 08h */
+struct nvme_format_nvm_compln_event {
+ __le32 nsid;
+ __u8 smallest_fpi;
+ __u8 format_nvm_status;
+ __le16 compln_info;
+ __le32 status_field;
+};
+
+/* persistent event type 09h */
+struct nvme_sanitize_start_event {
+ __le32 sani_cap;
+ __le32 sani_cdw10;
+ __le32 sani_cdw11;
+};
+
+/* persistent event type 0Ah */
+struct nvme_sanitize_compln_event {
+ __le16 sani_prog;
+ __le16 sani_status;
+ __le16 cmpln_info;
+ __u8 rsvd6[2];
+};
+
+/* persistent event type 0Dh */
+struct nvme_thermal_exc_event {
+ __u8 over_temp;
+ __u8 threshold;
+};
+
+/* persistent event entry head */
+struct nvme_persistent_event_entry_head {
+ __u8 etype;
+ __u8 etype_rev;
+ __u8 ehl;
+ __u8 rsvd3;
+ __le16 ctrl_id;
+ __le64 etimestamp;
+ __u8 rsvd14[6];
+ __le16 vsil;
+ __le16 el;
+} __attribute__((packed));
+
+/* persistent event log head */
+struct nvme_persistent_event_log_head {
+ __u8 log_id;
+ __u8 rsvd1[3];
+ __le32 tnev;
+ __le64 tll;
+ __u8 log_rev;
+ __u8 rsvd17;
+ __le16 head_len;
+ __le64 timestamp;
+ __u8 poh[16];
+ __le64 pcc;
+ __le16 vid;
+ __le16 ssvid;
+ __u8 sn[20];
+ __u8 mn[40];
+ __u8 subnqn[256];
+ __u8 rsvd372[108];
+ __u8 supp_event_bm[32];
+} __attribute__((packed));
+
+enum nvme_persistent_event_types {
+ NVME_SMART_HEALTH_EVENT = 0x01,
+ NVME_FW_COMMIT_EVENT = 0x02,
+ NVME_TIMESTAMP_EVENT = 0x03,
+ NVME_POWER_ON_RESET_EVENT = 0x04,
+ NVME_NSS_HW_ERROR_EVENT = 0x05,
+ NVME_CHANGE_NS_EVENT = 0x06,
+ NVME_FORMAT_START_EVENT = 0x07,
+ NVME_FORMAT_COMPLETION_EVENT = 0x08,
+ NVME_SANITIZE_START_EVENT = 0x09,
+ NVME_SANITIZE_COMPLETION_EVENT = 0x0a,
+ NVME_THERMAL_EXCURSION_EVENT = 0x0d
+};
+
+enum nvme_persistent_event_log_actions {
+ NVME_PEVENT_LOG_READ = 0x0,
+ NVME_PEVENT_LOG_EST_CTX_AND_READ = 0x1,
+ NVME_PEVENT_LOG_RELEASE_CTX = 0x2,
+};
+
enum {
NVME_SMART_CRIT_SPARE = 1 << 0,
NVME_SMART_CRIT_TEMPERATURE = 1 << 1,
NVME_LOG_TELEMETRY_CTRL = 0x08,
NVME_LOG_ENDURANCE_GROUP = 0x09,
NVME_LOG_ANA = 0x0c,
+ NVME_LOG_PERSISTENT_EVENT = 0x0d,
NVME_LOG_DISC = 0x70,
NVME_LOG_RESERVATION = 0x80,
NVME_LOG_SANITIZE = 0x81,
ENTRY("error-log", "Retrieve Error Log, show it", get_error_log)
ENTRY("effects-log", "Retrieve Command Effects Log, show it", get_effects_log)
ENTRY("endurance-log", "Retrieve Endurance Group Log, show it", get_endurance_log)
+ ENTRY("persistent-event-log", "Retrieve Presistent Event Log, show it", get_persistent_event_log)
ENTRY("get-feature", "Get feature and show the resulting value", get_feature)
ENTRY("device-self-test", "Perform the necessary tests to observe the performance", device_self_test)
ENTRY("self-test-log", "Retrieve the SELF-TEST Log, show it", self_test_log)
}
int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae,
- __u32 data_len, void *data)
+ __u8 lsp, __u32 data_len, void *data)
{
__u32 offset = 0, xfer_len = data_len;
void *ptr = data;
if (xfer_len > 4096)
xfer_len = 4096;
- ret = nvme_get_log13(fd, nsid, log_id, NVME_NO_LOG_LSP,
+ ret = nvme_get_log13(fd, nsid, log_id, lsp,
offset, 0, rae, xfer_len, ptr);
if (ret)
return ret;
int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log)
{
return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_FW_SLOT, true,
- sizeof(*fw_log), fw_log);
+ NVME_NO_LOG_LSP, sizeof(*fw_log), fw_log);
}
int nvme_changed_ns_list_log(int fd, struct nvme_changed_ns_list_log *changed_ns_list_log)
{
return nvme_get_log(fd, 0, NVME_LOG_CHANGED_NS, true,
- sizeof(changed_ns_list_log->log),
+ NVME_NO_LOG_LSP, sizeof(changed_ns_list_log->log),
changed_ns_list_log->log);
}
int nvme_error_log(int fd, int entries, struct nvme_error_log_page *err_log)
{
return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_ERROR, false,
- entries * sizeof(*err_log), err_log);
+ NVME_NO_LOG_LSP, entries * sizeof(*err_log), err_log);
}
int nvme_endurance_log(int fd, __u16 group_id, struct nvme_endurance_group_log *endurance_log)
int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log)
{
return nvme_get_log(fd, nsid, NVME_LOG_SMART, false,
- sizeof(*smart_log), smart_log);
+ NVME_NO_LOG_LSP, sizeof(*smart_log), smart_log);
}
int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo)
int nvme_self_test_log(int fd, __u32 nsid, struct nvme_self_test_log *self_test_log)
{
return nvme_get_log(fd, nsid, NVME_LOG_DEVICE_SELF_TEST, false,
- sizeof(*self_test_log), self_test_log);
+ NVME_NO_LOG_LSP, sizeof(*self_test_log), self_test_log);
}
int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log)
{
return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, false,
- sizeof(*effects_log), effects_log);
+ NVME_NO_LOG_LSP, sizeof(*effects_log), effects_log);
}
int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size)
{
- return nvme_get_log(fd, 0, NVME_LOG_DISC, false, size, log);
+ return nvme_get_log(fd, 0, NVME_LOG_DISC, false, NVME_NO_LOG_LSP, size, log);
}
int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log)
{
return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, false,
- sizeof(*sanitize_log), sanitize_log);
+ NVME_NO_LOG_LSP, sizeof(*sanitize_log), sanitize_log);
+}
+
+int nvme_persistent_event_log(int fd, __u8 action, __u32 size,
+ void *pevent_log_info)
+{
+ return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_PERSISTENT_EVENT,
+ false, action, size, pevent_log_info);
}
int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11,
int nvme_zns_identify_ns(int fd, __u32 nsid, void *data);
int nvme_identify_iocs(int fd, __u16 cntid, void *data);
int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae,
- __u32 data_len, void *data);
+ __u8 lsp, __u32 data_len, void *data);
int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo,
__u16 group_id, bool rae, __u8 uuid_ix,
__u32 data_len, void *data);
int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log);
int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size);
int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log);
+int nvme_persistent_event_log(int fd, __u8 action, __u32 size,
+ void *pevent_log_info);
int nvme_endurance_log(int fd, __u16 group_id,
struct nvme_endurance_group_log *endurance_log);
json_free_object(root);
}
+static const char *nvme_show_nss_hw_error(__u16 error_code)
+{
+ switch(error_code) {
+ case 0x01:
+ return "PCIe Correctable Error";
+ case 0x02:
+ return "PCIe Uncorrectable Non fatal Error";
+ case 0x03:
+ return "PCIe Uncorrectable Fatal Error";
+ case 0x04:
+ return "PCIe Link Status Change";
+ case 0x05:
+ return "PCIe Link Not Active";
+ case 0x06:
+ return "Critical Warning Condition";
+ case 0x07:
+ return "Endurance Group Critical Warning Condition";
+ case 0x08:
+ return "Unsafe Shutdown";
+ case 0x09:
+ return "Controller Fatal Status";
+ case 0xA:
+ return "Media and Data Integrity Status";
+ default:
+ return "Reserved";
+ }
+}
+
+void json_persistent_event_log(void *pevent_log_info,
+ __u32 size, enum nvme_print_flags flags)
+{
+ struct json_object *root;
+ struct json_object *valid_attrs;
+ struct json_array *valid;
+ __u32 offset, por_info_len, por_info_list;
+ __u64 *fw_rev;
+ char key[128];
+ struct nvme_smart_log *smart_event;
+ struct nvme_fw_commit_event *fw_commit_event;
+ struct nvme_time_stamp_change_event *ts_change_event;
+ struct nvme_power_on_reset_info_list *por_event;
+ struct nvme_nss_hw_err_event *nss_hw_err_event;
+ struct nvme_change_ns_event *ns_event;
+ struct nvme_format_nvm_start_event *format_start_event;
+ struct nvme_format_nvm_compln_event *format_cmpln_event;
+ struct nvme_sanitize_start_event *sanitize_start_event;
+ struct nvme_sanitize_compln_event *sanitize_cmpln_event;
+ struct nvme_thermal_exc_event *thermal_exc_event;
+ struct nvme_persistent_event_log_head *pevent_log_head;
+ struct nvme_persistent_event_entry_head *pevent_entry_head;
+
+ root = json_create_object();
+ valid = json_create_array();
+
+ offset = sizeof(*pevent_log_head);
+ if (size >= offset) {
+ pevent_log_head = pevent_log_info;
+ char sn[sizeof(pevent_log_head->sn) + 1],
+ mn[sizeof(pevent_log_head->mn) + 1],
+ subnqn[sizeof(pevent_log_head->subnqn) + 1];
+
+ snprintf(sn, sizeof(sn), "%-.*s",
+ (int)sizeof(pevent_log_head->sn), pevent_log_head->sn);
+ snprintf(mn, sizeof(mn), "%-.*s",
+ (int)sizeof(pevent_log_head->mn), pevent_log_head->mn);
+ snprintf(subnqn, sizeof(subnqn), "%-.*s",
+ (int)sizeof(pevent_log_head->subnqn), pevent_log_head->subnqn);
+
+ json_object_add_value_uint(root, "log_id",
+ pevent_log_head->log_id);
+ json_object_add_value_uint(root, "total_num_of_events",
+ le32_to_cpu(pevent_log_head->tnev));
+ json_object_add_value_uint(root, "total_log_len",
+ le64_to_cpu(pevent_log_head->tll));
+ json_object_add_value_uint(root, "log_revision",
+ pevent_log_head->log_rev);
+ json_object_add_value_uint(root, "log_header_len",
+ le16_to_cpu(pevent_log_head->head_len));
+ json_object_add_value_uint(root, "timestamp",
+ le64_to_cpu(pevent_log_head->timestamp));
+ json_object_add_value_float(root, "power_on_hours",
+ int128_to_double(pevent_log_head->poh));
+ json_object_add_value_uint(root, "power_cycle_count",
+ le64_to_cpu(pevent_log_head->pcc));
+ json_object_add_value_uint(root, "pci_vid",
+ le16_to_cpu(pevent_log_head->vid));
+ json_object_add_value_uint(root, "pci_ssvid",
+ le16_to_cpu(pevent_log_head->ssvid));
+ json_object_add_value_string(root, "sn", sn);
+ json_object_add_value_string(root, "mn", mn);
+ json_object_add_value_string(root, "subnqn", subnqn);
+ for (int i = 0; i < 32; i++) {
+ if (pevent_log_head->supp_event_bm[i] == 0)
+ continue;
+ sprintf(key, "bitmap_%d", i);
+ json_object_add_value_uint(root, key,
+ pevent_log_head->supp_event_bm[i]);
+ }
+ } else {
+ printf("No log data can be shown with this log len at least " \
+ "512 bytes is required or can be 0 to read the complete "\
+ "log page after context established\n");
+ return;
+ }
+ for (int i = 0; i < le32_to_cpu(pevent_log_head->tnev); i++) {
+ if (offset + sizeof(*pevent_entry_head) >= size)
+ break;
+
+ pevent_entry_head = pevent_log_info + offset;
+
+ if ((offset + pevent_entry_head->ehl + 3 +
+ le16_to_cpu(pevent_entry_head->el)) >= size)
+ break;
+ valid_attrs = json_create_object();
+
+ json_object_add_value_uint(valid_attrs, "event_type",
+ pevent_entry_head->etype);
+ json_object_add_value_uint(valid_attrs, "event_type_rev",
+ pevent_entry_head->etype_rev);
+ json_object_add_value_uint(valid_attrs, "event_header_len",
+ pevent_entry_head->ehl);
+ json_object_add_value_uint(valid_attrs, "ctrl_id",
+ le16_to_cpu(pevent_entry_head->ctrl_id));
+ json_object_add_value_uint(valid_attrs, "event_time_stamp",
+ le64_to_cpu(pevent_entry_head->etimestamp));
+ json_object_add_value_uint(valid_attrs, "vu_info_len",
+ le16_to_cpu(pevent_entry_head->vsil));
+ json_object_add_value_uint(valid_attrs, "event_len",
+ le16_to_cpu(pevent_entry_head->el));
+
+ offset += pevent_entry_head->ehl + 3;
+
+ switch(pevent_entry_head->etype) {
+ case NVME_SMART_HEALTH_EVENT:
+ smart_event = pevent_log_info + offset;
+ unsigned int temperature = ((smart_event->temperature[1] << 8) |
+ smart_event->temperature[0]);
+
+ long double data_units_read = int128_to_double(smart_event->data_units_read);
+ long double data_units_written = int128_to_double(smart_event->data_units_written);
+ long double host_read_commands = int128_to_double(smart_event->host_reads);
+ long double host_write_commands = int128_to_double(smart_event->host_writes);
+ long double controller_busy_time = int128_to_double(smart_event->ctrl_busy_time);
+ long double power_cycles = int128_to_double(smart_event->power_cycles);
+ long double power_on_hours = int128_to_double(smart_event->power_on_hours);
+ long double unsafe_shutdowns = int128_to_double(smart_event->unsafe_shutdowns);
+ long double media_errors = int128_to_double(smart_event->media_errors);
+ long double num_err_log_entries = int128_to_double(smart_event->num_err_log_entries);
+ json_object_add_value_int(valid_attrs, "critical_warning",
+ smart_event->critical_warning);
+
+ json_object_add_value_int(valid_attrs, "temperature",
+ temperature);
+ json_object_add_value_int(valid_attrs, "avail_spare",
+ smart_event->avail_spare);
+ json_object_add_value_int(valid_attrs, "spare_thresh",
+ smart_event->spare_thresh);
+ json_object_add_value_int(valid_attrs, "percent_used",
+ smart_event->percent_used);
+ json_object_add_value_int(valid_attrs,
+ "endurance_grp_critical_warning_summary",
+ smart_event->endu_grp_crit_warn_sumry);
+ json_object_add_value_float(valid_attrs, "data_units_read",
+ data_units_read);
+ json_object_add_value_float(valid_attrs, "data_units_written",
+ data_units_written);
+ json_object_add_value_float(valid_attrs, "host_read_commands",
+ host_read_commands);
+ json_object_add_value_float(valid_attrs, "host_write_commands",
+ host_write_commands);
+ json_object_add_value_float(valid_attrs, "controller_busy_time",
+ controller_busy_time);
+ json_object_add_value_float(valid_attrs, "power_cycles",
+ power_cycles);
+ json_object_add_value_float(valid_attrs, "power_on_hours",
+ power_on_hours);
+ json_object_add_value_float(valid_attrs, "unsafe_shutdowns",
+ unsafe_shutdowns);
+ json_object_add_value_float(valid_attrs, "media_errors",
+ media_errors);
+ json_object_add_value_float(valid_attrs, "num_err_log_entries",
+ num_err_log_entries);
+ json_object_add_value_uint(valid_attrs, "warning_temp_time",
+ le32_to_cpu(smart_event->warning_temp_time));
+ json_object_add_value_uint(valid_attrs, "critical_comp_time",
+ le32_to_cpu(smart_event->critical_comp_time));
+
+ for (int c = 0; c < 8; c++) {
+ __s32 temp = le16_to_cpu(smart_event->temp_sensor[c]);
+ if (temp == 0)
+ continue;
+ sprintf(key, "temperature_sensor_%d",c + 1);
+ json_object_add_value_int(valid_attrs, key, temp);
+ }
+
+ json_object_add_value_uint(valid_attrs, "thm_temp1_trans_count",
+ le32_to_cpu(smart_event->thm_temp1_trans_count));
+ json_object_add_value_uint(valid_attrs, "thm_temp2_trans_count",
+ le32_to_cpu(smart_event->thm_temp2_trans_count));
+ json_object_add_value_uint(valid_attrs, "thm_temp1_total_time",
+ le32_to_cpu(smart_event->thm_temp1_total_time));
+ json_object_add_value_uint(valid_attrs, "thm_temp2_total_time",
+ le32_to_cpu(smart_event->thm_temp2_total_time));
+ break;
+ case NVME_FW_COMMIT_EVENT:
+ fw_commit_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "old_fw_rev",
+ le64_to_cpu(fw_commit_event->old_fw_rev));
+ json_object_add_value_uint(valid_attrs, "new_fw_rev",
+ le64_to_cpu(fw_commit_event->new_fw_rev));
+ json_object_add_value_uint(valid_attrs, "fw_commit_action",
+ fw_commit_event->fw_commit_action);
+ json_object_add_value_uint(valid_attrs, "fw_slot",
+ fw_commit_event->fw_slot);
+ json_object_add_value_uint(valid_attrs, "sct_fw",
+ fw_commit_event->sct_fw);
+ json_object_add_value_uint(valid_attrs, "sc_fw",
+ fw_commit_event->sc_fw);
+ json_object_add_value_uint(valid_attrs,
+ "vu_assign_fw_commit_rc",
+ le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc));
+ break;
+ case NVME_TIMESTAMP_EVENT:
+ ts_change_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "prev_ts",
+ le64_to_cpu(ts_change_event->previous_timestamp));
+ json_object_add_value_uint(valid_attrs,
+ "ml_secs_since_reset",
+ le64_to_cpu(ts_change_event->ml_secs_since_reset));
+ break;
+ case NVME_POWER_ON_RESET_EVENT:
+ por_info_len = (le16_to_cpu(pevent_entry_head->el) -
+ le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev));
+
+ por_info_list = por_info_len / sizeof(*por_event);
+
+ fw_rev = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "fw_rev",
+ le64_to_cpu(*fw_rev));
+ for (int i = 0; i < por_info_list; i++) {
+ por_event = pevent_log_info + offset +
+ sizeof(*fw_rev) + i * sizeof(*por_event);
+ json_object_add_value_uint(valid_attrs, "ctrl_id",
+ le16_to_cpu(por_event->cid));
+ json_object_add_value_uint(valid_attrs, "fw_act",
+ por_event->fw_act);
+ json_object_add_value_uint(valid_attrs, "op_in_prog",
+ por_event->op_in_prog);
+ json_object_add_value_uint(valid_attrs, "ctrl_power_cycle",
+ le32_to_cpu(por_event->ctrl_power_cycle));
+ json_object_add_value_uint(valid_attrs, "power_on_ml_secs",
+ le64_to_cpu(por_event->power_on_ml_seconds));
+ json_object_add_value_uint(valid_attrs, "ctrl_time_stamp",
+ le64_to_cpu(por_event->ctrl_time_stamp));
+ }
+ break;
+ case NVME_NSS_HW_ERROR_EVENT:
+ nss_hw_err_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "nss_hw_err_code",
+ le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code));
+ break;
+ case NVME_CHANGE_NS_EVENT:
+ ns_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "nsmgt_cdw10",
+ le32_to_cpu(ns_event->nsmgt_cdw10));
+ json_object_add_value_uint(valid_attrs, "nsze",
+ le64_to_cpu(ns_event->nsze));
+ long double nscap = int128_to_double(ns_event->nscap);
+ json_object_add_value_float(valid_attrs, "nscap",
+ nscap);
+ json_object_add_value_uint(valid_attrs, "flbas",
+ ns_event->flbas);
+ json_object_add_value_uint(valid_attrs, "dps",
+ ns_event->dps);
+ json_object_add_value_uint(valid_attrs, "nmic",
+ ns_event->nmic);
+ json_object_add_value_uint(valid_attrs, "ana_grp_id",
+ le32_to_cpu(ns_event->ana_grp_id));
+ json_object_add_value_uint(valid_attrs, "nvmset_id",
+ le16_to_cpu(ns_event->nvmset_id));
+ json_object_add_value_uint(valid_attrs, "nsid",
+ le32_to_cpu(ns_event->nsid));
+ break;
+ case NVME_FORMAT_START_EVENT:
+ format_start_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "nsid",
+ le32_to_cpu(format_start_event->nsid));
+ json_object_add_value_uint(valid_attrs, "fna",
+ format_start_event->fna);
+ json_object_add_value_uint(valid_attrs, "format_nvm_cdw10",
+ le32_to_cpu(format_start_event->format_nvm_cdw10));
+ break;
+ case NVME_FORMAT_COMPLETION_EVENT:
+ format_cmpln_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "nsid",
+ le32_to_cpu(format_cmpln_event->nsid));
+ json_object_add_value_uint(valid_attrs, "smallest_fpi",
+ format_cmpln_event->smallest_fpi);
+ json_object_add_value_uint(valid_attrs, "format_nvm_status",
+ format_cmpln_event->format_nvm_status);
+ json_object_add_value_uint(valid_attrs, "compln_info",
+ le16_to_cpu(format_cmpln_event->compln_info));
+ json_object_add_value_uint(valid_attrs, "status_field",
+ le32_to_cpu(format_cmpln_event->status_field));
+ break;
+ case NVME_SANITIZE_START_EVENT:
+ sanitize_start_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "SANICAP",
+ le32_to_cpu(sanitize_start_event->sani_cap));
+ json_object_add_value_uint(valid_attrs, "sani_cdw10",
+ le32_to_cpu(sanitize_start_event->sani_cdw10));
+ json_object_add_value_uint(valid_attrs, "sani_cdw11",
+ le32_to_cpu(sanitize_start_event->sani_cdw11));
+ break;
+ case NVME_SANITIZE_COMPLETION_EVENT:
+ sanitize_cmpln_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "sani_prog",
+ le16_to_cpu(sanitize_cmpln_event->sani_prog));
+ json_object_add_value_uint(valid_attrs, "sani_status",
+ le16_to_cpu(sanitize_cmpln_event->sani_status));
+ json_object_add_value_uint(valid_attrs, "cmpln_info",
+ le16_to_cpu(sanitize_cmpln_event->cmpln_info));
+ break;
+ case NVME_THERMAL_EXCURSION_EVENT:
+ thermal_exc_event = pevent_log_info + offset;
+ json_object_add_value_uint(valid_attrs, "over_temp",
+ thermal_exc_event->over_temp);
+ json_object_add_value_uint(valid_attrs, "threshold",
+ thermal_exc_event->threshold);
+ break;
+ }
+
+ json_array_add_value_object(valid, valid_attrs);
+ offset += le16_to_cpu(pevent_entry_head->el);
+ }
+
+ json_object_add_value_array(root, "list_of_event_entries", valid);
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
+void nvme_show_persistent_event_log(void *pevent_log_info,
+ __u8 action, __u32 size, const char *devname,
+ enum nvme_print_flags flags)
+{
+ __u32 offset, por_info_len, por_info_list;
+ __u64 *fw_rev;
+ struct nvme_smart_log *smart_event;
+ struct nvme_fw_commit_event *fw_commit_event;
+ struct nvme_time_stamp_change_event *ts_change_event;
+ struct nvme_power_on_reset_info_list *por_event;
+ struct nvme_nss_hw_err_event *nss_hw_err_event;
+ struct nvme_change_ns_event *ns_event;
+ struct nvme_format_nvm_start_event *format_start_event;
+ struct nvme_format_nvm_compln_event *format_cmpln_event;
+ struct nvme_sanitize_start_event *sanitize_start_event;
+ struct nvme_sanitize_compln_event *sanitize_cmpln_event;
+ struct nvme_thermal_exc_event *thermal_exc_event;
+ struct nvme_persistent_event_log_head *pevent_log_head;
+ struct nvme_persistent_event_entry_head *pevent_entry_head;
+
+ if (flags & BINARY)
+ return d_raw((unsigned char *)pevent_log_info, size);
+ if (flags & JSON)
+ return json_persistent_event_log(pevent_log_info, size,
+ flags);
+
+ offset = sizeof(*pevent_log_head);
+
+ printf("Persistent Event Log for device: %s\n", devname);
+ printf("Action for Persistent Event Log: %u\n", action);
+ if (size >= offset) {
+ pevent_log_head = pevent_log_info;
+ printf("Log Identifier: %u\n", pevent_log_head->log_id);
+ printf("Total Number of Events: %u\n",
+ le32_to_cpu(pevent_log_head->tnev));
+ printf("Total Log Length : %"PRIu64"\n",
+ le64_to_cpu(pevent_log_head->tll));
+ printf("Log Revision: %u\n", pevent_log_head->log_rev);
+ printf("Log Header Length: %u\n", pevent_log_head->head_len);
+ printf("Timestamp: %"PRIu64"\n",
+ le64_to_cpu(pevent_log_head->timestamp));
+ printf("Power On Hours (POH): %'.0Lf\n",
+ int128_to_double(pevent_log_head->poh));
+ printf("Power Cycle Count: %"PRIu64"\n",
+ le64_to_cpu(pevent_log_head->pcc));
+ printf("PCI Vendor ID (VID): %u\n",
+ le16_to_cpu(pevent_log_head->vid));
+ printf("PCI Subsystem Vendor ID (SSVID): %u\n",
+ le16_to_cpu(pevent_log_head->ssvid));
+ printf("Serial Number (SN): %-.*s\n",
+ (int)sizeof(pevent_log_head->sn), pevent_log_head->sn);
+ printf("Model Number (MN): %-.*s\n",
+ (int)sizeof(pevent_log_head->mn), pevent_log_head->mn);
+ printf("NVM Subsystem NVMe Qualified Name (SUBNQN): %-.*s\n",
+ (int)sizeof(pevent_log_head->subnqn),
+ pevent_log_head->subnqn);
+ printf("Supported Events Bitmap: ");
+ for (int i = 0; i < 32; i++) {
+ if (pevent_log_head->supp_event_bm[i] == 0)
+ continue;
+ printf("BitMap[%d] is 0x%x\n", i,
+ pevent_log_head->supp_event_bm[i]);
+ }
+ } else {
+ printf("No log data can be shown with this log len at least " \
+ "512 bytes is required or can be 0 to read the complete "\
+ "log page after context established\n");
+ return;
+ }
+ printf("\n");
+ printf("\nPersistent Event Entries:\n");
+ for (int i = 0; i < le32_to_cpu(pevent_log_head->tnev); i++) {
+ if (offset + sizeof(*pevent_entry_head) >= size)
+ break;
+
+ pevent_entry_head = pevent_log_info + offset;
+
+ if ((offset + pevent_entry_head->ehl + 3 +
+ le16_to_cpu(pevent_entry_head->el)) >= size)
+ break;
+
+ printf("Event Type: %u\n", pevent_entry_head->etype);
+ printf("Event Type Revision: %u\n", pevent_entry_head->etype_rev);
+ printf("Event Header Length: %u\n", pevent_entry_head->ehl);
+ printf("Controller Identifier: %u\n",
+ le16_to_cpu(pevent_entry_head->ctrl_id));
+ printf("Event Timestamp: %"PRIu64"\n",
+ le64_to_cpu(pevent_entry_head->etimestamp));
+ printf("Vendor Specific Information Length: %u\n",
+ le16_to_cpu(pevent_entry_head->vsil));
+ printf("Event Length: %u\n", le16_to_cpu(pevent_entry_head->el));
+
+ offset += pevent_entry_head->ehl + 3;
+
+ switch(pevent_entry_head->etype) {
+ case NVME_SMART_HEALTH_EVENT:
+ smart_event = pevent_log_info + offset;
+ printf("Smart Health Event: \n");
+ nvme_show_smart_log(smart_event, NVME_NSID_ALL, devname, flags);
+ break;
+ case NVME_FW_COMMIT_EVENT:
+ fw_commit_event = pevent_log_info + offset;
+ printf("FW Commit Event: \n");
+ printf("Old Firmware Revision: %"PRIu64"\n",
+ le64_to_cpu(fw_commit_event->old_fw_rev));
+ printf("New Firmware Revision: %"PRIu64"\n",
+ le64_to_cpu(fw_commit_event->new_fw_rev));
+ printf("FW Commit Action: %u\n",
+ fw_commit_event->fw_commit_action);
+ printf("FW Slot: %u\n", fw_commit_event->fw_slot);
+ printf("Status Code Type for Firmware Commit Command: %u\n",
+ fw_commit_event->sct_fw);
+ printf("Status Returned for Firmware Commit Command: %u\n",
+ fw_commit_event->sc_fw);
+ printf("Vendor Assigned Firmware Commit Result Code: %u\n",
+ le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc));
+ break;
+ case NVME_TIMESTAMP_EVENT:
+ ts_change_event = pevent_log_info + offset;
+ printf("Time Stamp Change Event: \n");
+ printf("Previous Timestamp: %"PRIu64"\n",
+ le64_to_cpu(ts_change_event->previous_timestamp));
+ printf("Milliseconds Since Reset: %"PRIu64"\n",
+ le64_to_cpu(ts_change_event->ml_secs_since_reset));
+ break;
+ case NVME_POWER_ON_RESET_EVENT:
+ por_info_len = (le16_to_cpu(pevent_entry_head->el) -
+ le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev));
+
+ por_info_list = por_info_len / sizeof(*por_event);
+
+ printf("Power On Reset Event: \n");
+ fw_rev = pevent_log_info + offset;
+ printf("Firmware Revision: %"PRIu64"\n", le64_to_cpu(*fw_rev));
+ printf("Reset Information List: \n");
+
+ for (int i = 0; i < por_info_list; i++) {
+ por_event = pevent_log_info + offset +
+ sizeof(*fw_rev) + i * sizeof(*por_event);
+ printf("Controller ID: %u\n", le16_to_cpu(por_event->cid));
+ printf("Firmware Activation: %u\n",
+ por_event->fw_act);
+ printf("Operation in Progress: %u\n",
+ por_event->op_in_prog);
+ printf("Controller Power Cycle: %u\n",
+ le32_to_cpu(por_event->ctrl_power_cycle));
+ printf("Power on milliseconds: %"PRIu64"\n",
+ le64_to_cpu(por_event->power_on_ml_seconds));
+ printf("Controller Timestamp: %"PRIu64"\n",
+ le64_to_cpu(por_event->ctrl_time_stamp));
+ }
+ break;
+ case NVME_NSS_HW_ERROR_EVENT:
+ nss_hw_err_event = pevent_log_info + offset;
+ printf("NVM Subsystem Hardware Error Event Code: %u, %s\n",
+ le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code),
+ nvme_show_nss_hw_error(nss_hw_err_event->nss_hw_err_event_code));
+ break;
+ case NVME_CHANGE_NS_EVENT:
+ ns_event = pevent_log_info + offset;
+ printf("Change Namespace Event: \n");
+ printf("Namespace Management CDW10: %u\n",
+ le32_to_cpu(ns_event->nsmgt_cdw10));
+ printf("Namespace Size: %"PRIu64"\n",
+ le64_to_cpu(ns_event->nsze));
+ printf("Namespace Capacity: %'.0Lf\n",
+ int128_to_double(ns_event->nscap));
+ printf("Formatted LBA Size: %u\n", ns_event->flbas);
+ printf("End-to-end Data Protection Type Settings: %u\n",
+ ns_event->dps);
+ printf("Namespace Multi-path I/O and Namespace Sharing" \
+ " Capabilities: %u\n", ns_event->nmic);
+ printf("ANA Group Identifier: %u\n",
+ le32_to_cpu(ns_event->ana_grp_id));
+ printf("NVM Set Identifier: %u\n", le16_to_cpu(ns_event->nvmset_id));
+ printf("Namespace ID: %u\n", le32_to_cpu(ns_event->nsid));
+ break;
+ case NVME_FORMAT_START_EVENT:
+ format_start_event = pevent_log_info + offset;
+ printf("Format NVM Start Event: \n");
+ printf("Namespace Identifier: %u\n",
+ le32_to_cpu(format_start_event->nsid));
+ printf("Format NVM Attributes: %u\n",
+ format_start_event->fna);
+ printf("Format NVM CDW10: %u\n",
+ le32_to_cpu(format_start_event->format_nvm_cdw10));
+ break;
+ case NVME_FORMAT_COMPLETION_EVENT:
+ format_cmpln_event = pevent_log_info + offset;
+ printf("Format NVM Completion Event: \n");
+ printf("Namespace Identifier: %u\n",
+ le32_to_cpu(format_cmpln_event->nsid));
+ printf("Smallest Format Progress Indicator: %u\n",
+ format_cmpln_event->smallest_fpi);
+ printf("Format NVM Status: %u\n",
+ format_cmpln_event->format_nvm_status);
+ printf("Completion Information: %u\n",
+ le16_to_cpu(format_cmpln_event->compln_info));
+ printf("Status Field: %u\n",
+ le32_to_cpu(format_cmpln_event->status_field));
+ break;
+ case NVME_SANITIZE_START_EVENT:
+ sanitize_start_event = pevent_log_info + offset;
+ printf("Sanitize Start Event: \n");
+ printf("SANICAP: %u\n", sanitize_start_event->sani_cap);
+ printf("Sanitize CDW10: %u\n",
+ le32_to_cpu(sanitize_start_event->sani_cdw10));
+ printf("Sanitize CDW11: %u\n",
+ le32_to_cpu(sanitize_start_event->sani_cdw11));
+ break;
+ case NVME_SANITIZE_COMPLETION_EVENT:
+ sanitize_cmpln_event = pevent_log_info + offset;
+ printf("Sanitize Completion Event: \n");
+ printf("Sanitize Progress: %u\n",
+ le16_to_cpu(sanitize_cmpln_event->sani_prog));
+ printf("Sanitize Status: %u\n",
+ le16_to_cpu(sanitize_cmpln_event->sani_status));
+ printf("Completion Information: %u\n",
+ le16_to_cpu(sanitize_cmpln_event->cmpln_info));
+ break;
+ case NVME_THERMAL_EXCURSION_EVENT:
+ thermal_exc_event = pevent_log_info + offset;
+ printf("Thermal Excursion Event: \n");
+ printf("Over Temperature: %u\n", thermal_exc_event->over_temp);
+ printf("Threshold: %u\n", thermal_exc_event->threshold);
+ break;
+ default:
+ printf("Reserved Event\n\n");
+ }
+ offset += le16_to_cpu(pevent_entry_head->el);
+ printf("\n");
+ }
+}
+
static void nvme_show_subsystem(struct nvme_subsystem *s)
{
int i;
__u16 group_id, const char *devname, enum nvme_print_flags flags);
void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize,
const char *devname, enum nvme_print_flags flags);
+void json_persistent_event_log(void *pevent_log_info,
+ __u32 size, enum nvme_print_flags flags);
+void nvme_show_persistent_event_log(void *pevent_log_info,
+ __u8 action, __u32 size, const char *devname,
+ enum nvme_print_flags flags);
void nvme_show_ctrl_registers(void *bar, bool fabrics, enum nvme_print_flags flags);
void nvme_show_single_property(int offset, uint64_t prop, int human);
void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flags);
return nvme_status_to_errno(err, false);
}
+static int get_persistent_event_log(int argc, char **argv,
+ struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Retrieve Persistent Event log info for"\
+ "the given device in either decoded format(default),"\
+ " json or binary.";
+ const char *action = "action the controller shall take during"\
+ "processing this persistent log page command.";
+ const char *log_len = "number of bytes to retrieve";
+ const char *raw = "use binary output";
+ void *pevent_log_info;
+ struct nvme_persistent_event_log_head *pevent_log_head;
+ enum nvme_print_flags flags;
+ int err, fd;
+ bool huge;
+
+ struct config {
+ __u8 action;
+ __u32 log_len;
+ int raw_binary;
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .action = 0xff,
+ .log_len = 0,
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("action", 'a', &cfg.action, action),
+ OPT_UINT("log_len", 'l', &cfg.log_len, log_len),
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_END()
+ };
+
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+ if (cfg.raw_binary)
+ flags = BINARY;
+
+ pevent_log_head = calloc(sizeof(*pevent_log_head), 1);
+ if (!pevent_log_head) {
+ fprintf(stderr, "could not alloc buffer for persistent " \
+ "event log header\n");
+ err = -ENOMEM;
+ goto close_fd;
+ }
+
+ err = nvme_persistent_event_log(fd, cfg.action,
+ sizeof(*pevent_log_head), pevent_log_head);
+ if (err < 0) {
+ perror("persistent event log");
+ goto close_fd;
+ } else if (err) {
+ nvme_show_status(err);
+ goto close_fd;
+ }
+
+ if (cfg.action == NVME_PEVENT_LOG_RELEASE_CTX) {
+ printf("Releasing Persistent Event Log Context\n");
+ goto close_fd;
+ }
+
+ if (!cfg.log_len && cfg.action != NVME_PEVENT_LOG_EST_CTX_AND_READ) {
+ cfg.log_len = le64_to_cpu(pevent_log_head->tll);
+ } else if (!cfg.log_len && cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ) {
+ printf("Establishing Persistent Event Log Context\n");
+ goto close_fd;
+ }
+
+ /*
+ * if header aleady read with context establish action 0x1,
+ * action shall not be 0x1 again in the subsequent request,
+ * until the current context is released by issuing action
+ * with 0x2, otherwise throws command sequence error, make
+ * it as zero to read the log page
+ */
+ if (cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ)
+ cfg.action = NVME_PEVENT_LOG_READ;
+
+ pevent_log_info = nvme_alloc(cfg.log_len, &huge);
+ if (!pevent_log_info) {
+ fprintf(stderr, "could not alloc buffer for persistent " \
+ "event log page\n");
+ err = -ENOMEM;
+ goto close_fd;
+ }
+ err = nvme_persistent_event_log(fd, cfg.action,
+ cfg.log_len, pevent_log_info);
+ if (!err)
+ nvme_show_persistent_event_log(pevent_log_info, cfg.action,
+ cfg.log_len, devicename, flags);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("persistent event log");
+
+ nvme_free(pevent_log_info, huge);
+
+close_fd:
+ free(pevent_log_head);
+ close(fd);
+ret:
+ return nvme_status_to_errno(err, false);
+}
+
static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Retrieve desired number of bytes "\
if (fd < 0)
return fd;
- err = nvme_get_log(fd, 0xffffffff, 0xc0, false, sizeof(log), &log);
+ err = nvme_get_log(fd, 0xffffffff, 0xc0, false, NVME_NO_LOG_LSP,
+ sizeof(log), &log);
if (err) {
goto exit;
}
return fd;
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
- sizeof(smart_log), &smart_log);
+ NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
if (!err) {
if (cfg.json)
show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename);
return fd;
err = nvme_get_log(fd, NVME_NSID_ALL, 0xdd, false,
- sizeof(log), log);
+ NVME_NO_LOG_LSP, sizeof(log), log);
if (!err) {
if (!cfg.raw_binary)
printf("Intel Marketing Name Log:\n%s\n", log);
return fd;
err = nvme_get_log(fd, NVME_NSID_ALL, 0xc5, false,
- sizeof(stats), &stats);
+ NVME_NO_LOG_LSP, sizeof(stats), &stats);
if (!err) {
if (!cfg.raw_binary)
show_temp_stats(&stats);
flags = BINARY;
err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1,
- false, sizeof(stats), &stats);
+ false, NVME_NO_LOG_LSP, sizeof(stats), &stats);
if (!err) {
if (flags & JSON)
json_lat_stats(&stats, cfg.write);
return fd;
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
- sizeof(smart_log), &smart_log);
+ NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log);
LogPageHeader_t *pLogHeader = NULL;
if (ucLogID == 0xC1 || ucLogID == 0xC2 || ucLogID == 0xC4) {
- err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, CommonChunkSize, pTmpBuf);
+ err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP,
+ CommonChunkSize, pTmpBuf);
if (err == 0) {
pLogHeader = (LogPageHeader_t *) pTmpBuf;
LogPageHeader_t *pLogHeader1 = (LogPageHeader_t *) pLogHeader;
goto exit_status;
}
memset(pTempPtr, 0, nBuffSize);
- err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, nBuffSize, pTempPtr);
+ err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP,
+ nBuffSize, pTempPtr);
*pBuffer = pTempPtr;
exit_status:
log_page = 0xFB;
log_size = FB_log_size;
}
- err = nvme_get_log(fd, NVME_NSID_ALL, log_page, false, log_size, extSmartLog);
+ err = nvme_get_log(fd, NVME_NSID_ALL, log_page, false, NVME_NO_LOG_LSP,
+ log_size, extSmartLog);
if (err) {
printf("Unable to retrieve extended smart log for the drive\n");
goto out;
}
if (bSize != 0 && (dataBuffer = (unsigned char *)malloc(bSize)) != NULL) {
memset(dataBuffer, 0, bSize);
- err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, false, bSize, dataBuffer);
+ err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, false, NVME_NO_LOG_LSP,
+ bSize, dataBuffer);
}
break;
break;
}
memset(dataBuffer, 0, bSize);
- err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, false, bSize, dataBuffer);
+ err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, false, NVME_NO_LOG_LSP,
+ bSize, dataBuffer);
maxSize = aVendorLogs[i].nMaxSize - bSize;
while (err == 0 && maxSize > 0 && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) {
sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage);
WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg);
- err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, false, bSize, dataBuffer);
+ err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, false, NVME_NO_LOG_LSP,
+ bSize, dataBuffer);
if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef))
break;
maxSize -= bSize;
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, sizeof(smart_log),
- (void *)&smart_log);
+ err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, NVME_NO_LOG_LSP,
+ sizeof(smart_log), (void *)&smart_log);
if (!err) {
if (cfg.json)
show_sfx_smart_log_jsn(&smart_log, cfg.namespace_id, devicename);
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, sizeof(stats), (void *)&stats);
+ err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, NVME_NO_LOG_LSP,
+ sizeof(stats), (void *)&stats);
if (!err) {
if (!cfg.raw_binary)
show_lat_stats(&stats, cfg.write);
};
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_get_log(fd, 1, 0xc5, false, sizeof(logPageMap), &logPageMap);
+ err = nvme_get_log(fd, 1, 0xc5, false, NVME_NO_LOG_LSP,
+ sizeof(logPageMap), &logPageMap);
if (!err) {
if (strcmp(cfg.output_format,"json")) {
printf ("Seagate Supported Log-pages count :%d\n",
if (strcmp(cfg.output_format,"json"))
printf("Seagate Extended SMART Information :\n");
- err = nvme_get_log(fd, 1, 0xC4, false, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
+ err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP,
+ sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
if (!err) {
if (strcmp(cfg.output_format,"json")) {
printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
* Next get Log Page 0xCF
*/
- err = nvme_get_log(fd, 1, 0xCF, false, sizeof(logPageCF), &logPageCF);
+ err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP,
+ sizeof(logPageCF), &logPageCF);
if (!err) {
if(strcmp(cfg.output_format,"json")) {
/*printf("Seagate DRAM Supercap SMART Attributes :\n");*/
}
/* STEP-2 : Get Max temperature form Ext SMART-id 194 */
- err = nvme_get_log(fd, 1, 0xC4, false, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
+ err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP,
+ sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
if (!err) {
for(index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) {
if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) {
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
- cf_err = nvme_get_log(fd, 1, 0xCF, false, sizeof(ExtdSMARTInfo), &logPageCF);
+ cf_err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP,
+ sizeof(ExtdSMARTInfo), &logPageCF);
if(!cf_err) {
scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature;
if(strcmp(cfg.output_format,"json"))
printf("Seagate PCIe error counters Information :\n");
- err = nvme_get_log(fd, 1, 0xCB, false, sizeof(pcieErrorLog), &pcieErrorLog);
+ err = nvme_get_log(fd, 1, 0xCB, false, NVME_NO_LOG_LSP,
+ sizeof(pcieErrorLog), &pcieErrorLog);
if (!err) {
if(strcmp(cfg.output_format,"json")) {
print_vs_pcie_error_log(pcieErrorLog);
fd = parse_and_open(argc, argv, desc, opts);
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
- sizeof(smart_log), &smart_log);
+ NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
show_shannon_smart_log(&smart_log, cfg.namespace_id, devicename);
goto end;
}
err = nvme_get_log(fd, namespace_id, log_page, false,
- log_len, log);
+ NVME_NO_LOG_LSP, log_len, log);
if (err) {
fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__,
log_page);
/* Get the 0xC0 log data */
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE,
- false, WDC_NVME_EOL_STATUS_LOG_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_NVME_EOL_STATUS_LOG_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
/* Get the 0xC0 log data */
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE,
- false, WDC_NVME_SMART_CLOUD_ATTR_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_NVME_SMART_CLOUD_ATTR_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN);
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
- false, WDC_FB_CA_LOG_BUF_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN);
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
- false, WDC_FB_CA_LOG_BUF_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
memset(data, 0, sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN);
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
- false, WDC_BD_CA_LOG_BUF_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_BD_CA_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
memset(data, 0, sizeof (__u8) * WDC_ADD_LOG_BUF_LEN);
ret = nvme_get_log(fd, 0x01, WDC_NVME_ADD_LOG_OPCODE, false,
- WDC_ADD_LOG_BUF_LEN, data);
+ NVME_NO_LOG_LSP, WDC_ADD_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
if (ret == 0) {
memset(data, 0, sizeof (__u8) * WDC_NVME_VU_SMART_LOG_LEN);
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_VU_SMART_LOG_OPCODE,
- false, WDC_NVME_VU_SMART_LOG_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_NVME_VU_SMART_LOG_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN);
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID,
- false, WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN);
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID,
- false, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data);
+ false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
memset(dataBuffer, 0, dataBufferSize);
ret = nvme_get_log(fd, WDC_DE_GLOBAL_NSID, deVULogPagesList[vuLogIdx].logPageId,
- false, dataBufferSize, dataBuffer);
+ false, NVME_NO_LOG_LSP, dataBufferSize, dataBuffer);
if (ret) {
fprintf(stderr, "ERROR : WDC : nvme_get_log() for log page 0x%x failed, ret = %d\n",
deVULogPagesList[vuLogIdx].logPageId, ret);
}
ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_NAND_STATS_LOG_ID,
- false, WDC_NVME_NAND_STATS_SIZE, (void*)output);
+ false, NVME_NO_LOG_LSP, WDC_NVME_NAND_STATS_SIZE, (void*)output);
if (ret) {
fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__);
goto out;
}
err = nvme_get_log(fd, cfg.namespace_id, NVME_LOG_ZONE_CHANGED_LIST,
- cfg.rae, sizeof(log), &log);
+ cfg.rae, NVME_NO_LOG_LSP, sizeof(log), &log);
if (!err)
nvme_show_zns_changed(&log, flags);
else if (err > 0)