| File: | .build-ci/../plugins/sandisk/sandisk-utils.c |
| Warning: | line 757, column 4 Value stored to 'ret' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* |
| 3 | * Copyright (c) 2025 Sandisk Corporation or its affiliates. |
| 4 | * |
| 5 | * Author: Jeff Lien <jeff.lien@sandisk.com> |
| 6 | * Brandon Paupore <brandon.paupore@sandisk.com> |
| 7 | */ |
| 8 | |
| 9 | #include <errno(*__errno_location ()).h> |
| 10 | #include <fcntl.h> |
| 11 | #include <string.h> |
| 12 | #include <unistd.h> |
| 13 | #include <time.h> |
| 14 | |
| 15 | #include <libnvme.h> |
| 16 | |
| 17 | #include "common.h" |
| 18 | #include "nvme-cmds.h" |
| 19 | #include "nvme-print.h" |
| 20 | #include "nvme.h" |
| 21 | |
| 22 | #include "sandisk-utils.h" |
| 23 | #include "plugins/wdc/wdc-nvme-cmds.h" |
| 24 | |
| 25 | /* WDC UUID value */ |
| 26 | static const __u8 WDC_UUID[NVME_UUID_LEN16] = { |
| 27 | 0x2d, 0xb9, 0x8c, 0x52, 0x0c, 0x4c, 0x5a, 0x15, |
| 28 | 0xab, 0xe6, 0x33, 0x29, 0x9a, 0x70, 0xdf, 0xd0 |
| 29 | }; |
| 30 | |
| 31 | /* WDC_UUID value for SN640_3 devices and SN655 devices */ |
| 32 | static const __u8 WDC_UUID_SN640_3[NVME_UUID_LEN16] = { |
| 33 | 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, |
| 34 | 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 |
| 35 | }; |
| 36 | |
| 37 | /* Sandisk UUID value */ |
| 38 | static const __u8 SNDK_UUID[NVME_UUID_LEN16] = { |
| 39 | 0xde, 0x87, 0xd1, 0xeb, 0x72, 0xc5, 0x58, 0x0b, |
| 40 | 0xad, 0xd8, 0x3c, 0x29, 0xd1, 0x23, 0x7c, 0x70 |
| 41 | }; |
| 42 | |
| 43 | int sndk_get_pci_ids(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, |
| 44 | uint32_t *device_id, uint32_t *vendor_id) |
| 45 | { |
| 46 | char vid[256], did[256], id[32]; |
| 47 | libnvme_ctrl_t c = NULL((void*)0); |
| 48 | libnvme_ns_t n = NULL((void*)0); |
| 49 | const char *name; |
| 50 | int fd, ret; |
| 51 | |
| 52 | name = libnvme_transport_handle_get_name(hdl); |
| 53 | ret = libnvme_scan_ctrl(ctx, name, &c); |
| 54 | if (!ret) { |
| 55 | snprintf(vid, sizeof(vid), "%s/device/vendor", |
| 56 | libnvme_ctrl_get_sysfs_dir(c)); |
| 57 | snprintf(did, sizeof(did), "%s/device/device", |
| 58 | libnvme_ctrl_get_sysfs_dir(c)); |
| 59 | libnvme_free_ctrl(c); |
| 60 | } else { |
| 61 | ret = libnvme_scan_namespace(ctx, name, &n); |
| 62 | if (!ret) { |
| 63 | fprintf(stderrstderr, "Unable to find %s\n", name); |
| 64 | return ret; |
| 65 | } |
| 66 | |
| 67 | snprintf(vid, sizeof(vid), "%s/device/device/vendor", |
| 68 | libnvme_ns_get_sysfs_dir(n)); |
| 69 | snprintf(did, sizeof(did), "%s/device/device/device", |
| 70 | libnvme_ns_get_sysfs_dir(n)); |
| 71 | libnvme_free_ns(n); |
| 72 | } |
| 73 | |
| 74 | fd = open(vid, O_RDONLY00); |
| 75 | if (fd < 0) { |
| 76 | fprintf(stderrstderr, "ERROR: SNDK: %s : Open vendor file failed\n", __func__); |
| 77 | return -1; |
| 78 | } |
| 79 | |
| 80 | ret = read(fd, id, 32); |
| 81 | close(fd); |
| 82 | |
| 83 | if (ret < 0) { |
| 84 | fprintf(stderrstderr, "%s: Read of pci vendor id failed\n", __func__); |
| 85 | return -1; |
| 86 | } |
| 87 | id[ret < 32 ? ret : 31] = '\0'; |
| 88 | if (id[strlen(id) - 1] == '\n') |
| 89 | id[strlen(id) - 1] = '\0'; |
| 90 | |
| 91 | *vendor_id = strtol(id, NULL((void*)0), 0); |
| 92 | ret = 0; |
| 93 | |
| 94 | fd = open(did, O_RDONLY00); |
| 95 | if (fd < 0) { |
| 96 | fprintf(stderrstderr, "ERROR: SNDK: %s : Open device file failed\n", __func__); |
| 97 | return -1; |
| 98 | } |
| 99 | |
| 100 | ret = read(fd, id, 32); |
| 101 | close(fd); |
| 102 | |
| 103 | if (ret < 0) { |
| 104 | fprintf(stderrstderr, "ERROR: SNDK: %s: Read of pci device id failed\n", __func__); |
| 105 | return -1; |
| 106 | } |
| 107 | id[ret < 32 ? ret : 31] = '\0'; |
| 108 | if (id[strlen(id) - 1] == '\n') |
| 109 | id[strlen(id) - 1] = '\0'; |
| 110 | |
| 111 | *device_id = strtol(id, NULL((void*)0), 0); |
| 112 | return 0; |
| 113 | } |
| 114 | |
| 115 | int sndk_get_vendor_id(struct libnvme_transport_handle *hdl, uint32_t *vendor_id) |
| 116 | { |
| 117 | struct nvme_id_ctrl ctrl; |
| 118 | int ret; |
| 119 | |
| 120 | memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); |
| 121 | ret = nvme_identify_ctrl(hdl, &ctrl); |
| 122 | if (ret) { |
| 123 | fprintf(stderrstderr, "ERROR: SNDK: nvme_identify_ctrl() failed 0x%x\n", ret); |
| 124 | return -1; |
| 125 | } |
| 126 | |
| 127 | *vendor_id = (uint32_t) ctrl.vid; |
| 128 | |
| 129 | return ret; |
| 130 | } |
| 131 | |
| 132 | bool_Bool sndk_check_device(struct libnvme_global_ctx *ctx, |
| 133 | struct libnvme_transport_handle *hdl) |
| 134 | { |
| 135 | uint32_t read_device_id = -1, read_vendor_id = -1; |
| 136 | bool_Bool supported; |
| 137 | int ret; |
| 138 | |
| 139 | ret = sndk_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); |
| 140 | if (ret < 0) { |
| 141 | /* Use the identify nvme command to get vendor id due to NVMeOF device. */ |
| 142 | if (sndk_get_vendor_id(hdl, &read_vendor_id) < 0) |
| 143 | return false0; |
| 144 | } |
| 145 | |
| 146 | supported = false0; |
| 147 | |
| 148 | if (read_vendor_id == SNDK_NVME_SNDK_VID0x15b7 || |
| 149 | read_vendor_id == SNDK_NVME_WDC_VID0x1b96) |
| 150 | supported = true1; |
| 151 | else |
| 152 | fprintf(stderrstderr, |
| 153 | "ERROR: SNDK: unsupported Sandisk device, Vendor ID = 0x%x, Device ID = 0x%x\n", |
| 154 | read_vendor_id, read_device_id); |
| 155 | |
| 156 | return supported; |
| 157 | } |
| 158 | |
| 159 | void sndk_get_commit_action_bin(__u8 commit_action_type, char *action_bin) |
| 160 | { |
| 161 | switch (commit_action_type) { |
| 162 | case 0: |
| 163 | strcpy(action_bin, "000b"); |
| 164 | break; |
| 165 | case 1: |
| 166 | strcpy(action_bin, "001b"); |
| 167 | break; |
| 168 | case 2: |
| 169 | strcpy(action_bin, "010b"); |
| 170 | break; |
| 171 | case 3: |
| 172 | strcpy(action_bin, "011b"); |
| 173 | break; |
| 174 | case 4: |
| 175 | strcpy(action_bin, "100b"); |
| 176 | break; |
| 177 | case 5: |
| 178 | strcpy(action_bin, "101b"); |
| 179 | break; |
| 180 | case 6: |
| 181 | strcpy(action_bin, "110b"); |
| 182 | break; |
| 183 | case 7: |
| 184 | strcpy(action_bin, "111b"); |
| 185 | break; |
| 186 | default: |
| 187 | strcpy(action_bin, "INVALID"); |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | bool_Bool sndk_parse_dev_mng_log_entry(void *data, |
| 192 | __u32 entry_id, |
| 193 | struct sndk_c2_log_subpage_header **log_entry) |
| 194 | { |
| 195 | __u32 remaining_len = 0; |
| 196 | __u32 log_length = 0; |
| 197 | __u32 log_entry_size = 0; |
| 198 | __u32 log_entry_id = 0; |
| 199 | __u32 offset = 0; |
| 200 | bool_Bool found = false0; |
| 201 | struct sndk_c2_log_subpage_header *p_next_log_entry = NULL((void*)0); |
| 202 | struct sndk_c2_log_page_header *hdr_ptr = (struct sndk_c2_log_page_header *)data; |
| 203 | |
| 204 | log_length = le32_to_cpu(hdr_ptr->length); |
| 205 | /* Ensure log data is large enough for common header */ |
| 206 | if (log_length < sizeof(struct sndk_c2_log_page_header)) { |
| 207 | fprintf(stderrstderr, |
| 208 | "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"l" "x""\n", |
| 209 | __func__, log_length, sizeof(struct sndk_c2_log_page_header)); |
| 210 | return found; |
| 211 | } |
| 212 | |
| 213 | /* Get pointer to first log Entry */ |
| 214 | offset = sizeof(struct sndk_c2_log_page_header); |
| 215 | p_next_log_entry = (struct sndk_c2_log_subpage_header *)(((__u8 *)data) + offset); |
| 216 | remaining_len = log_length - offset; |
| 217 | |
| 218 | if (!log_entry) { |
| 219 | fprintf(stderrstderr, "ERROR: SNDK - %s: No log entry pointer.\n", __func__); |
| 220 | return found; |
| 221 | } |
| 222 | *log_entry = NULL((void*)0); |
| 223 | |
| 224 | /* Proceed only if there is at least enough data to read an entry header */ |
| 225 | while (remaining_len >= sizeof(struct sndk_c2_log_subpage_header)) { |
| 226 | /* Get size of the next entry */ |
| 227 | log_entry_size = le32_to_cpu(p_next_log_entry->length); |
| 228 | log_entry_id = le32_to_cpu(p_next_log_entry->entry_id); |
| 229 | |
| 230 | /* |
| 231 | * If log entry size is 0 or the log entry goes past the end |
| 232 | * of the data, we must be at the end of the data |
| 233 | */ |
| 234 | if (!log_entry_size || log_entry_size > remaining_len) { |
| 235 | fprintf(stderrstderr, "ERROR: SNDK: %s: Detected unaligned end of the data. ", |
| 236 | __func__); |
| 237 | fprintf(stderrstderr, "Data Offset: 0x%x Entry Size: 0x%x, ", |
| 238 | offset, log_entry_size); |
| 239 | fprintf(stderrstderr, "Remaining Log Length: 0x%x Entry Id: 0x%x\n", |
| 240 | remaining_len, log_entry_id); |
| 241 | |
| 242 | /* Force the loop to end */ |
| 243 | remaining_len = 0; |
| 244 | } else if (!log_entry_id || log_entry_id > 200) { |
| 245 | /* Invalid entry - fail the search */ |
| 246 | fprintf(stderrstderr, "ERROR: SNDK: %s: Invalid entry found at offset: 0x%x ", |
| 247 | __func__, offset); |
| 248 | fprintf(stderrstderr, "Entry Size: 0x%x, Remaining Log Length: 0x%x ", |
| 249 | log_entry_size, remaining_len); |
| 250 | fprintf(stderrstderr, "Entry Id: 0x%x\n", log_entry_id); |
| 251 | |
| 252 | /* Force the loop to end */ |
| 253 | remaining_len = 0; |
| 254 | } else { |
| 255 | if (log_entry_id == entry_id) { |
| 256 | found = true1; |
| 257 | *log_entry = p_next_log_entry; |
| 258 | remaining_len = 0; |
| 259 | } else { |
| 260 | remaining_len -= log_entry_size; |
| 261 | } |
| 262 | |
| 263 | if (remaining_len > 0) { |
| 264 | /* Increment the offset counter */ |
| 265 | offset += log_entry_size; |
| 266 | |
| 267 | /* Get the next entry */ |
| 268 | p_next_log_entry = |
| 269 | (struct sndk_c2_log_subpage_header *)(((__u8 *)data) + offset); |
| 270 | } |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | return found; |
| 275 | } |
| 276 | |
| 277 | bool_Bool sndk_nvme_parse_dev_status_log_entry(void *log_data, |
| 278 | __u32 entry_id, |
| 279 | __u32 *ret_data) |
| 280 | { |
| 281 | struct sndk_c2_log_subpage_header *entry_data = NULL((void*)0); |
| 282 | |
| 283 | if (sndk_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) { |
| 284 | if (entry_data) { |
| 285 | *ret_data = le32_to_cpu(entry_data->data); |
| 286 | return true1; |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | *ret_data = 0; |
| 291 | return false0; |
| 292 | } |
| 293 | |
| 294 | bool_Bool sndk_nvme_parse_dev_status_log_str(void *log_data, |
| 295 | __u32 entry_id, |
| 296 | char *ret_data, |
| 297 | __u32 *ret_data_len) |
| 298 | { |
| 299 | struct sndk_c2_log_subpage_header *entry_data = NULL((void*)0); |
| 300 | struct sndk_c2_cbs_data *entry_str_data = NULL((void*)0); |
| 301 | |
| 302 | if (sndk_parse_dev_mng_log_entry(log_data, entry_id, &entry_data)) { |
| 303 | if (entry_data) { |
| 304 | entry_str_data = (struct sndk_c2_cbs_data *)&entry_data->data; |
| 305 | memcpy(ret_data, |
| 306 | (void *)&entry_str_data->data, |
| 307 | le32_to_cpu(entry_str_data->length)); |
| 308 | *ret_data_len = le32_to_cpu(entry_str_data->length); |
| 309 | return true1; |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | *ret_data = 0; |
| 314 | *ret_data_len = 0; |
| 315 | return false0; |
| 316 | } |
| 317 | |
| 318 | |
| 319 | bool_Bool sndk_get_dev_mgment_data(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl, |
| 320 | void **data) |
| 321 | { |
| 322 | bool_Bool found = false0; |
| 323 | __u32 device_id = 0, vendor_id = 0; |
| 324 | int uuid_index = 0; |
| 325 | struct nvme_id_uuid_list uuid_list; |
| 326 | |
| 327 | *data = NULL((void*)0); |
| 328 | |
| 329 | /* The sndk_get_pci_ids function could fail when drives are connected |
| 330 | * via a PCIe switch. Therefore, the return code is intentionally |
| 331 | * being ignored. The device_id and vendor_id variables have been |
| 332 | * initialized to 0 so the code can continue on without issue for |
| 333 | * both cases: sndk_get_pci_ids successful or failed. |
| 334 | */ |
| 335 | sndk_get_pci_ids(ctx, hdl, &device_id, &vendor_id); |
| 336 | |
| 337 | memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); |
| 338 | if (!libnvme_get_uuid_list(hdl, &uuid_list)) { |
| 339 | /* check for the Sandisk UUID first */ |
| 340 | uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID); |
| 341 | |
| 342 | if (uuid_index < 0) { |
| 343 | /* The Sandisk UUID is not found; |
| 344 | * check for the WDC UUID second. |
| 345 | */ |
| 346 | uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID); |
| 347 | if (uuid_index < 0) |
| 348 | /* Check for the UUID used on SN640 and SN655 drives */ |
| 349 | uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3); |
| 350 | } |
| 351 | |
| 352 | if (uuid_index >= 0) |
| 353 | found = sndk_get_dev_mgmt_log_page_data(hdl, data, uuid_index); |
| 354 | else { |
| 355 | fprintf(stderrstderr, "%s: UUID lists are supported but a matching ", |
| 356 | __func__); |
| 357 | fprintf(stderrstderr, "uuid was not found\n"); |
| 358 | } |
| 359 | } else { |
| 360 | /* UUID lists are not supported, Default to uuid-index 0 */ |
| 361 | fprintf(stderrstderr, "INFO: SNDK: %s: UUID Lists not supported\n", |
| 362 | __func__); |
| 363 | uuid_index = 0; |
| 364 | found = sndk_get_dev_mgmt_log_page_data(hdl, data, uuid_index); |
| 365 | } |
| 366 | |
| 367 | return found; |
| 368 | } |
| 369 | |
| 370 | bool_Bool sndk_validate_dev_mng_log(void *data) |
| 371 | { |
| 372 | __u32 remaining_len = 0; |
| 373 | __u32 log_length = 0; |
| 374 | __u32 log_entry_size = 0; |
| 375 | __u32 log_entry_id = 0; |
| 376 | __u32 offset = 0; |
| 377 | bool_Bool valid_log = false0; |
| 378 | struct sndk_c2_log_subpage_header *p_next_log_entry = NULL((void*)0); |
| 379 | struct sndk_c2_log_page_header *hdr_ptr = (struct sndk_c2_log_page_header *)data; |
| 380 | |
| 381 | log_length = le32_to_cpu(hdr_ptr->length); |
| 382 | /* Ensure log data is large enough for common header */ |
| 383 | if (log_length < sizeof(struct sndk_c2_log_page_header)) { |
| 384 | fprintf(stderrstderr, |
| 385 | "ERROR: %s: log smaller than header. log_len: 0x%x HdrSize: %"PRIxPTR"l" "x""\n", |
| 386 | __func__, log_length, sizeof(struct sndk_c2_log_page_header)); |
| 387 | return valid_log; |
| 388 | } |
| 389 | |
| 390 | /* Get pointer to first log Entry */ |
| 391 | offset = sizeof(struct sndk_c2_log_page_header); |
| 392 | p_next_log_entry = (struct sndk_c2_log_subpage_header *)(((__u8 *)data) + offset); |
| 393 | remaining_len = log_length - offset; |
| 394 | |
| 395 | /* Proceed only if there is at least enough data to read an entry header */ |
| 396 | while (remaining_len >= sizeof(struct sndk_c2_log_subpage_header)) { |
| 397 | /* Get size of the next entry */ |
| 398 | log_entry_size = le32_to_cpu(p_next_log_entry->length); |
| 399 | log_entry_id = le32_to_cpu(p_next_log_entry->entry_id); |
| 400 | /* |
| 401 | * If log entry size is 0 or the log entry goes past the end |
| 402 | * of the data, we must be at the end of the data |
| 403 | */ |
| 404 | if (!log_entry_size || log_entry_size > remaining_len) { |
| 405 | fprintf(stderrstderr, "ERROR: SNDK: %s: Detected unaligned end of the data. ", |
| 406 | __func__); |
| 407 | fprintf(stderrstderr, "Data Offset: 0x%x Entry Size: 0x%x, ", |
| 408 | offset, log_entry_size); |
| 409 | fprintf(stderrstderr, "Remaining Log Length: 0x%x Entry Id: 0x%x\n", |
| 410 | remaining_len, log_entry_id); |
| 411 | |
| 412 | /* Force the loop to end */ |
| 413 | remaining_len = 0; |
| 414 | } else if (!log_entry_id || log_entry_id > 200) { |
| 415 | /* Invalid entry - fail the search */ |
| 416 | fprintf(stderrstderr, "ERROR: SNDK: %s: Invalid entry found at offset: 0x%x ", |
| 417 | __func__, offset); |
| 418 | fprintf(stderrstderr, "Entry Size: 0x%x, Remaining Log Length: 0x%x ", |
| 419 | log_entry_size, remaining_len); |
| 420 | fprintf(stderrstderr, "Entry Id: 0x%x\n", log_entry_id); |
| 421 | |
| 422 | /* Force the loop to end */ |
| 423 | remaining_len = 0; |
| 424 | valid_log = false0; |
| 425 | } else { |
| 426 | /* A valid log has at least one entry and no invalid entries */ |
| 427 | valid_log = true1; |
| 428 | remaining_len -= log_entry_size; |
| 429 | if (remaining_len > 0) { |
| 430 | /* Increment the offset counter */ |
| 431 | offset += log_entry_size; |
| 432 | /* Get the next entry */ |
| 433 | p_next_log_entry = |
| 434 | (struct sndk_c2_log_subpage_header *)(((__u8 *)data) + offset); |
| 435 | } |
| 436 | } |
| 437 | } |
| 438 | |
| 439 | return valid_log; |
| 440 | } |
| 441 | |
| 442 | bool_Bool sndk_get_dev_mgmt_log_page_data(struct libnvme_transport_handle *hdl, |
| 443 | void **log_data, |
| 444 | __u8 uuid_ix) |
| 445 | { |
| 446 | struct sndk_c2_log_page_header *hdr_ptr; |
| 447 | struct libnvme_passthru_cmd cmd; |
| 448 | bool_Bool valid = false0; |
| 449 | __u32 length = 0; |
| 450 | void *data; |
| 451 | int ret = 0; |
| 452 | |
| 453 | data = (__u8 *)malloc(sizeof(__u8) * SNDK_DEV_MGMNT_LOG_PAGE_LEN0x1000); |
| 454 | if (!data) { |
| 455 | fprintf(stderrstderr, "ERROR: SNDK: malloc: %s\n", libnvme_strerror(errno(*__errno_location ()))); |
| 456 | return false0; |
| 457 | } |
| 458 | |
| 459 | memset(data, 0, sizeof(__u8) * SNDK_DEV_MGMNT_LOG_PAGE_LEN0x1000); |
| 460 | |
| 461 | /* get the log page length */ |
| 462 | nvme_init_get_log(&cmd, NVME_NSID_ALL, |
| 463 | SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data, |
| 464 | SNDK_DEV_MGMNT_LOG_PAGE_LEN0x1000); |
| 465 | cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) << (NVME_LOG_CDW14_UUID_SHIFT)) |
| 466 | NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) << (NVME_LOG_CDW14_UUID_SHIFT)) |
| 467 | NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) << (NVME_LOG_CDW14_UUID_SHIFT)); |
| 468 | ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096); |
| 469 | if (ret) { |
| 470 | fprintf(stderrstderr, |
| 471 | "ERROR: SNDK: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n", |
| 472 | SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, uuid_ix, ret); |
| 473 | goto end; |
| 474 | } |
| 475 | |
| 476 | hdr_ptr = (struct sndk_c2_log_page_header *)data; |
| 477 | length = le32_to_cpu(hdr_ptr->length); |
| 478 | |
| 479 | if (length > SNDK_DEV_MGMNT_LOG_PAGE_LEN0x1000) { |
| 480 | /* Log page buffer too small for actual data */ |
| 481 | free(data); |
| 482 | data = calloc(length, sizeof(__u8)); |
| 483 | if (!data) { |
| 484 | fprintf(stderrstderr, "ERROR: SNDK: malloc: %s\n", libnvme_strerror(errno(*__errno_location ()))); |
| 485 | goto end; |
| 486 | } |
| 487 | |
| 488 | /* get the log page data with the increased length */ |
| 489 | nvme_init_get_log(&cmd, NVME_NSID_ALL, |
| 490 | SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, NVME_CSI_NVM, data, |
| 491 | length); |
| 492 | cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) << (NVME_LOG_CDW14_UUID_SHIFT)) |
| 493 | NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) << (NVME_LOG_CDW14_UUID_SHIFT)) |
| 494 | NVME_LOG_CDW14_UUID_MASK)(((__u32)(uuid_ix) & (NVME_LOG_CDW14_UUID_MASK)) << (NVME_LOG_CDW14_UUID_SHIFT)); |
| 495 | ret = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096); |
| 496 | if (ret) { |
| 497 | fprintf(stderrstderr, |
| 498 | "ERROR: SNDK: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n", |
| 499 | SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, uuid_ix, ret); |
| 500 | goto end; |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | valid = sndk_validate_dev_mng_log(data); |
| 505 | if (valid) { |
| 506 | /* Ensure size of log data matches length in log header */ |
| 507 | *log_data = calloc(length, sizeof(__u8)); |
| 508 | if (!*log_data) { |
| 509 | fprintf(stderrstderr, "ERROR: SNDK: calloc: %s\n", libnvme_strerror(errno(*__errno_location ()))); |
| 510 | valid = false0; |
| 511 | goto end; |
| 512 | } |
| 513 | memcpy((void *)*log_data, data, length); |
| 514 | } else { |
| 515 | fprintf(stderrstderr, "ERROR: SNDK: C2 log page not found with uuid index %d\n", |
| 516 | uuid_ix); |
| 517 | } |
| 518 | |
| 519 | end: |
| 520 | free(data); |
| 521 | return valid; |
| 522 | } |
| 523 | |
| 524 | __u64 sndk_get_drive_capabilities(struct libnvme_global_ctx *ctx, |
| 525 | struct libnvme_transport_handle *hdl) |
| 526 | { |
| 527 | uint32_t read_device_id = -1, read_vendor_id = -1; |
| 528 | __u64 capabilities = 0; |
| 529 | int ret; |
| 530 | |
| 531 | ret = sndk_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); |
| 532 | if (ret < 0) { |
| 533 | if (sndk_get_vendor_id(hdl, &read_vendor_id) < 0) |
| 534 | return capabilities; |
| 535 | } |
| 536 | |
| 537 | /* |
| 538 | * Below check condition is added due in NVMeOF device |
| 539 | * We aren't able to read the device_id in this case |
| 540 | * so we can only use the vendor_id |
| 541 | */ |
| 542 | if (read_device_id == -1 && read_vendor_id != -1) { |
| 543 | capabilities = sndk_get_enc_drive_capabilities(ctx, hdl); |
| 544 | return capabilities; |
| 545 | } |
| 546 | |
| 547 | switch (read_vendor_id) { |
| 548 | case SNDK_NVME_WDC_VID0x1b96: |
| 549 | switch (read_device_id) { |
| 550 | case SNDK_NVME_SNTMP_DEV_ID0x2761: |
| 551 | case SNDK_NVME_SNTMP_DEV_ID_10x2763: |
| 552 | capabilities |= (SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | |
| 553 | SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 | |
| 554 | SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | |
| 555 | SNDK_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 | |
| 556 | SNDK_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 | |
| 557 | SNDK_DRIVE_CAP_UDUI0x0000040000000000 | |
| 558 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | |
| 559 | SNDK_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 | |
| 560 | SNDK_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | |
| 561 | SNDK_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 | |
| 562 | SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | |
| 563 | SNDK_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000); |
| 564 | break; |
| 565 | |
| 566 | case SNDK_NVME_SN861_DEV_ID_E1S0x2750: |
| 567 | capabilities |= (SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | |
| 568 | SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 | |
| 569 | SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | |
| 570 | SNDK_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 | |
| 571 | SNDK_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 | |
| 572 | SNDK_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | |
| 573 | SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | |
| 574 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | |
| 575 | SNDK_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | |
| 576 | SNDK_DRIVE_CAP_INFO0x0000000000080000 | |
| 577 | SNDK_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | |
| 578 | SNDK_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 | |
| 579 | SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | |
| 580 | SNDK_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000); |
| 581 | break; |
| 582 | |
| 583 | case SNDK_NVME_SN861_DEV_ID_U20x2751: |
| 584 | case SNDK_NVME_SN861_DEV_ID_E3S0x2752: |
| 585 | capabilities |= (SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | |
| 586 | SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 | |
| 587 | SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | |
| 588 | SNDK_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 | |
| 589 | SNDK_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 | |
| 590 | SNDK_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | |
| 591 | SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | |
| 592 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | |
| 593 | SNDK_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | |
| 594 | SNDK_DRIVE_CAP_INFO0x0000000000080000 | |
| 595 | SNDK_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | |
| 596 | SNDK_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 | |
| 597 | SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | |
| 598 | SNDK_DRIVE_CAP_RESIZE_SN8610x0000080000000000 | |
| 599 | SNDK_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000); |
| 600 | break; |
| 601 | |
| 602 | default: |
| 603 | capabilities = 0; |
| 604 | } |
| 605 | break; |
| 606 | |
| 607 | case SNDK_NVME_SNDK_VID0x15b7: |
| 608 | switch (read_device_id) { |
| 609 | case SNDK_NVME_SNESSD1_DEV_ID_E1L0x2765: |
| 610 | case SNDK_NVME_SNESSD1_DEV_ID_E20x2766: |
| 611 | case SNDK_NVME_SNESSD1_DEV_ID_E3S0x2767: |
| 612 | case SNDK_NVME_SNESSD1_DEV_ID_E3L0x2768: |
| 613 | case SNDK_NVME_SNESSD1_DEV_ID_U20x2769: |
| 614 | capabilities |= (SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | |
| 615 | SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 | |
| 616 | SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | |
| 617 | SNDK_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 | |
| 618 | SNDK_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 | |
| 619 | SNDK_DRIVE_CAP_UDUI0x0000040000000000 | |
| 620 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | |
| 621 | SNDK_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 | |
| 622 | SNDK_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | |
| 623 | SNDK_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 | |
| 624 | SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | |
| 625 | SNDK_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000); |
| 626 | break; |
| 627 | |
| 628 | case SNDK_NVME_SNESSD3_DEV_ID_E20x2770: |
| 629 | case SNDK_NVME_SNESSD3_DEV_ID_U20x2771: |
| 630 | case SNDK_NVME_SNESSD3_DEV_ID_E3L0x2772: |
| 631 | case SNDK_NVME_SNESSD3_DEV_ID_E3S0x2773: |
| 632 | case SNDK_NVME_SNESSD3_DEV_ID_E1L0x2774: |
| 633 | capabilities |= (SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | |
| 634 | SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 | |
| 635 | SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | |
| 636 | SNDK_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 | |
| 637 | SNDK_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 | |
| 638 | SNDK_DRIVE_CAP_UDUI0x0000040000000000 | |
| 639 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | |
| 640 | SNDK_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 | |
| 641 | SNDK_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | |
| 642 | SNDK_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 | |
| 643 | SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | |
| 644 | SNDK_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000); |
| 645 | break; |
| 646 | |
| 647 | case SNDK_NVME_SN7150_DEV_ID_10x503b: |
| 648 | case SNDK_NVME_SN7150_DEV_ID_20x503c: |
| 649 | case SNDK_NVME_SN7150_DEV_ID_30x503d: |
| 650 | case SNDK_NVME_SN7150_DEV_ID_40x503e: |
| 651 | case SNDK_NVME_SN7150_DEV_ID_50x503f: |
| 652 | capabilities = SNDK_DRIVE_CAP_UDUI0x0000040000000000; |
| 653 | break; |
| 654 | |
| 655 | case SNDK_NVME_SNCSSD1_DEV_ID_M2_22300x5081: |
| 656 | case SNDK_NVME_SNCSSD1_DEV_ID_M2_22420x5082: |
| 657 | case SNDK_NVME_SNCSSD1_DEV_ID_M2_22800x5083: |
| 658 | capabilities = SNDK_DRIVE_CAP_UDUI0x0000040000000000; |
| 659 | break; |
| 660 | |
| 661 | case SNDK_NVME_SN862_DEV_ID_E1S_250x27A0: |
| 662 | case SNDK_NVME_SN862_DEV_ID_E1S_150x27A1: |
| 663 | case SNDK_NVME_SN862_DEV_ID_E1S_950x27A2: |
| 664 | case SNDK_NVME_SN862_DEV_ID_E3S0x27A3: |
| 665 | case SNDK_NVME_SN862_DEV_ID_U20x27A4: |
| 666 | case SNDK_NVME_SNESSD2_DEV_ID_E1S_950x2790: |
| 667 | case SNDK_NVME_SNESSD2_DEV_ID_E1S_150x2791: |
| 668 | case SNDK_NVME_SNESSD2_DEV_ID_E1L0x2792: |
| 669 | case SNDK_NVME_SNESSD2_DEV_ID_E3S0x2793: |
| 670 | case SNDK_NVME_SNESSD2_DEV_ID_E3L0x2794: |
| 671 | capabilities |= (SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 | |
| 672 | SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 | |
| 673 | SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 | |
| 674 | SNDK_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 | |
| 675 | SNDK_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 | |
| 676 | SNDK_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | |
| 677 | SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | |
| 678 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000 | |
| 679 | SNDK_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | |
| 680 | SNDK_DRIVE_CAP_INFO0x0000000000080000 | |
| 681 | SNDK_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 | |
| 682 | SNDK_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 | |
| 683 | SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | |
| 684 | SNDK_DRIVE_CAP_RESIZE_SN8610x0000080000000000 | |
| 685 | SNDK_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000); |
| 686 | break; |
| 687 | |
| 688 | default: |
| 689 | capabilities = 0; |
| 690 | } |
| 691 | break; |
| 692 | default: |
| 693 | capabilities = 0; |
| 694 | } |
| 695 | |
| 696 | /* Check for fallback WDC plugin support */ |
| 697 | if (!capabilities) |
| 698 | capabilities = run_wdc_get_drive_capabilities(ctx, hdl); |
| 699 | |
| 700 | return capabilities; |
| 701 | } |
| 702 | |
| 703 | __u64 sndk_get_enc_drive_capabilities(struct libnvme_global_ctx *ctx, |
| 704 | struct libnvme_transport_handle *hdl) |
| 705 | { |
| 706 | int ret; |
| 707 | uint32_t read_vendor_id; |
| 708 | __u64 capabilities = 0; |
| 709 | __u32 cust_id, market_name_len, |
| 710 | drive_form_factor = 0; |
| 711 | char marketing_name[64]; |
| 712 | void *dev_mng_log = NULL((void*)0); |
| 713 | int uuid_index = 0; |
| 714 | struct nvme_id_uuid_list uuid_list; |
| 715 | |
| 716 | memset(marketing_name, 0, 64); |
| 717 | |
| 718 | ret = sndk_get_vendor_id(hdl, &read_vendor_id); |
| 719 | if (ret < 0) |
| 720 | return capabilities; |
| 721 | |
| 722 | switch (read_vendor_id) { |
| 723 | case SNDK_NVME_WDC_VID0x1b96: |
| 724 | capabilities = (SNDK_DRIVE_CAP_INTERNAL_LOG0x0000000000000002 | |
| 725 | SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 | |
| 726 | SNDK_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 | |
| 727 | SNDK_DRIVE_CAP_RESIZE0x0000000000000100); |
| 728 | |
| 729 | /* Check for the Sandisk or WDC UUID index */ |
| 730 | memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); |
| 731 | if (!libnvme_get_uuid_list(hdl, &uuid_list)) { |
| 732 | /* check for the Sandisk UUID first */ |
| 733 | uuid_index = libnvme_find_uuid(&uuid_list, SNDK_UUID); |
| 734 | |
| 735 | if (uuid_index < 0) { |
| 736 | /* The Sandisk UUID is not found; |
| 737 | * check for the WDC UUID second. |
| 738 | */ |
| 739 | uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID); |
| 740 | if (uuid_index < 0) |
| 741 | /* Check for the UUID used on SN640 and SN655 drives */ |
| 742 | uuid_index = libnvme_find_uuid(&uuid_list, WDC_UUID_SN640_3); |
| 743 | } |
| 744 | } else { |
| 745 | /* UUID Lists not supported, Use default uuid index - 0 */ |
| 746 | fprintf(stderrstderr, "INFO: SNDK: %s: UUID Lists not supported\n", |
| 747 | __func__); |
| 748 | uuid_index = 0; |
| 749 | } |
| 750 | |
| 751 | /* verify the 0xC2 Device Manageability log page is supported */ |
| 752 | if (run_wdc_nvme_check_supported_log_page(ctx, hdl, |
| 753 | SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID0xC2, |
| 754 | uuid_index) == false0) { |
| 755 | fprintf(stderrstderr, "ERROR: SNDK: 0xC2 Log Page not supported, "); |
| 756 | fprintf(stderrstderr, "uuid_index: %d\n", uuid_index); |
| 757 | ret = -1; |
Value stored to 'ret' is never read | |
| 758 | goto out; |
| 759 | } |
| 760 | |
| 761 | if (!sndk_get_dev_mgment_data(ctx, hdl, &dev_mng_log)) { |
| 762 | fprintf(stderrstderr, "ERROR: SNDK: 0xC2 Log Page not found\n"); |
| 763 | ret = -1; |
| 764 | goto out; |
| 765 | } |
| 766 | |
| 767 | /* Get the customer ID */ |
| 768 | if (!sndk_nvme_parse_dev_status_log_entry(dev_mng_log, |
| 769 | SNDK_C2_CUSTOMER_ID_ID0x15, |
| 770 | (void *)&cust_id)) |
| 771 | fprintf(stderrstderr, "ERROR: SNDK: Get Customer FW ID Failed\n"); |
| 772 | |
| 773 | /* Get the marketing name */ |
| 774 | if (!sndk_nvme_parse_dev_status_log_str(dev_mng_log, |
| 775 | SNDK_C2_MARKETING_NAME_ID0x07, |
| 776 | (char *)marketing_name, |
| 777 | &market_name_len)) |
| 778 | fprintf(stderrstderr, "ERROR: SNDK: Get Marketing Name Failed\n"); |
| 779 | |
| 780 | /* Get the drive form factor */ |
| 781 | if (!sndk_nvme_parse_dev_status_log_entry(dev_mng_log, |
| 782 | SNDK_C2_FORM_FACTOR0x0A, |
| 783 | (void *)&drive_form_factor)) |
| 784 | fprintf(stderrstderr, "ERROR: SNDK: Getting Form Factor Failed\n"); |
| 785 | |
| 786 | /* verify the 0xC0 log page is supported */ |
| 787 | if (run_wdc_nvme_check_supported_log_page(ctx, hdl, |
| 788 | SNDK_NVME_GET_SMART_CLOUD_ATTR_LOG_ID0xC0, 0)) |
| 789 | capabilities |= SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000; |
| 790 | |
| 791 | /* verify the 0xC3 log page is supported */ |
| 792 | if (run_wdc_nvme_check_supported_log_page(ctx, hdl, |
| 793 | SNDK_LATENCY_MON_LOG_ID0xC3, 0)) |
| 794 | capabilities |= SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000; |
| 795 | |
| 796 | /* verify the 0xCB log page is supported */ |
| 797 | if (run_wdc_nvme_check_supported_log_page(ctx, hdl, |
| 798 | SNDK_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0)) |
| 799 | capabilities |= SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000; |
| 800 | |
| 801 | /* verify the 0xCA log page is supported */ |
| 802 | if (run_wdc_nvme_check_supported_log_page(ctx, hdl, |
| 803 | SNDK_NVME_GET_DEVICE_INFO_LOG_ID0xCA, 0)) |
| 804 | capabilities |= SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008; |
| 805 | |
| 806 | /* verify the 0xD0 log page is supported */ |
| 807 | if (run_wdc_nvme_check_supported_log_page(ctx, hdl, |
| 808 | SNDK_NVME_GET_VU_SMART_LOG_ID0xD0, 0)) |
| 809 | capabilities |= SNDK_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010; |
| 810 | |
| 811 | if ((cust_id == SNDK_CUSTOMER_ID_0x10040x1004) || |
| 812 | (cust_id == SNDK_CUSTOMER_ID_0x10080x1008) || |
| 813 | (cust_id == SNDK_CUSTOMER_ID_0x10050x1005) || |
| 814 | (cust_id == SNDK_CUSTOMER_ID_0x13040x1304)) |
| 815 | /* Set capabilities for OCP compliant drives */ |
| 816 | capabilities |= (SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | |
| 817 | SNDK_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | |
| 818 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000); |
| 819 | else if ((!strncmp(marketing_name, SNDK_SN861_MARKETING_NAME_1"Ultrastar DC SN861", market_name_len)) || |
| 820 | (!strncmp(marketing_name, SNDK_SN861_MARKETING_NAME_2"ULTRASTAR DC SN861", market_name_len))) { |
| 821 | /* Set capabilities for OCP compliant drives */ |
| 822 | capabilities |= (SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000 | |
| 823 | SNDK_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000 | |
| 824 | SNDK_DRIVE_CAP_VU_FID_CLEAR_PCIE0x0000000000800000); |
| 825 | |
| 826 | if ((drive_form_factor == SNDK_C2_FORM_FACTOR_SFF_U20x00000001) || |
| 827 | (drive_form_factor == SNDK_C2_FORM_FACTOR_EDSFF_E3S0x00000009)) |
| 828 | capabilities |= SNDK_DRIVE_CAP_RESIZE_SN8610x0000080000000000; |
| 829 | else |
| 830 | capabilities &= ~SNDK_DRIVE_CAP_RESIZE0x0000000000000100; |
| 831 | } else { |
| 832 | capabilities |= (SNDK_DRIVE_CAP_CLEAR_FW_ACT_HISTORY0x0000000000004000 | |
| 833 | SNDK_DRIVE_CAP_CLEAR_PCIE0x0000000000000080); |
| 834 | |
| 835 | /* if the 0xCB log page is supported */ |
| 836 | if (run_wdc_nvme_check_supported_log_page(ctx, hdl, |
| 837 | SNDK_NVME_GET_FW_ACT_HISTORY_LOG_ID0xCB, 0)) |
| 838 | capabilities |= SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY0x0000000000002000; |
| 839 | } |
| 840 | break; |
| 841 | default: |
| 842 | capabilities = 0; |
| 843 | } |
| 844 | |
| 845 | out: |
| 846 | return capabilities; |
| 847 | } |
| 848 | |
| 849 | int sndk_get_serial_name(struct libnvme_transport_handle *hdl, char *file, |
| 850 | size_t len, const char *suffix) |
| 851 | { |
| 852 | int i; |
| 853 | int ret; |
| 854 | int res_len = 0; |
| 855 | char orig[PATH_MAX4096] = {0}; |
| 856 | struct nvme_id_ctrl ctrl; |
| 857 | int ctrl_sn_len = sizeof(ctrl.sn); |
| 858 | |
| 859 | i = sizeof(ctrl.sn) - 1; |
| 860 | strncpy(orig, file, PATH_MAX4096 - 1); |
| 861 | memset(file, 0, len); |
| 862 | memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); |
| 863 | ret = nvme_identify_ctrl(hdl, &ctrl); |
| 864 | if (ret) { |
| 865 | fprintf(stderrstderr, "ERROR: SNDK: nvme_identify_ctrl() failed 0x%x\n", ret); |
| 866 | return -1; |
| 867 | } |
| 868 | /* Remove trailing spaces from the name */ |
| 869 | while (i && ctrl.sn[i] == ' ') { |
| 870 | ctrl.sn[i] = '\0'; |
| 871 | i--; |
| 872 | } |
| 873 | if (ctrl.sn[sizeof(ctrl.sn) - 1] == '\0') |
| 874 | ctrl_sn_len = strlen(ctrl.sn); |
| 875 | |
| 876 | res_len = snprintf(file, len, "%s%.*s%s", orig, ctrl_sn_len, ctrl.sn, suffix); |
| 877 | if (len <= res_len) { |
| 878 | fprintf(stderrstderr, |
| 879 | "ERROR: SNDK: cannot format SN due to unexpected length\n"); |
| 880 | return -1; |
| 881 | } |
| 882 | |
| 883 | return 0; |
| 884 | } |
| 885 | |
| 886 | void sndk_UtilsGetTime(struct SNDK_UtilsTimeInfo *timeInfo) |
| 887 | { |
| 888 | time_t currTime; |
| 889 | struct tm currTimeInfo; |
| 890 | |
| 891 | tzset(); |
| 892 | time(&currTime); |
| 893 | localtime_r(&currTime, &currTimeInfo); |
| 894 | |
| 895 | timeInfo->year = currTimeInfo.tm_year + 1900; |
| 896 | timeInfo->month = currTimeInfo.tm_mon + 1; |
| 897 | timeInfo->dayOfWeek = currTimeInfo.tm_wday; |
| 898 | timeInfo->dayOfMonth = currTimeInfo.tm_mday; |
| 899 | timeInfo->hour = currTimeInfo.tm_hour; |
| 900 | timeInfo->minute = currTimeInfo.tm_min; |
| 901 | timeInfo->second = currTimeInfo.tm_sec; |
| 902 | timeInfo->msecs = 0; |
| 903 | timeInfo->isDST = currTimeInfo.tm_isdst; |
| 904 | #ifdef NVME_HAVE_TM_GMTOFF |
| 905 | timeInfo->zone = -currTimeInfo.tm_gmtoff / 60; |
| 906 | #else /* NVME_HAVE_TM_GMTOFF */ |
| 907 | timeInfo->zone = -1 * (timezone / 60); |
| 908 | #endif /* NVME_HAVE_TM_GMTOFF */ |
| 909 | } |
| 910 | |
| 911 | int sndk_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, |
| 912 | const char *format, ...) |
| 913 | { |
| 914 | int res = 0; |
| 915 | va_list vArgs; |
| 916 | |
| 917 | va_start(vArgs, format)__builtin_va_start(vArgs, format); |
| 918 | res = vsnprintf(buffer, sizeOfBuffer, format, vArgs); |
| 919 | va_end(vArgs)__builtin_va_end(vArgs); |
| 920 | |
| 921 | return res; |
| 922 | } |
| 923 | |
| 924 | /* Verify the Controller Initiated Option is enabled */ |
| 925 | int sndk_check_ctrl_telemetry_option_disabled(struct libnvme_transport_handle *hdl) |
| 926 | { |
| 927 | int err; |
| 928 | __u64 result; |
| 929 | |
| 930 | err = nvme_get_features(hdl, 0, |
| 931 | SNDK_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID0xD2, |
| 932 | NVME_GET_FEATURES_SEL_CURRENT, 0, 0, |
| 933 | NULL((void*)0), 4, &result); |
| 934 | if (!err) { |
| 935 | if (result) { |
| 936 | fprintf(stderrstderr, |
| 937 | "%s: Controller-initiated option telemetry disabled\n", |
| 938 | __func__); |
| 939 | return -EINVAL22; |
| 940 | } |
| 941 | } else { |
| 942 | fprintf(stderrstderr, "ERROR: SNDK: Get telemetry option feature failed."); |
| 943 | nvme_show_status(err); |
| 944 | return -EPERM1; |
| 945 | } |
| 946 | |
| 947 | return 0; |
| 948 | } |