1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "bdev_nvme.h" 37 #include "common.h" 38 39 #include "spdk/string.h" 40 #include "spdk/rpc.h" 41 #include "spdk/util.h" 42 43 #include "spdk_internal/log.h" 44 #include "spdk/bdev_module.h" 45 46 struct open_descriptors { 47 void *desc; 48 struct spdk_bdev *bdev; 49 TAILQ_ENTRY(open_descriptors) tqlst; 50 }; 51 typedef TAILQ_HEAD(, open_descriptors) open_descriptors_t; 52 53 static int 54 rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out) 55 { 56 enum spdk_bdev_timeout_action *action = out; 57 58 if (spdk_json_strequal(val, "none") == true) { 59 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE; 60 } else if (spdk_json_strequal(val, "abort") == true) { 61 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT; 62 } else if (spdk_json_strequal(val, "reset") == true) { 63 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET; 64 } else { 65 SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n"); 66 return -EINVAL; 67 } 68 69 return 0; 70 } 71 72 static const struct spdk_json_object_decoder rpc_bdev_nvme_options_decoders[] = { 73 {"action_on_timeout", offsetof(struct spdk_bdev_nvme_opts, action_on_timeout), rpc_decode_action_on_timeout, true}, 74 {"timeout_us", offsetof(struct spdk_bdev_nvme_opts, timeout_us), spdk_json_decode_uint64, true}, 75 {"retry_count", offsetof(struct spdk_bdev_nvme_opts, retry_count), spdk_json_decode_uint32, true}, 76 {"nvme_adminq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_adminq_poll_period_us), spdk_json_decode_uint64, true}, 77 {"nvme_ioq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_ioq_poll_period_us), spdk_json_decode_uint64, true}, 78 {"io_queue_requests", offsetof(struct spdk_bdev_nvme_opts, io_queue_requests), spdk_json_decode_uint32, true}, 79 }; 80 81 static void 82 spdk_rpc_set_bdev_nvme_options(struct spdk_jsonrpc_request *request, 83 const struct spdk_json_val *params) 84 { 85 struct spdk_bdev_nvme_opts opts; 86 struct spdk_json_write_ctx *w; 87 int rc; 88 89 spdk_bdev_nvme_get_opts(&opts); 90 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders, 91 SPDK_COUNTOF(rpc_bdev_nvme_options_decoders), 92 &opts)) { 93 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 94 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 95 "spdk_json_decode_object failed"); 96 return; 97 } 98 99 rc = spdk_bdev_nvme_set_opts(&opts); 100 if (rc) { 101 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 102 return; 103 } 104 105 w = spdk_jsonrpc_begin_result(request); 106 spdk_json_write_bool(w, true); 107 spdk_jsonrpc_end_result(request, w); 108 109 return; 110 } 111 SPDK_RPC_REGISTER("set_bdev_nvme_options", spdk_rpc_set_bdev_nvme_options, SPDK_RPC_STARTUP) 112 113 struct rpc_bdev_nvme_hotplug { 114 bool enabled; 115 uint64_t period_us; 116 }; 117 118 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = { 119 {"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false}, 120 {"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true}, 121 }; 122 123 static void 124 rpc_set_bdev_nvme_hotplug_done(void *ctx) 125 { 126 struct spdk_jsonrpc_request *request = ctx; 127 struct spdk_json_write_ctx *w = spdk_jsonrpc_begin_result(request); 128 129 spdk_json_write_bool(w, true); 130 spdk_jsonrpc_end_result(request, w); 131 } 132 133 static void 134 spdk_rpc_set_bdev_nvme_hotplug(struct spdk_jsonrpc_request *request, 135 const struct spdk_json_val *params) 136 { 137 struct rpc_bdev_nvme_hotplug req = {false, 0}; 138 int rc; 139 140 if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders, 141 SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) { 142 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 143 rc = -EINVAL; 144 goto invalid; 145 } 146 147 rc = spdk_bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_set_bdev_nvme_hotplug_done, 148 request); 149 if (rc) { 150 goto invalid; 151 } 152 153 return; 154 invalid: 155 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc)); 156 } 157 SPDK_RPC_REGISTER("set_bdev_nvme_hotplug", spdk_rpc_set_bdev_nvme_hotplug, SPDK_RPC_RUNTIME) 158 159 struct rpc_construct_nvme { 160 char *name; 161 char *trtype; 162 char *adrfam; 163 char *traddr; 164 char *trsvcid; 165 char *subnqn; 166 char *hostnqn; 167 char *hostaddr; 168 char *hostsvcid; 169 bool prchk_reftag; 170 bool prchk_guard; 171 }; 172 173 static void 174 free_rpc_construct_nvme(struct rpc_construct_nvme *req) 175 { 176 free(req->name); 177 free(req->trtype); 178 free(req->adrfam); 179 free(req->traddr); 180 free(req->trsvcid); 181 free(req->subnqn); 182 free(req->hostnqn); 183 free(req->hostaddr); 184 free(req->hostsvcid); 185 } 186 187 static const struct spdk_json_object_decoder rpc_construct_nvme_decoders[] = { 188 {"name", offsetof(struct rpc_construct_nvme, name), spdk_json_decode_string}, 189 {"trtype", offsetof(struct rpc_construct_nvme, trtype), spdk_json_decode_string}, 190 {"traddr", offsetof(struct rpc_construct_nvme, traddr), spdk_json_decode_string}, 191 192 {"adrfam", offsetof(struct rpc_construct_nvme, adrfam), spdk_json_decode_string, true}, 193 {"trsvcid", offsetof(struct rpc_construct_nvme, trsvcid), spdk_json_decode_string, true}, 194 {"subnqn", offsetof(struct rpc_construct_nvme, subnqn), spdk_json_decode_string, true}, 195 {"hostnqn", offsetof(struct rpc_construct_nvme, hostnqn), spdk_json_decode_string, true}, 196 {"hostaddr", offsetof(struct rpc_construct_nvme, hostaddr), spdk_json_decode_string, true}, 197 {"hostsvcid", offsetof(struct rpc_construct_nvme, hostsvcid), spdk_json_decode_string, true}, 198 199 {"prchk_reftag", offsetof(struct rpc_construct_nvme, prchk_reftag), spdk_json_decode_bool, true}, 200 {"prchk_guard", offsetof(struct rpc_construct_nvme, prchk_guard), spdk_json_decode_bool, true} 201 }; 202 203 #define NVME_MAX_BDEVS_PER_RPC 128 204 205 struct rpc_create_nvme_bdev_ctx { 206 struct rpc_construct_nvme req; 207 size_t count; 208 const char *names[NVME_MAX_BDEVS_PER_RPC]; 209 struct spdk_jsonrpc_request *request; 210 }; 211 212 static void 213 spdk_rpc_construct_nvme_bdev_done(void *cb_ctx, int rc) 214 { 215 struct rpc_create_nvme_bdev_ctx *ctx = cb_ctx; 216 struct spdk_jsonrpc_request *request = ctx->request; 217 struct spdk_json_write_ctx *w; 218 size_t i; 219 220 if (rc < 0) { 221 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 222 goto exit; 223 } 224 225 w = spdk_jsonrpc_begin_result(request); 226 spdk_json_write_array_begin(w); 227 for (i = 0; i < ctx->count; i++) { 228 spdk_json_write_string(w, ctx->names[i]); 229 } 230 spdk_json_write_array_end(w); 231 spdk_jsonrpc_end_result(request, w); 232 233 exit: 234 free_rpc_construct_nvme(&ctx->req); 235 free(ctx); 236 } 237 238 static void 239 spdk_rpc_construct_nvme_bdev(struct spdk_jsonrpc_request *request, 240 const struct spdk_json_val *params) 241 { 242 struct rpc_create_nvme_bdev_ctx *ctx; 243 struct spdk_nvme_transport_id trid = {}; 244 struct spdk_nvme_host_id hostid = {}; 245 uint32_t prchk_flags = 0; 246 int rc; 247 248 ctx = calloc(1, sizeof(*ctx)); 249 if (!ctx) { 250 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 251 return; 252 } 253 254 if (spdk_json_decode_object(params, rpc_construct_nvme_decoders, 255 SPDK_COUNTOF(rpc_construct_nvme_decoders), 256 &ctx->req)) { 257 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 258 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 259 "spdk_json_decode_object failed"); 260 goto cleanup; 261 } 262 263 /* Parse trtype */ 264 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype); 265 if (rc < 0) { 266 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype); 267 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 268 ctx->req.trtype); 269 goto cleanup; 270 } 271 272 /* Parse traddr */ 273 snprintf(trid.traddr, sizeof(trid.traddr), "%s", ctx->req.traddr); 274 275 /* Parse adrfam */ 276 if (ctx->req.adrfam) { 277 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam); 278 if (rc < 0) { 279 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam); 280 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 281 ctx->req.adrfam); 282 goto cleanup; 283 } 284 } 285 286 /* Parse trsvcid */ 287 if (ctx->req.trsvcid) { 288 snprintf(trid.trsvcid, sizeof(trid.trsvcid), "%s", ctx->req.trsvcid); 289 } 290 291 /* Parse subnqn */ 292 if (ctx->req.subnqn) { 293 snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx->req.subnqn); 294 } 295 296 if (ctx->req.hostaddr) { 297 snprintf(hostid.hostaddr, sizeof(hostid.hostaddr), "%s", ctx->req.hostaddr); 298 } 299 300 if (ctx->req.hostsvcid) { 301 snprintf(hostid.hostsvcid, sizeof(hostid.hostsvcid), "%s", ctx->req.hostsvcid); 302 } 303 304 if (ctx->req.prchk_reftag) { 305 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG; 306 } 307 308 if (ctx->req.prchk_guard) { 309 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD; 310 } 311 312 ctx->request = request; 313 ctx->count = NVME_MAX_BDEVS_PER_RPC; 314 rc = spdk_bdev_nvme_create(&trid, &hostid, ctx->req.name, ctx->names, &ctx->count, ctx->req.hostnqn, 315 prchk_flags, spdk_rpc_construct_nvme_bdev_done, ctx); 316 if (rc) { 317 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 318 goto cleanup; 319 } 320 321 return; 322 323 cleanup: 324 free_rpc_construct_nvme(&ctx->req); 325 free(ctx); 326 } 327 SPDK_RPC_REGISTER("construct_nvme_bdev", spdk_rpc_construct_nvme_bdev, SPDK_RPC_RUNTIME) 328 329 static void 330 spdk_rpc_dump_nvme_controller_info(struct spdk_json_write_ctx *w, 331 struct nvme_bdev_ctrlr *nvme_bdev_ctrlr) 332 { 333 struct spdk_nvme_transport_id *trid; 334 335 trid = &nvme_bdev_ctrlr->trid; 336 337 spdk_json_write_object_begin(w); 338 spdk_json_write_named_string(w, "name", nvme_bdev_ctrlr->name); 339 340 spdk_json_write_named_object_begin(w, "trid"); 341 nvme_bdev_dump_trid_json(trid, w); 342 spdk_json_write_object_end(w); 343 344 spdk_json_write_object_end(w); 345 } 346 347 struct rpc_get_nvme_controllers { 348 char *name; 349 }; 350 351 static void 352 free_rpc_get_nvme_controllers(struct rpc_get_nvme_controllers *r) 353 { 354 free(r->name); 355 } 356 357 static const struct spdk_json_object_decoder rpc_get_nvme_controllers_decoders[] = { 358 {"name", offsetof(struct rpc_get_nvme_controllers, name), spdk_json_decode_string, true}, 359 }; 360 361 static void 362 spdk_rpc_get_nvme_controllers(struct spdk_jsonrpc_request *request, 363 const struct spdk_json_val *params) 364 { 365 struct rpc_get_nvme_controllers req = {}; 366 struct spdk_json_write_ctx *w; 367 struct nvme_bdev_ctrlr *ctrlr = NULL; 368 369 if (params && spdk_json_decode_object(params, rpc_get_nvme_controllers_decoders, 370 SPDK_COUNTOF(rpc_get_nvme_controllers_decoders), 371 &req)) { 372 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 373 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 374 "spdk_json_decode_object failed"); 375 goto cleanup; 376 } 377 378 if (req.name) { 379 ctrlr = nvme_bdev_ctrlr_get_by_name(req.name); 380 if (ctrlr == NULL) { 381 SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name); 382 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name); 383 goto cleanup; 384 } 385 } 386 387 w = spdk_jsonrpc_begin_result(request); 388 spdk_json_write_array_begin(w); 389 390 if (ctrlr != NULL) { 391 spdk_rpc_dump_nvme_controller_info(w, ctrlr); 392 } else { 393 for (ctrlr = nvme_bdev_first_ctrlr(); ctrlr; ctrlr = nvme_bdev_next_ctrlr(ctrlr)) { 394 spdk_rpc_dump_nvme_controller_info(w, ctrlr); 395 } 396 } 397 398 spdk_json_write_array_end(w); 399 400 spdk_jsonrpc_end_result(request, w); 401 402 cleanup: 403 free_rpc_get_nvme_controllers(&req); 404 } 405 SPDK_RPC_REGISTER("get_nvme_controllers", spdk_rpc_get_nvme_controllers, SPDK_RPC_RUNTIME) 406 407 struct rpc_delete_nvme { 408 char *name; 409 }; 410 411 static void 412 free_rpc_delete_nvme(struct rpc_delete_nvme *req) 413 { 414 free(req->name); 415 } 416 417 static const struct spdk_json_object_decoder rpc_delete_nvme_decoders[] = { 418 {"name", offsetof(struct rpc_delete_nvme, name), spdk_json_decode_string}, 419 }; 420 421 static void 422 spdk_rpc_delete_nvme_controller(struct spdk_jsonrpc_request *request, 423 const struct spdk_json_val *params) 424 { 425 struct rpc_delete_nvme req = {NULL}; 426 struct spdk_json_write_ctx *w; 427 int rc = 0; 428 429 if (spdk_json_decode_object(params, rpc_delete_nvme_decoders, 430 SPDK_COUNTOF(rpc_delete_nvme_decoders), 431 &req)) { 432 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 433 "spdk_json_decode_object failed"); 434 goto cleanup; 435 } 436 437 rc = spdk_bdev_nvme_delete(req.name); 438 if (rc != 0) { 439 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 440 goto cleanup; 441 } 442 443 w = spdk_jsonrpc_begin_result(request); 444 spdk_json_write_bool(w, true); 445 spdk_jsonrpc_end_result(request, w); 446 447 cleanup: 448 free_rpc_delete_nvme(&req); 449 } 450 SPDK_RPC_REGISTER("delete_nvme_controller", spdk_rpc_delete_nvme_controller, SPDK_RPC_RUNTIME) 451 452 struct rpc_apply_firmware { 453 char *filename; 454 char *bdev_name; 455 }; 456 457 static void 458 free_rpc_apply_firmware(struct rpc_apply_firmware *req) 459 { 460 free(req->filename); 461 free(req->bdev_name); 462 } 463 464 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = { 465 {"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string}, 466 {"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string}, 467 }; 468 469 struct firmware_update_info { 470 void *fw_image; 471 void *p; 472 unsigned int size; 473 unsigned int size_remaining; 474 unsigned int offset; 475 unsigned int transfer; 476 477 void *desc; 478 struct spdk_io_channel *ch; 479 struct spdk_jsonrpc_request *request; 480 struct spdk_nvme_ctrlr *ctrlr; 481 open_descriptors_t desc_head; 482 struct rpc_apply_firmware *req; 483 }; 484 485 static void 486 apply_firmware_cleanup(void *cb_arg) 487 { 488 struct open_descriptors *opt, *tmp; 489 struct firmware_update_info *firm_ctx = cb_arg; 490 491 if (!firm_ctx) { 492 return; 493 } 494 495 if (firm_ctx->fw_image) { 496 spdk_free(firm_ctx->fw_image); 497 } 498 499 if (firm_ctx->req) { 500 free_rpc_apply_firmware(firm_ctx->req); 501 free(firm_ctx->req); 502 } 503 TAILQ_FOREACH_SAFE(opt, &firm_ctx->desc_head, tqlst, tmp) { 504 TAILQ_REMOVE(&firm_ctx->desc_head, opt, tqlst); 505 spdk_bdev_close(opt->desc); 506 free(opt); 507 } 508 free(firm_ctx); 509 } 510 511 static void 512 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 513 { 514 int rc; 515 struct spdk_json_write_ctx *w; 516 struct firmware_update_info *firm_ctx = cb_arg; 517 518 spdk_bdev_free_io(bdev_io); 519 520 if (!success) { 521 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 522 "firmware commit failed."); 523 apply_firmware_cleanup(firm_ctx); 524 return; 525 } 526 527 if ((rc = spdk_nvme_ctrlr_reset(firm_ctx->ctrlr)) != 0) { 528 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 529 "Controller reset failed."); 530 apply_firmware_cleanup(firm_ctx); 531 return; 532 } 533 534 w = spdk_jsonrpc_begin_result(firm_ctx->request); 535 spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress."); 536 spdk_jsonrpc_end_result(firm_ctx->request, w); 537 apply_firmware_cleanup(firm_ctx); 538 } 539 540 static void 541 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 542 { 543 struct spdk_nvme_cmd cmd = {}; 544 struct spdk_nvme_fw_commit fw_commit; 545 int slot = 0; 546 int rc; 547 struct firmware_update_info *firm_ctx = cb_arg; 548 enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG; 549 550 if (!success) { 551 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 552 "firmware download failed ."); 553 spdk_bdev_free_io(bdev_io); 554 apply_firmware_cleanup(firm_ctx); 555 return; 556 } 557 558 firm_ctx->p += firm_ctx->transfer; 559 firm_ctx->offset += firm_ctx->transfer; 560 firm_ctx->size_remaining -= firm_ctx->transfer; 561 562 switch (firm_ctx->size_remaining) { 563 case 0: 564 /* firmware download completed. Commit firmware */ 565 memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit)); 566 fw_commit.fs = slot; 567 fw_commit.ca = commit_action; 568 569 cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT; 570 memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t)); 571 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0, 572 apply_firmware_complete_reset, firm_ctx); 573 if (rc) { 574 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 575 "firmware commit failed."); 576 spdk_bdev_free_io(bdev_io); 577 apply_firmware_cleanup(firm_ctx); 578 return; 579 } 580 break; 581 default: 582 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 583 cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 584 585 cmd.cdw10 = (firm_ctx->transfer >> 2) - 1; 586 cmd.cdw11 = firm_ctx->offset >> 2; 587 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p, 588 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 589 if (rc) { 590 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 591 "firmware download failed."); 592 spdk_bdev_free_io(bdev_io); 593 apply_firmware_cleanup(firm_ctx); 594 return; 595 } 596 break; 597 } 598 } 599 600 static void 601 spdk_rpc_apply_nvme_firmware(struct spdk_jsonrpc_request *request, 602 const struct spdk_json_val *params) 603 { 604 int rc; 605 int fd = -1; 606 struct stat fw_stat; 607 struct spdk_nvme_ctrlr *ctrlr; 608 char msg[1024]; 609 struct spdk_bdev *bdev; 610 struct spdk_bdev *bdev2; 611 struct open_descriptors *opt; 612 struct spdk_bdev_desc *desc; 613 struct spdk_nvme_cmd *cmd; 614 struct firmware_update_info *firm_ctx; 615 616 firm_ctx = malloc(sizeof(struct firmware_update_info)); 617 if (!firm_ctx) { 618 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 619 "Memory allocation error."); 620 return; 621 } 622 firm_ctx->fw_image = NULL; 623 TAILQ_INIT(&firm_ctx->desc_head); 624 firm_ctx->request = request; 625 626 firm_ctx->req = malloc(sizeof(struct rpc_apply_firmware)); 627 if (!firm_ctx->req) { 628 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 629 "Memory allocation error."); 630 free(firm_ctx); 631 return; 632 } 633 634 if (spdk_json_decode_object(params, rpc_apply_firmware_decoders, 635 SPDK_COUNTOF(rpc_apply_firmware_decoders), firm_ctx->req)) { 636 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 637 "spdk_json_decode_object failed."); 638 free(firm_ctx->req); 639 free(firm_ctx); 640 return; 641 } 642 643 if ((bdev = spdk_bdev_get_by_name(firm_ctx->req->bdev_name)) == NULL) { 644 snprintf(msg, sizeof(msg), "bdev %s were not found", firm_ctx->req->bdev_name); 645 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 646 apply_firmware_cleanup(firm_ctx); 647 return; 648 } 649 650 if ((ctrlr = spdk_bdev_nvme_get_ctrlr(bdev)) == NULL) { 651 snprintf(msg, sizeof(msg), "Controller information for %s were not found.", 652 firm_ctx->req->bdev_name); 653 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 654 apply_firmware_cleanup(firm_ctx); 655 return; 656 } 657 firm_ctx->ctrlr = ctrlr; 658 659 for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) { 660 661 if (spdk_bdev_nvme_get_ctrlr(bdev2) != ctrlr) { 662 continue; 663 } 664 665 if (!(opt = malloc(sizeof(struct open_descriptors)))) { 666 snprintf(msg, sizeof(msg), "Memory allocation error."); 667 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 668 apply_firmware_cleanup(firm_ctx); 669 return; 670 } 671 672 if ((rc = spdk_bdev_open(bdev2, true, NULL, NULL, &desc)) != 0) { 673 snprintf(msg, sizeof(msg), "Device %s is in use.", firm_ctx->req->bdev_name); 674 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 675 free(opt); 676 apply_firmware_cleanup(firm_ctx); 677 return; 678 } 679 680 opt->desc = desc; 681 opt->bdev = bdev; 682 TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst); 683 } 684 685 /* 686 * find a descriptor associated with our bdev 687 */ 688 firm_ctx->desc = NULL; 689 TAILQ_FOREACH(opt, &firm_ctx->desc_head, tqlst) { 690 if (opt->bdev == bdev) { 691 firm_ctx->desc = opt->desc; 692 break; 693 } 694 } 695 696 if (!firm_ctx->desc) { 697 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 698 "No descriptor were found."); 699 apply_firmware_cleanup(firm_ctx); 700 return; 701 } 702 703 firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc); 704 if (!firm_ctx->ch) { 705 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 706 "No channels were found."); 707 apply_firmware_cleanup(firm_ctx); 708 return; 709 } 710 711 fd = open(firm_ctx->req->filename, O_RDONLY); 712 if (fd < 0) { 713 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "open file failed."); 714 apply_firmware_cleanup(firm_ctx); 715 return; 716 } 717 718 rc = fstat(fd, &fw_stat); 719 if (rc < 0) { 720 close(fd); 721 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "fstat failed."); 722 apply_firmware_cleanup(firm_ctx); 723 return; 724 } 725 726 firm_ctx->size = fw_stat.st_size; 727 if (fw_stat.st_size % 4) { 728 close(fd); 729 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 730 "Firmware image size is not multiple of 4."); 731 apply_firmware_cleanup(firm_ctx); 732 return; 733 } 734 735 firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL, 736 SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 737 if (!firm_ctx->fw_image) { 738 close(fd); 739 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 740 "Memory allocation error."); 741 apply_firmware_cleanup(firm_ctx); 742 return; 743 } 744 firm_ctx->p = firm_ctx->fw_image; 745 746 if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) { 747 close(fd); 748 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 749 "Read firmware image failed!"); 750 apply_firmware_cleanup(firm_ctx); 751 return; 752 } 753 close(fd); 754 755 firm_ctx->offset = 0; 756 firm_ctx->size_remaining = firm_ctx->size; 757 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 758 759 cmd = malloc(sizeof(struct spdk_nvme_cmd)); 760 if (!cmd) { 761 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 762 "Memory allocation error."); 763 apply_firmware_cleanup(firm_ctx); 764 return; 765 } 766 memset(cmd, 0, sizeof(struct spdk_nvme_cmd)); 767 cmd->opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 768 769 cmd->cdw10 = (firm_ctx->transfer >> 2) - 1; 770 cmd->cdw11 = firm_ctx->offset >> 2; 771 772 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, cmd, firm_ctx->p, 773 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 774 if (rc) { 775 free(cmd); 776 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 777 "Read firmware image failed!"); 778 apply_firmware_cleanup(firm_ctx); 779 return; 780 } 781 } 782 SPDK_RPC_REGISTER("apply_nvme_firmware", spdk_rpc_apply_nvme_firmware, SPDK_RPC_RUNTIME) 783