]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/bdev/nvme/bdev_nvme_rpc.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / lib / bdev / nvme / bdev_nvme_rpc.c
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 };
79
80 static void
81 spdk_rpc_set_bdev_nvme_options(struct spdk_jsonrpc_request *request,
82 const struct spdk_json_val *params)
83 {
84 struct spdk_bdev_nvme_opts opts;
85 struct spdk_json_write_ctx *w;
86 int rc;
87
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),
91 &opts)) {
92 SPDK_ERRLOG("spdk_json_decode_object failed\n");
93 rc = -EINVAL;
94 goto invalid;
95 }
96
97 rc = spdk_bdev_nvme_set_opts(&opts);
98 if (rc) {
99 goto invalid;
100 }
101
102 w = spdk_jsonrpc_begin_result(request);
103 if (w != NULL) {
104 spdk_json_write_bool(w, true);
105 spdk_jsonrpc_end_result(request, w);
106 }
107
108 return;
109 invalid:
110 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
111 }
112 SPDK_RPC_REGISTER("set_bdev_nvme_options", spdk_rpc_set_bdev_nvme_options, SPDK_RPC_STARTUP)
113
114 struct rpc_bdev_nvme_hotplug {
115 bool enabled;
116 uint64_t period_us;
117 };
118
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},
122 };
123
124 static void
125 rpc_set_bdev_nvme_hotplug_done(void *ctx)
126 {
127 struct spdk_jsonrpc_request *request = ctx;
128 struct spdk_json_write_ctx *w = spdk_jsonrpc_begin_result(request);
129
130 if (w != NULL) {
131 spdk_json_write_bool(w, true);
132 spdk_jsonrpc_end_result(request, w);
133 }
134 }
135
136 static void
137 spdk_rpc_set_bdev_nvme_hotplug(struct spdk_jsonrpc_request *request,
138 const struct spdk_json_val *params)
139 {
140 struct rpc_bdev_nvme_hotplug req = {false, 0};
141 int rc;
142
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");
146 rc = -EINVAL;
147 goto invalid;
148 }
149
150 rc = spdk_bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_set_bdev_nvme_hotplug_done,
151 request);
152 if (rc) {
153 goto invalid;
154 }
155
156 return;
157 invalid:
158 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
159 }
160 SPDK_RPC_REGISTER("set_bdev_nvme_hotplug", spdk_rpc_set_bdev_nvme_hotplug, SPDK_RPC_RUNTIME)
161
162 struct rpc_construct_nvme {
163 char *name;
164 char *trtype;
165 char *adrfam;
166 char *traddr;
167 char *trsvcid;
168 char *subnqn;
169 char *hostnqn;
170 char *hostaddr;
171 char *hostsvcid;
172 bool prchk_reftag;
173 bool prchk_guard;
174 };
175
176 static void
177 free_rpc_construct_nvme(struct rpc_construct_nvme *req)
178 {
179 free(req->name);
180 free(req->trtype);
181 free(req->adrfam);
182 free(req->traddr);
183 free(req->trsvcid);
184 free(req->subnqn);
185 free(req->hostnqn);
186 free(req->hostaddr);
187 free(req->hostsvcid);
188 }
189
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},
194
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},
201
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}
204 };
205
206 #define NVME_MAX_BDEVS_PER_RPC 128
207
208 struct rpc_create_nvme_bdev_ctx {
209 struct rpc_construct_nvme req;
210 size_t count;
211 const char *names[NVME_MAX_BDEVS_PER_RPC];
212 struct spdk_jsonrpc_request *request;
213 };
214
215 static void
216 spdk_rpc_construct_nvme_bdev_done(void *cb_ctx, int rc)
217 {
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;
221 size_t i;
222
223 w = spdk_jsonrpc_begin_result(request);
224 if (w == NULL) {
225 goto exit;
226 }
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 spdk_json_write_array_begin(w);
234 for (i = 0; i < ctx->count; i++) {
235 spdk_json_write_string(w, ctx->names[i]);
236 }
237 spdk_json_write_array_end(w);
238 spdk_jsonrpc_end_result(request, w);
239
240 exit:
241 free_rpc_construct_nvme(&ctx->req);
242 free(ctx);
243 }
244
245 static void
246 spdk_rpc_construct_nvme_bdev(struct spdk_jsonrpc_request *request,
247 const struct spdk_json_val *params)
248 {
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;
253 int rc;
254
255 ctx = calloc(1, sizeof(*ctx));
256 if (!ctx) {
257 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(ENOMEM));
258 return;
259 }
260
261 if (spdk_json_decode_object(params, rpc_construct_nvme_decoders,
262 SPDK_COUNTOF(rpc_construct_nvme_decoders),
263 &ctx->req)) {
264 SPDK_ERRLOG("spdk_json_decode_object failed\n");
265 goto invalid;
266 }
267
268 /* Parse trtype */
269 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype);
270 if (rc < 0) {
271 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype);
272 goto invalid;
273 }
274
275 /* Parse traddr */
276 snprintf(trid.traddr, sizeof(trid.traddr), "%s", ctx->req.traddr);
277
278 /* Parse adrfam */
279 if (ctx->req.adrfam) {
280 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam);
281 if (rc < 0) {
282 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam);
283 goto invalid;
284 }
285 }
286
287 /* Parse trsvcid */
288 if (ctx->req.trsvcid) {
289 snprintf(trid.trsvcid, sizeof(trid.trsvcid), "%s", ctx->req.trsvcid);
290 }
291
292 /* Parse subnqn */
293 if (ctx->req.subnqn) {
294 snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx->req.subnqn);
295 }
296
297 if (ctx->req.hostaddr) {
298 snprintf(hostid.hostaddr, sizeof(hostid.hostaddr), "%s", ctx->req.hostaddr);
299 }
300
301 if (ctx->req.hostsvcid) {
302 snprintf(hostid.hostsvcid, sizeof(hostid.hostsvcid), "%s", ctx->req.hostsvcid);
303 }
304
305 if (ctx->req.prchk_reftag) {
306 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
307 }
308
309 if (ctx->req.prchk_guard) {
310 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
311 }
312
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)) {
317 goto invalid;
318 }
319
320 return;
321
322 invalid:
323 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
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 goto invalid;
374 }
375
376 if (req.name) {
377 ctrlr = nvme_bdev_ctrlr_get_by_name(req.name);
378 if (ctrlr == NULL) {
379 SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name);
380 goto invalid;
381 }
382 }
383
384 free_rpc_get_nvme_controllers(&req);
385 w = spdk_jsonrpc_begin_result(request);
386 if (w == NULL) {
387 return;
388 }
389
390 spdk_json_write_array_begin(w);
391
392 if (ctrlr != NULL) {
393 spdk_rpc_dump_nvme_controller_info(w, ctrlr);
394 } else {
395 for (ctrlr = nvme_bdev_first_ctrlr(); ctrlr; ctrlr = nvme_bdev_next_ctrlr(ctrlr)) {
396 spdk_rpc_dump_nvme_controller_info(w, ctrlr);
397 }
398 }
399
400 spdk_json_write_array_end(w);
401
402 spdk_jsonrpc_end_result(request, w);
403
404 return;
405
406 invalid:
407 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
408
409 free_rpc_get_nvme_controllers(&req);
410 }
411 SPDK_RPC_REGISTER("get_nvme_controllers", spdk_rpc_get_nvme_controllers, SPDK_RPC_RUNTIME)
412
413 struct rpc_delete_nvme {
414 char *name;
415 };
416
417 static void
418 free_rpc_delete_nvme(struct rpc_delete_nvme *req)
419 {
420 free(req->name);
421 }
422
423 static const struct spdk_json_object_decoder rpc_delete_nvme_decoders[] = {
424 {"name", offsetof(struct rpc_delete_nvme, name), spdk_json_decode_string},
425 };
426
427 static void
428 spdk_rpc_delete_nvme_controller(struct spdk_jsonrpc_request *request,
429 const struct spdk_json_val *params)
430 {
431 struct rpc_delete_nvme req = {NULL};
432 struct spdk_json_write_ctx *w;
433 int rc = 0;
434
435 if (spdk_json_decode_object(params, rpc_delete_nvme_decoders,
436 SPDK_COUNTOF(rpc_delete_nvme_decoders),
437 &req)) {
438 rc = -EINVAL;
439 goto invalid;
440 }
441
442 rc = spdk_bdev_nvme_delete(req.name);
443 if (rc != 0) {
444 goto invalid;
445 }
446
447 free_rpc_delete_nvme(&req);
448
449 w = spdk_jsonrpc_begin_result(request);
450 if (w == NULL) {
451 return;
452 }
453
454 spdk_json_write_bool(w, true);
455 spdk_jsonrpc_end_result(request, w);
456 return;
457
458 invalid:
459 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
460 spdk_strerror(-rc));
461 free_rpc_delete_nvme(&req);
462 }
463 SPDK_RPC_REGISTER("delete_nvme_controller", spdk_rpc_delete_nvme_controller, SPDK_RPC_RUNTIME)
464
465 struct rpc_apply_firmware {
466 char *filename;
467 char *bdev_name;
468 };
469
470 static void
471 free_rpc_apply_firmware(struct rpc_apply_firmware *req)
472 {
473 free(req->filename);
474 free(req->bdev_name);
475 }
476
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},
480 };
481
482 struct firmware_update_info {
483 void *fw_image;
484 void *p;
485 unsigned int size;
486 unsigned int size_remaining;
487 unsigned int offset;
488 unsigned int transfer;
489
490 void *desc;
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;
496 };
497
498 static void
499 apply_firmware_cleanup(void *cb_arg)
500 {
501 struct open_descriptors *opt, *tmp;
502 struct firmware_update_info *firm_ctx = cb_arg;
503
504 if (!firm_ctx) {
505 return;
506 }
507
508 if (firm_ctx->fw_image) {
509 spdk_dma_free(firm_ctx->fw_image);
510 }
511
512 if (firm_ctx->req) {
513 free_rpc_apply_firmware(firm_ctx->req);
514 free(firm_ctx->req);
515 }
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);
519 free(opt);
520 }
521 free(firm_ctx);
522 }
523
524 static void
525 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
526 {
527 int rc;
528 struct spdk_json_write_ctx *w;
529 struct firmware_update_info *firm_ctx = cb_arg;
530
531 spdk_bdev_free_io(bdev_io);
532
533 if (!success) {
534 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
535 "firmware commit failed.");
536 apply_firmware_cleanup(firm_ctx);
537 return;
538 }
539
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);
544 return;
545 }
546
547 if (!(w = spdk_jsonrpc_begin_result(firm_ctx->request))) {
548 apply_firmware_cleanup(firm_ctx);
549 return;
550 }
551
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);
555 }
556
557 static void
558 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
559 {
560 struct spdk_nvme_cmd cmd = {};
561 struct spdk_nvme_fw_commit fw_commit;
562 int slot = 0;
563 int rc;
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;
566
567 if (!success) {
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);
572 return;
573 }
574
575 firm_ctx->p += firm_ctx->transfer;
576 firm_ctx->offset += firm_ctx->transfer;
577 firm_ctx->size_remaining -= firm_ctx->transfer;
578
579 switch (firm_ctx->size_remaining) {
580 case 0:
581 /* firmware download completed. Commit firmware */
582 memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit));
583 fw_commit.fs = slot;
584 fw_commit.ca = commit_action;
585
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);
590 if (rc) {
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);
595 return;
596 }
597 break;
598 default:
599 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
600 cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
601
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);
606 if (rc) {
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);
611 return;
612 }
613 break;
614 }
615 }
616
617 static void
618 spdk_rpc_apply_nvme_firmware(struct spdk_jsonrpc_request *request,
619 const struct spdk_json_val *params)
620 {
621 int rc;
622 int fd = -1;
623 struct stat fw_stat;
624 struct spdk_nvme_ctrlr *ctrlr;
625 char msg[1024];
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;
632
633 firm_ctx = malloc(sizeof(struct firmware_update_info));
634 if (!firm_ctx) {
635 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
636 "Memory allocation error.");
637 return;
638 }
639 firm_ctx->fw_image = NULL;
640 TAILQ_INIT(&firm_ctx->desc_head);
641 firm_ctx->request = request;
642
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.");
647 free(firm_ctx);
648 return;
649 }
650
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.");
655 free(firm_ctx->req);
656 free(firm_ctx);
657 return;
658 }
659
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);
664 return;
665 }
666
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);
672 return;
673 }
674 firm_ctx->ctrlr = ctrlr;
675
676 for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) {
677
678 if (spdk_bdev_nvme_get_ctrlr(bdev2) != ctrlr) {
679 continue;
680 }
681
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);
686 return;
687 }
688
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);
692 free(opt);
693 apply_firmware_cleanup(firm_ctx);
694 return;
695 }
696
697 opt->desc = desc;
698 opt->bdev = bdev;
699 TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst);
700 }
701
702 /*
703 * find a descriptor associated with our bdev
704 */
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;
709 break;
710 }
711 }
712
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);
717 return;
718 }
719
720 firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc);
721 if (!firm_ctx->ch) {
722 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
723 "No channels were found.");
724 apply_firmware_cleanup(firm_ctx);
725 return;
726 }
727
728 fd = open(firm_ctx->req->filename, O_RDONLY);
729 if (fd < 0) {
730 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "open file failed.");
731 apply_firmware_cleanup(firm_ctx);
732 return;
733 }
734
735 rc = fstat(fd, &fw_stat);
736 if (rc < 0) {
737 close(fd);
738 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "fstat failed.");
739 apply_firmware_cleanup(firm_ctx);
740 return;
741 }
742
743 firm_ctx->size = fw_stat.st_size;
744 if (fw_stat.st_size % 4) {
745 close(fd);
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);
749 return;
750 }
751
752 firm_ctx->fw_image = spdk_dma_zmalloc(firm_ctx->size, 4096, NULL);
753 if (!firm_ctx->fw_image) {
754 close(fd);
755 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
756 "Memory allocation error.");
757 apply_firmware_cleanup(firm_ctx);
758 return;
759 }
760 firm_ctx->p = firm_ctx->fw_image;
761
762 if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) {
763 close(fd);
764 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
765 "Read firmware image failed!");
766 apply_firmware_cleanup(firm_ctx);
767 return;
768 }
769 close(fd);
770
771 firm_ctx->offset = 0;
772 firm_ctx->size_remaining = firm_ctx->size;
773 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
774
775 cmd = malloc(sizeof(struct spdk_nvme_cmd));
776 if (!cmd) {
777 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
778 "Memory allocation error.");
779 apply_firmware_cleanup(firm_ctx);
780 return;
781 }
782 memset(cmd, 0, sizeof(struct spdk_nvme_cmd));
783 cmd->opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
784
785 cmd->cdw10 = (firm_ctx->transfer >> 2) - 1;
786 cmd->cdw11 = firm_ctx->offset >> 2;
787
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);
790 if (rc) {
791 free(cmd);
792 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
793 "Read firmware image failed!");
794 apply_firmware_cleanup(firm_ctx);
795 return;
796 }
797 }
798 SPDK_RPC_REGISTER("apply_nvme_firmware", spdk_rpc_apply_nvme_firmware, SPDK_RPC_RUNTIME)