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