4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk/stdinc.h"
36 #include "bdev_nvme.h"
39 #include "spdk/string.h"
41 #include "spdk/util.h"
43 #include "spdk_internal/log.h"
44 #include "spdk/bdev_module.h"
46 struct open_descriptors
{
48 struct spdk_bdev
*bdev
;
49 TAILQ_ENTRY(open_descriptors
) tqlst
;
51 typedef TAILQ_HEAD(, open_descriptors
) open_descriptors_t
;
54 rpc_decode_action_on_timeout(const struct spdk_json_val
*val
, void *out
)
56 enum spdk_bdev_timeout_action
*action
= out
;
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
;
65 SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n");
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},
81 spdk_rpc_set_bdev_nvme_options(struct spdk_jsonrpc_request
*request
,
82 const struct spdk_json_val
*params
)
84 struct spdk_bdev_nvme_opts opts
;
85 struct spdk_json_write_ctx
*w
;
88 spdk_bdev_nvme_get_opts(&opts
);
89 if (params
&& spdk_json_decode_object(params
, rpc_bdev_nvme_options_decoders
,
90 SPDK_COUNTOF(rpc_bdev_nvme_options_decoders
),
92 SPDK_ERRLOG("spdk_json_decode_object failed\n");
97 rc
= spdk_bdev_nvme_set_opts(&opts
);
102 w
= spdk_jsonrpc_begin_result(request
);
104 spdk_json_write_bool(w
, true);
105 spdk_jsonrpc_end_result(request
, w
);
110 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, spdk_strerror(-rc
));
112 SPDK_RPC_REGISTER("set_bdev_nvme_options", spdk_rpc_set_bdev_nvme_options
, SPDK_RPC_STARTUP
)
114 struct rpc_bdev_nvme_hotplug
{
119 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders
[] = {
120 {"enable", offsetof(struct rpc_bdev_nvme_hotplug
, enabled
), spdk_json_decode_bool
, false},
121 {"period_us", offsetof(struct rpc_bdev_nvme_hotplug
, period_us
), spdk_json_decode_uint64
, true},
125 rpc_set_bdev_nvme_hotplug_done(void *ctx
)
127 struct spdk_jsonrpc_request
*request
= ctx
;
128 struct spdk_json_write_ctx
*w
= spdk_jsonrpc_begin_result(request
);
131 spdk_json_write_bool(w
, true);
132 spdk_jsonrpc_end_result(request
, w
);
137 spdk_rpc_set_bdev_nvme_hotplug(struct spdk_jsonrpc_request
*request
,
138 const struct spdk_json_val
*params
)
140 struct rpc_bdev_nvme_hotplug req
= {false, 0};
143 if (spdk_json_decode_object(params
, rpc_bdev_nvme_hotplug_decoders
,
144 SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders
), &req
)) {
145 SPDK_ERRLOG("spdk_json_decode_object failed\n");
150 rc
= spdk_bdev_nvme_set_hotplug(req
.enabled
, req
.period_us
, rpc_set_bdev_nvme_hotplug_done
,
158 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, spdk_strerror(-rc
));
160 SPDK_RPC_REGISTER("set_bdev_nvme_hotplug", spdk_rpc_set_bdev_nvme_hotplug
, SPDK_RPC_RUNTIME
)
162 struct rpc_construct_nvme
{
177 free_rpc_construct_nvme(struct rpc_construct_nvme
*req
)
187 free(req
->hostsvcid
);
190 static const struct spdk_json_object_decoder rpc_construct_nvme_decoders
[] = {
191 {"name", offsetof(struct rpc_construct_nvme
, name
), spdk_json_decode_string
},
192 {"trtype", offsetof(struct rpc_construct_nvme
, trtype
), spdk_json_decode_string
},
193 {"traddr", offsetof(struct rpc_construct_nvme
, traddr
), spdk_json_decode_string
},
195 {"adrfam", offsetof(struct rpc_construct_nvme
, adrfam
), spdk_json_decode_string
, true},
196 {"trsvcid", offsetof(struct rpc_construct_nvme
, trsvcid
), spdk_json_decode_string
, true},
197 {"subnqn", offsetof(struct rpc_construct_nvme
, subnqn
), spdk_json_decode_string
, true},
198 {"hostnqn", offsetof(struct rpc_construct_nvme
, hostnqn
), spdk_json_decode_string
, true},
199 {"hostaddr", offsetof(struct rpc_construct_nvme
, hostaddr
), spdk_json_decode_string
, true},
200 {"hostsvcid", offsetof(struct rpc_construct_nvme
, hostsvcid
), spdk_json_decode_string
, true},
202 {"prchk_reftag", offsetof(struct rpc_construct_nvme
, prchk_reftag
), spdk_json_decode_bool
, true},
203 {"prchk_guard", offsetof(struct rpc_construct_nvme
, prchk_guard
), spdk_json_decode_bool
, true}
206 #define NVME_MAX_BDEVS_PER_RPC 128
208 struct rpc_create_nvme_bdev_ctx
{
209 struct rpc_construct_nvme req
;
211 const char *names
[NVME_MAX_BDEVS_PER_RPC
];
212 struct spdk_jsonrpc_request
*request
;
216 spdk_rpc_construct_nvme_bdev_done(void *cb_ctx
, int rc
)
218 struct rpc_create_nvme_bdev_ctx
*ctx
= cb_ctx
;
219 struct spdk_jsonrpc_request
*request
= ctx
->request
;
220 struct spdk_json_write_ctx
*w
;
223 w
= spdk_jsonrpc_begin_result(request
);
229 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
233 spdk_json_write_array_begin(w
);
234 for (i
= 0; i
< ctx
->count
; i
++) {
235 spdk_json_write_string(w
, ctx
->names
[i
]);
237 spdk_json_write_array_end(w
);
238 spdk_jsonrpc_end_result(request
, w
);
241 free_rpc_construct_nvme(&ctx
->req
);
246 spdk_rpc_construct_nvme_bdev(struct spdk_jsonrpc_request
*request
,
247 const struct spdk_json_val
*params
)
249 struct rpc_create_nvme_bdev_ctx
*ctx
;
250 struct spdk_nvme_transport_id trid
= {};
251 struct spdk_nvme_host_id hostid
= {};
252 uint32_t prchk_flags
= 0;
255 ctx
= calloc(1, sizeof(*ctx
));
257 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, spdk_strerror(ENOMEM
));
261 if (spdk_json_decode_object(params
, rpc_construct_nvme_decoders
,
262 SPDK_COUNTOF(rpc_construct_nvme_decoders
),
264 SPDK_ERRLOG("spdk_json_decode_object failed\n");
269 rc
= spdk_nvme_transport_id_parse_trtype(&trid
.trtype
, ctx
->req
.trtype
);
271 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx
->req
.trtype
);
276 snprintf(trid
.traddr
, sizeof(trid
.traddr
), "%s", ctx
->req
.traddr
);
279 if (ctx
->req
.adrfam
) {
280 rc
= spdk_nvme_transport_id_parse_adrfam(&trid
.adrfam
, ctx
->req
.adrfam
);
282 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx
->req
.adrfam
);
288 if (ctx
->req
.trsvcid
) {
289 snprintf(trid
.trsvcid
, sizeof(trid
.trsvcid
), "%s", ctx
->req
.trsvcid
);
293 if (ctx
->req
.subnqn
) {
294 snprintf(trid
.subnqn
, sizeof(trid
.subnqn
), "%s", ctx
->req
.subnqn
);
297 if (ctx
->req
.hostaddr
) {
298 snprintf(hostid
.hostaddr
, sizeof(hostid
.hostaddr
), "%s", ctx
->req
.hostaddr
);
301 if (ctx
->req
.hostsvcid
) {
302 snprintf(hostid
.hostsvcid
, sizeof(hostid
.hostsvcid
), "%s", ctx
->req
.hostsvcid
);
305 if (ctx
->req
.prchk_reftag
) {
306 prchk_flags
|= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG
;
309 if (ctx
->req
.prchk_guard
) {
310 prchk_flags
|= SPDK_NVME_IO_FLAGS_PRCHK_GUARD
;
313 ctx
->request
= request
;
314 ctx
->count
= NVME_MAX_BDEVS_PER_RPC
;
315 if (spdk_bdev_nvme_create(&trid
, &hostid
, ctx
->req
.name
, ctx
->names
, &ctx
->count
, ctx
->req
.hostnqn
,
316 prchk_flags
, spdk_rpc_construct_nvme_bdev_done
, ctx
)) {
323 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
324 free_rpc_construct_nvme(&ctx
->req
);
327 SPDK_RPC_REGISTER("construct_nvme_bdev", spdk_rpc_construct_nvme_bdev
, SPDK_RPC_RUNTIME
)
330 spdk_rpc_dump_nvme_controller_info(struct spdk_json_write_ctx
*w
,
331 struct nvme_bdev_ctrlr
*nvme_bdev_ctrlr
)
333 struct spdk_nvme_transport_id
*trid
;
335 trid
= &nvme_bdev_ctrlr
->trid
;
337 spdk_json_write_object_begin(w
);
338 spdk_json_write_named_string(w
, "name", nvme_bdev_ctrlr
->name
);
340 spdk_json_write_named_object_begin(w
, "trid");
341 nvme_bdev_dump_trid_json(trid
, w
);
342 spdk_json_write_object_end(w
);
344 spdk_json_write_object_end(w
);
347 struct rpc_get_nvme_controllers
{
352 free_rpc_get_nvme_controllers(struct rpc_get_nvme_controllers
*r
)
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},
362 spdk_rpc_get_nvme_controllers(struct spdk_jsonrpc_request
*request
,
363 const struct spdk_json_val
*params
)
365 struct rpc_get_nvme_controllers req
= {};
366 struct spdk_json_write_ctx
*w
;
367 struct nvme_bdev_ctrlr
*ctrlr
= NULL
;
369 if (params
&& spdk_json_decode_object(params
, rpc_get_nvme_controllers_decoders
,
370 SPDK_COUNTOF(rpc_get_nvme_controllers_decoders
),
372 SPDK_ERRLOG("spdk_json_decode_object failed\n");
377 ctrlr
= nvme_bdev_ctrlr_get_by_name(req
.name
);
379 SPDK_ERRLOG("ctrlr '%s' does not exist\n", req
.name
);
384 free_rpc_get_nvme_controllers(&req
);
385 w
= spdk_jsonrpc_begin_result(request
);
390 spdk_json_write_array_begin(w
);
393 spdk_rpc_dump_nvme_controller_info(w
, ctrlr
);
395 for (ctrlr
= nvme_bdev_first_ctrlr(); ctrlr
; ctrlr
= nvme_bdev_next_ctrlr(ctrlr
)) {
396 spdk_rpc_dump_nvme_controller_info(w
, ctrlr
);
400 spdk_json_write_array_end(w
);
402 spdk_jsonrpc_end_result(request
, w
);
407 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
409 free_rpc_get_nvme_controllers(&req
);
411 SPDK_RPC_REGISTER("get_nvme_controllers", spdk_rpc_get_nvme_controllers
, SPDK_RPC_RUNTIME
)
413 struct rpc_delete_nvme
{
418 free_rpc_delete_nvme(struct rpc_delete_nvme
*req
)
423 static const struct spdk_json_object_decoder rpc_delete_nvme_decoders
[] = {
424 {"name", offsetof(struct rpc_delete_nvme
, name
), spdk_json_decode_string
},
428 spdk_rpc_delete_nvme_controller(struct spdk_jsonrpc_request
*request
,
429 const struct spdk_json_val
*params
)
431 struct rpc_delete_nvme req
= {NULL
};
432 struct spdk_json_write_ctx
*w
;
435 if (spdk_json_decode_object(params
, rpc_delete_nvme_decoders
,
436 SPDK_COUNTOF(rpc_delete_nvme_decoders
),
442 rc
= spdk_bdev_nvme_delete(req
.name
);
447 free_rpc_delete_nvme(&req
);
449 w
= spdk_jsonrpc_begin_result(request
);
454 spdk_json_write_bool(w
, true);
455 spdk_jsonrpc_end_result(request
, w
);
459 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
,
461 free_rpc_delete_nvme(&req
);
463 SPDK_RPC_REGISTER("delete_nvme_controller", spdk_rpc_delete_nvme_controller
, SPDK_RPC_RUNTIME
)
465 struct rpc_apply_firmware
{
471 free_rpc_apply_firmware(struct rpc_apply_firmware
*req
)
474 free(req
->bdev_name
);
477 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders
[] = {
478 {"filename", offsetof(struct rpc_apply_firmware
, filename
), spdk_json_decode_string
},
479 {"bdev_name", offsetof(struct rpc_apply_firmware
, bdev_name
), spdk_json_decode_string
},
482 struct firmware_update_info
{
486 unsigned int size_remaining
;
488 unsigned int transfer
;
491 struct spdk_io_channel
*ch
;
492 struct spdk_jsonrpc_request
*request
;
493 struct spdk_nvme_ctrlr
*ctrlr
;
494 open_descriptors_t desc_head
;
495 struct rpc_apply_firmware
*req
;
499 apply_firmware_cleanup(void *cb_arg
)
501 struct open_descriptors
*opt
, *tmp
;
502 struct firmware_update_info
*firm_ctx
= cb_arg
;
508 if (firm_ctx
->fw_image
) {
509 spdk_dma_free(firm_ctx
->fw_image
);
513 free_rpc_apply_firmware(firm_ctx
->req
);
516 TAILQ_FOREACH_SAFE(opt
, &firm_ctx
->desc_head
, tqlst
, tmp
) {
517 TAILQ_REMOVE(&firm_ctx
->desc_head
, opt
, tqlst
);
518 spdk_bdev_close(opt
->desc
);
525 apply_firmware_complete_reset(struct spdk_bdev_io
*bdev_io
, bool success
, void *cb_arg
)
528 struct spdk_json_write_ctx
*w
;
529 struct firmware_update_info
*firm_ctx
= cb_arg
;
531 spdk_bdev_free_io(bdev_io
);
534 spdk_jsonrpc_send_error_response(firm_ctx
->request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
535 "firmware commit failed.");
536 apply_firmware_cleanup(firm_ctx
);
540 if ((rc
= spdk_nvme_ctrlr_reset(firm_ctx
->ctrlr
)) != 0) {
541 spdk_jsonrpc_send_error_response(firm_ctx
->request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
542 "Controller reset failed.");
543 apply_firmware_cleanup(firm_ctx
);
547 if (!(w
= spdk_jsonrpc_begin_result(firm_ctx
->request
))) {
548 apply_firmware_cleanup(firm_ctx
);
552 spdk_json_write_string(w
, "firmware commit succeeded. Controller reset in progress.");
553 spdk_jsonrpc_end_result(firm_ctx
->request
, w
);
554 apply_firmware_cleanup(firm_ctx
);
558 apply_firmware_complete(struct spdk_bdev_io
*bdev_io
, bool success
, void *cb_arg
)
560 struct spdk_nvme_cmd cmd
= {};
561 struct spdk_nvme_fw_commit fw_commit
;
564 struct firmware_update_info
*firm_ctx
= cb_arg
;
565 enum spdk_nvme_fw_commit_action commit_action
= SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG
;
568 spdk_jsonrpc_send_error_response(firm_ctx
->request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
569 "firmware download failed .");
570 spdk_bdev_free_io(bdev_io
);
571 apply_firmware_cleanup(firm_ctx
);
575 firm_ctx
->p
+= firm_ctx
->transfer
;
576 firm_ctx
->offset
+= firm_ctx
->transfer
;
577 firm_ctx
->size_remaining
-= firm_ctx
->transfer
;
579 switch (firm_ctx
->size_remaining
) {
581 /* firmware download completed. Commit firmware */
582 memset(&fw_commit
, 0, sizeof(struct spdk_nvme_fw_commit
));
584 fw_commit
.ca
= commit_action
;
586 cmd
.opc
= SPDK_NVME_OPC_FIRMWARE_COMMIT
;
587 memcpy(&cmd
.cdw10
, &fw_commit
, sizeof(uint32_t));
588 rc
= spdk_bdev_nvme_admin_passthru(firm_ctx
->desc
, firm_ctx
->ch
, &cmd
, NULL
, 0,
589 apply_firmware_complete_reset
, firm_ctx
);
591 spdk_jsonrpc_send_error_response(firm_ctx
->request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
592 "firmware commit failed.");
593 spdk_bdev_free_io(bdev_io
);
594 apply_firmware_cleanup(firm_ctx
);
599 firm_ctx
->transfer
= spdk_min(firm_ctx
->size_remaining
, 4096);
600 cmd
.opc
= SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD
;
602 cmd
.cdw10
= (firm_ctx
->transfer
>> 2) - 1;
603 cmd
.cdw11
= firm_ctx
->offset
>> 2;
604 rc
= spdk_bdev_nvme_admin_passthru(firm_ctx
->desc
, firm_ctx
->ch
, &cmd
, firm_ctx
->p
,
605 firm_ctx
->transfer
, apply_firmware_complete
, firm_ctx
);
607 spdk_jsonrpc_send_error_response(firm_ctx
->request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
608 "firmware download failed.");
609 spdk_bdev_free_io(bdev_io
);
610 apply_firmware_cleanup(firm_ctx
);
618 spdk_rpc_apply_nvme_firmware(struct spdk_jsonrpc_request
*request
,
619 const struct spdk_json_val
*params
)
624 struct spdk_nvme_ctrlr
*ctrlr
;
626 struct spdk_bdev
*bdev
;
627 struct spdk_bdev
*bdev2
;
628 struct open_descriptors
*opt
;
629 struct spdk_bdev_desc
*desc
;
630 struct spdk_nvme_cmd
*cmd
;
631 struct firmware_update_info
*firm_ctx
;
633 firm_ctx
= malloc(sizeof(struct firmware_update_info
));
635 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
636 "Memory allocation error.");
639 firm_ctx
->fw_image
= NULL
;
640 TAILQ_INIT(&firm_ctx
->desc_head
);
641 firm_ctx
->request
= request
;
643 firm_ctx
->req
= malloc(sizeof(struct rpc_apply_firmware
));
644 if (!firm_ctx
->req
) {
645 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
646 "Memory allocation error.");
651 if (spdk_json_decode_object(params
, rpc_apply_firmware_decoders
,
652 SPDK_COUNTOF(rpc_apply_firmware_decoders
), firm_ctx
->req
)) {
653 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
654 "spdk_json_decode_object failed.");
660 if ((bdev
= spdk_bdev_get_by_name(firm_ctx
->req
->bdev_name
)) == NULL
) {
661 snprintf(msg
, sizeof(msg
), "bdev %s were not found", firm_ctx
->req
->bdev_name
);
662 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, msg
);
663 apply_firmware_cleanup(firm_ctx
);
667 if ((ctrlr
= spdk_bdev_nvme_get_ctrlr(bdev
)) == NULL
) {
668 snprintf(msg
, sizeof(msg
), "Controller information for %s were not found.",
669 firm_ctx
->req
->bdev_name
);
670 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, msg
);
671 apply_firmware_cleanup(firm_ctx
);
674 firm_ctx
->ctrlr
= ctrlr
;
676 for (bdev2
= spdk_bdev_first(); bdev2
; bdev2
= spdk_bdev_next(bdev2
)) {
678 if (spdk_bdev_nvme_get_ctrlr(bdev2
) != ctrlr
) {
682 if (!(opt
= malloc(sizeof(struct open_descriptors
)))) {
683 snprintf(msg
, sizeof(msg
), "Memory allocation error.");
684 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, msg
);
685 apply_firmware_cleanup(firm_ctx
);
689 if ((rc
= spdk_bdev_open(bdev2
, true, NULL
, NULL
, &desc
)) != 0) {
690 snprintf(msg
, sizeof(msg
), "Device %s is in use.", firm_ctx
->req
->bdev_name
);
691 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, msg
);
693 apply_firmware_cleanup(firm_ctx
);
699 TAILQ_INSERT_TAIL(&firm_ctx
->desc_head
, opt
, tqlst
);
703 * find a descriptor associated with our bdev
705 firm_ctx
->desc
= NULL
;
706 TAILQ_FOREACH(opt
, &firm_ctx
->desc_head
, tqlst
) {
707 if (opt
->bdev
== bdev
) {
708 firm_ctx
->desc
= opt
->desc
;
713 if (!firm_ctx
->desc
) {
714 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
715 "No descriptor were found.");
716 apply_firmware_cleanup(firm_ctx
);
720 firm_ctx
->ch
= spdk_bdev_get_io_channel(firm_ctx
->desc
);
722 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
723 "No channels were found.");
724 apply_firmware_cleanup(firm_ctx
);
728 fd
= open(firm_ctx
->req
->filename
, O_RDONLY
);
730 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, "open file failed.");
731 apply_firmware_cleanup(firm_ctx
);
735 rc
= fstat(fd
, &fw_stat
);
738 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, "fstat failed.");
739 apply_firmware_cleanup(firm_ctx
);
743 firm_ctx
->size
= fw_stat
.st_size
;
744 if (fw_stat
.st_size
% 4) {
746 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
747 "Firmware image size is not multiple of 4.");
748 apply_firmware_cleanup(firm_ctx
);
752 firm_ctx
->fw_image
= spdk_dma_zmalloc(firm_ctx
->size
, 4096, NULL
);
753 if (!firm_ctx
->fw_image
) {
755 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
756 "Memory allocation error.");
757 apply_firmware_cleanup(firm_ctx
);
760 firm_ctx
->p
= firm_ctx
->fw_image
;
762 if (read(fd
, firm_ctx
->p
, firm_ctx
->size
) != ((ssize_t
)(firm_ctx
->size
))) {
764 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
765 "Read firmware image failed!");
766 apply_firmware_cleanup(firm_ctx
);
771 firm_ctx
->offset
= 0;
772 firm_ctx
->size_remaining
= firm_ctx
->size
;
773 firm_ctx
->transfer
= spdk_min(firm_ctx
->size_remaining
, 4096);
775 cmd
= malloc(sizeof(struct spdk_nvme_cmd
));
777 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
778 "Memory allocation error.");
779 apply_firmware_cleanup(firm_ctx
);
782 memset(cmd
, 0, sizeof(struct spdk_nvme_cmd
));
783 cmd
->opc
= SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD
;
785 cmd
->cdw10
= (firm_ctx
->transfer
>> 2) - 1;
786 cmd
->cdw11
= firm_ctx
->offset
>> 2;
788 rc
= spdk_bdev_nvme_admin_passthru(firm_ctx
->desc
, firm_ctx
->ch
, cmd
, firm_ctx
->p
,
789 firm_ctx
->transfer
, apply_firmware_complete
, firm_ctx
);
792 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
793 "Read firmware image failed!");
794 apply_firmware_cleanup(firm_ctx
);
798 SPDK_RPC_REGISTER("apply_nvme_firmware", spdk_rpc_apply_nvme_firmware
, SPDK_RPC_RUNTIME
)