NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
nvmf_doca_io.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include "nvmf_doca_io.h"
27 #include "nvme_pci_type_config.h"
28 #include <doca_transport_common.h>
29 
30 #include <spdk/util.h>
31 
32 #include <doca_log.h>
33 
34 DOCA_LOG_REGISTER(NVME_PCI_COMMON);
35 
38 
39 #define CACHELINE_SIZE_BYTES 64
40 
41 /*
42  * Method invoked once bind DB done message is received from DPA
43  *
44  * @msg [in]: The bind done message that was received from DPA
45  */
46 static void nvmf_doca_io_handle_bind_sq_db_done_msg(const struct comch_msg *msg);
47 
48 /*
49  * Method invoked once unbind DB done message is received from DPA
50  *
51  * @msg [in]: The unbind done message that was received from DPA
52  */
53 static void nvmf_doca_io_handle_unbind_sq_db_done_msg(const struct comch_msg *msg);
54 
55 /*
56  * Method invoked once Host DB message is received from DPA
57  *
58  * @io [in]: The IO used to receive the message
59  * @msg [in]: The Host DB message that was received from DPA
60  */
61 static void nvmf_doca_io_handle_host_db_msg(struct nvmf_doca_io *io, const struct comch_msg *msg);
62 
63 /*
64  * Continue the async flow of stopping the communication channel
65  *
66  * @comch [in]: The NVMf DOCA DPA communication channel to stop
67  */
69 
70 /*
71  * Continue the async flow of stopping the IO
72  *
73  * @io [in]: The NVMf DOCA IO to stop
74  */
75 static void nvmf_doca_io_stop_continue(struct nvmf_doca_io *io);
76 
77 /*
78  * Continue the async flow of stopping the CQ
79  *
80  * @cq [in]: The NVMf DOCA CQ to stop
81  */
82 static void nvmf_doca_cq_stop_continue(struct nvmf_doca_cq *cq);
83 
84 /*
85  * Continue the async flow of stopping the SQ
86  *
87  * @sq [in]: The NVMf DOCA SQ to stop
88  */
89 static void nvmf_doca_sq_stop_continue(struct nvmf_doca_sq *sq);
90 
91 /*
92  * Method invoked once a message is received from DPA
93  *
94  * @io [in]: The IO used to receive the message
95  * @msg [in]: The message that was received from DPA
96  */
97 static void nvmf_doca_io_handle_dpa_msg(struct nvmf_doca_io *io, const struct comch_msg *msg)
98 {
99  switch (msg->type) {
102  break;
105  break;
108  break;
109  default:
110  DOCA_LOG_ERR("Failed to handle DPA message: Received unknown message type %d", msg->type);
111  break;
112  }
113 }
114 
115 /*
116  * Callback invoked once a message is received from DPA successfully
117  *
118  * @recv_task [in]: The receive task
119  * @task_user_data [in]: User data that was previously provided with the task
120  * @ctx_user_data [in]: User data that was previously set for the consumer context
121  */
122 static void nvmf_doca_dpa_msgq_recv_cb(struct doca_comch_consumer_task_post_recv *recv_task,
123  union doca_data task_user_data,
124  union doca_data ctx_user_data)
125 {
126  (void)task_user_data;
127 
129 
130  struct nvmf_doca_io *io = ctx_user_data.ptr;
131  struct comch_msg msg = *(struct comch_msg *)doca_comch_consumer_task_post_recv_get_imm_data(recv_task);
132  struct doca_task *task = doca_comch_consumer_task_post_recv_as_task(recv_task);
133 
134  result = doca_task_submit(task);
135  if (result != DOCA_SUCCESS) {
136  DOCA_LOG_ERR("DPA MsgQ receive callback failed: Failed to resubmit receive task - %s",
138  doca_task_free(task);
139  }
140 
141  nvmf_doca_io_handle_dpa_msg(io, &msg);
142 }
143 
144 /*
145  * Callback invoked once consumer encounters a receive error
146  *
147  * @recv_task [in]: The receive task
148  * @task_user_data [in]: User data that was previously provided with the task
149  * @ctx_user_data [in]: User data that was previously set for the consumer context
150  */
151 static void nvmf_doca_dpa_msgq_recv_error_cb(struct doca_comch_consumer_task_post_recv *recv_task,
152  union doca_data task_user_data,
153  union doca_data ctx_user_data)
154 {
155  (void)task_user_data;
156  (void)ctx_user_data;
157 
158  struct doca_task *task = doca_comch_consumer_task_post_recv_as_task(recv_task);
159 
160  doca_task_free(task);
161 }
162 
163 /*
164  * Callback invoked once a message is sent to DPA successfully
165  *
166  * @send_task [in]: The send task
167  * @task_user_data [in]: User data that was previously provided with the task
168  * @ctx_user_data [in]: User data that was previously set for the producer context
169  */
170 static void nvmf_doca_dpa_msgq_send_cb(struct doca_comch_producer_task_send *send_task,
171  union doca_data task_user_data,
172  union doca_data ctx_user_data)
173 {
174  (void)task_user_data;
175  (void)ctx_user_data;
176 
177  struct doca_task *task = doca_comch_producer_task_send_as_task(send_task);
178 
179  doca_task_free(task);
180 }
181 
182 /*
183  * Callback invoked once producer encounters a send error
184  *
185  * @send_task [in]: The send task
186  * @task_user_data [in]: User data that was previously provided with the task
187  * @ctx_user_data [in]: User data that was previously set for the producer context
188  */
189 static void nvmf_doca_dpa_msgq_send_error_cb(struct doca_comch_producer_task_send *send_task,
190  union doca_data task_user_data,
191  union doca_data ctx_user_data)
192 {
193  (void)task_user_data;
194  (void)ctx_user_data;
195 
196  struct doca_task *task = doca_comch_producer_task_send_as_task(send_task);
197 
198  doca_task_free(task);
199 }
200 
201 /*
202  * Callback invoked once consumer/producer state changes
203  *
204  * @user_data [in]: The user data associated with the context
205  * @ctx [in]: The consumer/producer context
206  * @prev_state [in]: The previous state
207  * @next_state [in]: The new state
208  */
210  struct doca_ctx *ctx,
211  enum doca_ctx_states prev_state,
212  enum doca_ctx_states next_state)
213 {
214  (void)ctx;
215  (void)prev_state;
216 
217  struct nvmf_doca_io *io = user_data.ptr;
218 
219  switch (next_state) {
220  case DOCA_CTX_STATE_IDLE:
222  break;
226  default:
227  break;
228  }
229 }
230 
232  struct doca_dev *dev;
233  struct doca_dpa *dpa;
234  bool is_send;
235  uint32_t max_num_msg;
236  struct doca_comch_consumer_completion *consumer_comp;
238  struct doca_dpa_completion *producer_comp;
240  struct doca_pe *pe;
244 };
245 
246 /*
247  * Create NVMf DOCA DPA MsgQ for single direction communication with DPA
248  *
249  * @attr [in]: The MsgQ attributes
250  * @msgq [out]: The newly created MsgQ
251  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
252  */
254  struct nvmf_doca_dpa_msgq *msgq)
255 {
256  struct doca_ctx *consumer_ctx;
257  struct doca_ctx *producer_ctx;
259 
260  memset(msgq, 0, sizeof(*msgq));
261 
262  msgq->is_send = attr->is_send;
263 
264  result = doca_comch_msgq_create(attr->dev, &msgq->msgq);
265  if (result != DOCA_SUCCESS) {
266  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to create MsgQ - %s",
268  return result;
269  }
270  result = doca_comch_msgq_set_max_num_consumers(msgq->msgq, /*max_num_consumers=*/1);
271  if (result != DOCA_SUCCESS) {
272  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to set max number of consumers - %s",
274  return result;
275  }
276  result = doca_comch_msgq_set_max_num_producers(msgq->msgq, /*max_num_producers=*/1);
277  if (result != DOCA_SUCCESS) {
278  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to set max number of producers - %s",
280  return result;
281  }
282  if (attr->is_send) {
284  if (result != DOCA_SUCCESS) {
285  DOCA_LOG_ERR(
286  "Failed to create NVMf DOCA DPA MsgQ: Failed to failed to set consumer to DPA - %s",
288  return result;
289  }
290  } else {
292  if (result != DOCA_SUCCESS) {
293  DOCA_LOG_ERR(
294  "Failed to create NVMf DOCA DPA MsgQ: Failed to failed to set producer to DPA - %s",
296  return result;
297  }
298  }
300  if (result != DOCA_SUCCESS) {
301  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to start MsgQ - %s",
303  return result;
304  }
305 
307  if (result != DOCA_SUCCESS) {
308  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to create consumer - %s",
310  return result;
311  }
312  consumer_ctx = doca_comch_consumer_as_ctx(msgq->consumer);
314  if (result != DOCA_SUCCESS) {
315  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to set consumer immediate data length - %s",
317  return result;
318  }
319  if (attr->is_send) {
320  /* Consumer on DPA */
321  result = doca_ctx_set_datapath_on_dpa(consumer_ctx, attr->dpa);
322  if (result != DOCA_SUCCESS) {
323  DOCA_LOG_ERR(
324  "Failed to create NVMf DOCA DPA MsgQ: Failed to set consumer data path to DPA - %s",
326  return result;
327  }
328  result = doca_comch_consumer_set_completion(msgq->consumer, attr->consumer_comp, /*user_data=*/0);
329  if (result != DOCA_SUCCESS) {
330  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to set consumer completion - %s",
332  return result;
333  }
335  if (result != DOCA_SUCCESS) {
336  DOCA_LOG_ERR(
337  "Failed to create NVMf DOCA DPA MsgQ: Failed to set consumer max number of receive messages - %s",
339  return result;
340  }
341  } else {
342  /* Consumer on DPU */
343  union doca_data ctx_user_data;
344  ctx_user_data.ptr = attr->ctx_user_data;
345  result = doca_ctx_set_user_data(consumer_ctx, ctx_user_data);
346  if (result != DOCA_SUCCESS) {
347  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to set consumer user data - %s",
349  return result;
350  }
352  if (result != DOCA_SUCCESS) {
353  DOCA_LOG_ERR(
354  "Failed to create NVMf DOCA DPA MsgQ: Failed to set consumer context state changed callback - %s",
356  return result;
357  }
358  result = doca_pe_connect_ctx(attr->pe, consumer_ctx);
359  if (result != DOCA_SUCCESS) {
360  DOCA_LOG_ERR(
361  "Failed to create NVMf DOCA DPA MsgQ: Failed to connect consumer to progress engine - %s",
363  return result;
364  }
368  attr->max_num_msg);
369  if (result != DOCA_SUCCESS) {
370  DOCA_LOG_ERR(
371  "Failed to create NVMf DOCA DPA MsgQ: Failed to set consumer task configurations - %s",
373  return result;
374  }
375  }
376  result = doca_ctx_start(consumer_ctx);
377  if (result != DOCA_SUCCESS) {
378  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to start consumer - %s",
380  return result;
381  }
382 
384  if (result != DOCA_SUCCESS) {
385  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to create producer - %s",
387  return result;
388  }
389  producer_ctx = doca_comch_producer_as_ctx(msgq->producer);
390  if (attr->is_send) {
391  /* Producer on DPU */
392  union doca_data ctx_user_data;
393  ctx_user_data.ptr = attr->ctx_user_data;
394  result = doca_ctx_set_user_data(producer_ctx, ctx_user_data);
395  if (result != DOCA_SUCCESS) {
396  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to set producer user data - %s",
398  return result;
399  }
401  if (result != DOCA_SUCCESS) {
402  DOCA_LOG_ERR(
403  "Failed to create NVMf DOCA DPA MsgQ: Failed to set producer context state changed callback - %s",
405  return result;
406  }
407  result = doca_pe_connect_ctx(attr->pe, producer_ctx);
408  if (result != DOCA_SUCCESS) {
409  DOCA_LOG_ERR(
410  "Failed to create NVMf DOCA DPA MsgQ: Failed to connect producer to progress engine - %s",
412  return result;
413  }
417  attr->max_num_msg);
418  if (result != DOCA_SUCCESS) {
419  DOCA_LOG_ERR(
420  "Failed to create NVMf DOCA DPA MsgQ: Failed to set producer task configurations - %s",
422  return result;
423  }
424  } else {
425  /* Producer on DPA */
426  result = doca_ctx_set_datapath_on_dpa(producer_ctx, attr->dpa);
427  if (result != DOCA_SUCCESS) {
428  DOCA_LOG_ERR(
429  "Failed to create NVMf DOCA DPA MsgQ: Failed to set producer data path to DPA - %s",
431  return result;
432  }
434  if (result != DOCA_SUCCESS) {
435  DOCA_LOG_ERR(
436  "Failed to create NVMf DOCA DPA MsgQ: Failed to set producer max number of send messages - %s",
438  return result;
439  }
441  if (result != DOCA_SUCCESS) {
442  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to set producer completion - %s",
444  return result;
445  }
446  }
447  result = doca_ctx_start(producer_ctx);
448  if (result != DOCA_SUCCESS) {
449  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA MsgQ: Failed to start producer - %s",
451  return result;
452  }
453 
454  return DOCA_SUCCESS;
455 }
456 
457 /*
458  * Stop the NVMf DOCA DPA MsgQ
459  *
460  * This operation is async, once operation completes then nvmf_doca_dpa_comch_msgq_ctx_state_changed_cb() will be
461  * invoked
462  *
463  * @msgq [in]: The NVMf DOCA DPA MsgQ to stop
464  */
466 {
467  struct doca_ctx *ctx;
469 
470  if (msgq->is_send) {
472  } else {
474  }
475 
478  DOCA_LOG_ERR("Failed to stop NVMf DOCA MsgQ: Failed to stop context - %s", doca_error_get_name(result));
479  }
480 }
481 
482 /*
483  * Destroy NVMf DOCA DPA MsgQ
484  *
485  * @msgq [in]: The MsgQ to destroy
486  */
488 {
490 
491  if (msgq->producer != NULL) {
494  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA MsgQ: Failed to stop producer - %s",
496  }
498  if (result != DOCA_SUCCESS) {
499  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA MsgQ: Failed to destroy producer - %s",
501  }
502  msgq->producer = NULL;
503  }
504 
505  if (msgq->consumer != NULL) {
508  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA MsgQ: Failed to stop consumer - %s",
510  }
512  if (result != DOCA_SUCCESS) {
513  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA MsgQ: Failed to destroy consumer - %s",
515  }
516  msgq->consumer = NULL;
517  }
518 
519  if (msgq->msgq != NULL) {
522  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA MsgQ: Failed to stop MsgQ - %s",
524  }
526  if (result != DOCA_SUCCESS) {
527  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA MsgQ: Failed to destroy MsgQ - %s",
529  }
530  msgq->msgq = NULL;
531  }
532 }
533 
534 /*
535  * Send message to DPA using NVMf DOCA DPA MsgQ
536  *
537  * @msgq [in]: The MsgQ to be used for the send operation
538  * @msg [in]: The message to send
539  * @msg_size [in]: The message size
540  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
541  */
542 static doca_error_t nvmf_doca_dpa_msgq_send(struct nvmf_doca_dpa_msgq *msgq, void *msg, uint32_t msg_size)
543 {
545 
546  struct doca_comch_producer_task_send *send_task;
548  NULL,
549  msg,
550  msg_size,
551  /*consumer_id=*/1,
552  &send_task);
553  if (result != DOCA_SUCCESS) {
554  DOCA_LOG_ERR("Failed to send msg using NVMf DOCA DPA MsgQ: Failed to allocate send task - %s",
556  return result;
557  }
558 
559  struct doca_task *task = doca_comch_producer_task_send_as_task(send_task);
560  result = doca_task_submit(task);
561  if (result != DOCA_SUCCESS) {
562  DOCA_LOG_ERR("Failed to send msg using NVMf DOCA DPA MsgQ: Failed to submit send task - %s",
564  doca_task_free(task);
565  return result;
566  }
567 
568  return DOCA_SUCCESS;
569 }
570 
572  struct doca_dev *dev;
573  struct doca_dpa *dpa;
574  struct doca_dpa_thread *dpa_thread;
575  uint32_t max_num_msg;
576  struct doca_pe *pe;
578 };
579 
580 /*
581  * Create NVMf DOCA DPA communication channel for full-duplex communication with DPA
582  *
583  * @attr [in]: The communication channel attributes
584  * @comch [out]: The newly created communication channel
585  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
586  */
588  struct nvmf_doca_dpa_comch *comch)
589 {
591 
592  memset(comch, 0, sizeof(*comch));
593 
595  if (result != DOCA_SUCCESS) {
596  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA comch: Failed to create consumer completion - %s",
598  return result;
599  }
601  if (result != DOCA_SUCCESS) {
602  DOCA_LOG_ERR(
603  "Failed to create NVMf DOCA DPA comch: Failed to set consumer completion max number of receive messages - %s",
605  return result;
606  }
608  if (result != DOCA_SUCCESS) {
609  DOCA_LOG_ERR(
610  "Failed to create NVMf DOCA DPA comch: Failed to set consumer completion immediate data length - %s",
612  return result;
613  }
615  if (result != DOCA_SUCCESS) {
616  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA comch: Failed to set consumer completion DPA thread - %s",
618  return result;
619  }
621  if (result != DOCA_SUCCESS) {
622  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA comch: Failed to start consumer completion - %s",
624  return result;
625  }
626 
628  if (result != DOCA_SUCCESS) {
629  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA comch: Failed to create producer completion - %s",
631  return result;
632  }
634  if (result != DOCA_SUCCESS) {
635  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA comch: Failed to set producer completion DPA thread - %s",
637  return result;
638  }
640  if (result != DOCA_SUCCESS) {
641  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA comch: Failed to start producer completion - %s",
643  return result;
644  }
645 
646  struct nvmf_doca_dpa_msgq_create_attr msgq_attr = {
647  .dev = attr->dev,
648  .dpa = attr->dpa,
649  .max_num_msg = attr->max_num_msg,
650  .consumer_comp = comch->consumer_comp,
651  .producer_comp = comch->producer_comp,
652  .pe = attr->pe,
653  .ctx_state_changed_cb = nvmf_doca_dpa_comch_msgq_ctx_state_changed_cb,
654  .ctx_user_data = attr->ctx_user_data,
655  };
656  msgq_attr.is_send = true;
657  result = nvmf_doca_dpa_msgq_create(&msgq_attr, &comch->send);
658  if (result != DOCA_SUCCESS)
659  return result;
660 
661  msgq_attr.is_send = false;
662  result = nvmf_doca_dpa_msgq_create(&msgq_attr, &comch->recv);
663  if (result != DOCA_SUCCESS)
664  return result;
665 
666  for (uint32_t idx = 0; idx < attr->max_num_msg; idx++) {
667  struct doca_comch_consumer_task_post_recv *recv_task;
669  if (result != DOCA_SUCCESS) {
670  DOCA_LOG_ERR(
671  "Failed to create NVMf DOCA DPA comch: Failed to allocate receive message at idx %u - %s",
672  idx,
674  return result;
675  }
676  struct doca_task *task = doca_comch_consumer_task_post_recv_as_task(recv_task);
677  result = doca_task_submit(task);
678  if (result != DOCA_SUCCESS) {
679  DOCA_LOG_ERR(
680  "Failed to create NVMf DOCA DPA comch: Failed to submit receive message at idx %u - %s",
681  idx,
683  doca_task_free(task);
684  return result;
685  }
686  }
687 
688  return DOCA_SUCCESS;
689 }
690 
691 /*
692  * Check if a DOCA context state is idle
693  *
694  * @ctx [in]: The DOCA context to check
695  * @return: true in case context is idle and false otherwise
696  */
697 static bool is_ctx_idle(struct doca_ctx *ctx)
698 {
699  enum doca_ctx_states ctx_state;
701 
702  result = doca_ctx_get_state(ctx, &ctx_state);
703  if (result != DOCA_SUCCESS) {
704  DOCA_LOG_ERR("Failed to check if context is idle: Failed to get context state - %s",
706  return false;
707  }
708 
709  return ctx_state == DOCA_CTX_STATE_IDLE;
710 }
711 
712 /*
713  * Check if the NVMf DOCA DPA communication channel is stopped
714  *
715  * @comch [in]: The NVMf DOCA DPA communication channel to check
716  * @return: true in case context is idle and false otherwise
717  */
719 {
722 }
723 
724 /*
725  * Continue async flow of stopping the NVMf DOCA DPA communication channel
726  *
727  * @comch [in]: The NVMf DOCA DPA communication channel to stop
728  */
730 {
731  if (!nvmf_doca_dpa_comch_idle(comch)) {
732  return;
733  }
734 
735  struct nvmf_doca_io *io = SPDK_CONTAINEROF(comch, struct nvmf_doca_io, comch);
737 }
738 
739 /*
740  * Stop the NVMf DOCA DPA communication channel
741  *
742  * This operation is async, once operation completes then nvmf_doca_dpa_comch_stop_continue() will be invoked
743  *
744  * @comch [in]: The NVMf DOCA DPA communication channel to stop
745  */
747 {
750 }
751 
752 /*
753  * Destroy NVMf DOCA DPA communication channel
754  *
755  * @comch [in]: The communication channel to destroy
756  */
758 {
760 
763 
764  if (comch->producer_comp != NULL) {
766  if (result != DOCA_SUCCESS)
767  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA comch: Failed to stop producer completion - %s",
770  if (result != DOCA_SUCCESS)
771  DOCA_LOG_ERR(
772  "Failed to destroy NVMf DOCA DPA comch: Failed to destroy producer completion - %s",
775  }
776 
777  if (comch->consumer_comp != NULL) {
780  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA comch: Failed to stop consumer completion - %s",
783  if (result != DOCA_SUCCESS)
784  DOCA_LOG_ERR(
785  "Failed to destroy NVMf DOCA DPA comch: Failed to destroy consumer completion - %s",
788  }
789 }
790 
792  struct doca_pe *pe;
793  struct doca_dev *dev;
794  struct doca_mmap *remote_queue_mmap;
796  uint16_t queue_depth;
797  uint8_t element_size;
803 };
804 
805 /*
806  * Create NVMf DOCA queue for read/write data from Host SQ/CQ
807  *
808  * @attr [in]: The queue attributes
809  * @queue [out]: The newly created queue
810  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
811  */
813  struct nvmf_doca_queue *queue)
814 {
815  struct doca_ctx *dma_ctx;
817 
818  memset(queue, 0, sizeof(*queue));
819 
820  uint32_t num_elements = attr->queue_depth;
821 
822  result = doca_buf_inventory_create(num_elements * 2, &queue->inventory);
823  if (result != DOCA_SUCCESS) {
824  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to create inventory - %s",
826  return result;
827  }
829  if (result != DOCA_SUCCESS) {
830  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to start inventory - %s",
832  return result;
833  }
834 
835  result = doca_dma_create(attr->dev, &queue->dma);
836  if (result != DOCA_SUCCESS) {
837  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to create DMA context - %s",
839  return result;
840  }
841  result = doca_dma_task_memcpy_set_conf(queue->dma, attr->success_cb, attr->error_cb, num_elements);
842  if (result != DOCA_SUCCESS) {
843  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to set DMA context task consigurations - %s",
845  return result;
846  }
847  dma_ctx = doca_dma_as_ctx(queue->dma);
848  result = doca_pe_connect_ctx(attr->pe, dma_ctx);
849  if (result != DOCA_SUCCESS) {
850  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to connect DMA context to progress engine - %s",
852  return result;
853  }
854  union doca_data ctx_user_data;
855  ctx_user_data.ptr = attr->dma_user_data;
856  result = doca_ctx_set_user_data(dma_ctx, ctx_user_data);
857  if (result != DOCA_SUCCESS) {
858  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to set DMA context user data - %s",
860  return result;
861  }
863  if (result != DOCA_SUCCESS) {
864  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to set DMA context state changed callback - %s",
866  return result;
867  }
868  result = doca_ctx_start(dma_ctx);
869  if (result != DOCA_SUCCESS) {
870  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to start DMA context - %s",
872  return result;
873  }
874 
875  uint32_t queue_size = num_elements * attr->element_size;
876  queue->local_queue_address = calloc(1, queue_size);
877  if (queue->local_queue_address == NULL) {
878  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to allocate memory for local queue");
879  return DOCA_ERROR_NO_MEMORY;
880  }
881 
883  if (result != DOCA_SUCCESS) {
884  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to create local queue mmap - %s",
886  return result;
887  }
889  if (result != DOCA_SUCCESS) {
890  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to create local queue mmap - %s",
892  return result;
893  }
897  if (result != DOCA_SUCCESS) {
898  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to set local queue mmap permissions - %s",
900  return result;
901  }
902  result = doca_mmap_add_dev(queue->local_queue_mmap, attr->dev);
903  if (result != DOCA_SUCCESS) {
904  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to add device to local queue mmap - %s",
906  return result;
907  }
909  if (result != DOCA_SUCCESS) {
910  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to start local queue mmap - %s",
912  return result;
913  }
914 
915  queue->elements = calloc(num_elements, sizeof(*queue->elements));
916  if (queue->elements == NULL) {
917  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to allocate memory for queue element tasks");
918  return DOCA_ERROR_NO_MEMORY;
919  }
920 
921  for (uint32_t idx = 0; idx < num_elements; idx++) {
922  void *local_element_address = (uint8_t *)queue->local_queue_address + idx * attr->element_size;
923  struct doca_buf *local_element_buf;
925  queue->local_queue_mmap,
926  local_element_address,
927  attr->element_size,
928  &local_element_buf);
929  if (result != DOCA_SUCCESS) {
930  DOCA_LOG_ERR("Failed to create NVMf DOCA Queue: Failed to get local buffer from inventory - %s",
932  return result;
933  }
934 
935  void *remote_element_address = (uint8_t *)attr->remote_queue_address + idx * attr->element_size;
936  struct doca_buf *remote_element_buf;
938  attr->remote_queue_mmap,
939  remote_element_address,
940  attr->element_size,
941  &remote_element_buf);
942  if (result != DOCA_SUCCESS) {
943  DOCA_LOG_ERR(
944  "Failed to create NVMf DOCA Queue: Failed to get remote buffer from inventory - %s",
946  doca_buf_dec_refcount(local_element_buf, NULL);
947  return result;
948  }
949 
950  struct doca_buf *src_buf = attr->is_read_from_remote ? remote_element_buf : local_element_buf;
951  struct doca_buf *dst_buf = attr->is_read_from_remote ? local_element_buf : remote_element_buf;
952 
953  result = doca_buf_set_data_len(src_buf, attr->element_size);
954  if (result != DOCA_SUCCESS) {
955  DOCA_LOG_ERR(
956  "Failed to create NVMf DOCA Queue: Failed to set data length of source buffer for element at index %u - %s",
957  idx,
959  doca_buf_dec_refcount(local_element_buf, NULL);
960  doca_buf_dec_refcount(remote_element_buf, NULL);
961  return result;
962  }
963 
964  union doca_data task_data;
965  task_data.u64 = idx;
966  result =
967  doca_dma_task_memcpy_alloc_init(queue->dma, src_buf, dst_buf, task_data, &queue->elements[idx]);
968  if (result != DOCA_SUCCESS) {
969  DOCA_LOG_ERR(
970  "Failed to create NVMf DOCA Queue: Failed to allocate DMA task for element at index %u - %s",
971  idx,
973  doca_buf_dec_refcount(local_element_buf, NULL);
974  doca_buf_dec_refcount(remote_element_buf, NULL);
975  return result;
976  }
977  }
978  queue->num_elements = num_elements;
979 
980  return DOCA_SUCCESS;
981 }
982 
983 /*
984  * Free all elements of the NVMf DOCA queue
985  *
986  * As long as the DMA tasks are not free then the DMA context will not move to idle state
987  *
988  * @queue [in]: The NVMf DOCA queue
989  */
991 {
993 
994  if (queue->elements != NULL) {
995  for (uint32_t idx = 0; idx < queue->num_elements; idx++) {
996  struct doca_dma_task_memcpy *element = queue->elements[idx];
997  if (element == NULL)
998  continue;
999 
1000  struct doca_buf *src_buf = (struct doca_buf *)doca_dma_task_memcpy_get_src(element);
1001  struct doca_buf *dst_buf = doca_dma_task_memcpy_get_dst(element);
1002 
1004  result = doca_buf_dec_refcount(src_buf, NULL);
1005  if (result != DOCA_SUCCESS)
1006  DOCA_LOG_ERR(
1007  "Failed to destroy NVMf DOCA Queue: Failed to free source buffer at index %u - %s",
1008  idx,
1010  result = doca_buf_dec_refcount(dst_buf, NULL);
1011  if (result != DOCA_SUCCESS)
1012  DOCA_LOG_ERR(
1013  "Failed to destroy NVMf DOCA Queue: Failed to free destination buffer at index %u - %s",
1014  idx,
1016  }
1017  queue->num_elements = 0;
1018 
1019  free(queue->elements);
1020  queue->elements = NULL;
1021  }
1022 }
1023 
1024 /*
1025  * Check if a DOCA context state is running
1026  *
1027  * @ctx [in]: The DOCA context to check
1028  * @return: true in case context is running and false otherwise
1029  */
1030 static bool is_ctx_running(struct doca_ctx *ctx)
1031 {
1032  enum doca_ctx_states ctx_state;
1034 
1035  result = doca_ctx_get_state(ctx, &ctx_state);
1036  if (result != DOCA_SUCCESS) {
1037  DOCA_LOG_ERR("Failed to check if context is idle: Failed to get context state - %s",
1039  return false;
1040  }
1041 
1042  return ctx_state == DOCA_CTX_STATE_RUNNING;
1043 }
1044 
1045 /*
1046  * Stop the NVMf DOCA queue
1047  *
1048  * This operation is async, once operation completes then nvmf_doca_cq_queue_dma_state_changed_cb() or
1049  * nvmf_doca_sq_queue_dma_state_changed_cb() will be invoked. Depending on owner of the queue
1050  *
1051  * @queue [in]: The NVMf DOCA queue to stop
1052  */
1053 static void nvmf_doca_queue_stop(struct nvmf_doca_queue *queue)
1054 {
1056  size_t num_inflight;
1057 
1058  if (!is_ctx_running(doca_dma_as_ctx(queue->dma))) {
1059  return;
1060  }
1061 
1064  DOCA_LOG_ERR("Failed to stop NVMf DOCA Queue: Failed to stop DMA context - %s",
1066  }
1067 
1068  result = doca_ctx_get_num_inflight_tasks(doca_dma_as_ctx(queue->dma), &num_inflight);
1069  if (result != DOCA_SUCCESS) {
1070  DOCA_LOG_ERR("Failed to stop NVMf DOCA Queue: Failed to get number of inflight DMA tasks - %s",
1072  return;
1073  }
1074  if (num_inflight == 0) {
1076  }
1077 }
1078 
1079 /*
1080  * Destroy NVMf DOCA queue
1081  *
1082  * @queue [in]: The queue to destroy
1083  */
1084 static void nvmf_doca_queue_destroy(struct nvmf_doca_queue *queue)
1085 {
1087 
1089 
1090  if (queue->local_queue_mmap != NULL) {
1092  if (result != DOCA_SUCCESS)
1093  DOCA_LOG_ERR("Failed to destroy NVMf DOCA Queue: Failed to destroy local queue mmap %s",
1095  queue->local_queue_mmap = NULL;
1096  }
1097 
1098  if (queue->local_queue_address != NULL) {
1099  free(queue->local_queue_address);
1100  queue->local_queue_address = NULL;
1101  }
1102 
1103  if (queue->dma != NULL) {
1106  DOCA_LOG_ERR("Failed to destroy NVMf DOCA Queue: Failed to stop DMA context %s",
1108  result = doca_dma_destroy(queue->dma);
1109  if (result != DOCA_SUCCESS)
1110  DOCA_LOG_ERR("Failed to destroy NVMf DOCA Queue: Failed to destroy DMA context %s",
1112  queue->dma = NULL;
1113  }
1114 
1115  if (queue->inventory != NULL) {
1117  if (result != DOCA_SUCCESS)
1118  DOCA_LOG_ERR("Failed to destroy NVMf DOCA Queue: Failed to destroy inventory %s",
1120  queue->inventory = NULL;
1121  }
1122 }
1123 
1125  struct doca_pe *pe;
1126  struct doca_dev *dev;
1127  struct doca_devemu_pci_dev *nvme_dev;
1128  uint16_t cq_depth;
1129  struct doca_mmap *host_cq_mmap;
1131  struct doca_devemu_pci_db_completion *db_comp;
1132  uint32_t cq_id;
1133  struct nvmf_doca_io *io;
1134 };
1135 
1136 /*
1137  * Update the consumer index of the CQ
1138  *
1139  * @cq [in]: The CQ that is being updated
1140  * @new_ci [in]: The new CQ producer index as provided by the Host
1141  */
1142 static void nvmf_doca_cq_update_ci(struct nvmf_doca_cq *cq, uint32_t new_ci)
1143 {
1144  cq->ci = new_ci;
1145 }
1146 
1147 /*
1148  * Raise an MSI-X towards the Host
1149  *
1150  * @io [in]: The IO that posted the original CQE
1151  */
1152 static void nvmf_doca_io_raise_msix(struct nvmf_doca_io *io)
1153 {
1154  if (io->msix == NULL)
1155  return;
1156 
1157  struct comch_msg msg = {
1159  };
1160  nvmf_doca_dpa_msgq_send(&io->comch.send, &msg, sizeof(msg));
1161 }
1162 
1163 void nvmf_doca_io_post_cqe(struct nvmf_doca_io *io, const struct nvmf_doca_cqe *cqe, union doca_data user_data)
1164 {
1165  struct doca_buf *host_cqe_buf;
1166  const struct doca_buf *dpu_cqe_buf;
1167  struct nvmf_doca_cqe *dpu_cqe;
1168  struct nvmf_doca_cq *cq = &io->cq;
1169  uint32_t cqe_idx = cq->pi % (cq->queue.num_elements);
1170  struct doca_dma_task_memcpy *cqe_task = cq->queue.elements[cqe_idx];
1171 
1172  host_cqe_buf = doca_dma_task_memcpy_get_dst(cqe_task);
1173  doca_buf_reset_data_len(host_cqe_buf);
1174 
1175  dpu_cqe_buf = doca_dma_task_memcpy_get_src(cqe_task);
1176  doca_buf_get_head(dpu_cqe_buf, (void **)&dpu_cqe);
1177  *dpu_cqe = *cqe;
1178 
1183  uint16_t cqe_phase = !((cq->pi / cq->queue.num_elements) % 2);
1184  ((struct spdk_nvme_cpl *)dpu_cqe)->status.p = cqe_phase;
1185 
1186  struct doca_task *task = doca_dma_task_memcpy_as_task(cqe_task);
1187  doca_task_set_user_data(task, user_data);
1188  doca_task_submit(task);
1189 
1190  cq->pi++;
1191 }
1192 
1193 /*
1194  * Callback invoked once a CQE has been successfully posted to Host
1195  *
1196  * @task [in]: The DMA memcpy task
1197  * @task_user_data [in]: User data that was previously provided with the task
1198  * @ctx_user_data [in]: User data that was previously set for the DMA context
1199  */
1200 static void nvmf_doca_cq_cqe_post_cb(struct doca_dma_task_memcpy *task,
1201  union doca_data task_user_data,
1202  union doca_data ctx_user_data)
1203 {
1204  (void)task;
1205 
1206  struct nvmf_doca_cq *cq = ctx_user_data.ptr;
1207 
1209  cq->io->post_cqe_cb(cq, task_user_data);
1210 }
1211 
1212 /*
1213  * Callback invoked once post of CQE fails
1214  *
1215  * @task [in]: The DMA memcpy task
1216  * @task_user_data [in]: User data that was previously provided with the task
1217  * @ctx_user_data [in]: User data that was previously set for the DMA context
1218  */
1219 static void nvmf_doca_cq_cqe_post_error_cb(struct doca_dma_task_memcpy *task,
1220  union doca_data task_user_data,
1221  union doca_data ctx_user_data)
1222 {
1223  (void)task;
1224  (void)task_user_data;
1225 
1226  size_t num_inflight;
1228  struct nvmf_doca_sq *cq = ctx_user_data.ptr;
1229 
1231  if (result != DOCA_SUCCESS) {
1232  DOCA_LOG_ERR("Failed to stop NVMf DOCA CQ: Failed to get number of inflight DMA tasks - %s",
1234  return;
1235  }
1236  if (num_inflight == 0) {
1238  }
1239 }
1240 
1241 /*
1242  * Callback invoked once state change occurs to the DMA context held by the CQ queue
1243  *
1244  * @user_data [in]: The user data associated with the context
1245  * @ctx [in]: The DMA context
1246  * @prev_state [in]: The previous state
1247  * @next_state [in]: The new state
1248  */
1249 static void nvmf_doca_cq_queue_dma_state_changed_cb(const union doca_data user_data,
1250  struct doca_ctx *ctx,
1251  enum doca_ctx_states prev_state,
1252  enum doca_ctx_states next_state)
1253 {
1254  (void)ctx;
1255  (void)prev_state;
1256 
1257  struct nvmf_doca_cq *cq = user_data.ptr;
1258 
1259  switch (next_state) {
1260  case DOCA_CTX_STATE_IDLE:
1262  break;
1266  default:
1267  break;
1268  }
1269 }
1270 
1271 /*
1272  * Create NVMf DOCA CQ for writing CQEs to Host CQ
1273  *
1274  * @attr [in]: The CQ attributes
1275  * @cq [out]: The newly created CQ
1276  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1277  */
1279 {
1281 
1282  memset(cq, 0, sizeof(*cq));
1283 
1284  cq->io = attr->io;
1285  cq->cq_id = attr->cq_id;
1286 
1287  struct nvmf_doca_queue_create_attr queue_attr = {
1288  .pe = attr->pe,
1289  .dev = attr->dev,
1290  .remote_queue_mmap = attr->host_cq_mmap,
1291  .remote_queue_address = attr->host_cq_address,
1292  .queue_depth = attr->cq_depth,
1293  .element_size = sizeof(struct nvmf_doca_cqe),
1294  .is_read_from_remote = false,
1295  .success_cb = nvmf_doca_cq_cqe_post_cb,
1296  .error_cb = nvmf_doca_cq_cqe_post_error_cb,
1297  .dma_state_changed_cb = nvmf_doca_cq_queue_dma_state_changed_cb,
1298  .dma_user_data = cq,
1299  };
1300  result = nvmf_doca_queue_create(&queue_attr, &cq->queue);
1301  if (result != DOCA_SUCCESS) {
1302  DOCA_LOG_ERR("Failed to create NVMf DOCA CQ: Failed to create queue - %s", doca_error_get_name(result));
1303  return result;
1304  }
1305 
1306  uint32_t cq_db_id = 2 * attr->cq_id + 1;
1308  attr->db_comp,
1311  cq_db_id,
1312  /*user_data=*/0,
1313  &cq->db);
1314  if (result != DOCA_SUCCESS) {
1315  DOCA_LOG_ERR("Failed to create NVMf DOCA CQ: Failed to create DB - %s", doca_error_get_name(result));
1316  return result;
1317  }
1319  if (result != DOCA_SUCCESS) {
1320  DOCA_LOG_ERR("Failed to create NVMf DOCA CQ: Failed to start DB - %s", doca_error_get_name(result));
1321  return result;
1322  }
1323  return DOCA_SUCCESS;
1324 }
1325 
1326 /*
1327  * Check if the NVMf DOCA CQ is stopped
1328  *
1329  * @cq [in]: The NVMf DOCA CQ to check
1330  * @return: true in case CQ is idle and false otherwise
1331  */
1332 static bool nvmf_doca_cq_idle(struct nvmf_doca_cq *cq)
1333 {
1334  return is_ctx_idle(doca_dma_as_ctx(cq->queue.dma));
1335 }
1336 
1337 /*
1338  * Stop the NVMf DOCA CQ
1339  *
1340  * This operation is async, once operation completes then nvmf_doca_cq_stop_continue() will be invoked
1341  *
1342  * @cq [in]: The NVMf DOCA CQ to stop
1343  */
1344 static void nvmf_doca_cq_stop(struct nvmf_doca_cq *cq)
1345 {
1347 
1350  DOCA_LOG_ERR("Failed to stop NVMf DOCA CQ: Failed to stop DB - %s", doca_error_get_name(result));
1351  }
1352 
1354 }
1355 
1356 /*
1357  * Continue async flow of stopping the NVMf DOCA CQ
1358  *
1359  * @cq [in]: The NVMf DOCA CQ to stop
1360  */
1362 {
1363  /* If reached here means DMA context has been successfully stopped now we can continue stopping the IO */
1365 }
1366 
1367 /*
1368  * Destroy NVMf DOCA CQ
1369  *
1370  * @cq [in]: The CQ to destroy
1371  */
1372 static void nvmf_doca_cq_destroy(struct nvmf_doca_cq *cq)
1373 {
1375 
1376  if (cq->db != NULL) {
1379  DOCA_LOG_ERR("Failed to destroy NVMf DOCA CQ: Failed to stop DB - %s",
1382  if (result != DOCA_SUCCESS)
1383  DOCA_LOG_ERR("Failed to destroy NVMf DOCA CQ: Failed to destroy DB - %s",
1385  cq->db = NULL;
1386  }
1387 
1389 }
1390 
1392  struct doca_dpa *dpa;
1395 };
1396 
1397 /*
1398  * Create NVMf DOCA DPA thread
1399  *
1400  * @attr [in]: The thread attributes
1401  * @dpa_thread [out]: The newly created DPA thread
1402  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1403  */
1405  struct nvmf_doca_dpa_thread *dpa_thread)
1406 {
1408 
1409  memset(dpa_thread, 0, sizeof(*dpa_thread));
1410 
1411  dpa_thread->dpa = attr->dpa;
1412 
1413  result = doca_dpa_mem_alloc(attr->dpa, attr->thread_arg_size, &dpa_thread->arg);
1414  if (result != DOCA_SUCCESS) {
1415  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA thread: Failed to allocate thread argument memory - %s",
1417  return result;
1418  }
1419 
1420  result = doca_dpa_thread_create(attr->dpa, &dpa_thread->thread);
1421  if (result != DOCA_SUCCESS) {
1422  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA thread: Failed to create DPA thread - %s",
1424  return result;
1425  }
1426  result = doca_dpa_thread_set_func_arg(dpa_thread->thread, attr->thread_handler, dpa_thread->arg);
1427  if (result != DOCA_SUCCESS) {
1428  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA thread: Failed to set DPA thread function - %s",
1430  return result;
1431  }
1432  result = doca_dpa_thread_start(dpa_thread->thread);
1433  if (result != DOCA_SUCCESS) {
1434  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA thread: Failed to start DPA thread - %s",
1436  return result;
1437  }
1438 
1439  return DOCA_SUCCESS;
1440 }
1441 
1442 /*
1443  * Copy arguments and run the NVMf DOCA DPA thread
1444  *
1445  * @dpa_thread [in]: The DPA thread to run
1446  * @arg [in]: Pointer to arguments that will be copied to DPA as the DPA thread arguments
1447  * @arg_size [in]: The size in bytes of the thread arguments
1448  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1449  */
1450 static doca_error_t nvmf_doca_dpa_thread_run(struct nvmf_doca_dpa_thread *dpa_thread, void *arg, size_t arg_size)
1451 {
1453 
1454  result = doca_dpa_h2d_memcpy(dpa_thread->dpa, dpa_thread->arg, arg, arg_size);
1455  if (result != DOCA_SUCCESS) {
1456  DOCA_LOG_ERR("Failed to run NVMf DOCA DPA thread: Failed to update DPA thread argument - %s",
1458  return result;
1459  }
1460 
1461  result = doca_dpa_thread_run(dpa_thread->thread);
1462  if (result != DOCA_SUCCESS) {
1463  DOCA_LOG_ERR("Failed to run NVMf DOCA DPA thread: Failed to run DPA thread - %s",
1465  return result;
1466  }
1467 
1468  return DOCA_SUCCESS;
1469 }
1470 
1471 /*
1472  * Destroy NVMf DOCA DPA thread
1473  *
1474  * @dpa_thread [in]: The DPA thread to destroy
1475  */
1477 {
1479 
1480  if (dpa_thread->thread != NULL) {
1481  result = doca_dpa_thread_stop(dpa_thread->thread);
1483  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA thread: Failed to stop DPA thread - %s",
1485  result = doca_dpa_thread_destroy(dpa_thread->thread);
1486  if (result != DOCA_SUCCESS)
1487  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA thread: Failed to destroy DPA thread - %s",
1489  dpa_thread->thread = NULL;
1490  }
1491 
1492  if (dpa_thread->arg != 0) {
1493  result = doca_dpa_mem_free(dpa_thread->dpa, dpa_thread->arg);
1494  if (result != DOCA_SUCCESS)
1495  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DPA thread: Failed to free DPA thread argument - %s",
1497  dpa_thread->arg = 0;
1498  }
1499 }
1500 
1501 /*
1502  * Fills the DPA thread argument with the relevant DPA handles to be later copied to the DPA thread
1503  *
1504  * @io [in]: The NVMf DOCA IO that contains the DPA resources
1505  * @arg [out]: The returned thread argument that was filled
1506  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1507  */
1509 {
1511 
1518 
1520  if (result != DOCA_SUCCESS) {
1521  DOCA_LOG_ERR(
1522  "Failed to fill NVMf DOCA IO thread argument: Failed to get consumer completion context DPA handle - %s",
1524  return result;
1525  }
1527  if (result != DOCA_SUCCESS) {
1528  DOCA_LOG_ERR(
1529  "Failed to fill NVMf DOCA IO thread argument: Failed to get producer completion context DPA handle - %s",
1531  return result;
1532  }
1534  if (result != DOCA_SUCCESS) {
1535  DOCA_LOG_ERR("Failed to fill NVMf DOCA IO thread argument: Failed to get consumer DPA handle - %s",
1537  return result;
1538  }
1540  if (result != DOCA_SUCCESS) {
1541  DOCA_LOG_ERR("Failed to fill NVMf DOCA IO thread argument: Failed to get producer DPA handle - %s",
1543  return result;
1544  }
1545 
1547  if (result != DOCA_SUCCESS) {
1548  DOCA_LOG_ERR(
1549  "Failed to fill NVMf DOCA IO thread argument: Failed to get DB completion context DPA handle - %s",
1551  return result;
1552  }
1553 
1554  dpa_msix = 0;
1555  if (io->msix != NULL) {
1557  if (result != DOCA_SUCCESS) {
1558  DOCA_LOG_ERR("Failed to fill NVMf DOCA IO thread argument: Failed to get MSI-X DPA handle - %s",
1560  return result;
1561  }
1562  }
1563 
1564  *arg = (struct io_thread_arg){
1566  .dpa_producer_comp = dpa_producer_comp,
1567  .dpa_producer = dpa_producer,
1568  .dpa_consumer = dpa_consumer,
1569  .dpa_db_comp = dpa_db_comp,
1570  .dpa_msix = dpa_msix,
1571  };
1572 
1573  return DOCA_SUCCESS;
1574 }
1575 
1576 /*
1577  * Initialize and run the NVMf DOCA DPA thread
1578  *
1579  * @io [in]: The NVMf DOCA IO that contains the DPA resources
1580  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1581  */
1583 {
1584  struct io_thread_arg arg;
1586 
1588  if (result != DOCA_SUCCESS)
1589  return result;
1590 
1591  doca_dpa_dev_devemu_pci_db_t dpa_cq_db;
1592  result = doca_devemu_pci_db_get_dpa_handle(io->cq.db, &dpa_cq_db);
1593  if (result != DOCA_SUCCESS) {
1594  DOCA_LOG_ERR("Failed to run IO DPA thread: Failed to get CQ DB DPA handle");
1595  return result;
1596  }
1597 
1598  uint64_t rpc_ret;
1601  &rpc_ret,
1602  arg.dpa_db_comp,
1603  dpa_cq_db,
1604  arg.dpa_consumer);
1605  if (result != DOCA_SUCCESS) {
1606  DOCA_LOG_ERR("Failed to run IO DPA thread: Failed to issue initialize thread RPC - %s",
1608  return result;
1609  }
1610  if (rpc_ret != RPC_RETURN_STATUS_SUCCESS) {
1611  DOCA_LOG_ERR("Failed to run IO DPA thread: The initialize thread RPC has failed");
1612  return result;
1613  }
1614 
1615  result = nvmf_doca_dpa_thread_run(&io->dpa_thread, &arg, sizeof(arg));
1616  if (result != DOCA_SUCCESS)
1617  return result;
1618 
1619  return DOCA_SUCCESS;
1620 }
1621 
1623 {
1625 
1626  struct nvmf_doca_dpa_thread_create_attr dpa_thread_attr = {
1627  .dpa = attr->dpa,
1628  .thread_handler = io_thread,
1629  .thread_arg_size = sizeof(struct io_thread_arg),
1630  };
1631  result = nvmf_doca_dpa_thread_create(&dpa_thread_attr, &io->dpa_thread);
1632  if (result != DOCA_SUCCESS) {
1634  return result;
1635  }
1636 
1637  struct nvmf_doca_dpa_comch_create_attr comch_attr = {
1638  .dev = attr->dev,
1639  .dpa = attr->dpa,
1640  .dpa_thread = io->dpa_thread.thread,
1641  .max_num_msg = MAX_NUM_COMCH_MSGS,
1642  .pe = attr->pe,
1643  .ctx_user_data = io,
1644  };
1645  result = nvmf_doca_dpa_comch_create(&comch_attr, &io->comch);
1646  if (result != DOCA_SUCCESS) {
1648  return result;
1649  }
1650 
1652  if (result != DOCA_SUCCESS) {
1653  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA IO: Failed to create DB completion context - %s",
1656  return result;
1657  }
1659  if (result != DOCA_SUCCESS) {
1660  DOCA_LOG_ERR(
1661  "Failed to create NVMf DOCA DPA IO: Failed to set DB completion context max number of doorbells - %s",
1664  return result;
1665  }
1667  if (result != DOCA_SUCCESS) {
1668  DOCA_LOG_ERR("Failed to create NVMf DOCA DPA IO: Failed to start DB completion context - %s",
1671  return result;
1672  }
1673 
1674  if (attr->enable_msix) {
1678  attr->msix_idx,
1679  /*user_data=*/attr->msix_idx,
1680  &io->msix);
1681  if (result != DOCA_SUCCESS) {
1683  return result;
1684  }
1685  }
1686 
1687  struct nvmf_doca_cq_create_attr cq_attr = {
1688  .pe = attr->pe,
1689  .dev = attr->dev,
1690  .nvme_dev = attr->nvme_dev,
1691  .cq_depth = attr->cq_depth,
1692  .host_cq_mmap = attr->host_cq_mmap,
1693  .host_cq_address = attr->host_cq_address,
1694  .db_comp = io->db_comp,
1695  .cq_id = attr->cq_id,
1696  .io = io,
1697  };
1698  result = nvmf_doca_cq_create(&cq_attr, &io->cq);
1699  if (result != DOCA_SUCCESS) {
1701  return result;
1702  }
1703 
1705  if (result != DOCA_SUCCESS) {
1707  return result;
1708  }
1709 
1710  TAILQ_INIT(&io->sq_list);
1711  io->post_cqe_cb = attr->post_cqe_cb;
1712  io->fetch_sqe_cb = attr->fetch_sqe_cb;
1713  io->copy_data_cb = attr->copy_data_cb;
1714  io->stop_sq_cb = attr->stop_sq_cb;
1715  io->stop_io_cb = attr->stop_io_cb;
1716 
1717  return DOCA_SUCCESS;
1718 }
1719 
1721 {
1723 
1725 
1726  if (io->msix != NULL) {
1728  if (result != DOCA_SUCCESS)
1729  DOCA_LOG_ERR("Failed to destroy NVMf DOCA IO: Failed to destroy MSI-X");
1730  io->msix = NULL;
1731  }
1732 
1733  if (io->db_comp != NULL) {
1735  if (result != DOCA_SUCCESS && result != DOCA_SUCCESS)
1736  DOCA_LOG_ERR("Failed to destroy NVMf DOCA IO: Failed to stop DB completion context");
1738  if (result != DOCA_SUCCESS)
1739  DOCA_LOG_ERR("Failed to destroy NVMf DOCA IO: Failed to destroy DB completion context");
1740  io->db_comp = NULL;
1741  }
1742 
1744 
1746 }
1747 
1749 {
1750  if (!TAILQ_EMPTY(&io->sq_list)) {
1751  DOCA_LOG_ERR("Failed to stop IO: Not all SQs have been removed");
1752  return;
1753  }
1754 
1755  if (!nvmf_doca_cq_idle(&io->cq)) {
1756  nvmf_doca_cq_stop(&io->cq);
1757  return;
1758  }
1759 
1761 }
1762 
1763 /*
1764  * Continue async flow of stopping the NVMf DOCA IO
1765  *
1766  * @io [in]: The NVMf DOCA IO to stop
1767  */
1769 {
1770  if (!nvmf_doca_cq_idle(&io->cq)) {
1771  return;
1772  }
1773 
1774  if (!nvmf_doca_dpa_comch_idle(&io->comch)) {
1776  return;
1777  }
1778 
1779  io->stop_io_cb(io);
1780 }
1781 
1783  struct doca_pe *pe;
1784  struct doca_dev *dev;
1787  struct doca_mmap *host_data_mmap;
1792 };
1793 
1794 struct doca_buf *nvmf_doca_sq_get_dpu_buffer(struct nvmf_doca_sq *sq)
1795 {
1796  struct doca_buf *buf;
1797 
1799 
1800  return buf;
1801 }
1802 
1803 struct doca_buf *nvmf_doca_sq_get_host_buffer(struct nvmf_doca_sq *sq, uintptr_t host_io_address)
1804 {
1805  struct doca_buf *buf;
1806 
1809  (void *)host_io_address,
1811  &buf);
1812 
1813  return buf;
1814 }
1815 
1817  struct doca_buf *dst_buffer,
1818  struct doca_buf *src_buffer,
1819  size_t length,
1820  union doca_data user_data)
1821 {
1822  struct doca_dma_task_memcpy *dma_task;
1823 
1824  doca_buf_reset_data_len(dst_buffer);
1825  doca_buf_set_data_len(src_buffer, length);
1826 
1827  doca_dma_task_memcpy_alloc_init(sq->dma_pool.dma, src_buffer, dst_buffer, user_data, &dma_task);
1829 }
1830 
1831 /*
1832  * Callback invoked once data has been successfully copied from/to Host
1833  *
1834  * @task [in]: The DMA memcpy task
1835  * @task_user_data [in]: User data that was previously provided with the task
1836  * @ctx_user_data [in]: User data that was previously set for the DMA context
1837  */
1838 static void nvmf_doca_dma_pool_copy_cb(struct doca_dma_task_memcpy *task,
1839  union doca_data task_user_data,
1840  union doca_data ctx_user_data)
1841 {
1842  struct nvmf_doca_sq *sq = ctx_user_data.ptr;
1843  struct doca_buf *dst = doca_dma_task_memcpy_get_dst(task);
1844  struct doca_buf *src = (struct doca_buf *)doca_dma_task_memcpy_get_src(task);
1845 
1847 
1848  sq->io->copy_data_cb(sq, dst, src, task_user_data);
1849 }
1850 
1851 /*
1852  * Callback invoked once copy of data fails
1853  *
1854  * @task [in]: The DMA memcpy task
1855  * @task_user_data [in]: User data that was previously provided with the task
1856  * @ctx_user_data [in]: User data that was previously set for the DMA context
1857  */
1858 static void nvmf_doca_dma_pool_copy_error_cb(struct doca_dma_task_memcpy *task,
1859  union doca_data task_user_data,
1860  union doca_data ctx_user_data)
1861 {
1862  (void)task_user_data;
1863  (void)ctx_user_data;
1864 
1866 }
1867 
1868 /*
1869  * Callback invoked once state change occurs to the DMA context held by the DMA pool
1870  *
1871  * @user_data [in]: The user data associated with the context
1872  * @ctx [in]: The DMA context
1873  * @prev_state [in]: The previous state
1874  * @next_state [in]: The new state
1875  */
1876 static void nvmf_doca_dma_pool_dma_state_changed_cb(const union doca_data user_data,
1877  struct doca_ctx *ctx,
1878  enum doca_ctx_states prev_state,
1879  enum doca_ctx_states next_state)
1880 {
1881  (void)ctx;
1882  (void)prev_state;
1883 
1884  struct nvmf_doca_sq *sq = user_data.ptr;
1885 
1886  switch (next_state) {
1887  case DOCA_CTX_STATE_IDLE:
1889  break;
1893  default:
1894  break;
1895  }
1896 }
1897 
1898 /*
1899  * Create NVMf DOCA DMA pool for copying data between Host and DPU
1900  *
1901  * @attr [in]: The DMA pool attributes
1902  * @dma_pool [out]: The newly created DMA pool
1903  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1904  */
1906  struct nvmf_doca_dma_pool *dma_pool)
1907 {
1909 
1910  memset(dma_pool, 0, sizeof(*dma_pool));
1911 
1912  uint32_t local_data_memory_size = attr->max_dma_operations * attr->max_dma_operation_size;
1913  dma_pool->local_data_memory = spdk_dma_zmalloc(local_data_memory_size, CACHELINE_SIZE_BYTES, NULL);
1914  if (dma_pool->local_data_memory == NULL) {
1915  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to allocate memory for local data");
1916  return DOCA_ERROR_NO_MEMORY;
1917  }
1918 
1920  if (result != DOCA_SUCCESS) {
1921  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to create local data mmap - %s",
1923  return result;
1924  }
1926  if (result != DOCA_SUCCESS) {
1927  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to create local data mmap - %s",
1929  return result;
1930  }
1932  if (result != DOCA_SUCCESS) {
1933  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to set local data mmap permissions - %s",
1935  return result;
1936  }
1938  if (result != DOCA_SUCCESS) {
1939  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to add device to local dma mmap - %s",
1941  return result;
1942  }
1944  if (result != DOCA_SUCCESS) {
1945  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to start local dma mmap - %s",
1947  return result;
1948  }
1949 
1951  attr->max_dma_operation_size,
1954  if (result != DOCA_SUCCESS) {
1955  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to create local data pool - %s",
1957  return result;
1958  }
1960  if (result != DOCA_SUCCESS) {
1961  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to start local data pool - %s",
1963  return result;
1964  }
1965 
1967  if (result != DOCA_SUCCESS) {
1968  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to create Host data inventory - %s",
1970  return result;
1971  }
1973  if (result != DOCA_SUCCESS) {
1974  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to start Host data inventory - %s",
1976  return result;
1977  }
1979 
1980  result = doca_dma_create(attr->dev, &dma_pool->dma);
1981  if (result != DOCA_SUCCESS) {
1982  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to create DMA context - %s",
1984  return result;
1985  }
1987  attr->success_cb,
1988  attr->error_cb,
1989  attr->max_dma_operations);
1990  if (result != DOCA_SUCCESS) {
1991  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to set DMA context task consigurations - %s",
1993  return result;
1994  }
1995  struct doca_ctx *dma_ctx = doca_dma_as_ctx(dma_pool->dma);
1996  result = doca_pe_connect_ctx(attr->pe, dma_ctx);
1997  if (result != DOCA_SUCCESS) {
1998  DOCA_LOG_ERR(
1999  "Failed to create NVMf DOCA DMA pool: Failed to connect DMA context to progress engine - %s",
2001  return result;
2002  }
2003  union doca_data ctx_user_data;
2004  ctx_user_data.ptr = attr->dma_user_data;
2005  result = doca_ctx_set_user_data(dma_ctx, ctx_user_data);
2006  if (result != DOCA_SUCCESS) {
2007  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to set DMA context user data - %s",
2009  return result;
2010  }
2012  if (result != DOCA_SUCCESS) {
2013  DOCA_LOG_ERR(
2014  "Failed to create NVMf DOCA DMA pool: Failed to set DMA context state changed callback - %s",
2016  return result;
2017  }
2018  result = doca_ctx_start(dma_ctx);
2019  if (result != DOCA_SUCCESS) {
2020  DOCA_LOG_ERR("Failed to create NVMf DOCA DMA pool: Failed to start DMA context - %s",
2022  return result;
2023  }
2024 
2025  return DOCA_SUCCESS;
2026 }
2027 
2028 /*
2029  * Stop the NVMf DOCA DMA pool
2030  *
2031  * This operation is async, once operation completes then nvmf_doca_dma_pool_dma_state_changed_cb() will be invoked
2032  *
2033  * @dma_pool [in]: The NVMf DOCA DMA pool to stop
2034  */
2035 static void nvmf_doca_dma_pool_stop(struct nvmf_doca_dma_pool *dma_pool)
2036 {
2038 
2039  if (!is_ctx_running(doca_dma_as_ctx(dma_pool->dma))) {
2040  return;
2041  }
2042 
2043  result = doca_ctx_stop(doca_dma_as_ctx(dma_pool->dma));
2045  DOCA_LOG_ERR("Failed to stop NVMf DOCA DMA pool: Failed to stop context - %s",
2047  }
2048 }
2049 
2050 /*
2051  * Destroy NVMf DOCA DMA pool
2052  *
2053  * @dma_pool [in]: The DMA pool to destroy
2054  */
2055 static void nvmf_doca_dma_pool_destroy(struct nvmf_doca_dma_pool *dma_pool)
2056 {
2058 
2059  if (dma_pool->dma != NULL) {
2060  result = doca_ctx_stop(doca_dma_as_ctx(dma_pool->dma));
2062  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DMA pool: Failed to stop DMA context %s",
2064  result = doca_dma_destroy(dma_pool->dma);
2065  if (result != DOCA_SUCCESS)
2066  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DMA pool: Failed to destroy DMA context %s",
2068  dma_pool->dma = NULL;
2069  }
2070 
2071  dma_pool->host_data_mmap = NULL;
2072  if (dma_pool->host_data_inventory != NULL) {
2074  if (result != DOCA_SUCCESS)
2075  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DMA pool: Failed to destroy host data inventory %s",
2077  dma_pool->host_data_inventory = NULL;
2078  }
2079 
2080  if (dma_pool->local_data_pool != NULL) {
2082  if (result != DOCA_SUCCESS)
2083  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DMA pool: Failed to destroy local data pool %s",
2085  dma_pool->local_data_pool = NULL;
2086  }
2087 
2088  if (dma_pool->local_data_mmap != NULL) {
2090  if (result != DOCA_SUCCESS)
2091  DOCA_LOG_ERR("Failed to destroy NVMf DOCA DMA pool: Failed to destroy local data mmap %s",
2093  dma_pool->local_data_mmap = NULL;
2094  }
2095 
2096  if (dma_pool->local_data_memory != NULL) {
2097  spdk_dma_free(dma_pool->local_data_memory);
2098  dma_pool->local_data_memory = NULL;
2099  }
2100 }
2101 
2102 /*
2103  * Update the producer index of the SQ
2104  *
2105  * This may cause read operations of SQEs
2106  *
2107  * @sq [in]: The SQ that is being updated
2108  * @new_pi [in]: The new SQ producer index as provided by the Host
2109  */
2110 static void nvmf_doca_sq_update_pi(struct nvmf_doca_sq *sq, uint32_t new_pi)
2111 {
2112  struct doca_dma_task_memcpy *sqe_task;
2113  struct doca_buf *dst_buffer;
2114  uint16_t sqe_idx;
2115  uint16_t pi = sq->pi;
2116  uint16_t num_sqes;
2117  if (new_pi >= pi) {
2118  num_sqes = (new_pi - pi);
2119  } else {
2120  num_sqes = ((sq->queue.num_elements - pi) + new_pi);
2121  }
2122 
2123  for (uint16_t sqe_count = 0; sqe_count < num_sqes; sqe_count++) {
2124  sqe_idx = (pi + sqe_count) % sq->queue.num_elements;
2125  sqe_task = sq->queue.elements[sqe_idx];
2126 
2127  dst_buffer = doca_dma_task_memcpy_get_dst(sqe_task);
2128  doca_buf_reset_data_len(dst_buffer);
2129  if (sqe_count == (num_sqes - 1)) {
2131  } else {
2134  }
2135  }
2136 
2137  sq->pi = new_pi;
2138 }
2139 
2140 /*
2141  * Method invoked once Host DB message is received from DPA
2142  *
2143  * @io [in]: The IO used to receive the message
2144  * @msg [in]: The Host DB message that was received from DPA
2145  */
2146 static void nvmf_doca_io_handle_host_db_msg(struct nvmf_doca_io *io, const struct comch_msg *msg)
2147 {
2148  struct nvmf_doca_sq *sq = (struct nvmf_doca_sq *)msg->host_db_data.db_user_data;
2149  uint32_t db_value = msg->host_db_data.db_value;
2150 
2151  if (sq == NULL) {
2153  } else {
2155  }
2156 }
2157 
2158 /*
2159  * Callback invoked once a SQE has been successfully read from Host
2160  *
2161  * @task [in]: The DMA memcpy task
2162  * @task_user_data [in]: User data that was previously provided with the task
2163  * @ctx_user_data [in]: User data that was previously set for the DMA context
2164  */
2165 static void nvmf_doca_sq_sqe_read_cb(struct doca_dma_task_memcpy *task,
2166  union doca_data task_user_data,
2167  union doca_data ctx_user_data)
2168 {
2169  struct doca_buf *sqe_buf;
2170  struct nvmf_doca_sqe *sqe;
2171  struct nvmf_doca_sq *sq = ctx_user_data.ptr;
2172  uint16_t sqe_idx = task_user_data.u64;
2173 
2174  sqe_buf = doca_dma_task_memcpy_get_dst(task);
2175  doca_buf_get_data(sqe_buf, (void **)&sqe);
2176 
2177  sq->io->fetch_sqe_cb(sq, sqe, sqe_idx);
2178 }
2179 
2180 /*
2181  * Callback invoked once read of SQE fails
2182  *
2183  * @task [in]: The DMA memcpy task
2184  * @task_user_data [in]: User data that was previously provided with the task
2185  * @ctx_user_data [in]: User data that was previously set for the DMA context
2186  */
2187 static void nvmf_doca_sq_sqe_read_error_cb(struct doca_dma_task_memcpy *task,
2188  union doca_data task_user_data,
2189  union doca_data ctx_user_data)
2190 {
2191  (void)task;
2192  (void)task_user_data;
2193 
2194  size_t num_inflight;
2196  struct nvmf_doca_sq *sq = ctx_user_data.ptr;
2197 
2199  if (result != DOCA_SUCCESS) {
2200  DOCA_LOG_ERR("Failed to stop NVMf DOCA SQ: Failed to get number of inflight DMA tasks - %s",
2202  return;
2203  }
2204  if (num_inflight == 0) {
2206  }
2207 }
2208 
2209 /*
2210  * Callback invoked once state change occurs to the DMA context held by the SQ queue
2211  *
2212  * @user_data [in]: The user data associated with the context
2213  * @ctx [in]: The DMA context
2214  * @prev_state [in]: The previous state
2215  * @next_state [in]: The new state
2216  */
2217 static void nvmf_doca_sq_queue_dma_state_changed_cb(const union doca_data user_data,
2218  struct doca_ctx *ctx,
2219  enum doca_ctx_states prev_state,
2220  enum doca_ctx_states next_state)
2221 {
2222  (void)ctx;
2223  (void)prev_state;
2224 
2225  struct nvmf_doca_sq *sq = user_data.ptr;
2226 
2227  switch (next_state) {
2228  case DOCA_CTX_STATE_IDLE:
2230  break;
2234  default:
2235  break;
2236  }
2237 }
2238 
2239 /*
2240  * Creates NVMF doca requests pool and associates it with the given SQ.
2241  *
2242  * @sq [in]: The SQ that holds the requests pool
2243  * @num_requests [in]: Number of requests to be allocated
2244  * @doca_pg [in]: Doca poll group taking care of the request
2245  * @return: DOCA_SUCCESS on success and DOCA_ERROR_NO_MEMORY when allocation fails.
2246  */
2247 static doca_error_t nvmf_doca_request_pool_create(struct nvmf_doca_sq *sq, size_t num_requests)
2248 {
2249  sq->request_pool_memory = calloc(num_requests, sizeof(struct nvmf_doca_request));
2250  if (sq->request_pool_memory == NULL) {
2251  DOCA_LOG_ERR("Failed to create NVMf DOCA SQ SPDK request pool: Failed to allocate memory for requests");
2252  return DOCA_ERROR_NO_MEMORY;
2253  }
2254 
2255  TAILQ_INIT(&sq->request_pool);
2256  for (size_t request_idx = 0; request_idx < num_requests; request_idx++) {
2257  struct nvmf_doca_request *request = &(sq->request_pool_memory[request_idx]);
2258  request->request.cmd = (union nvmf_h2c_msg *)&request->command;
2259  request->request.rsp = (union nvmf_c2h_msg *)&request->cq_entry;
2260  request->request.qpair = &sq->spdk_qp;
2261  request->request.stripped_data = NULL;
2262  TAILQ_INSERT_TAIL(&(sq->request_pool), request, link);
2263  }
2264  return DOCA_SUCCESS;
2265 }
2266 
2267 /*
2268  * Destroys NVMF doca requests pool.
2269  *
2270  * @sq [in]: The SQ that holds the requests pool
2271  * @return: DOCA_SUCCESS on success and DOCCA_ERROR otherwise
2272  */
2274 {
2275  if (sq->request_pool_memory != NULL) {
2276  TAILQ_INIT(&(sq->request_pool));
2277  free(sq->request_pool_memory);
2278  sq->request_pool_memory = NULL;
2279  }
2280 
2281  return DOCA_SUCCESS;
2282 }
2283 
2284 /*
2285  * This function is responsible for obtaining an NVMF request object from the pool associated
2286  * with the given SQ.
2287  *
2288  * @sq [in]: The SQ that holds the requests pool
2289  * @return: NVMF doca request
2290  */
2292 {
2293  struct nvmf_doca_request *request = TAILQ_FIRST(&sq->request_pool);
2294  if (request == NULL) {
2295  return NULL;
2296  }
2297 
2298  TAILQ_REMOVE(&(sq->request_pool), request, link);
2299 
2300  return request;
2301 }
2302 
2303 /*
2304  * This method is responsible for freeing an NVMF request that has been processed.
2305  * It returns the request back to the pool associated with the given SQ, making it available for reuse.
2306  *
2307  * @sq [in]: The SQ that holds the requests pool
2308  * @request [in]: NVMF doca request
2309  */
2311 {
2312  memset(&request->command, 0, sizeof(request->command));
2313  memset(&request->cq_entry, 0, sizeof(request->cq_entry));
2314  request->data_from_alloc = false;
2315  request->cb_arg = NULL;
2316  request->doca_cb = NULL;
2317  request->request.data = NULL;
2318  request->request.iovcnt = 0;
2319  request->request.length = 0;
2320  request->prp_dpu_buf = NULL;
2321  request->prp_host_buf = NULL;
2322  request->num_of_buffers = 0;
2323  request->residual_length = 0;
2324  request->sqe_idx = 0;
2325 
2326  TAILQ_INSERT_TAIL(&sq->request_pool, request, link);
2327 }
2328 
2329 /*
2330  * This method completes an NVMF request by invoking its associated callback and then freeing the request.
2331  *
2332  * @request [in]: NVMF doca request to complete
2333  */
2335 {
2336  if (request->doca_cb != NULL) {
2337  request->doca_cb(request, request->cb_arg);
2338  }
2339 }
2340 
2341 /*
2342  * Determines the correct SQ for the request and then invokes the internal mechanism to free the request.
2343  *
2344  * @request [in]: NVMF doca request to free
2345  */
2347 {
2348  struct nvmf_doca_sq *sq = SPDK_CONTAINEROF(request->request.qpair, struct nvmf_doca_sq, spdk_qp);
2349 
2350  int used_host_bufs = request->request.iovcnt;
2351  int used_dpu_bufs = request->request.iovcnt;
2352  while (used_dpu_bufs > 0) {
2353  if (request->dpu_buffer[used_dpu_bufs - 1])
2354  doca_buf_dec_refcount(request->dpu_buffer[used_dpu_bufs - 1], NULL);
2355  used_dpu_bufs--;
2356  }
2357 
2358  while (used_host_bufs > 0) {
2359  if (request->host_buffer[used_host_bufs - 1])
2360  doca_buf_dec_refcount(request->host_buffer[used_host_bufs - 1], NULL);
2361  used_host_bufs--;
2362  }
2363 
2364  if (request->prp_dpu_buf != NULL) {
2366  }
2367 
2368  if (request->prp_host_buf != NULL) {
2370  }
2371 
2372  if (request->data_from_alloc) {
2373  free(request->request.data);
2374  }
2375 
2376  nvmf_doca_request_free_impl(sq, request);
2377 }
2378 
2379 /*
2380  * Destroy NVMf DOCA SQ
2381  *
2382  * @sq [in]: The SQ to destroy
2383  */
2384 static void nvmf_doca_sq_destroy(struct nvmf_doca_sq *sq)
2385 {
2387 
2388  if (sq->db != NULL) {
2390  if (result != DOCA_SUCCESS)
2391  DOCA_LOG_ERR("Failed to destroy NVMf DOCA SQ: Failed to destroy DB - %s",
2393  sq->db = NULL;
2394  }
2395 
2397 
2399 
2401 }
2402 
2404  struct doca_pe *pe;
2405  struct doca_dev *dev;
2406  struct doca_devemu_pci_dev *nvme_dev;
2407  uint16_t sq_depth;
2408  struct doca_mmap *host_sq_mmap;
2410  struct doca_devemu_pci_db_completion *db_comp;
2411  uint32_t sq_id;
2412  struct nvmf_doca_io *io;
2413  struct spdk_nvmf_transport *transport;
2414  void *ctx;
2415 };
2416 
2417 /*
2418  * Create NVMf DOCA SQ for reading SQEs from Host SQ
2419  *
2420  * @attr [in]: The SQ attributes
2421  * @sq [in]: The SQ to initialize
2422  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
2423  */
2425 {
2427 
2429  if (result != DOCA_SUCCESS) {
2431  return result;
2432  }
2433 
2434  struct nvmf_doca_queue_create_attr queue_attr = {
2435  .pe = attr->pe,
2436  .dev = attr->dev,
2437  .remote_queue_mmap = attr->host_sq_mmap,
2438  .remote_queue_address = attr->host_sq_address,
2439  .queue_depth = attr->sq_depth,
2440  .element_size = sizeof(struct nvmf_doca_sqe),
2441  .is_read_from_remote = true,
2442  .success_cb = nvmf_doca_sq_sqe_read_cb,
2443  .error_cb = nvmf_doca_sq_sqe_read_error_cb,
2444  .dma_state_changed_cb = nvmf_doca_sq_queue_dma_state_changed_cb,
2445  .dma_user_data = sq,
2446  };
2447  result = nvmf_doca_queue_create(&queue_attr, &sq->queue);
2448  if (result != DOCA_SUCCESS) {
2450  return result;
2451  }
2452 
2453  const uint32_t num_sq_elements = attr->sq_depth;
2454  struct nvmf_doca_dma_pool_create_attr dma_pool_attr = {
2455  .pe = attr->pe,
2456  .dev = attr->dev,
2457  .max_dma_operations = num_sq_elements * NVMF_REQ_MAX_BUFFERS,
2458  .max_dma_operation_size = DMA_POOL_DATA_BUFFER_SIZE,
2459  .host_data_mmap = attr->host_sq_mmap,
2460  .success_cb = nvmf_doca_dma_pool_copy_cb,
2462  .dma_state_changed_cb = nvmf_doca_dma_pool_dma_state_changed_cb,
2463  .dma_user_data = sq,
2464  };
2465  result = nvmf_doca_dma_pool_create(&dma_pool_attr, &sq->dma_pool);
2466  if (result != DOCA_SUCCESS) {
2468  return result;
2469  }
2470 
2471  const uint32_t sq_db_id = 2 * attr->sq_id;
2473  attr->db_comp,
2476  sq_db_id,
2477  /*user_data=*/(uint64_t)sq,
2478  &sq->db);
2479  if (result != DOCA_SUCCESS) {
2480  DOCA_LOG_ERR("Failed to create NVMf DOCA SQ: Failed to create DB - %s", doca_error_get_name(result));
2482  return result;
2483  }
2485  if (result != DOCA_SUCCESS) {
2486  DOCA_LOG_ERR("Failed to add SQ to NVMf DOCA IO: Failed to SQ DB DPA handle - %s",
2489  return result;
2490  }
2491  sq->io = attr->io;
2492  sq->sq_id = attr->sq_id;
2493  sq->spdk_qp.qid = attr->sq_id;
2494  sq->spdk_qp.transport = attr->transport;
2495  sq->ctx = attr->ctx;
2496  sq->result = DOCA_SUCCESS;
2497 
2498  return DOCA_SUCCESS;
2499 }
2500 
2502 {
2503  TAILQ_REMOVE(&sq->io->sq_list, sq, link);
2505 }
2506 
2507 /*
2508  * Method invoked once unbind DB done message is received from DPA
2509  *
2510  * @msg [in]: The unbind done message that was received from DPA
2511  */
2513 {
2514  struct nvmf_doca_sq *sq = (struct nvmf_doca_sq *)msg->unbind_sq_db_done_data.cookie;
2515 
2518 }
2519 
2520 /*
2521  * Progress the add operation of the NVMf DOCA SQ by a step depending on current state
2522  *
2523  * @sq [in]: The SQ that is being added
2524  */
2526 {
2527  struct spdk_nvmf_tgt *target;
2528 
2529  // NVMF_DOCA_SQ_DB_BOUND
2530  sq->result = doca_devemu_pci_db_start(sq->db);
2531  if (sq->result != DOCA_SUCCESS) {
2532  DOCA_LOG_ERR("Failed to add SQ to NVMf DOCA IO: Failed to start DB - %s",
2535  return;
2536  }
2537  target = spdk_nvmf_get_first_tgt();
2538  spdk_nvmf_tgt_new_qpair(target, &sq->spdk_qp);
2539 }
2540 
2541 /*
2542  * Continue the async flow of stopping the SQ
2543  *
2544  * @sq [in]: The NVMf DOCA SQ to stop
2545  */
2547 {
2548  if (sq->spdk_qp.state != SPDK_NVMF_QPAIR_ERROR && sq->spdk_qp.state != SPDK_NVMF_QPAIR_UNINITIALIZED) {
2549  return;
2550  }
2551 
2553  struct nvmf_doca_io *io = sq->io;
2554  struct comch_msg unbind_msg = {
2556  .unbind_sq_db_data =
2557  {
2558  .db = sq->db_handle,
2559  .cookie = (uint64_t)sq,
2560  },
2561  };
2562 
2565  DOCA_LOG_ERR("Failed to stop NVMf DOCA SQ: Failed to stop SQ DB - %s", doca_error_get_name(result));
2566  }
2567 
2568  if (sq->db_state == NVMF_DOCA_SQ_DB_BOUND) {
2569  result = nvmf_doca_dpa_msgq_send(&sq->io->comch.send, &unbind_msg, sizeof(unbind_msg));
2570  if (result != DOCA_SUCCESS) {
2571  DOCA_LOG_ERR(
2572  "Failed to remove SQ from NVMf DOCA IO: Failed to send unbind SQ DB message to DPA - %s",
2574  }
2576  return;
2577  }
2578  if (sq->db_state != NVMF_DOCA_SQ_DB_UNBOUND) {
2579  return;
2580  }
2581 
2583 
2584  if (!is_ctx_idle(doca_dma_as_ctx(sq->dma_pool.dma))) {
2585  return;
2586  }
2587 
2589 
2590  if (!is_ctx_idle(doca_dma_as_ctx(sq->queue.dma))) {
2591  return;
2592  }
2593 
2594  io->stop_sq_cb(sq);
2595 }
2596 
2598 {
2599  spdk_nvmf_qpair_disconnect(&sq->spdk_qp, (nvmf_qpair_disconnect_cb)nvmf_doca_sq_stop_continue, sq);
2600 }
2601 
2602 void nvmf_doca_io_add_sq(struct nvmf_doca_io *io, const struct nvmf_doca_io_add_sq_attr *attr, struct nvmf_doca_sq *sq)
2603 {
2604  struct nvmf_doca_sq_create_attr sq_attr = {
2605  .pe = attr->pe,
2606  .dev = attr->dev,
2607  .nvme_dev = attr->nvme_dev,
2608  .sq_depth = attr->sq_depth,
2609  .host_sq_mmap = attr->host_sq_mmap,
2610  .host_sq_address = attr->host_sq_address,
2611  .db_comp = io->db_comp,
2612  .sq_id = attr->sq_id,
2613  .io = io,
2614  .transport = attr->transport,
2615  .ctx = attr->ctx,
2616  };
2617  doca_error_t result = nvmf_doca_sq_create(&sq_attr, sq);
2618  if (result != DOCA_SUCCESS)
2619  return;
2620 
2621  TAILQ_INSERT_TAIL(&io->sq_list, sq, link);
2622 
2623  struct comch_msg msg = {
2625  .bind_sq_db_data =
2626  {
2627  .db = sq->db_handle,
2628  .cookie = (uint64_t)sq,
2629  },
2630  };
2631  sq->result = nvmf_doca_dpa_msgq_send(&sq->io->comch.send, &msg, sizeof(msg));
2632  if (sq->result != DOCA_SUCCESS) {
2633  DOCA_LOG_ERR("Failed to add SQ to NVMf DOCA IO: Failed to send bind SQ DB message to DPA - %s",
2636  return;
2637  }
2639 }
2640 
2641 /*
2642  * Method invoked once bind DB done message is received from DPA
2643  *
2644  * @msg [in]: The bind done message that was received from DPA
2645  */
2647 {
2648  struct nvmf_doca_sq *sq = (struct nvmf_doca_sq *)msg->bind_sq_db_done_data.cookie;
2649 
2652 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
uint64_t dpa_db_comp
uint64_t dpa_consumer_comp
uint64_t dpa_msix
uint64_t dpa_producer
uint64_t dpa_producer_comp
#define MAX_NUM_COMCH_MSGS
uint32_t db_value
#define RPC_RETURN_STATUS_SUCCESS
uint64_t dpa_consumer
@ COMCH_MSG_TYPE_RAISE_MSIX
@ COMCH_MSG_TYPE_BIND_SQ_DB_DONE
@ COMCH_MSG_TYPE_HOST_DB
@ COMCH_MSG_TYPE_UNBIND_SQ_DB_DONE
@ COMCH_MSG_TYPE_UNBIND_SQ_DB
@ COMCH_MSG_TYPE_BIND_SQ_DB
static uint64_t *restrict src
Definition: dpaintrin.h:230
if(bitoffset % 64+bitlength > 64) result|
DOCA_STABLE doca_error_t doca_buf_inventory_destroy(struct doca_buf_inventory *inventory)
Destroy buffer inventory structure.
static doca_error_t doca_buf_inventory_buf_get_by_addr(struct doca_buf_inventory *inventory, struct doca_mmap *mmap, void *addr, size_t len, struct doca_buf **buf)
Allocate single element from buffer inventory and point it to the buffer defined by addr & len argume...
DOCA_STABLE doca_error_t doca_buf_inventory_start(struct doca_buf_inventory *inventory)
Start element retrieval from inventory.
DOCA_STABLE doca_error_t doca_buf_inventory_create(size_t num_elements, struct doca_buf_inventory **inventory)
Allocates buffer inventory with default/unset attributes.
DOCA_STABLE doca_error_t doca_buf_pool_create(size_t num_elements, size_t element_size, const struct doca_mmap *mmap, struct doca_buf_pool **buf_pool)
Allocates a buffer pool and sets it with doca_buf objects.
DOCA_STABLE doca_error_t doca_buf_pool_buf_alloc(struct doca_buf_pool *buf_pool, struct doca_buf **buf)
This method acquires a doca_buf from a DOCA buffer pool, pointing to an allocated empty buffer.
DOCA_STABLE doca_error_t doca_buf_pool_destroy(struct doca_buf_pool *buf_pool)
Destroy a buffer pool structure.
DOCA_STABLE doca_error_t doca_buf_pool_start(struct doca_buf_pool *buf_pool)
Start a DOCA buffer pool.
DOCA_STABLE doca_error_t doca_buf_dec_refcount(struct doca_buf *buf, uint16_t *refcount)
Decrease the object reference count by 1, if 0 reached, return the element back to the inventory.
DOCA_STABLE doca_error_t doca_buf_set_data_len(struct doca_buf *buf, size_t data_len)
DOCA_STABLE doca_error_t doca_buf_get_data(const struct doca_buf *buf, void **data)
Get the buffer's data.
DOCA_STABLE doca_error_t doca_buf_get_head(const struct doca_buf *buf, void **head)
Get the buffer's head.
DOCA_STABLE doca_error_t doca_buf_reset_data_len(struct doca_buf *buf)
DOCA_STABLE doca_error_t doca_comch_consumer_set_imm_data_len(struct doca_comch_consumer *consumer, uint32_t imm_data_len)
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_create(struct doca_comch_consumer_completion **consumer_comp)
Allocate DOCA Comch consumer completion context on DPA.
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_set_completion(struct doca_comch_consumer *consumer, struct doca_comch_consumer_completion *consumer_comp, uint32_t user_data)
Associate consumer with DPA completion context.
uint64_t doca_dpa_dev_comch_consumer_completion_t
DPA handle for DPA consumer completion context.
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_stop(struct doca_comch_consumer_completion *consumer_comp)
Stop DOCA Comch consumer completion context.
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_set_max_num_recv(struct doca_comch_consumer_completion *consumer_comp, uint32_t max_num_recv)
Set the maximal number of receive operations across all consumers associated with the completion cont...
uint64_t doca_dpa_dev_comch_consumer_t
DPA handle for DPA consumer.
DOCA_STABLE doca_error_t doca_comch_consumer_destroy(struct doca_comch_consumer *consumer)
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_get_dpa_handle(struct doca_comch_consumer *consumer, doca_dpa_dev_comch_consumer_t *dpa_consumer)
Retrieve the handle in the dpa memory space of a doca_comch_consumer.
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_get_dpa_handle(struct doca_comch_consumer_completion *consumer_comp, doca_dpa_dev_comch_consumer_completion_t *consumer_comp_handle)
Get the DPA handle for the DOCA Comch consumer completion context.
DOCA_STABLE doca_error_t doca_comch_consumer_task_post_recv_set_conf(struct doca_comch_consumer *consumer, doca_comch_consumer_task_post_recv_completion_cb_t task_completion_cb, doca_comch_consumer_task_post_recv_completion_cb_t task_error_cb, uint32_t num_post_recv_tasks)
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_destroy(struct doca_comch_consumer_completion *consumer_comp)
Destroy the DOCA Comch consumer completion context.
DOCA_STABLE const uint8_t * doca_comch_consumer_task_post_recv_get_imm_data(const struct doca_comch_consumer_task_post_recv *task)
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_set_dev_max_num_recv(struct doca_comch_consumer *consumer, uint32_t dev_num_recv)
Set the maximal number of receive operations for a DPA consumer.
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_set_imm_data_len(struct doca_comch_consumer_completion *consumer_comp, uint32_t imm_data_len)
DOCA_STABLE doca_error_t doca_comch_consumer_task_post_recv_alloc_init(struct doca_comch_consumer *consumer, struct doca_buf *buf, struct doca_comch_consumer_task_post_recv **task)
Allocate and initialize a doca_consumer post receive task.
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_set_dpa_thread(struct doca_comch_consumer_completion *consumer_comp, struct doca_dpa_thread *dpa_thread)
Set the DOCA DPA thread of the completion context.
DOCA_STABLE struct doca_ctx * doca_comch_consumer_as_ctx(struct doca_comch_consumer *consumer)
DOCA_STABLE struct doca_task * doca_comch_consumer_task_post_recv_as_task(struct doca_comch_consumer_task_post_recv *task)
DOCA_EXPERIMENTAL doca_error_t doca_comch_consumer_completion_start(struct doca_comch_consumer_completion *consumer_comp)
Start DOCA Comch consumer completion context.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_create(struct doca_dev *dev, struct doca_comch_msgq **msgq)
Create a DOCA Comch MsgQ instance.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_producer_create(struct doca_comch_msgq *msgq, struct doca_comch_producer **producer)
Create a DOCA Comch producer instance.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_consumer_create(struct doca_comch_msgq *msgq, struct doca_comch_consumer **consumer)
Create a DOCA Comch consumer instance.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_set_dpa_producer(struct doca_comch_msgq *msgq, struct doca_dpa *dpa)
Set producers to DPA. All producers on this MsgQ will be created for DPA.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_set_max_num_consumers(struct doca_comch_msgq *msgq, uint32_t max_num_consumers)
Set the maximal number of consumers that can be created using this MsgQ.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_set_dpa_consumer(struct doca_comch_msgq *msgq, struct doca_dpa *dpa)
Set consumers to DPA. All consumers on this MsgQ will be created for DPA.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_stop(struct doca_comch_msgq *msgq)
Stop DOCA Comch MsgQ.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_set_max_num_producers(struct doca_comch_msgq *msgq, uint32_t max_num_producers)
Set the maximal number of producers that can be created using this MsgQ.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_start(struct doca_comch_msgq *msgq)
Start DOCA Comch MsgQ.
DOCA_EXPERIMENTAL doca_error_t doca_comch_msgq_destroy(struct doca_comch_msgq *msgq)
Destroy a DOCA Comch MsgQ instance.
DOCA_EXPERIMENTAL doca_error_t doca_comch_producer_get_dpa_handle(struct doca_comch_producer *producer, doca_dpa_dev_comch_producer_t *dpa_producer)
Retrieve the handle in the dpa memory space of a doca_comch_producer.
DOCA_EXPERIMENTAL doca_error_t doca_comch_producer_set_dev_max_num_send(struct doca_comch_producer *producer, uint32_t dev_num_send)
Set the maximal number of send operations for a DPA producer.
DOCA_STABLE struct doca_task * doca_comch_producer_task_send_as_task(struct doca_comch_producer_task_send *task)
DOCA_STABLE doca_error_t doca_comch_producer_task_send_set_conf(struct doca_comch_producer *producer, doca_comch_producer_task_send_completion_cb_t task_completion_cb, doca_comch_producer_task_send_completion_cb_t task_error_cb, uint32_t num_send_tasks)
DOCA_STABLE doca_error_t doca_comch_producer_destroy(struct doca_comch_producer *producer)
DOCA_STABLE struct doca_ctx * doca_comch_producer_as_ctx(struct doca_comch_producer *producer)
DOCA_EXPERIMENTAL doca_error_t doca_comch_producer_dpa_completion_attach(struct doca_comch_producer *producer, struct doca_dpa_completion *dpa_comp)
Associate producer with DPA completion context.
DOCA_STABLE doca_error_t doca_comch_producer_task_send_alloc_init(struct doca_comch_producer *producer, const struct doca_buf *buf, uint8_t *imm_data, uint32_t imm_data_len, uint32_t consumer_id, struct doca_comch_producer_task_send **task)
uint64_t doca_dpa_dev_comch_producer_t
DPA handle for DPA producer.
void(* doca_ctx_state_changed_callback_t)(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
Function to execute on context state change.
Definition: doca_ctx.h:123
DOCA_STABLE doca_error_t doca_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_EXPERIMENTAL doca_error_t doca_ctx_set_datapath_on_dpa(struct doca_ctx *ctx, struct doca_dpa *dpa_dev)
This function binds the DOCA context to a dpa device.
DOCA_STABLE doca_error_t doca_ctx_get_state(const struct doca_ctx *ctx, enum doca_ctx_states *state)
Get context state.
DOCA_STABLE doca_error_t doca_ctx_set_state_changed_cb(struct doca_ctx *ctx, doca_ctx_state_changed_callback_t cb)
Set state changed callback.
DOCA_STABLE doca_error_t doca_ctx_set_user_data(struct doca_ctx *ctx, union doca_data user_data)
set user data to context
DOCA_STABLE doca_error_t doca_ctx_get_num_inflight_tasks(const struct doca_ctx *ctx, size_t *num_inflight_tasks)
Get number of in flight tasks in a doca context.
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
doca_ctx_states
This enum defines the states of a context.
Definition: doca_ctx.h:83
@ DOCA_CTX_STATE_STARTING
Definition: doca_ctx.h:93
@ DOCA_CTX_STATE_STOPPING
Definition: doca_ctx.h:106
@ DOCA_CTX_STATE_IDLE
Definition: doca_ctx.h:88
@ DOCA_CTX_STATE_RUNNING
Definition: doca_ctx.h:98
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_completion_create(struct doca_dpa_thread *th, struct doca_devemu_pci_db_completion **db_comp)
Allocate DOCA devemu PCI device doorbell completion context on DPA. The created completion context wi...
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_completion_stop(struct doca_devemu_pci_db_completion *db_comp)
Stop DOCA devemu PCI device doorbell completion context.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_get_dpa_handle(struct doca_devemu_pci_db *db, doca_dpa_dev_devemu_pci_db_t *db_handle)
Get the DPA handle for the DOCA devemu PCI device doorbell.
uint64_t doca_dpa_dev_devemu_pci_db_completion_t
DPA handle for emulated PCI device doorbell completion context.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_destroy(struct doca_devemu_pci_db *db)
Destroy the DOCA devemu PCI device doorbell.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_msix_create_on_dpa(struct doca_devemu_pci_dev *pci_dev, uint8_t bar_id, uint64_t bar_start_addr, uint16_t msix_idx, uint64_t user_data_on_dpa, struct doca_devemu_pci_msix **msix)
Allocate DOCA devemu PCI device MSI-X context on DPA.
uint64_t doca_dpa_dev_devemu_pci_db_t
DPA handle for emulated PCI device doorbell.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_msix_get_dpa_handle(struct doca_devemu_pci_msix *msix, doca_dpa_dev_devemu_pci_msix_t *msix_handle)
Get the DPA handle for the DOCA devemu PCI device MSI-X.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_msix_destroy(struct doca_devemu_pci_msix *msix)
Destroy the DOCA devemu PCI device MSI-X.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_completion_get_dpa_handle(struct doca_devemu_pci_db_completion *db_comp, doca_dpa_dev_devemu_pci_db_completion_t *db_comp_handle)
Get the DPA handle for the DOCA devemu PCI device doorbell completion context.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_completion_destroy(struct doca_devemu_pci_db_completion *db_comp)
Destroy the DOCA devemu PCI device doorbell completion context.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_completion_start(struct doca_devemu_pci_db_completion *db_comp)
Start DOCA devemu PCI device doorbell completion context.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_stop(struct doca_devemu_pci_db *db)
Stop DOCA devemu PCI device doorbell. A stopped doorbell will not trigger completions on the associat...
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_completion_set_max_num_dbs(struct doca_devemu_pci_db_completion *db_comp, uint32_t num_dbs)
Set the maximal number of doorbells that can be associated with the completion context.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_create_on_dpa(struct doca_devemu_pci_dev *pci_dev, struct doca_devemu_pci_db_completion *db_comp, uint8_t bar_id, uint64_t bar_start_addr, uint32_t db_id, uint64_t user_data_on_dpa, struct doca_devemu_pci_db **db)
Allocate DOCA devemu PCI device doorbell on DPA. The created doorbell will be associated with a singl...
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_db_start(struct doca_devemu_pci_db *db)
Start DOCA devemu PCI device doorbell. A started doorbell will be able to trigger completions on the ...
uint64_t doca_dpa_dev_devemu_pci_msix_t
DPA handle for emulated PCI device MSI-X.
DOCA_STABLE const struct doca_buf * doca_dma_task_memcpy_get_src(const struct doca_dma_task_memcpy *task)
This method gets source buffer from memcpy task.
DOCA_STABLE struct doca_task * doca_dma_task_memcpy_as_task(struct doca_dma_task_memcpy *task)
This method converts a memcpy task to doca_task.
DOCA_STABLE doca_error_t doca_dma_task_memcpy_alloc_init(struct doca_dma *dma, const struct doca_buf *src, struct doca_buf *dst, union doca_data user_data, struct doca_dma_task_memcpy **task)
This method allocates and initializes a DMA memcpy task.
DOCA_STABLE struct doca_ctx * doca_dma_as_ctx(struct doca_dma *dma)
DOCA_STABLE struct doca_buf * doca_dma_task_memcpy_get_dst(const struct doca_dma_task_memcpy *task)
This method gets destination buffer from memcpy task.
DOCA_STABLE doca_error_t doca_dma_task_memcpy_set_conf(struct doca_dma *dma, doca_dma_task_memcpy_completion_cb_t task_completion_cb, doca_dma_task_memcpy_completion_cb_t task_error_cb, uint32_t num_memcpy_tasks)
This method sets the DMA memcpy tasks configuration.
void(* doca_dma_task_memcpy_completion_cb_t)(struct doca_dma_task_memcpy *task, union doca_data task_user_data, union doca_data ctx_user_data)
Function to execute on DMA memcpy task completion.
Definition: doca_dma.h:77
DOCA_STABLE doca_error_t doca_dma_create(struct doca_dev *dev, struct doca_dma **dma)
DOCA_STABLE doca_error_t doca_dma_destroy(struct doca_dma *dma)
DOCA_EXPERIMENTAL doca_error_t doca_dpa_thread_run(struct doca_dpa_thread *dpa_thread)
Run DPA thread.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_thread_create(struct doca_dpa *dpa, struct doca_dpa_thread **dpa_thread)
Create DPA thread.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_destroy(struct doca_dpa_completion *dpa_comp)
Destroy DPA completion context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_set_thread(struct doca_dpa_completion *dpa_comp, struct doca_dpa_thread *dpa_thread)
Set DPA completion context thread.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_mem_alloc(struct doca_dpa *dpa, size_t size, doca_dpa_dev_uintptr_t *dev_ptr)
Allocate DPA heap memory.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_start(struct doca_dpa_completion *dpa_comp)
Start DPA completion context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_mem_free(struct doca_dpa *dpa, doca_dpa_dev_uintptr_t dev_ptr)
Free the previously allocated DPA memory.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_rpc(struct doca_dpa *dpa, doca_dpa_func_t *func, uint64_t *retval,...)
RPC to run DPA kernel.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_get_dpa_handle(struct doca_dpa_completion *dpa_comp, doca_dpa_dev_completion_t *handle)
Get DPA completion context handle.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_create(struct doca_dpa *dpa, unsigned int queue_size, struct doca_dpa_completion **dpa_comp)
Create DPA completion context.
void() doca_dpa_func_t(void)
Generic function pointer type.
Definition: doca_dpa.h:118
uint64_t doca_dpa_dev_completion_t
DPA completion handle type definition.
Definition: doca_dpa.h:88
DOCA_EXPERIMENTAL doca_error_t doca_dpa_thread_set_func_arg(struct doca_dpa_thread *dpa_thread, doca_dpa_func_t *func, uint64_t arg)
Set DPA thread entry point and its argument.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_h2d_memcpy(struct doca_dpa *dpa, doca_dpa_dev_uintptr_t dst_ptr, void *src_ptr, size_t size)
Copy from host memory to DPA Heap.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_stop(struct doca_dpa_completion *dpa_comp)
Stop DPA completion context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_thread_start(struct doca_dpa_thread *dpa_thread)
Start DPA thread.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_thread_stop(struct doca_dpa_thread *dpa_thread)
Stop DPA thread.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_thread_destroy(struct doca_dpa_thread *dpa_thread)
Destroy DPA thread.
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_name(doca_error_t error)
Returns the string representation of an error code name.
@ DOCA_ERROR_BAD_STATE
Definition: doca_error.h:56
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
@ DOCA_ERROR_IN_PROGRESS
Definition: doca_error.h:64
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
DOCA_STABLE doca_error_t doca_mmap_set_memrange(struct doca_mmap *mmap, void *addr, size_t len)
Set the memory range of DOCA memory map.
DOCA_STABLE doca_error_t doca_mmap_destroy(struct doca_mmap *mmap)
Destroy DOCA Memory Map structure.
DOCA_STABLE doca_error_t doca_mmap_create(struct doca_mmap **mmap)
Allocates zero size memory map object with default/unset attributes.
DOCA_STABLE doca_error_t doca_mmap_set_permissions(struct doca_mmap *mmap, uint32_t access_mask)
Set access flags of the registered memory.
DOCA_STABLE doca_error_t doca_mmap_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
DOCA_STABLE doca_error_t doca_mmap_add_dev(struct doca_mmap *mmap, struct doca_dev *dev)
Register DOCA memory map on a given device.
DOCA_EXPERIMENTAL doca_error_t doca_task_submit_ex(struct doca_task *task, uint32_t flags)
Extended version of doca_task_submit.
DOCA_STABLE doca_error_t doca_pe_connect_ctx(struct doca_pe *pe, struct doca_ctx *ctx)
This method connects a context to a progress engine.
DOCA_STABLE doca_error_t doca_task_submit(struct doca_task *task)
Submit a task to a progress engine.
DOCA_STABLE void doca_task_set_user_data(struct doca_task *task, union doca_data user_data)
Set user data to a task.
DOCA_STABLE void doca_task_free(struct doca_task *task)
Free a task back to where it was allocated from.
@ DOCA_TASK_SUBMIT_FLAG_FLUSH
Definition: doca_pe.h:76
@ DOCA_TASK_SUBMIT_FLAG_OPTIMIZE_REPORTS
Definition: doca_pe.h:84
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
@ DOCA_ACCESS_FLAG_LOCAL_READ_ONLY
Definition: doca_types.h:82
static const struct bar_db_region_config db_configs[PCI_TYPE_NUM_BAR_DB_REGIONS]
static const struct bar_region_config msix_table_configs[PCI_TYPE_NUM_BAR_MSIX_TABLE_REGIONS]
static void nvmf_doca_dpa_thread_destroy(struct nvmf_doca_dpa_thread *dpa_thread)
static void nvmf_doca_dma_pool_copy_error_cb(struct doca_dma_task_memcpy *task, union doca_data task_user_data, union doca_data ctx_user_data)
static void nvmf_doca_cq_stop_continue(struct nvmf_doca_cq *cq)
struct doca_buf * nvmf_doca_sq_get_dpu_buffer(struct nvmf_doca_sq *sq)
static void nvmf_doca_dma_pool_dma_state_changed_cb(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
static void nvmf_doca_dpa_msgq_destroy(struct nvmf_doca_dpa_msgq *msgq)
Definition: nvmf_doca_io.c:487
#define CACHELINE_SIZE_BYTES
Definition: nvmf_doca_io.c:39
static void nvmf_doca_dpa_msgq_send_cb(struct doca_comch_producer_task_send *send_task, union doca_data task_user_data, union doca_data ctx_user_data)
Definition: nvmf_doca_io.c:170
static void nvmf_doca_dma_pool_destroy(struct nvmf_doca_dma_pool *dma_pool)
static void nvmf_doca_dpa_comch_destroy(struct nvmf_doca_dpa_comch *comch)
Definition: nvmf_doca_io.c:757
struct doca_buf * nvmf_doca_sq_get_host_buffer(struct nvmf_doca_sq *sq, uintptr_t host_io_address)
static void nvmf_doca_request_free_impl(struct nvmf_doca_sq *sq, struct nvmf_doca_request *request)
void nvmf_doca_request_free(struct nvmf_doca_request *request)
static void nvmf_doca_sq_add_continue(struct nvmf_doca_sq *sq)
void nvmf_doca_io_add_sq(struct nvmf_doca_io *io, const struct nvmf_doca_io_add_sq_attr *attr, struct nvmf_doca_sq *sq)
static doca_error_t nvmf_doca_io_fill_thread_arg(struct nvmf_doca_io *io, struct io_thread_arg *arg)
static void nvmf_doca_cq_queue_dma_state_changed_cb(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
static void nvmf_doca_dma_pool_copy_cb(struct doca_dma_task_memcpy *task, union doca_data task_user_data, union doca_data ctx_user_data)
static doca_error_t nvmf_doca_request_pool_destroy(struct nvmf_doca_sq *sq)
static void nvmf_doca_dpa_comch_stop_continue(struct nvmf_doca_dpa_comch *comch)
Definition: nvmf_doca_io.c:729
static void nvmf_doca_cq_destroy(struct nvmf_doca_cq *cq)
static void nvmf_doca_io_stop_continue(struct nvmf_doca_io *io)
static void nvmf_doca_dma_pool_stop(struct nvmf_doca_dma_pool *dma_pool)
static doca_error_t nvmf_doca_cq_create(const struct nvmf_doca_cq_create_attr *attr, struct nvmf_doca_cq *cq)
doca_dpa_func_t io_thread
static doca_error_t nvmf_doca_queue_create(const struct nvmf_doca_queue_create_attr *attr, struct nvmf_doca_queue *queue)
Definition: nvmf_doca_io.c:812
static doca_error_t nvmf_doca_dpa_thread_run(struct nvmf_doca_dpa_thread *dpa_thread, void *arg, size_t arg_size)
static void nvmf_doca_dpa_msgq_recv_error_cb(struct doca_comch_consumer_task_post_recv *recv_task, union doca_data task_user_data, union doca_data ctx_user_data)
Definition: nvmf_doca_io.c:151
void nvmf_doca_request_complete(struct nvmf_doca_request *request)
static doca_error_t nvmf_doca_dma_pool_create(const struct nvmf_doca_dma_pool_create_attr *attr, struct nvmf_doca_dma_pool *dma_pool)
static void nvmf_doca_sq_update_pi(struct nvmf_doca_sq *sq, uint32_t new_pi)
void nvmf_doca_sq_copy_data(struct nvmf_doca_sq *sq, struct doca_buf *dst_buffer, struct doca_buf *src_buffer, size_t length, union doca_data user_data)
static void nvmf_doca_io_handle_unbind_sq_db_done_msg(const struct comch_msg *msg)
static void nvmf_doca_cq_cqe_post_error_cb(struct doca_dma_task_memcpy *task, union doca_data task_user_data, union doca_data ctx_user_data)
static void nvmf_doca_io_raise_msix(struct nvmf_doca_io *io)
static void nvmf_doca_cq_cqe_post_cb(struct doca_dma_task_memcpy *task, union doca_data task_user_data, union doca_data ctx_user_data)
DOCA_LOG_REGISTER(NVME_PCI_COMMON)
static void nvmf_doca_dpa_comch_msgq_ctx_state_changed_cb(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
Definition: nvmf_doca_io.c:209
static void nvmf_doca_dpa_msgq_recv_cb(struct doca_comch_consumer_task_post_recv *recv_task, union doca_data task_user_data, union doca_data ctx_user_data)
Definition: nvmf_doca_io.c:122
static void nvmf_doca_io_handle_host_db_msg(struct nvmf_doca_io *io, const struct comch_msg *msg)
static doca_error_t nvmf_doca_dpa_comch_create(const struct nvmf_doca_dpa_comch_create_attr *attr, struct nvmf_doca_dpa_comch *comch)
Definition: nvmf_doca_io.c:587
struct nvmf_doca_request * nvmf_doca_request_get(struct nvmf_doca_sq *sq)
static bool nvmf_doca_cq_idle(struct nvmf_doca_cq *cq)
void nvmf_doca_io_destroy(struct nvmf_doca_io *io)
static void nvmf_doca_sq_destroy(struct nvmf_doca_sq *sq)
static void nvmf_doca_sq_sqe_read_cb(struct doca_dma_task_memcpy *task, union doca_data task_user_data, union doca_data ctx_user_data)
static doca_error_t nvmf_doca_dpa_msgq_send(struct nvmf_doca_dpa_msgq *msgq, void *msg, uint32_t msg_size)
Definition: nvmf_doca_io.c:542
static void nvmf_doca_sq_sqe_read_error_cb(struct doca_dma_task_memcpy *task, union doca_data task_user_data, union doca_data ctx_user_data)
static doca_error_t nvmf_doca_dpa_msgq_create(const struct nvmf_doca_dpa_msgq_create_attr *attr, struct nvmf_doca_dpa_msgq *msgq)
Definition: nvmf_doca_io.c:253
static bool is_ctx_idle(struct doca_ctx *ctx)
Definition: nvmf_doca_io.c:697
doca_dpa_func_t io_thread_init_rpc
static void nvmf_doca_queue_destroy(struct nvmf_doca_queue *queue)
static bool is_ctx_running(struct doca_ctx *ctx)
static void nvmf_doca_queue_free_elements(struct nvmf_doca_queue *queue)
Definition: nvmf_doca_io.c:990
doca_error_t nvmf_doca_io_create(const struct nvmf_doca_io_create_attr *attr, struct nvmf_doca_io *io)
static doca_error_t nvmf_doca_sq_create(const struct nvmf_doca_sq_create_attr *attr, struct nvmf_doca_sq *sq)
static void nvmf_doca_io_handle_dpa_msg(struct nvmf_doca_io *io, const struct comch_msg *msg)
Definition: nvmf_doca_io.c:97
static doca_error_t nvmf_doca_request_pool_create(struct nvmf_doca_sq *sq, size_t num_requests)
void nvmf_doca_sq_stop(struct nvmf_doca_sq *sq)
static void nvmf_doca_dpa_msgq_stop(struct nvmf_doca_dpa_msgq *msgq)
Definition: nvmf_doca_io.c:465
void nvmf_doca_io_stop(struct nvmf_doca_io *io)
static void nvmf_doca_queue_stop(struct nvmf_doca_queue *queue)
static void nvmf_doca_dpa_msgq_send_error_cb(struct doca_comch_producer_task_send *send_task, union doca_data task_user_data, union doca_data ctx_user_data)
Definition: nvmf_doca_io.c:189
static void nvmf_doca_sq_queue_dma_state_changed_cb(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
void nvmf_doca_io_post_cqe(struct nvmf_doca_io *io, const struct nvmf_doca_cqe *cqe, union doca_data user_data)
static bool nvmf_doca_dpa_comch_idle(struct nvmf_doca_dpa_comch *comch)
Definition: nvmf_doca_io.c:718
static void nvmf_doca_io_handle_bind_sq_db_done_msg(const struct comch_msg *msg)
static void nvmf_doca_cq_update_ci(struct nvmf_doca_cq *cq, uint32_t new_ci)
static void nvmf_doca_cq_stop(struct nvmf_doca_cq *cq)
static doca_error_t nvmf_doca_dpa_thread_create(const struct nvmf_doca_dpa_thread_create_attr *attr, struct nvmf_doca_dpa_thread *dpa_thread)
void nvmf_doca_io_rm_sq(struct nvmf_doca_sq *sq)
static void nvmf_doca_sq_stop_continue(struct nvmf_doca_sq *sq)
static doca_error_t nvmf_doca_io_run_dpa_thread(struct nvmf_doca_io *io)
static void nvmf_doca_dpa_comch_stop(struct nvmf_doca_dpa_comch *comch)
Definition: nvmf_doca_io.c:746
#define DMA_POOL_DATA_BUFFER_SIZE
Definition: nvmf_doca_io.h:50
@ NVMF_DOCA_SQ_DB_UNBOUND
Definition: nvmf_doca_io.h:138
@ NVMF_DOCA_SQ_DB_BOUND
Definition: nvmf_doca_io.h:140
@ NVMF_DOCA_SQ_DB_UNBIND_REQUESTED
Definition: nvmf_doca_io.h:141
@ NVMF_DOCA_SQ_DB_BIND_REQUESTED
Definition: nvmf_doca_io.h:139
__UINTPTR_TYPE__ uintptr_t
Definition: stdint.h:298
struct bar_region_config region
struct comch_msg::@18::@20 bind_sq_db_done_data
enum comch_msg_type type
Definition: dma_copy_core.h:73
struct comch_msg::@18::@23 host_db_data
struct comch_msg::@18::@22 unbind_sq_db_done_data
struct doca_devemu_pci_db_completion * db_comp
struct doca_mmap * host_cq_mmap
struct doca_dev * dev
struct nvmf_doca_io * io
struct doca_devemu_pci_dev * nvme_dev
struct doca_devemu_pci_db * db
Definition: nvmf_doca_io.h:87
uint32_t pi
Definition: nvmf_doca_io.h:90
struct nvmf_doca_queue queue
Definition: nvmf_doca_io.h:86
uint32_t cq_id
Definition: nvmf_doca_io.h:85
uint32_t ci
Definition: nvmf_doca_io.h:89
struct nvmf_doca_io * io
Definition: nvmf_doca_io.h:88
struct doca_mmap * host_data_mmap
doca_dma_task_memcpy_completion_cb_t success_cb
doca_ctx_state_changed_callback_t dma_state_changed_cb
doca_dma_task_memcpy_completion_cb_t error_cb
struct doca_buf_inventory * host_data_inventory
Definition: nvmf_doca_io.h:100
struct doca_dma * dma
Definition: nvmf_doca_io.h:101
struct doca_mmap * host_data_mmap
Definition: nvmf_doca_io.h:99
struct doca_mmap * local_data_mmap
Definition: nvmf_doca_io.h:97
struct doca_buf_pool * local_data_pool
Definition: nvmf_doca_io.h:98
void * local_data_memory
Definition: nvmf_doca_io.h:96
struct doca_dpa_thread * dpa_thread
Definition: nvmf_doca_io.c:574
struct doca_comch_consumer_completion * consumer_comp
Definition: nvmf_doca_io.h:71
struct nvmf_doca_dpa_msgq recv
Definition: nvmf_doca_io.h:70
struct nvmf_doca_dpa_msgq send
Definition: nvmf_doca_io.h:68
struct doca_dpa_completion * producer_comp
Definition: nvmf_doca_io.h:69
doca_ctx_state_changed_callback_t ctx_state_changed_cb
Definition: nvmf_doca_io.c:241
struct doca_comch_consumer_completion * consumer_comp
Definition: nvmf_doca_io.c:236
struct doca_dpa_completion * producer_comp
Definition: nvmf_doca_io.c:238
struct doca_comch_consumer * consumer
Definition: nvmf_doca_io.h:63
struct doca_comch_msgq * msgq
Definition: nvmf_doca_io.h:61
struct doca_comch_producer * producer
Definition: nvmf_doca_io.h:62
struct doca_dpa * dpa
Definition: nvmf_doca_io.h:172
doca_dpa_dev_uintptr_t arg
Definition: nvmf_doca_io.h:174
struct doca_dpa_thread * thread
Definition: nvmf_doca_io.h:173
struct spdk_nvmf_transport * transport
Definition: nvmf_doca_io.h:256
struct doca_dev * dev
Definition: nvmf_doca_io.h:250
struct doca_devemu_pci_dev * nvme_dev
Definition: nvmf_doca_io.h:251
struct doca_mmap * host_sq_mmap
Definition: nvmf_doca_io.h:253
struct doca_pe * pe
Definition: nvmf_doca_io.h:249
struct doca_mmap * host_cq_mmap
Definition: nvmf_doca_io.h:206
nvmf_doca_sq_copy_data_cb copy_data_cb
Definition: nvmf_doca_io.h:213
struct doca_dpa * dpa
Definition: nvmf_doca_io.h:203
nvmf_doca_cq_post_cqe_cb post_cqe_cb
Definition: nvmf_doca_io.h:211
struct doca_dev * dev
Definition: nvmf_doca_io.h:201
nvmf_doca_sq_fetch_sqe_cb fetch_sqe_cb
Definition: nvmf_doca_io.h:212
nvmf_doca_io_stop_cb stop_io_cb
Definition: nvmf_doca_io.h:215
nvmf_doca_sq_stop_cb stop_sq_cb
Definition: nvmf_doca_io.h:214
struct doca_pe * pe
Definition: nvmf_doca_io.h:200
struct doca_devemu_pci_dev * nvme_dev
Definition: nvmf_doca_io.h:202
struct doca_devemu_pci_db_completion * db_comp
Definition: nvmf_doca_io.h:186
struct nvmf_doca_dpa_comch comch
Definition: nvmf_doca_io.h:184
nvmf_doca_io_stop_cb stop_io_cb
Definition: nvmf_doca_io.h:192
struct nvmf_doca_dpa_thread dpa_thread
Definition: nvmf_doca_io.h:183
struct doca_devemu_pci_msix * msix
Definition: nvmf_doca_io.h:187
nvmf_doca_cq_post_cqe_cb post_cqe_cb
Definition: nvmf_doca_io.h:188
struct nvmf_doca_cq cq
Definition: nvmf_doca_io.h:185
nvmf_doca_sq_stop_cb stop_sq_cb
Definition: nvmf_doca_io.h:191
nvmf_doca_sq_copy_data_cb copy_data_cb
Definition: nvmf_doca_io.h:190
nvmf_doca_sq_fetch_sqe_cb fetch_sqe_cb
Definition: nvmf_doca_io.h:189
doca_dma_task_memcpy_completion_cb_t error_cb
Definition: nvmf_doca_io.c:800
doca_dma_task_memcpy_completion_cb_t success_cb
Definition: nvmf_doca_io.c:799
struct doca_mmap * remote_queue_mmap
Definition: nvmf_doca_io.c:794
doca_ctx_state_changed_callback_t dma_state_changed_cb
Definition: nvmf_doca_io.c:801
struct doca_mmap * local_queue_mmap
Definition: nvmf_doca_io.h:77
struct doca_buf_inventory * inventory
Definition: nvmf_doca_io.h:75
uint32_t num_elements
Definition: nvmf_doca_io.h:81
struct doca_dma * dma
Definition: nvmf_doca_io.h:76
struct doca_dma_task_memcpy ** elements
Definition: nvmf_doca_io.h:79
void * local_queue_address
Definition: nvmf_doca_io.h:78
struct spdk_nvme_cpl cq_entry
Definition: nvmf_doca_io.h:113
struct doca_buf * prp_dpu_buf
Definition: nvmf_doca_io.h:118
struct doca_buf * dpu_buffer[NVMF_REQ_MAX_BUFFERS]
Definition: nvmf_doca_io.h:115
struct spdk_nvmf_request request
Definition: nvmf_doca_io.h:111
struct doca_buf * host_buffer[NVMF_REQ_MAX_BUFFERS]
Definition: nvmf_doca_io.h:116
struct doca_buf * prp_host_buf
Definition: nvmf_doca_io.h:117
struct spdk_nvme_cmd command
Definition: nvmf_doca_io.h:114
struct spdk_nvmf_transport * transport
struct doca_devemu_pci_db_completion * db_comp
struct doca_devemu_pci_dev * nvme_dev
struct doca_mmap * host_sq_mmap
struct doca_dev * dev
struct nvmf_doca_io * io
doca_error_t result
Definition: nvmf_doca_io.h:158
enum nvmf_doca_sq_db_state db_state
Definition: nvmf_doca_io.h:157
struct nvmf_doca_request * request_pool_memory
Definition: nvmf_doca_io.h:159
uint32_t sq_id
Definition: nvmf_doca_io.h:154
doca_dpa_dev_devemu_pci_db_t db_handle
Definition: nvmf_doca_io.h:151
struct nvmf_doca_dma_pool dma_pool
Definition: nvmf_doca_io.h:149
struct nvmf_doca_io * io
Definition: nvmf_doca_io.h:152
struct doca_devemu_pci_db * db
Definition: nvmf_doca_io.h:150
struct spdk_nvmf_qpair spdk_qp
Definition: nvmf_doca_io.h:147
uint32_t pi
Definition: nvmf_doca_io.h:153
struct nvmf_doca_queue queue
Definition: nvmf_doca_io.h:148
Convenience type for representing opaque data.
Definition: doca_types.h:56
uint64_t u64
Definition: doca_types.h:58
void * ptr
Definition: doca_types.h:57
struct upf_accel_ctx * ctx