1 /* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2023 Cisco Systems, Inc.
6 #include <vnet/dev/dev.h>
8 #include <dev_ena/ena.h>
9 #include <dev_ena/ena_inlines.h>
11 VLIB_REGISTER_LOG_CLASS (ena_log, static) = {
13 .subclass_name = "queue",
17 ena_rx_queue_free (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
19 ena_rxq_t *eq = vnet_dev_get_rx_queue_data (rxq);
20 vnet_dev_port_t *port = rxq->port;
21 vnet_dev_t *dev = port->dev;
23 ASSERT (rxq->started == 0);
24 ASSERT (eq->cq_created == 0);
25 ASSERT (eq->sq_created == 0);
27 log_debug (dev, "queue %u", rxq->queue_id);
29 foreach_pointer (p, eq->buffer_indices, eq->compl_sqe_indices)
33 foreach_pointer (p, eq->cqes, eq->sqes)
34 vnet_dev_dma_mem_free (vm, dev, p);
38 ena_rx_queue_alloc (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
40 vnet_dev_port_t *port = rxq->port;
41 vnet_dev_t *dev = port->dev;
42 ena_rxq_t *eq = vnet_dev_get_rx_queue_data (rxq);
46 ASSERT (eq->buffer_indices == 0);
47 ASSERT (eq->compl_sqe_indices == 0);
48 ASSERT (eq->cqes == 0);
49 ASSERT (eq->sqes == 0);
51 log_debug (dev, "queue %u", rxq->queue_id);
53 eq->buffer_indices = clib_mem_alloc_aligned (
54 sizeof (eq->buffer_indices[0]) * size, CLIB_CACHE_LINE_BYTES);
56 eq->compl_sqe_indices = clib_mem_alloc_aligned (
57 sizeof (eq->compl_sqe_indices[0]) * size, CLIB_CACHE_LINE_BYTES);
59 if ((rv = vnet_dev_dma_mem_alloc (vm, dev, sizeof (eq->cqes[0]) * size, 0,
60 (void **) &eq->cqes)))
63 if ((rv = vnet_dev_dma_mem_alloc (vm, dev, sizeof (eq->sqes[0]) * size, 0,
64 (void **) &eq->sqes)))
70 ena_rx_queue_free (vm, rxq);
75 ena_tx_queue_free (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
77 ena_txq_t *eq = vnet_dev_get_tx_queue_data (txq);
78 vnet_dev_port_t *port = txq->port;
79 vnet_dev_t *dev = port->dev;
81 ASSERT (txq->started == 0);
83 log_debug (dev, "queue %u", txq->queue_id);
85 foreach_pointer (p, eq->buffer_indices, eq->sqe_templates)
89 foreach_pointer (p, eq->cqes, eq->sqes)
90 vnet_dev_dma_mem_free (vm, dev, p);
94 ena_tx_queue_alloc (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
96 vnet_dev_port_t *port = txq->port;
97 vnet_dev_t *dev = port->dev;
98 ena_txq_t *eq = vnet_dev_get_tx_queue_data (txq);
102 ASSERT (eq->buffer_indices == 0);
103 ASSERT (eq->sqe_templates == 0);
104 ASSERT (eq->cqes == 0);
105 ASSERT (eq->sqes == 0);
107 log_debug (dev, "queue %u", txq->queue_id);
109 eq->buffer_indices = clib_mem_alloc_aligned (
110 sizeof (eq->buffer_indices[0]) * size, CLIB_CACHE_LINE_BYTES);
111 eq->sqe_templates = clib_mem_alloc_aligned (
112 sizeof (eq->sqe_templates[0]) * size, CLIB_CACHE_LINE_BYTES);
114 if ((rv = vnet_dev_dma_mem_alloc (vm, dev, sizeof (eq->cqes[0]) * size, 0,
115 (void **) &eq->cqes)))
118 if ((rv = vnet_dev_dma_mem_alloc (vm, dev, sizeof (eq->sqes[0]) * size, 0,
119 (void **) &eq->sqes)))
125 ena_tx_queue_free (vm, txq);
130 ena_rx_queue_start (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
132 ena_rxq_t *eq = vnet_dev_get_rx_queue_data (rxq);
133 vnet_dev_port_t *port = rxq->port;
134 vnet_dev_t *dev = port->dev;
135 ena_device_t *ed = vnet_dev_get_data (dev);
136 u16 buffer_size = vnet_dev_get_rx_queue_buffer_data_size (vm, rxq);
137 u16 size = rxq->size;
140 /* Create Completion Queue */
141 ena_aq_create_cq_resp_t cqresp;
142 ena_aq_create_cq_cmd_t cqcmd = {
143 .interrupt_mode_enabled = 1,
144 .cq_entry_size_words = sizeof (ena_rx_cdesc_t) / 4,
149 ena_set_mem_addr (vm, dev, &cqcmd.cq_ba, eq->cqes);
150 if ((rv = ena_aq_create_cq (vm, dev, &cqcmd, &cqresp)))
152 log_err (dev, "queue %u cq creation failed", rxq->queue_id);
156 eq->cq_idx = cqresp.cq_idx;
159 log_debug (dev, "queue %u cq %u created", rxq->queue_id, eq->cq_idx);
161 /* Create Submission Queue */
162 ena_aq_create_sq_resp_t sqresp;
163 ena_aq_create_sq_cmd_t sqcmd = {
164 .sq_direction = ENA_ADMIN_SQ_DIRECTION_RX,
165 .placement_policy = ENA_ADMIN_SQ_PLACEMENT_POLICY_HOST,
166 .completion_policy = ENA_ADMIN_SQ_COMPLETION_POLICY_DESC,
167 .is_physically_contiguous = 1,
169 .cq_idx = cqresp.cq_idx,
172 ena_set_mem_addr (vm, dev, &sqcmd.sq_ba, eq->sqes);
173 if ((rv = ena_aq_create_sq (vm, dev, &sqcmd, &sqresp)))
175 log_err (dev, "queue %u sq creation failed", rxq->queue_id);
179 eq->sq_idx = sqresp.sq_idx;
180 eq->sq_db = (u32 *) ((u8 *) ed->reg_bar + sqresp.sq_doorbell_offset);
183 log_debug (dev, "queue %u sq %u created, sq_db %p", rxq->queue_id,
184 eq->sq_idx, eq->sq_db);
186 for (int i = 0; i < size; i++)
188 eq->sqes[i] = (ena_rx_desc_t){
190 .length = buffer_size,
194 .reserved5 = 1, /* ena_com says MBO */
198 eq->buffer_indices[i] = VLIB_BUFFER_INVALID_INDEX;
199 eq->compl_sqe_indices[i] = i;
203 eq->n_compl_sqes = size;
208 ena_rx_queue_stop (vm, rxq);
213 ena_tx_queue_start (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
215 ena_txq_t *eq = vnet_dev_get_tx_queue_data (txq);
216 vnet_dev_port_t *port = txq->port;
217 vnet_dev_t *dev = port->dev;
218 ena_device_t *ed = vnet_dev_get_data (dev);
219 u16 size = txq->size;
222 /* Create Completion Queue */
223 ena_aq_create_cq_resp_t cqresp;
224 ena_aq_create_cq_cmd_t cqcmd = {
225 .interrupt_mode_enabled = 1,
226 .cq_entry_size_words = sizeof (ena_tx_cdesc_t) / 4,
231 ena_set_mem_addr (vm, dev, &cqcmd.cq_ba, eq->cqes);
232 if ((rv = ena_aq_create_cq (vm, dev, &cqcmd, &cqresp)))
234 log_err (dev, "queue %u cq creation failed", txq->queue_id);
238 eq->cq_idx = cqresp.cq_idx;
241 log_debug (dev, "queue %u cq %u created", txq->queue_id, eq->cq_idx);
243 /* Create Submission Queue */
244 ena_aq_create_sq_resp_t sqresp;
245 ena_aq_create_sq_cmd_t sqcmd = {
246 .sq_direction = ENA_ADMIN_SQ_DIRECTION_TX,
247 .placement_policy = eq->llq ? ENA_ADMIN_SQ_PLACEMENT_POLICY_DEVICE :
248 ENA_ADMIN_SQ_PLACEMENT_POLICY_HOST,
249 .completion_policy = ENA_ADMIN_SQ_COMPLETION_POLICY_DESC,
250 .is_physically_contiguous = 1,
252 .cq_idx = cqresp.cq_idx,
256 ena_set_mem_addr (vm, dev, &sqcmd.sq_ba, eq->sqes);
257 if ((rv = ena_aq_create_sq (vm, dev, &sqcmd, &sqresp)))
259 log_err (dev, "queue %u sq creation failed", txq->queue_id);
263 eq->sq_idx = sqresp.sq_idx;
264 eq->sq_db = (u32 *) ((u8 *) ed->reg_bar + sqresp.sq_doorbell_offset);
267 log_debug (dev, "queue %u sq %u created, sq_db %p", txq->queue_id,
268 eq->sq_idx, eq->sq_db);
270 for (u32 i = 0; i < size; i++)
272 eq->sqe_templates[i] =
273 (ena_tx_desc_t){ .req_id_lo = i, .req_id_hi = i >> 10, .comp_req = 1 }
276 eq->buffer_indices[i] = VLIB_BUFFER_INVALID_INDEX;
286 (ena_tx_llq_desc128_t *) ((u8 *) ed->mem_bar +
287 sqresp.llq_descriptors_offset);
290 log_debug (dev, "queue %u sq %u created, sq_db %p llq_desc %p",
291 txq->queue_id, eq->sq_idx, eq->sq_db,
292 eq->llq ? eq->llq_descs : 0);
296 ena_tx_queue_stop (vm, txq);
301 ena_free_sq_buffer_indices (vlib_main_t *vm, u32 *sq_buffer_indices,
304 u32 *to = sq_buffer_indices;
306 for (u32 *from = to; from < sq_buffer_indices + n_desc; from++)
307 if (from[0] != VLIB_BUFFER_INVALID_INDEX)
310 if (to - sq_buffer_indices > 0)
311 vlib_buffer_free (vm, sq_buffer_indices, to - sq_buffer_indices);
315 ena_rx_queue_stop (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
317 ena_rxq_t *eq = vnet_dev_get_rx_queue_data (rxq);
318 vnet_dev_t *dev = rxq->port->dev;
323 ena_aq_destroy_sq_cmd_t cmd = {
324 .sq_idx = eq->sq_idx,
325 .sq_direction = ENA_ADMIN_SQ_DIRECTION_TX,
328 if ((rv = ena_aq_destroy_sq (vm, dev, &cmd)))
329 log_err (dev, "queue %u failed to destroy sq %u", rxq->queue_id,
336 ena_aq_destroy_cq_cmd_t cmd = {
337 .cq_idx = eq->cq_idx,
340 if ((rv = ena_aq_destroy_cq (vm, dev, &cmd)))
341 log_err (dev, "queue %u failed to destroy cq %u", rxq->queue_id,
346 if (eq->n_compl_sqes < rxq->size)
347 ena_free_sq_buffer_indices (vm, eq->buffer_indices, rxq->size);
351 ena_tx_queue_stop (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
353 ena_txq_t *eq = vnet_dev_get_tx_queue_data (txq);
354 vnet_dev_t *dev = txq->port->dev;
359 ena_aq_destroy_sq_cmd_t cmd = {
360 .sq_idx = eq->sq_idx,
361 .sq_direction = ENA_ADMIN_SQ_DIRECTION_TX,
364 if ((rv = ena_aq_destroy_sq (vm, dev, &cmd)))
365 log_err (dev, "queue %u failed to destroy sq %u", txq->queue_id,
372 ena_aq_destroy_cq_cmd_t cmd = {
373 .cq_idx = eq->cq_idx,
376 if ((rv = ena_aq_destroy_cq (vm, dev, &cmd)))
377 log_err (dev, "queue %u failed to destroy cq %u", txq->queue_id,
382 if (eq->sq_head != eq->sq_tail)
383 ena_free_sq_buffer_indices (vm, eq->buffer_indices, txq->size);