1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2e04da24cSKrishna Kanth Reddy * Copyright (c) Samsung Electronics Co., Ltd. 3e04da24cSKrishna Kanth Reddy * All rights reserved. 4e04da24cSKrishna Kanth Reddy */ 5e04da24cSKrishna Kanth Reddy 6e04da24cSKrishna Kanth Reddy #include "spdk/stdinc.h" 7e04da24cSKrishna Kanth Reddy 8e04da24cSKrishna Kanth Reddy #include "spdk/env.h" 9e04da24cSKrishna Kanth Reddy #include "spdk/nvme.h" 10e04da24cSKrishna Kanth Reddy #include "spdk/string.h" 11e04da24cSKrishna Kanth Reddy 12e04da24cSKrishna Kanth Reddy struct nvme_io { 13e04da24cSKrishna Kanth Reddy struct spdk_nvme_ctrlr *ctrlr; 14e04da24cSKrishna Kanth Reddy struct spdk_nvme_transport_id trid; 15e04da24cSKrishna Kanth Reddy struct spdk_nvme_ns *ns; 16e04da24cSKrishna Kanth Reddy unsigned nsid; 17e04da24cSKrishna Kanth Reddy unsigned rlba; 18e04da24cSKrishna Kanth Reddy unsigned nlbas; 19e04da24cSKrishna Kanth Reddy unsigned wlba; 20e04da24cSKrishna Kanth Reddy uint32_t lba_size; 21e04da24cSKrishna Kanth Reddy unsigned done; 22e04da24cSKrishna Kanth Reddy }; 23e04da24cSKrishna Kanth Reddy 24e04da24cSKrishna Kanth Reddy struct config { 25e04da24cSKrishna Kanth Reddy struct nvme_io pmr_dev; 26e04da24cSKrishna Kanth Reddy size_t copy_size; 27e04da24cSKrishna Kanth Reddy }; 28e04da24cSKrishna Kanth Reddy 29e04da24cSKrishna Kanth Reddy static struct config g_config; 30e04da24cSKrishna Kanth Reddy 31e04da24cSKrishna Kanth Reddy /* Namespaces index from 1. Return 0 to invoke an error */ 32e04da24cSKrishna Kanth Reddy static unsigned 33e04da24cSKrishna Kanth Reddy get_nsid(const struct spdk_nvme_transport_id *trid) 34e04da24cSKrishna Kanth Reddy { 35e04da24cSKrishna Kanth Reddy if (!strcmp(trid->traddr, g_config.pmr_dev.trid.traddr)) { 36e04da24cSKrishna Kanth Reddy return g_config.pmr_dev.nsid; 37e04da24cSKrishna Kanth Reddy } 38e04da24cSKrishna Kanth Reddy return 0; 39e04da24cSKrishna Kanth Reddy } 40e04da24cSKrishna Kanth Reddy 41e04da24cSKrishna Kanth Reddy static void 42e04da24cSKrishna Kanth Reddy check_io(void *arg, const struct spdk_nvme_cpl *completion) 43e04da24cSKrishna Kanth Reddy { 44e04da24cSKrishna Kanth Reddy g_config.pmr_dev.done = 1; 45e04da24cSKrishna Kanth Reddy } 46e04da24cSKrishna Kanth Reddy 47e04da24cSKrishna Kanth Reddy static int 48e04da24cSKrishna Kanth Reddy pmr_persistence(void) 49e04da24cSKrishna Kanth Reddy { 50e04da24cSKrishna Kanth Reddy int rc = 0; 51e04da24cSKrishna Kanth Reddy void *pmr_buf, *buf; 52e04da24cSKrishna Kanth Reddy size_t sz; 53e04da24cSKrishna Kanth Reddy struct spdk_nvme_qpair *qpair; 54e04da24cSKrishna Kanth Reddy 55e04da24cSKrishna Kanth Reddy /* Allocate Queue Pair for the Controller with PMR */ 56e04da24cSKrishna Kanth Reddy qpair = spdk_nvme_ctrlr_alloc_io_qpair(g_config.pmr_dev.ctrlr, NULL, 0); 57e04da24cSKrishna Kanth Reddy if (qpair == NULL) { 58e04da24cSKrishna Kanth Reddy printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n"); 59e04da24cSKrishna Kanth Reddy return -ENOMEM; 60e04da24cSKrishna Kanth Reddy } 61e04da24cSKrishna Kanth Reddy 62e04da24cSKrishna Kanth Reddy /* Enable the PMR */ 63e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ctrlr_enable_pmr(g_config.pmr_dev.ctrlr); 64e04da24cSKrishna Kanth Reddy if (rc) { 65e04da24cSKrishna Kanth Reddy printf("ERROR: Enabling PMR failed\n"); 66e04da24cSKrishna Kanth Reddy printf("Are you sure %s has a valid PMR?\n", 67e04da24cSKrishna Kanth Reddy g_config.pmr_dev.trid.traddr); 68e04da24cSKrishna Kanth Reddy goto free_qpair; 69e04da24cSKrishna Kanth Reddy } 70e04da24cSKrishna Kanth Reddy 71e04da24cSKrishna Kanth Reddy /* Allocate buffer from PMR */ 72e04da24cSKrishna Kanth Reddy pmr_buf = spdk_nvme_ctrlr_map_pmr(g_config.pmr_dev.ctrlr, &sz); 73e04da24cSKrishna Kanth Reddy if (pmr_buf == NULL || sz < g_config.copy_size) { 74e04da24cSKrishna Kanth Reddy printf("ERROR: PMR buffer allocation failed\n"); 75e04da24cSKrishna Kanth Reddy rc = -ENOMEM; 76e04da24cSKrishna Kanth Reddy goto disable_pmr; 77e04da24cSKrishna Kanth Reddy } 78e04da24cSKrishna Kanth Reddy 79e04da24cSKrishna Kanth Reddy /* Clear the done flag */ 80e04da24cSKrishna Kanth Reddy g_config.pmr_dev.done = 0; 81e04da24cSKrishna Kanth Reddy 82e04da24cSKrishna Kanth Reddy /* Do the write to the PMR IO buffer, reading from rlba */ 83e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ns_cmd_read(g_config.pmr_dev.ns, qpair, pmr_buf, 84e04da24cSKrishna Kanth Reddy g_config.pmr_dev.rlba, g_config.pmr_dev.nlbas, 85e04da24cSKrishna Kanth Reddy check_io, NULL, 0); 86e04da24cSKrishna Kanth Reddy if (rc != 0) { 87e04da24cSKrishna Kanth Reddy fprintf(stderr, "Read I/O to PMR failed\n"); 88e04da24cSKrishna Kanth Reddy rc = -EIO; 89e04da24cSKrishna Kanth Reddy goto unmap_pmr; 90e04da24cSKrishna Kanth Reddy } 91e04da24cSKrishna Kanth Reddy while (!g_config.pmr_dev.done) { 92e04da24cSKrishna Kanth Reddy spdk_nvme_qpair_process_completions(qpair, 0); 93e04da24cSKrishna Kanth Reddy } 94e04da24cSKrishna Kanth Reddy 95e04da24cSKrishna Kanth Reddy /* Clear the done flag */ 96e04da24cSKrishna Kanth Reddy g_config.pmr_dev.done = 0; 97e04da24cSKrishna Kanth Reddy 98e04da24cSKrishna Kanth Reddy pmr_buf = NULL; 99e04da24cSKrishna Kanth Reddy 100e04da24cSKrishna Kanth Reddy /* Free PMR buffer */ 101e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ctrlr_unmap_pmr(g_config.pmr_dev.ctrlr); 102e04da24cSKrishna Kanth Reddy if (rc) { 103e04da24cSKrishna Kanth Reddy printf("ERROR: Unmapping PMR failed\n"); 104e04da24cSKrishna Kanth Reddy goto disable_pmr; 105e04da24cSKrishna Kanth Reddy } 106e04da24cSKrishna Kanth Reddy 107e04da24cSKrishna Kanth Reddy /* Disable the PMR */ 108e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ctrlr_disable_pmr(g_config.pmr_dev.ctrlr); 109e04da24cSKrishna Kanth Reddy if (rc) { 110e04da24cSKrishna Kanth Reddy printf("ERROR: Disabling PMR failed\n"); 111e04da24cSKrishna Kanth Reddy goto free_qpair; 112e04da24cSKrishna Kanth Reddy } 113e04da24cSKrishna Kanth Reddy 114e04da24cSKrishna Kanth Reddy /* Free the queue */ 115e04da24cSKrishna Kanth Reddy spdk_nvme_ctrlr_free_io_qpair(qpair); 116e04da24cSKrishna Kanth Reddy 117e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ctrlr_reset(g_config.pmr_dev.ctrlr); 118e04da24cSKrishna Kanth Reddy if (rc) { 119e04da24cSKrishna Kanth Reddy printf("ERROR: Resetting Controller failed\n"); 120e04da24cSKrishna Kanth Reddy return rc; 121e04da24cSKrishna Kanth Reddy } 122e04da24cSKrishna Kanth Reddy 123e04da24cSKrishna Kanth Reddy /* Allocate Queue Pair for the Controller with PMR */ 124e04da24cSKrishna Kanth Reddy qpair = spdk_nvme_ctrlr_alloc_io_qpair(g_config.pmr_dev.ctrlr, NULL, 0); 125e04da24cSKrishna Kanth Reddy if (qpair == NULL) { 126e04da24cSKrishna Kanth Reddy printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n"); 127e04da24cSKrishna Kanth Reddy return -ENOMEM; 128e04da24cSKrishna Kanth Reddy } 129e04da24cSKrishna Kanth Reddy 130e04da24cSKrishna Kanth Reddy /* Enable the PMR */ 131e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ctrlr_enable_pmr(g_config.pmr_dev.ctrlr); 132e04da24cSKrishna Kanth Reddy if (rc) { 133e04da24cSKrishna Kanth Reddy printf("ERROR: Enabling PMR failed\n"); 134e04da24cSKrishna Kanth Reddy goto free_qpair; 135e04da24cSKrishna Kanth Reddy } 136e04da24cSKrishna Kanth Reddy 137e04da24cSKrishna Kanth Reddy /* Allocate buffer from PMR */ 138e04da24cSKrishna Kanth Reddy pmr_buf = spdk_nvme_ctrlr_map_pmr(g_config.pmr_dev.ctrlr, &sz); 139e04da24cSKrishna Kanth Reddy if (pmr_buf == NULL || sz < g_config.copy_size) { 140e04da24cSKrishna Kanth Reddy printf("ERROR: PMR buffer allocation failed\n"); 141e04da24cSKrishna Kanth Reddy rc = -ENOMEM; 142e04da24cSKrishna Kanth Reddy goto disable_pmr; 143e04da24cSKrishna Kanth Reddy } 144e04da24cSKrishna Kanth Reddy 145e04da24cSKrishna Kanth Reddy /* Do the read from the PMR IO buffer, write to wlba */ 146e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ns_cmd_write(g_config.pmr_dev.ns, qpair, pmr_buf, 147e04da24cSKrishna Kanth Reddy g_config.pmr_dev.wlba, g_config.pmr_dev.nlbas, 148e04da24cSKrishna Kanth Reddy check_io, NULL, 0); 149e04da24cSKrishna Kanth Reddy if (rc != 0) { 150e04da24cSKrishna Kanth Reddy fprintf(stderr, "Read I/O from PMR failed\n"); 151e04da24cSKrishna Kanth Reddy rc = -EIO; 152e04da24cSKrishna Kanth Reddy goto unmap_pmr; 153e04da24cSKrishna Kanth Reddy } 154e04da24cSKrishna Kanth Reddy while (!g_config.pmr_dev.done) { 155e04da24cSKrishna Kanth Reddy spdk_nvme_qpair_process_completions(qpair, 0); 156e04da24cSKrishna Kanth Reddy } 157e04da24cSKrishna Kanth Reddy 158e04da24cSKrishna Kanth Reddy /* Clear the done flag */ 159e04da24cSKrishna Kanth Reddy g_config.pmr_dev.done = 0; 160e04da24cSKrishna Kanth Reddy 161*186b109dSJim Harris buf = spdk_zmalloc(g_config.copy_size, 0x1000, NULL, SPDK_ENV_NUMA_ID_ANY, SPDK_MALLOC_DMA); 162e04da24cSKrishna Kanth Reddy if (buf == NULL) { 163e04da24cSKrishna Kanth Reddy printf("ERROR: Buffer allocation failed\n"); 164e04da24cSKrishna Kanth Reddy rc = -ENOMEM; 165e04da24cSKrishna Kanth Reddy goto unmap_pmr; 166e04da24cSKrishna Kanth Reddy } 167e04da24cSKrishna Kanth Reddy 168e04da24cSKrishna Kanth Reddy /* Do the read from wlba to a buffer */ 169e04da24cSKrishna Kanth Reddy rc = spdk_nvme_ns_cmd_read(g_config.pmr_dev.ns, qpair, buf, 170e04da24cSKrishna Kanth Reddy g_config.pmr_dev.wlba, g_config.pmr_dev.nlbas, 171e04da24cSKrishna Kanth Reddy check_io, NULL, 0); 172e04da24cSKrishna Kanth Reddy if (rc != 0) { 173e04da24cSKrishna Kanth Reddy fprintf(stderr, "Read I/O from WLBA failed\n"); 174e04da24cSKrishna Kanth Reddy rc = -EIO; 175e04da24cSKrishna Kanth Reddy goto free_buf; 176e04da24cSKrishna Kanth Reddy } 177e04da24cSKrishna Kanth Reddy while (!g_config.pmr_dev.done) { 178e04da24cSKrishna Kanth Reddy spdk_nvme_qpair_process_completions(qpair, 0); 179e04da24cSKrishna Kanth Reddy } 180e04da24cSKrishna Kanth Reddy 181e04da24cSKrishna Kanth Reddy /* Clear the done flag */ 182e04da24cSKrishna Kanth Reddy g_config.pmr_dev.done = 0; 183e04da24cSKrishna Kanth Reddy 184e04da24cSKrishna Kanth Reddy /* Compare the data in the read buffer to the PMR buffer */ 185e04da24cSKrishna Kanth Reddy if (memcmp(buf, pmr_buf, g_config.copy_size)) { 186e04da24cSKrishna Kanth Reddy printf("PMR Data Not Persistent, after Controller Reset\n"); 187e04da24cSKrishna Kanth Reddy rc = -EIO; 188e04da24cSKrishna Kanth Reddy } else { 189e04da24cSKrishna Kanth Reddy printf("PMR Data is Persistent across Controller Reset\n"); 190e04da24cSKrishna Kanth Reddy } 191e04da24cSKrishna Kanth Reddy 192e04da24cSKrishna Kanth Reddy free_buf: 193e04da24cSKrishna Kanth Reddy spdk_free(buf); 194e04da24cSKrishna Kanth Reddy 195e04da24cSKrishna Kanth Reddy unmap_pmr: 196e04da24cSKrishna Kanth Reddy /* Free PMR buffer */ 197e04da24cSKrishna Kanth Reddy spdk_nvme_ctrlr_unmap_pmr(g_config.pmr_dev.ctrlr); 198e04da24cSKrishna Kanth Reddy 199e04da24cSKrishna Kanth Reddy disable_pmr: 200e04da24cSKrishna Kanth Reddy /* Disable the PMR */ 201e04da24cSKrishna Kanth Reddy spdk_nvme_ctrlr_disable_pmr(g_config.pmr_dev.ctrlr); 202e04da24cSKrishna Kanth Reddy 203e04da24cSKrishna Kanth Reddy free_qpair: 204e04da24cSKrishna Kanth Reddy /* Free the queue */ 205e04da24cSKrishna Kanth Reddy spdk_nvme_ctrlr_free_io_qpair(qpair); 206e04da24cSKrishna Kanth Reddy 207e04da24cSKrishna Kanth Reddy return rc; 208e04da24cSKrishna Kanth Reddy } 209e04da24cSKrishna Kanth Reddy 210e04da24cSKrishna Kanth Reddy static bool 211e04da24cSKrishna Kanth Reddy probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, 212e04da24cSKrishna Kanth Reddy struct spdk_nvme_ctrlr_opts *opts) 213e04da24cSKrishna Kanth Reddy { 214e04da24cSKrishna Kanth Reddy /* We will only attach to the Controller specified by the user */ 215e04da24cSKrishna Kanth Reddy if (spdk_nvme_transport_id_compare(trid, &g_config.pmr_dev.trid)) { 216e04da24cSKrishna Kanth Reddy printf("%s - not probed %s!\n", __func__, trid->traddr); 217e04da24cSKrishna Kanth Reddy return 0; 218e04da24cSKrishna Kanth Reddy } 219e04da24cSKrishna Kanth Reddy 220e04da24cSKrishna Kanth Reddy printf("%s - probed %s!\n", __func__, trid->traddr); 221e04da24cSKrishna Kanth Reddy return 1; 222e04da24cSKrishna Kanth Reddy } 223e04da24cSKrishna Kanth Reddy 224e04da24cSKrishna Kanth Reddy static void 225e04da24cSKrishna Kanth Reddy attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, 226e04da24cSKrishna Kanth Reddy struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts) 227e04da24cSKrishna Kanth Reddy { 228e04da24cSKrishna Kanth Reddy struct spdk_nvme_ns *ns; 229e04da24cSKrishna Kanth Reddy 230e04da24cSKrishna Kanth Reddy ns = spdk_nvme_ctrlr_get_ns(ctrlr, get_nsid(trid)); 231e04da24cSKrishna Kanth Reddy if (ns == NULL) { 232e04da24cSKrishna Kanth Reddy fprintf(stderr, "Could not locate namespace %d on controller %s.\n", 233e04da24cSKrishna Kanth Reddy get_nsid(trid), trid->traddr); 234e04da24cSKrishna Kanth Reddy exit(-1); 235e04da24cSKrishna Kanth Reddy } 236e04da24cSKrishna Kanth Reddy 237e04da24cSKrishna Kanth Reddy g_config.pmr_dev.ctrlr = ctrlr; 238e04da24cSKrishna Kanth Reddy g_config.pmr_dev.ns = ns; 239e04da24cSKrishna Kanth Reddy g_config.pmr_dev.lba_size = spdk_nvme_ns_get_sector_size(ns); 240e04da24cSKrishna Kanth Reddy 241e04da24cSKrishna Kanth Reddy printf("%s - attached %s!\n", __func__, trid->traddr); 242e04da24cSKrishna Kanth Reddy } 243e04da24cSKrishna Kanth Reddy 244e04da24cSKrishna Kanth Reddy static void 245e04da24cSKrishna Kanth Reddy usage(char *program_name) 246e04da24cSKrishna Kanth Reddy { 247e04da24cSKrishna Kanth Reddy printf("%s options (all mandatory)", program_name); 248e04da24cSKrishna Kanth Reddy printf("\n"); 249e04da24cSKrishna Kanth Reddy printf("\t[-p PCIe address of the NVMe Device with PMR support]\n"); 250e04da24cSKrishna Kanth Reddy printf("\t[-n Namespace ID]\n"); 251e04da24cSKrishna Kanth Reddy printf("\t[-r Read LBA]\n"); 252e04da24cSKrishna Kanth Reddy printf("\t[-l Number of LBAs to read]\n"); 253e04da24cSKrishna Kanth Reddy printf("\t[-w Write LBA]\n"); 254e04da24cSKrishna Kanth Reddy printf("\n"); 255e04da24cSKrishna Kanth Reddy } 256e04da24cSKrishna Kanth Reddy 257e04da24cSKrishna Kanth Reddy static int 258e04da24cSKrishna Kanth Reddy parse_args(int argc, char **argv) 259e04da24cSKrishna Kanth Reddy { 260e04da24cSKrishna Kanth Reddy int op; 261e04da24cSKrishna Kanth Reddy unsigned num_args = 0; 262e04da24cSKrishna Kanth Reddy long int val; 263e04da24cSKrishna Kanth Reddy 264e04da24cSKrishna Kanth Reddy while ((op = getopt(argc, argv, "p:n:r:l:w:")) != -1) { 265e04da24cSKrishna Kanth Reddy switch (op) { 266e04da24cSKrishna Kanth Reddy case 'p': 267e04da24cSKrishna Kanth Reddy snprintf(&g_config.pmr_dev.trid.traddr[0], SPDK_NVMF_TRADDR_MAX_LEN + 1, 268e04da24cSKrishna Kanth Reddy "%s", optarg); 269e04da24cSKrishna Kanth Reddy 270e04da24cSKrishna Kanth Reddy g_config.pmr_dev.trid.trtype = SPDK_NVME_TRANSPORT_PCIE; 271e04da24cSKrishna Kanth Reddy 272e04da24cSKrishna Kanth Reddy spdk_nvme_transport_id_populate_trstring(&g_config.pmr_dev.trid, 273e04da24cSKrishna Kanth Reddy spdk_nvme_transport_id_trtype_str(g_config.pmr_dev.trid.trtype)); 274e04da24cSKrishna Kanth Reddy 275e04da24cSKrishna Kanth Reddy num_args++; 276e04da24cSKrishna Kanth Reddy break; 277e04da24cSKrishna Kanth Reddy case 'n': 278e04da24cSKrishna Kanth Reddy case 'r': 279e04da24cSKrishna Kanth Reddy case 'l': 280e04da24cSKrishna Kanth Reddy case 'w': 281e04da24cSKrishna Kanth Reddy val = spdk_strtol(optarg, 10); 282e04da24cSKrishna Kanth Reddy if (val < 0) { 283e04da24cSKrishna Kanth Reddy fprintf(stderr, "Converting a string to integer failed\n"); 284e04da24cSKrishna Kanth Reddy return val; 285e04da24cSKrishna Kanth Reddy } 286e04da24cSKrishna Kanth Reddy switch (op) { 287e04da24cSKrishna Kanth Reddy case 'n': 288e04da24cSKrishna Kanth Reddy g_config.pmr_dev.nsid = (unsigned)val; 289e04da24cSKrishna Kanth Reddy num_args++; 290e04da24cSKrishna Kanth Reddy break; 291e04da24cSKrishna Kanth Reddy case 'r': 292e04da24cSKrishna Kanth Reddy g_config.pmr_dev.rlba = (unsigned)val; 293e04da24cSKrishna Kanth Reddy num_args++; 294e04da24cSKrishna Kanth Reddy break; 295e04da24cSKrishna Kanth Reddy case 'l': 296e04da24cSKrishna Kanth Reddy g_config.pmr_dev.nlbas = (unsigned)val; 297e04da24cSKrishna Kanth Reddy num_args++; 298e04da24cSKrishna Kanth Reddy break; 299e04da24cSKrishna Kanth Reddy case 'w': 300e04da24cSKrishna Kanth Reddy g_config.pmr_dev.wlba = (unsigned)val; 301e04da24cSKrishna Kanth Reddy num_args++; 302e04da24cSKrishna Kanth Reddy break; 303e04da24cSKrishna Kanth Reddy } 304e04da24cSKrishna Kanth Reddy break; 305e04da24cSKrishna Kanth Reddy default: 306e04da24cSKrishna Kanth Reddy usage(argv[0]); 307e04da24cSKrishna Kanth Reddy return 1; 308e04da24cSKrishna Kanth Reddy } 309e04da24cSKrishna Kanth Reddy } 310e04da24cSKrishna Kanth Reddy 311e04da24cSKrishna Kanth Reddy if (num_args != 5) { 312e04da24cSKrishna Kanth Reddy usage(argv[0]); 313e04da24cSKrishna Kanth Reddy return 1; 314e04da24cSKrishna Kanth Reddy } 315e04da24cSKrishna Kanth Reddy 316e04da24cSKrishna Kanth Reddy return 0; 317e04da24cSKrishna Kanth Reddy } 318e04da24cSKrishna Kanth Reddy 319e04da24cSKrishna Kanth Reddy static void 320e04da24cSKrishna Kanth Reddy cleanup(void) 321e04da24cSKrishna Kanth Reddy { 322e04da24cSKrishna Kanth Reddy struct spdk_nvme_detach_ctx *detach_ctx = NULL; 323e04da24cSKrishna Kanth Reddy 324e04da24cSKrishna Kanth Reddy spdk_nvme_detach_async(g_config.pmr_dev.ctrlr, &detach_ctx); 325e04da24cSKrishna Kanth Reddy 3264fe4040aSShuhei Matsumoto if (detach_ctx) { 3274fe4040aSShuhei Matsumoto spdk_nvme_detach_poll(detach_ctx); 328e04da24cSKrishna Kanth Reddy } 329e04da24cSKrishna Kanth Reddy } 330e04da24cSKrishna Kanth Reddy 3318dd1cd21SBen Walker int 3328dd1cd21SBen Walker main(int argc, char **argv) 333e04da24cSKrishna Kanth Reddy { 334e04da24cSKrishna Kanth Reddy int rc = 0; 335e04da24cSKrishna Kanth Reddy struct spdk_env_opts opts; 336e04da24cSKrishna Kanth Reddy 337e04da24cSKrishna Kanth Reddy /* 338e04da24cSKrishna Kanth Reddy * Parse the input arguments. For now we use the following 339e04da24cSKrishna Kanth Reddy * format list: 340e04da24cSKrishna Kanth Reddy * 341e04da24cSKrishna Kanth Reddy * -p <pci id> -n <namespace> -r <Read LBA> -l <number of LBAs> -w <Write LBA> 342e04da24cSKrishna Kanth Reddy * 343e04da24cSKrishna Kanth Reddy */ 344e04da24cSKrishna Kanth Reddy rc = parse_args(argc, argv); 345e04da24cSKrishna Kanth Reddy if (rc) { 346e04da24cSKrishna Kanth Reddy fprintf(stderr, "Error in parse_args(): %d\n", rc); 347e04da24cSKrishna Kanth Reddy return rc; 348e04da24cSKrishna Kanth Reddy } 349e04da24cSKrishna Kanth Reddy 350e04da24cSKrishna Kanth Reddy /* 351e04da24cSKrishna Kanth Reddy * SPDK relies on an abstraction around the local environment 352e04da24cSKrishna Kanth Reddy * named env that handles memory allocation and PCI device operations. 353e04da24cSKrishna Kanth Reddy * This library must be initialized first. 354e04da24cSKrishna Kanth Reddy * 355e04da24cSKrishna Kanth Reddy */ 35657fd99b9SJim Harris opts.opts_size = sizeof(opts); 357e04da24cSKrishna Kanth Reddy spdk_env_opts_init(&opts); 358e04da24cSKrishna Kanth Reddy opts.name = "pmr_persistence"; 359e04da24cSKrishna Kanth Reddy opts.shm_id = 0; 360e04da24cSKrishna Kanth Reddy if (spdk_env_init(&opts) < 0) { 361e04da24cSKrishna Kanth Reddy fprintf(stderr, "Unable to initialize SPDK env\n"); 362e04da24cSKrishna Kanth Reddy return 1; 363e04da24cSKrishna Kanth Reddy } 364e04da24cSKrishna Kanth Reddy 365e04da24cSKrishna Kanth Reddy /* 366e04da24cSKrishna Kanth Reddy * PMRs only apply to PCIe attached NVMe controllers so we 367e04da24cSKrishna Kanth Reddy * only probe the PCIe bus. This is the default when we pass 368e04da24cSKrishna Kanth Reddy * in NULL for the first argument. 369e04da24cSKrishna Kanth Reddy */ 370e04da24cSKrishna Kanth Reddy 371e04da24cSKrishna Kanth Reddy rc = spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL); 372e04da24cSKrishna Kanth Reddy if (rc) { 373e04da24cSKrishna Kanth Reddy fprintf(stderr, "Error in spdk_nvme_probe(): %d\n", rc); 374e04da24cSKrishna Kanth Reddy cleanup(); 375e04da24cSKrishna Kanth Reddy return rc; 376e04da24cSKrishna Kanth Reddy } 377e04da24cSKrishna Kanth Reddy 378e04da24cSKrishna Kanth Reddy g_config.copy_size = g_config.pmr_dev.nlbas * g_config.pmr_dev.lba_size; 379e04da24cSKrishna Kanth Reddy 380e04da24cSKrishna Kanth Reddy /* 381e04da24cSKrishna Kanth Reddy * Call the pmr_persistence() function which performs the data copy 382e04da24cSKrishna Kanth Reddy * to PMR region, resets the Controller and verifies the data persistence 383e04da24cSKrishna Kanth Reddy * or returns an error code if it fails. 384e04da24cSKrishna Kanth Reddy */ 385e04da24cSKrishna Kanth Reddy rc = pmr_persistence(); 386e04da24cSKrishna Kanth Reddy if (rc) { 387e04da24cSKrishna Kanth Reddy fprintf(stderr, "Error in pmr_persistence(): %d\n", rc); 388e04da24cSKrishna Kanth Reddy } 389e04da24cSKrishna Kanth Reddy 390e04da24cSKrishna Kanth Reddy cleanup(); 391e04da24cSKrishna Kanth Reddy 392e04da24cSKrishna Kanth Reddy return rc; 393e04da24cSKrishna Kanth Reddy } 394