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/config.h" 40 41 #include "spdk/string.h" 42 #include "spdk/rpc.h" 43 #include "spdk/util.h" 44 45 #include "spdk_internal/log.h" 46 #include "spdk/bdev_module.h" 47 48 struct open_descriptors { 49 void *desc; 50 struct spdk_bdev *bdev; 51 TAILQ_ENTRY(open_descriptors) tqlst; 52 }; 53 typedef TAILQ_HEAD(, open_descriptors) open_descriptors_t; 54 55 static int 56 rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out) 57 { 58 enum spdk_bdev_timeout_action *action = out; 59 60 if (spdk_json_strequal(val, "none") == true) { 61 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE; 62 } else if (spdk_json_strequal(val, "abort") == true) { 63 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT; 64 } else if (spdk_json_strequal(val, "reset") == true) { 65 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET; 66 } else { 67 SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n"); 68 return -EINVAL; 69 } 70 71 return 0; 72 } 73 74 static const struct spdk_json_object_decoder rpc_bdev_nvme_options_decoders[] = { 75 {"action_on_timeout", offsetof(struct spdk_bdev_nvme_opts, action_on_timeout), rpc_decode_action_on_timeout, true}, 76 {"timeout_us", offsetof(struct spdk_bdev_nvme_opts, timeout_us), spdk_json_decode_uint64, true}, 77 {"retry_count", offsetof(struct spdk_bdev_nvme_opts, retry_count), spdk_json_decode_uint32, true}, 78 {"arbitration_burst", offsetof(struct spdk_bdev_nvme_opts, arbitration_burst), spdk_json_decode_uint32, true}, 79 {"low_priority_weight", offsetof(struct spdk_bdev_nvme_opts, low_priority_weight), spdk_json_decode_uint32, true}, 80 {"medium_priority_weight", offsetof(struct spdk_bdev_nvme_opts, medium_priority_weight), spdk_json_decode_uint32, true}, 81 {"high_priority_weight", offsetof(struct spdk_bdev_nvme_opts, high_priority_weight), spdk_json_decode_uint32, true}, 82 {"nvme_adminq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_adminq_poll_period_us), spdk_json_decode_uint64, true}, 83 {"nvme_ioq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_ioq_poll_period_us), spdk_json_decode_uint64, true}, 84 {"io_queue_requests", offsetof(struct spdk_bdev_nvme_opts, io_queue_requests), spdk_json_decode_uint32, true}, 85 }; 86 87 static void 88 spdk_rpc_bdev_nvme_set_options(struct spdk_jsonrpc_request *request, 89 const struct spdk_json_val *params) 90 { 91 struct spdk_bdev_nvme_opts opts; 92 struct spdk_json_write_ctx *w; 93 int rc; 94 95 spdk_bdev_nvme_get_opts(&opts); 96 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders, 97 SPDK_COUNTOF(rpc_bdev_nvme_options_decoders), 98 &opts)) { 99 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 100 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 101 "spdk_json_decode_object failed"); 102 return; 103 } 104 105 rc = spdk_bdev_nvme_set_opts(&opts); 106 if (rc) { 107 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 108 return; 109 } 110 111 w = spdk_jsonrpc_begin_result(request); 112 spdk_json_write_bool(w, true); 113 spdk_jsonrpc_end_result(request, w); 114 115 return; 116 } 117 SPDK_RPC_REGISTER("bdev_nvme_set_options", spdk_rpc_bdev_nvme_set_options, SPDK_RPC_STARTUP) 118 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_options, set_bdev_nvme_options) 119 120 struct rpc_bdev_nvme_hotplug { 121 bool enabled; 122 uint64_t period_us; 123 }; 124 125 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = { 126 {"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false}, 127 {"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true}, 128 }; 129 130 static void 131 rpc_bdev_nvme_set_hotplug_done(void *ctx) 132 { 133 struct spdk_jsonrpc_request *request = ctx; 134 struct spdk_json_write_ctx *w = spdk_jsonrpc_begin_result(request); 135 136 spdk_json_write_bool(w, true); 137 spdk_jsonrpc_end_result(request, w); 138 } 139 140 static void 141 spdk_rpc_bdev_nvme_set_hotplug(struct spdk_jsonrpc_request *request, 142 const struct spdk_json_val *params) 143 { 144 struct rpc_bdev_nvme_hotplug req = {false, 0}; 145 int rc; 146 147 if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders, 148 SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) { 149 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 150 rc = -EINVAL; 151 goto invalid; 152 } 153 154 rc = spdk_bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_bdev_nvme_set_hotplug_done, 155 request); 156 if (rc) { 157 goto invalid; 158 } 159 160 return; 161 invalid: 162 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc)); 163 } 164 SPDK_RPC_REGISTER("bdev_nvme_set_hotplug", spdk_rpc_bdev_nvme_set_hotplug, SPDK_RPC_RUNTIME) 165 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_hotplug, set_bdev_nvme_hotplug) 166 167 struct rpc_bdev_nvme_attach_controller { 168 char *name; 169 char *trtype; 170 char *adrfam; 171 char *traddr; 172 char *trsvcid; 173 char *subnqn; 174 char *hostnqn; 175 char *hostaddr; 176 char *hostsvcid; 177 bool prchk_reftag; 178 bool prchk_guard; 179 }; 180 181 static void 182 free_rpc_bdev_nvme_attach_controller(struct rpc_bdev_nvme_attach_controller *req) 183 { 184 free(req->name); 185 free(req->trtype); 186 free(req->adrfam); 187 free(req->traddr); 188 free(req->trsvcid); 189 free(req->subnqn); 190 free(req->hostnqn); 191 free(req->hostaddr); 192 free(req->hostsvcid); 193 } 194 195 static const struct spdk_json_object_decoder rpc_bdev_nvme_attach_controller_decoders[] = { 196 {"name", offsetof(struct rpc_bdev_nvme_attach_controller, name), spdk_json_decode_string}, 197 {"trtype", offsetof(struct rpc_bdev_nvme_attach_controller, trtype), spdk_json_decode_string}, 198 {"traddr", offsetof(struct rpc_bdev_nvme_attach_controller, traddr), spdk_json_decode_string}, 199 200 {"adrfam", offsetof(struct rpc_bdev_nvme_attach_controller, adrfam), spdk_json_decode_string, true}, 201 {"trsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, trsvcid), spdk_json_decode_string, true}, 202 {"subnqn", offsetof(struct rpc_bdev_nvme_attach_controller, subnqn), spdk_json_decode_string, true}, 203 {"hostnqn", offsetof(struct rpc_bdev_nvme_attach_controller, hostnqn), spdk_json_decode_string, true}, 204 {"hostaddr", offsetof(struct rpc_bdev_nvme_attach_controller, hostaddr), spdk_json_decode_string, true}, 205 {"hostsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, hostsvcid), spdk_json_decode_string, true}, 206 207 {"prchk_reftag", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_reftag), spdk_json_decode_bool, true}, 208 {"prchk_guard", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_guard), spdk_json_decode_bool, true} 209 }; 210 211 #define NVME_MAX_BDEVS_PER_RPC 128 212 213 struct rpc_bdev_nvme_attach_controller_ctx { 214 struct rpc_bdev_nvme_attach_controller req; 215 uint32_t count; 216 const char *names[NVME_MAX_BDEVS_PER_RPC]; 217 struct spdk_jsonrpc_request *request; 218 }; 219 220 static void 221 spdk_rpc_bdev_nvme_attach_controller_done(void *cb_ctx, size_t bdev_count, int rc) 222 { 223 struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx; 224 struct spdk_jsonrpc_request *request = ctx->request; 225 struct spdk_json_write_ctx *w; 226 size_t i; 227 228 if (rc < 0) { 229 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 230 goto exit; 231 } 232 233 w = spdk_jsonrpc_begin_result(request); 234 spdk_json_write_array_begin(w); 235 for (i = 0; i < bdev_count; i++) { 236 spdk_json_write_string(w, ctx->names[i]); 237 } 238 spdk_json_write_array_end(w); 239 spdk_jsonrpc_end_result(request, w); 240 241 exit: 242 free_rpc_bdev_nvme_attach_controller(&ctx->req); 243 free(ctx); 244 } 245 246 static void 247 spdk_rpc_bdev_nvme_attach_controller(struct spdk_jsonrpc_request *request, 248 const struct spdk_json_val *params) 249 { 250 struct rpc_bdev_nvme_attach_controller_ctx *ctx; 251 struct spdk_nvme_transport_id trid = {}; 252 struct spdk_nvme_host_id hostid = {}; 253 uint32_t prchk_flags = 0; 254 int rc; 255 256 ctx = calloc(1, sizeof(*ctx)); 257 if (!ctx) { 258 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 259 return; 260 } 261 262 if (spdk_json_decode_object(params, rpc_bdev_nvme_attach_controller_decoders, 263 SPDK_COUNTOF(rpc_bdev_nvme_attach_controller_decoders), 264 &ctx->req)) { 265 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 266 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 267 "spdk_json_decode_object failed"); 268 goto cleanup; 269 } 270 271 /* Parse trtype */ 272 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype); 273 if (rc < 0) { 274 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype); 275 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 276 ctx->req.trtype); 277 goto cleanup; 278 } 279 280 /* Parse traddr */ 281 snprintf(trid.traddr, sizeof(trid.traddr), "%s", ctx->req.traddr); 282 283 /* Parse adrfam */ 284 if (ctx->req.adrfam) { 285 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam); 286 if (rc < 0) { 287 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam); 288 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 289 ctx->req.adrfam); 290 goto cleanup; 291 } 292 } 293 294 /* Parse trsvcid */ 295 if (ctx->req.trsvcid) { 296 snprintf(trid.trsvcid, sizeof(trid.trsvcid), "%s", ctx->req.trsvcid); 297 } 298 299 /* Parse subnqn */ 300 if (ctx->req.subnqn) { 301 snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx->req.subnqn); 302 } 303 304 if (ctx->req.hostaddr) { 305 snprintf(hostid.hostaddr, sizeof(hostid.hostaddr), "%s", ctx->req.hostaddr); 306 } 307 308 if (ctx->req.hostsvcid) { 309 snprintf(hostid.hostsvcid, sizeof(hostid.hostsvcid), "%s", ctx->req.hostsvcid); 310 } 311 312 if (ctx->req.prchk_reftag) { 313 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG; 314 } 315 316 if (ctx->req.prchk_guard) { 317 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD; 318 } 319 320 ctx->request = request; 321 ctx->count = NVME_MAX_BDEVS_PER_RPC; 322 rc = spdk_bdev_nvme_create(&trid, &hostid, ctx->req.name, ctx->names, ctx->count, ctx->req.hostnqn, 323 prchk_flags, spdk_rpc_bdev_nvme_attach_controller_done, ctx); 324 if (rc) { 325 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 326 goto cleanup; 327 } 328 329 return; 330 331 cleanup: 332 free_rpc_bdev_nvme_attach_controller(&ctx->req); 333 free(ctx); 334 } 335 SPDK_RPC_REGISTER("bdev_nvme_attach_controller", spdk_rpc_bdev_nvme_attach_controller, 336 SPDK_RPC_RUNTIME) 337 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_attach_controller, construct_nvme_bdev) 338 339 static void 340 spdk_rpc_dump_nvme_controller_info(struct spdk_json_write_ctx *w, 341 struct nvme_bdev_ctrlr *nvme_bdev_ctrlr) 342 { 343 struct spdk_nvme_transport_id *trid; 344 345 trid = &nvme_bdev_ctrlr->trid; 346 347 spdk_json_write_object_begin(w); 348 spdk_json_write_named_string(w, "name", nvme_bdev_ctrlr->name); 349 350 #ifdef SPDK_CONFIG_NVME_CUSE 351 char *cuse_device; 352 353 cuse_device = spdk_nvme_cuse_get_ctrlr_name(nvme_bdev_ctrlr->ctrlr); 354 if (cuse_device) { 355 spdk_json_write_named_string(w, "cuse_device", cuse_device); 356 } 357 #endif 358 359 spdk_json_write_named_object_begin(w, "trid"); 360 nvme_bdev_dump_trid_json(trid, w); 361 spdk_json_write_object_end(w); 362 363 spdk_json_write_object_end(w); 364 } 365 366 struct rpc_bdev_nvme_get_controllers { 367 char *name; 368 }; 369 370 static void 371 free_rpc_bdev_nvme_get_controllers(struct rpc_bdev_nvme_get_controllers *r) 372 { 373 free(r->name); 374 } 375 376 static const struct spdk_json_object_decoder rpc_bdev_nvme_get_controllers_decoders[] = { 377 {"name", offsetof(struct rpc_bdev_nvme_get_controllers, name), spdk_json_decode_string, true}, 378 }; 379 380 static void 381 spdk_rpc_bdev_nvme_get_controllers(struct spdk_jsonrpc_request *request, 382 const struct spdk_json_val *params) 383 { 384 struct rpc_bdev_nvme_get_controllers req = {}; 385 struct spdk_json_write_ctx *w; 386 struct nvme_bdev_ctrlr *ctrlr = NULL; 387 388 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_get_controllers_decoders, 389 SPDK_COUNTOF(rpc_bdev_nvme_get_controllers_decoders), 390 &req)) { 391 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 392 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 393 "spdk_json_decode_object failed"); 394 goto cleanup; 395 } 396 397 if (req.name) { 398 ctrlr = nvme_bdev_ctrlr_get_by_name(req.name); 399 if (ctrlr == NULL) { 400 SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name); 401 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name); 402 goto cleanup; 403 } 404 } 405 406 w = spdk_jsonrpc_begin_result(request); 407 spdk_json_write_array_begin(w); 408 409 if (ctrlr != NULL) { 410 spdk_rpc_dump_nvme_controller_info(w, ctrlr); 411 } else { 412 for (ctrlr = nvme_bdev_first_ctrlr(); ctrlr; ctrlr = nvme_bdev_next_ctrlr(ctrlr)) { 413 spdk_rpc_dump_nvme_controller_info(w, ctrlr); 414 } 415 } 416 417 spdk_json_write_array_end(w); 418 419 spdk_jsonrpc_end_result(request, w); 420 421 cleanup: 422 free_rpc_bdev_nvme_get_controllers(&req); 423 } 424 SPDK_RPC_REGISTER("bdev_nvme_get_controllers", spdk_rpc_bdev_nvme_get_controllers, SPDK_RPC_RUNTIME) 425 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_get_controllers, get_nvme_controllers) 426 427 struct rpc_bdev_nvme_detach_controller { 428 char *name; 429 }; 430 431 static void 432 free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req) 433 { 434 free(req->name); 435 } 436 437 static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = { 438 {"name", offsetof(struct rpc_bdev_nvme_detach_controller, name), spdk_json_decode_string}, 439 }; 440 441 static void 442 spdk_rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request, 443 const struct spdk_json_val *params) 444 { 445 struct rpc_bdev_nvme_detach_controller req = {NULL}; 446 struct spdk_json_write_ctx *w; 447 int rc = 0; 448 449 if (spdk_json_decode_object(params, rpc_bdev_nvme_detach_controller_decoders, 450 SPDK_COUNTOF(rpc_bdev_nvme_detach_controller_decoders), 451 &req)) { 452 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 453 "spdk_json_decode_object failed"); 454 goto cleanup; 455 } 456 457 rc = spdk_bdev_nvme_delete(req.name); 458 if (rc != 0) { 459 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 460 goto cleanup; 461 } 462 463 w = spdk_jsonrpc_begin_result(request); 464 spdk_json_write_bool(w, true); 465 spdk_jsonrpc_end_result(request, w); 466 467 cleanup: 468 free_rpc_bdev_nvme_detach_controller(&req); 469 } 470 SPDK_RPC_REGISTER("bdev_nvme_detach_controller", spdk_rpc_bdev_nvme_detach_controller, 471 SPDK_RPC_RUNTIME) 472 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_detach_controller, delete_nvme_controller) 473 474 struct rpc_apply_firmware { 475 char *filename; 476 char *bdev_name; 477 }; 478 479 static void 480 free_rpc_apply_firmware(struct rpc_apply_firmware *req) 481 { 482 free(req->filename); 483 free(req->bdev_name); 484 } 485 486 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = { 487 {"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string}, 488 {"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string}, 489 }; 490 491 struct firmware_update_info { 492 void *fw_image; 493 void *p; 494 unsigned int size; 495 unsigned int size_remaining; 496 unsigned int offset; 497 unsigned int transfer; 498 499 void *desc; 500 struct spdk_io_channel *ch; 501 struct spdk_jsonrpc_request *request; 502 struct spdk_nvme_ctrlr *ctrlr; 503 open_descriptors_t desc_head; 504 struct rpc_apply_firmware *req; 505 }; 506 507 static void 508 apply_firmware_cleanup(void *cb_arg) 509 { 510 struct open_descriptors *opt, *tmp; 511 struct firmware_update_info *firm_ctx = cb_arg; 512 513 if (!firm_ctx) { 514 return; 515 } 516 517 if (firm_ctx->fw_image) { 518 spdk_free(firm_ctx->fw_image); 519 } 520 521 if (firm_ctx->req) { 522 free_rpc_apply_firmware(firm_ctx->req); 523 free(firm_ctx->req); 524 } 525 TAILQ_FOREACH_SAFE(opt, &firm_ctx->desc_head, tqlst, tmp) { 526 TAILQ_REMOVE(&firm_ctx->desc_head, opt, tqlst); 527 spdk_bdev_close(opt->desc); 528 free(opt); 529 } 530 free(firm_ctx); 531 } 532 533 static void 534 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 535 { 536 int rc; 537 struct spdk_json_write_ctx *w; 538 struct firmware_update_info *firm_ctx = cb_arg; 539 540 spdk_bdev_free_io(bdev_io); 541 542 if (!success) { 543 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 544 "firmware commit failed."); 545 apply_firmware_cleanup(firm_ctx); 546 return; 547 } 548 549 if ((rc = spdk_nvme_ctrlr_reset(firm_ctx->ctrlr)) != 0) { 550 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 551 "Controller reset failed."); 552 apply_firmware_cleanup(firm_ctx); 553 return; 554 } 555 556 w = spdk_jsonrpc_begin_result(firm_ctx->request); 557 spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress."); 558 spdk_jsonrpc_end_result(firm_ctx->request, w); 559 apply_firmware_cleanup(firm_ctx); 560 } 561 562 static void 563 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 564 { 565 struct spdk_nvme_cmd cmd = {}; 566 struct spdk_nvme_fw_commit fw_commit; 567 int slot = 0; 568 int rc; 569 struct firmware_update_info *firm_ctx = cb_arg; 570 enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG; 571 572 if (!success) { 573 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 574 "firmware download failed ."); 575 spdk_bdev_free_io(bdev_io); 576 apply_firmware_cleanup(firm_ctx); 577 return; 578 } 579 580 firm_ctx->p += firm_ctx->transfer; 581 firm_ctx->offset += firm_ctx->transfer; 582 firm_ctx->size_remaining -= firm_ctx->transfer; 583 584 switch (firm_ctx->size_remaining) { 585 case 0: 586 /* firmware download completed. Commit firmware */ 587 memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit)); 588 fw_commit.fs = slot; 589 fw_commit.ca = commit_action; 590 591 cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT; 592 memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t)); 593 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0, 594 apply_firmware_complete_reset, firm_ctx); 595 if (rc) { 596 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 597 "firmware commit failed."); 598 spdk_bdev_free_io(bdev_io); 599 apply_firmware_cleanup(firm_ctx); 600 return; 601 } 602 break; 603 default: 604 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 605 cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 606 607 cmd.cdw10 = (firm_ctx->transfer >> 2) - 1; 608 cmd.cdw11 = firm_ctx->offset >> 2; 609 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p, 610 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 611 if (rc) { 612 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 613 "firmware download failed."); 614 spdk_bdev_free_io(bdev_io); 615 apply_firmware_cleanup(firm_ctx); 616 return; 617 } 618 break; 619 } 620 } 621 622 static void 623 spdk_rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request, 624 const struct spdk_json_val *params) 625 { 626 int rc; 627 int fd = -1; 628 struct stat fw_stat; 629 struct spdk_nvme_ctrlr *ctrlr; 630 char msg[1024]; 631 struct spdk_bdev *bdev; 632 struct spdk_bdev *bdev2; 633 struct open_descriptors *opt; 634 struct spdk_bdev_desc *desc; 635 struct spdk_nvme_cmd *cmd; 636 struct firmware_update_info *firm_ctx; 637 638 firm_ctx = malloc(sizeof(struct firmware_update_info)); 639 if (!firm_ctx) { 640 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 641 "Memory allocation error."); 642 return; 643 } 644 firm_ctx->fw_image = NULL; 645 TAILQ_INIT(&firm_ctx->desc_head); 646 firm_ctx->request = request; 647 648 firm_ctx->req = malloc(sizeof(struct rpc_apply_firmware)); 649 if (!firm_ctx->req) { 650 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 651 "Memory allocation error."); 652 free(firm_ctx); 653 return; 654 } 655 656 if (spdk_json_decode_object(params, rpc_apply_firmware_decoders, 657 SPDK_COUNTOF(rpc_apply_firmware_decoders), firm_ctx->req)) { 658 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 659 "spdk_json_decode_object failed."); 660 free(firm_ctx->req); 661 free(firm_ctx); 662 return; 663 } 664 665 if ((bdev = spdk_bdev_get_by_name(firm_ctx->req->bdev_name)) == NULL) { 666 snprintf(msg, sizeof(msg), "bdev %s were not found", firm_ctx->req->bdev_name); 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 ((ctrlr = spdk_bdev_nvme_get_ctrlr(bdev)) == NULL) { 673 snprintf(msg, sizeof(msg), "Controller information for %s were not found.", 674 firm_ctx->req->bdev_name); 675 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 676 apply_firmware_cleanup(firm_ctx); 677 return; 678 } 679 firm_ctx->ctrlr = ctrlr; 680 681 for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) { 682 683 if (spdk_bdev_nvme_get_ctrlr(bdev2) != ctrlr) { 684 continue; 685 } 686 687 if (!(opt = malloc(sizeof(struct open_descriptors)))) { 688 snprintf(msg, sizeof(msg), "Memory allocation error."); 689 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 690 apply_firmware_cleanup(firm_ctx); 691 return; 692 } 693 694 if ((rc = spdk_bdev_open(bdev2, true, NULL, NULL, &desc)) != 0) { 695 snprintf(msg, sizeof(msg), "Device %s is in use.", firm_ctx->req->bdev_name); 696 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 697 free(opt); 698 apply_firmware_cleanup(firm_ctx); 699 return; 700 } 701 702 opt->desc = desc; 703 opt->bdev = bdev; 704 TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst); 705 } 706 707 /* 708 * find a descriptor associated with our bdev 709 */ 710 firm_ctx->desc = NULL; 711 TAILQ_FOREACH(opt, &firm_ctx->desc_head, tqlst) { 712 if (opt->bdev == bdev) { 713 firm_ctx->desc = opt->desc; 714 break; 715 } 716 } 717 718 if (!firm_ctx->desc) { 719 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 720 "No descriptor were found."); 721 apply_firmware_cleanup(firm_ctx); 722 return; 723 } 724 725 firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc); 726 if (!firm_ctx->ch) { 727 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 728 "No channels were found."); 729 apply_firmware_cleanup(firm_ctx); 730 return; 731 } 732 733 fd = open(firm_ctx->req->filename, O_RDONLY); 734 if (fd < 0) { 735 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "open file failed."); 736 apply_firmware_cleanup(firm_ctx); 737 return; 738 } 739 740 rc = fstat(fd, &fw_stat); 741 if (rc < 0) { 742 close(fd); 743 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "fstat failed."); 744 apply_firmware_cleanup(firm_ctx); 745 return; 746 } 747 748 firm_ctx->size = fw_stat.st_size; 749 if (fw_stat.st_size % 4) { 750 close(fd); 751 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 752 "Firmware image size is not multiple of 4."); 753 apply_firmware_cleanup(firm_ctx); 754 return; 755 } 756 757 firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL, 758 SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 759 if (!firm_ctx->fw_image) { 760 close(fd); 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 firm_ctx->p = firm_ctx->fw_image; 767 768 if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) { 769 close(fd); 770 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 771 "Read firmware image failed!"); 772 apply_firmware_cleanup(firm_ctx); 773 return; 774 } 775 close(fd); 776 777 firm_ctx->offset = 0; 778 firm_ctx->size_remaining = firm_ctx->size; 779 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 780 781 cmd = malloc(sizeof(struct spdk_nvme_cmd)); 782 if (!cmd) { 783 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 784 "Memory allocation error."); 785 apply_firmware_cleanup(firm_ctx); 786 return; 787 } 788 memset(cmd, 0, sizeof(struct spdk_nvme_cmd)); 789 cmd->opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 790 791 cmd->cdw10 = (firm_ctx->transfer >> 2) - 1; 792 cmd->cdw11 = firm_ctx->offset >> 2; 793 794 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, cmd, firm_ctx->p, 795 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 796 if (rc) { 797 free(cmd); 798 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 799 "Read firmware image failed!"); 800 apply_firmware_cleanup(firm_ctx); 801 return; 802 } 803 } 804 SPDK_RPC_REGISTER("bdev_nvme_apply_firmware", spdk_rpc_bdev_nvme_apply_firmware, SPDK_RPC_RUNTIME) 805 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_apply_firmware, apply_nvme_firmware) 806