From owner-svn-src-all@freebsd.org Sat Nov 19 17:16:56 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5C80CC4B489; Sat, 19 Nov 2016 17:16:56 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A2FC665E39; Sat, 19 Nov 2016 17:13:14 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uAJHDDAq082980; Sat, 19 Nov 2016 17:13:13 GMT (envelope-from imp@FreeBSD.org) Received: (from imp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uAJHDD4N082979; Sat, 19 Nov 2016 17:13:13 GMT (envelope-from imp@FreeBSD.org) Message-Id: <201611191713.uAJHDD4N082979@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: imp set sender to imp@FreeBSD.org using -f From: Warner Losh Date: Sat, 19 Nov 2016 17:13:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r308856 - head/sbin/nvmecontrol X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Nov 2016 17:16:56 -0000 Author: imp Date: Sat Nov 19 17:13:12 2016 New Revision: 308856 URL: https://svnweb.freebsd.org/changeset/base/308856 Log: Decode the Intel-specific Additional SMART data page (0xca) and print it in human readable form. Include a pointer to the public spec that was followed to implement this in the code. Samsung also implements page 0xca on some of their drives, but the format is slighly different, so the code skips printing zero keys. Samsung's log page has additional, unknown data after the end of Intel defined data which isn't displayed. Supported by: Netfix, Inc Modified: head/sbin/nvmecontrol/logpage.c Modified: head/sbin/nvmecontrol/logpage.c ============================================================================== --- head/sbin/nvmecontrol/logpage.c Sat Nov 19 17:13:08 2016 (r308855) +++ head/sbin/nvmecontrol/logpage.c Sat Nov 19 17:13:12 2016 (r308856) @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); typedef void (*print_fn_t)(void *buf, uint32_t size); - struct kv_name { uint32_t key; @@ -106,6 +105,15 @@ uint128_to_str(uint128_t u, char *buf, s return end; } +/* "fMissing" from endian.h */ +static __inline uint64_t +le48dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((uint64_t)le16dec(p + 4) << 32) | le32dec(p)); +} + static void * get_log_buffer(uint32_t size) { @@ -278,6 +286,13 @@ print_log_firmware(void *buf, uint32_t s } } +/* + * Intel specific log pages from + * http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/ssd-dc-p3700-spec.pdf + * + * Though the version as of this date has a typo for the size of log page 0xca, + * offset 147: it is only 1 byte, not 6. + */ static void print_intel_temp_stats(void *buf, uint32_t size __unused) { @@ -301,6 +316,68 @@ print_intel_temp_stats(void *buf, uint32 printf("Estimated Temperature Offset: %ju C/K\n", (uintmax_t)temp->est_offset); } +static void +print_intel_add_smart(void *buf, uint32_t size __unused) +{ + uint8_t *walker = buf; + uint8_t *end = walker + 150; + const char *name; + uint64_t raw; + uint8_t normalized; + + static struct kv_name kv[] = + { + { 0xab, "Program Fail Count" }, + { 0xac, "Erase Fail Count" }, + { 0xad, "Wear Leveling Count" }, + { 0xb8, "End to End Error Count" }, + { 0xc7, "CRC Error Count" }, + { 0xe2, "Timed: Media Wear" }, + { 0xe3, "Timed: Host Read %" }, + { 0xe4, "Timed: Elapsed Time" }, + { 0xea, "Thermal Throttle Status" }, + { 0xf0, "Retry Buffer Overflows" }, + { 0xf3, "PLL Lock Loss Count" }, + { 0xf4, "NAND Bytes Written" }, + { 0xf5, "Host Bytes Written" }, + }; + + printf("Additional SMART Data Log\n"); + printf("=========================\n"); + /* + * walker[0] = Key + * walker[1,2] = reserved + * walker[3] = Normalized Value + * walker[4] = reserved + * walker[5..10] = Little Endian Raw value + * (or other represenations) + * walker[11] = reserved + */ + while (walker < end) { + name = kv_lookup(kv, nitems(kv), *walker); + normalized = walker[3]; + raw = le48dec(walker + 5); + switch (*walker){ + case 0: + break; + case 0xad: + printf("%-32s: %3d min: %u max: %u ave: %u\n", name, normalized, + le16dec(walker + 5), le16dec(walker + 7), le16dec(walker + 9)); + break; + case 0xe2: + printf("%-32s: %3d %.3f%%\n", name, normalized, raw / 1024.0); + break; + case 0xea: + printf("%-32s: %3d %d%% %d times\n", name, normalized, walker[5], le32dec(walker+6)); + break; + default: + printf("%-32s: %3d %ju\n", name, normalized, (uintmax_t)raw); + break; + } + walker += 12; + } +} + /* * HGST's 0xc1 page. This is a grab bag of additional data. Please see * https://www.hgst.com/sites/default/files/resources/US_SN150_ProdManual.pdf @@ -719,6 +796,8 @@ static struct logpage_function { sizeof(struct nvme_firmware_page)}, {INTEL_LOG_TEMP_STATS, print_intel_temp_stats, sizeof(struct intel_log_temp_stats)}, + {INTEL_LOG_ADD_SMART, print_intel_add_smart, + DEFAULT_SIZE}, {HGST_INFO_LOG, print_hgst_info_log, DEFAULT_SIZE}, {0, NULL,