1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #include <sys/param.h> 30 #include <sys/ioccom.h> 31 32 #include <ctype.h> 33 #include <err.h> 34 #include <fcntl.h> 35 #include <stdbool.h> 36 #include <stddef.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include <sys/endian.h> 42 43 #include "nvmecontrol.h" 44 45 struct samsung_log_extended_smart 46 { 47 uint8_t kv[256];/* Key-Value pair */ 48 uint32_t lwaf; /* Lifetime Write Amplification */ 49 uint32_t thwaf; /* Trailing Hour Write Amplification Factor */ 50 uint64_t luw[2]; /* Lifetime User Writes */ 51 uint64_t lnw[2]; /* Lifetime NAND Writes */ 52 uint64_t lur[2]; /* Lifetime User Reads */ 53 uint32_t lrbc; /* Lifetime Retired Block Count */ 54 uint16_t ct; /* Current Temperature */ 55 uint16_t ch; /* Capacitor Health */ 56 uint32_t luurb; /* Lifetime Unused Reserved Block */ 57 uint64_t rrc; /* Read Reclaim Count */ 58 uint64_t lueccc; /* Lifetime Uncorrectable ECC count */ 59 uint32_t lurb; /* Lifetime Used Reserved Block */ 60 uint64_t poh[2]; /* Power on Hours */ 61 uint64_t npoc[2];/* Normal Power Off Count */ 62 uint64_t spoc[2];/* Sudden Power Off Count */ 63 uint32_t pi; /* Performance Indicator */ 64 } __packed; 65 66 static void 67 print_samsung_extended_smart(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused) 68 { 69 struct samsung_log_extended_smart *temp = buf; 70 char cbuf[UINT128_DIG + 1]; 71 uint8_t *walker = buf; 72 uint8_t *end = walker + 150; 73 const char *name; 74 uint64_t raw; 75 uint8_t normalized; 76 77 static struct kv_name kv[] = 78 { 79 { 0xab, "Lifetime Program Fail Count" }, 80 { 0xac, "Lifetime Erase Fail Count" }, 81 { 0xad, "Lifetime Wear Leveling Count" }, 82 { 0xb8, "Lifetime End to End Error Count" }, 83 { 0xc7, "Lifetime CRC Error Count" }, 84 { 0xe2, "Media Wear %" }, 85 { 0xe3, "Host Read %" }, 86 { 0xe4, "Workload Timer" }, 87 { 0xea, "Lifetime Thermal Throttle Status" }, 88 { 0xf4, "Lifetime Phy Pages Written Count" }, 89 { 0xf5, "Lifetime Data Units Written" }, 90 }; 91 92 printf("Extended SMART Information\n"); 93 printf("=========================\n"); 94 /* 95 * walker[0] = Key 96 * walker[1,2] = reserved 97 * walker[3] = Normalized Value 98 * walker[4] = reserved 99 * walker[5..10] = Little Endian Raw value 100 * (or other represenations) 101 * walker[11] = reserved 102 */ 103 while (walker < end) { 104 name = kv_lookup(kv, nitems(kv), *walker); 105 normalized = walker[3]; 106 raw = le48dec(walker + 5); 107 switch (*walker){ 108 case 0: 109 break; 110 case 0xad: 111 printf("%2X %-41s: %3d min: %u max: %u ave: %u\n", 112 le16dec(walker), name, normalized, 113 le16dec(walker + 5), le16dec(walker + 7), le16dec(walker + 9)); 114 break; 115 case 0xe2: 116 printf("%2X %-41s: %3d %.3f%%\n", 117 le16dec(walker), name, normalized, 118 raw / 1024.0); 119 break; 120 case 0xea: 121 printf("%2X %-41s: %3d %d%% %d times\n", 122 le16dec(walker), name, normalized, 123 walker[5], le32dec(walker+6)); 124 break; 125 default: 126 printf("%2X %-41s: %3d %ju\n", 127 le16dec(walker), name, normalized, 128 (uintmax_t)raw); 129 break; 130 } 131 walker += 12; 132 } 133 134 printf(" Lifetime Write Amplification Factor : %u\n", le32dec(&temp->lwaf)); 135 printf(" Trailing Hour Write Amplification Factor : %u\n", le32dec(&temp->thwaf)); 136 printf(" Lifetime User Writes : %s\n", 137 uint128_to_str(to128(temp->luw), cbuf, sizeof(cbuf))); 138 printf(" Lifetime NAND Writes : %s\n", 139 uint128_to_str(to128(temp->lnw), cbuf, sizeof(cbuf))); 140 printf(" Lifetime User Reads : %s\n", 141 uint128_to_str(to128(temp->lur), cbuf, sizeof(cbuf))); 142 printf(" Lifetime Retired Block Count : %u\n", le32dec(&temp->lrbc)); 143 printf(" Current Temperature : "); 144 print_temp_K(le16dec(&temp->ct)); 145 printf(" Capacitor Health : %u\n", le16dec(&temp->ch)); 146 printf(" Reserved Erase Block Count : %u\n", le32dec(&temp->luurb)); 147 printf(" Read Reclaim Count : %ju\n", (uintmax_t) le64dec(&temp->rrc)); 148 printf(" Lifetime Uncorrectable ECC Count : %ju\n", (uintmax_t) le64dec(&temp->lueccc)); 149 printf(" Reallocated Block Count : %u\n", le32dec(&temp->lurb)); 150 printf(" Power on Hours : %s\n", 151 uint128_to_str(to128(temp->poh), cbuf, sizeof(cbuf))); 152 printf(" Normal Power Off Count : %s\n", 153 uint128_to_str(to128(temp->npoc), cbuf, sizeof(cbuf))); 154 printf(" Sudden Power Off Count : %s\n", 155 uint128_to_str(to128(temp->spoc), cbuf, sizeof(cbuf))); 156 printf(" Performance Indicator : %u\n", le32dec(&temp->pi)); 157 } 158 159 #define SAMSUNG_LOG_EXTEND_SMART 0xca 160 161 NVME_LOGPAGE(samsung_extended_smart, 162 SAMSUNG_LOG_EXTEND_SMART, "samsung", "Extended SMART Information", 163 print_samsung_extended_smart, DEFAULT_SIZE); 164