1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2022 Wanpeng Qian <wanpengqian@gmail.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/ioccom.h> 33 34 #include <ctype.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <stdbool.h> 38 #include <stddef.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include <sys/endian.h> 44 45 #include "nvmecontrol.h" 46 47 struct samsung_log_extended_smart 48 { 49 uint8_t kv[256];/* Key-Value pair */ 50 uint32_t lwaf; /* Lifetime Write Amplification */ 51 uint32_t thwaf; /* Trailing Hour Write Amplification Factor */ 52 uint64_t luw[2]; /* Lifetime User Writes */ 53 uint64_t lnw[2]; /* Lifetime NAND Writes */ 54 uint64_t lur[2]; /* Lifetime User Reads */ 55 uint32_t lrbc; /* Lifetime Retired Block Count */ 56 uint16_t ct; /* Current Temperature */ 57 uint16_t ch; /* Capacitor Health */ 58 uint32_t luurb; /* Lifetime Unused Reserved Block */ 59 uint64_t rrc; /* Read Reclaim Count */ 60 uint64_t lueccc; /* Lifetime Uncorrectable ECC count */ 61 uint32_t lurb; /* Lifetime Used Reserved Block */ 62 uint64_t poh[2]; /* Power on Hours */ 63 uint64_t npoc[2];/* Normal Power Off Count */ 64 uint64_t spoc[2];/* Sudden Power Off Count */ 65 uint32_t pi; /* Performance Indicator */ 66 } __packed; 67 68 static void 69 print_samsung_extended_smart(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused) 70 { 71 struct samsung_log_extended_smart *temp = buf; 72 char cbuf[UINT128_DIG + 1]; 73 uint8_t *walker = buf; 74 uint8_t *end = walker + 150; 75 const char *name; 76 uint64_t raw; 77 uint8_t normalized; 78 79 static struct kv_name kv[] = 80 { 81 { 0xab, "Lifetime Program Fail Count" }, 82 { 0xac, "Lifetime Erase Fail Count" }, 83 { 0xad, "Lifetime Wear Leveling Count" }, 84 { 0xb8, "Lifetime End to End Error Count" }, 85 { 0xc7, "Lifetime CRC Error Count" }, 86 { 0xe2, "Media Wear %" }, 87 { 0xe3, "Host Read %" }, 88 { 0xe4, "Workload Timer" }, 89 { 0xea, "Lifetime Thermal Throttle Status" }, 90 { 0xf4, "Lifetime Phy Pages Written Count" }, 91 { 0xf5, "Lifetime Data Units Written" }, 92 }; 93 94 printf("Extended SMART Information\n"); 95 printf("=========================\n"); 96 /* 97 * walker[0] = Key 98 * walker[1,2] = reserved 99 * walker[3] = Normalized Value 100 * walker[4] = reserved 101 * walker[5..10] = Little Endian Raw value 102 * (or other represenations) 103 * walker[11] = reserved 104 */ 105 while (walker < end) { 106 name = kv_lookup(kv, nitems(kv), *walker); 107 normalized = walker[3]; 108 raw = le48dec(walker + 5); 109 switch (*walker){ 110 case 0: 111 break; 112 case 0xad: 113 printf("%2X %-41s: %3d min: %u max: %u ave: %u\n", 114 le16dec(walker), name, normalized, 115 le16dec(walker + 5), le16dec(walker + 7), le16dec(walker + 9)); 116 break; 117 case 0xe2: 118 printf("%2X %-41s: %3d %.3f%%\n", 119 le16dec(walker), name, normalized, 120 raw / 1024.0); 121 break; 122 case 0xea: 123 printf("%2X %-41s: %3d %d%% %d times\n", 124 le16dec(walker), name, normalized, 125 walker[5], le32dec(walker+6)); 126 break; 127 default: 128 printf("%2X %-41s: %3d %ju\n", 129 le16dec(walker), name, normalized, 130 (uintmax_t)raw); 131 break; 132 } 133 walker += 12; 134 } 135 136 printf(" Lifetime Write Amplification Factor : %u\n", le32dec(&temp->lwaf)); 137 printf(" Trailing Hour Write Amplification Factor : %u\n", le32dec(&temp->thwaf)); 138 printf(" Lifetime User Writes : %s\n", 139 uint128_to_str(to128(temp->luw), cbuf, sizeof(cbuf))); 140 printf(" Lifetime NAND Writes : %s\n", 141 uint128_to_str(to128(temp->lnw), cbuf, sizeof(cbuf))); 142 printf(" Lifetime User Reads : %s\n", 143 uint128_to_str(to128(temp->lur), cbuf, sizeof(cbuf))); 144 printf(" Lifetime Retired Block Count : %u\n", le32dec(&temp->lrbc)); 145 printf(" Current Temperature : "); 146 print_temp_K(le16dec(&temp->ct)); 147 printf(" Capacitor Health : %u\n", le16dec(&temp->ch)); 148 printf(" Reserved Erase Block Count : %u\n", le32dec(&temp->luurb)); 149 printf(" Read Reclaim Count : %ju\n", (uintmax_t) le64dec(&temp->rrc)); 150 printf(" Lifetime Uncorrectable ECC Count : %ju\n", (uintmax_t) le64dec(&temp->lueccc)); 151 printf(" Reallocated Block Count : %u\n", le32dec(&temp->lurb)); 152 printf(" Power on Hours : %s\n", 153 uint128_to_str(to128(temp->poh), cbuf, sizeof(cbuf))); 154 printf(" Normal Power Off Count : %s\n", 155 uint128_to_str(to128(temp->npoc), cbuf, sizeof(cbuf))); 156 printf(" Sudden Power Off Count : %s\n", 157 uint128_to_str(to128(temp->spoc), cbuf, sizeof(cbuf))); 158 printf(" Performance Indicator : %u\n", le32dec(&temp->pi)); 159 } 160 161 #define SAMSUNG_LOG_EXTEND_SMART 0xca 162 163 NVME_LOGPAGE(samsung_extended_smart, 164 SAMSUNG_LOG_EXTEND_SMART, "samsung", "Extended SMART Information", 165 print_samsung_extended_smart, DEFAULT_SIZE); 166