Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 Marvell
3 : : */
4 : :
5 : : #include <unistd.h>
6 : :
7 : : #include <rte_common.h>
8 : : #include <rte_eal.h>
9 : : #include <rte_errno.h>
10 : :
11 : : #include "virtio_cvq.h"
12 : : #include "virtqueue.h"
13 : :
14 : : static struct virtio_pmd_ctrl *
15 : 0 : virtio_send_command_packed(struct virtcrypto_ctl *cvq,
16 : : struct virtio_pmd_ctrl *ctrl,
17 : : int *dlen, int dnum)
18 : : {
19 : 0 : struct virtqueue *vq = virtcrypto_cq_to_vq(cvq);
20 : : int head;
21 : 0 : struct vring_packed_desc *desc = vq->vq_packed.ring.desc;
22 : : struct virtio_pmd_ctrl *result;
23 : : uint16_t flags;
24 : : int sum = 0;
25 : : int nb_descs = 0;
26 : : int k;
27 : :
28 : : /*
29 : : * Format is enforced in qemu code:
30 : : * One TX packet for header;
31 : : * At least one TX packet per argument;
32 : : * One RX packet for ACK.
33 : : */
34 : 0 : head = vq->vq_avail_idx;
35 : 0 : flags = vq->vq_packed.cached_flags;
36 : 0 : desc[head].addr = cvq->hdr_mem;
37 : 0 : desc[head].len = sizeof(struct virtio_crypto_op_ctrl_req);
38 : 0 : vq->vq_free_cnt--;
39 : : nb_descs++;
40 [ # # ]: 0 : if (++vq->vq_avail_idx >= vq->vq_nentries) {
41 : 0 : vq->vq_avail_idx -= vq->vq_nentries;
42 : 0 : vq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;
43 : : }
44 : :
45 [ # # ]: 0 : for (k = 0; k < dnum; k++) {
46 : 0 : desc[vq->vq_avail_idx].addr = cvq->hdr_mem
47 : : + sizeof(struct virtio_crypto_op_ctrl_req)
48 : 0 : + sizeof(ctrl->input) + sizeof(uint8_t) * sum;
49 : 0 : desc[vq->vq_avail_idx].len = dlen[k];
50 : 0 : desc[vq->vq_avail_idx].flags = VRING_DESC_F_NEXT |
51 : 0 : vq->vq_packed.cached_flags;
52 : 0 : sum += dlen[k];
53 : 0 : vq->vq_free_cnt--;
54 : 0 : nb_descs++;
55 [ # # ]: 0 : if (++vq->vq_avail_idx >= vq->vq_nentries) {
56 : 0 : vq->vq_avail_idx -= vq->vq_nentries;
57 : 0 : vq->vq_packed.cached_flags ^=
58 : : VRING_PACKED_DESC_F_AVAIL_USED;
59 : : }
60 : : }
61 : :
62 : 0 : desc[vq->vq_avail_idx].addr = cvq->hdr_mem
63 : 0 : + sizeof(struct virtio_crypto_op_ctrl_req);
64 : 0 : desc[vq->vq_avail_idx].len = sizeof(ctrl->input);
65 : 0 : desc[vq->vq_avail_idx].flags = VRING_DESC_F_WRITE |
66 : 0 : vq->vq_packed.cached_flags;
67 : 0 : vq->vq_free_cnt--;
68 : 0 : nb_descs++;
69 [ # # ]: 0 : if (++vq->vq_avail_idx >= vq->vq_nentries) {
70 : 0 : vq->vq_avail_idx -= vq->vq_nentries;
71 : 0 : vq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;
72 : : }
73 : :
74 : 0 : virtqueue_store_flags_packed(&desc[head], VRING_DESC_F_NEXT | flags,
75 [ # # ]: 0 : vq->hw->weak_barriers);
76 : :
77 [ # # ]: 0 : virtio_wmb(vq->hw->weak_barriers);
78 : 0 : cvq->notify_queue(vq, cvq->notify_cookie);
79 : :
80 : : /* wait for used desc in virtqueue
81 : : * desc_is_used has a load-acquire or rte_io_rmb inside
82 : : */
83 : 0 : while (!desc_is_used(&desc[head], vq))
84 : 0 : usleep(100);
85 : :
86 : : /* now get used descriptors */
87 : 0 : vq->vq_free_cnt += nb_descs;
88 : 0 : vq->vq_used_cons_idx += nb_descs;
89 [ # # ]: 0 : if (vq->vq_used_cons_idx >= vq->vq_nentries) {
90 : 0 : vq->vq_used_cons_idx -= vq->vq_nentries;
91 : 0 : vq->vq_packed.used_wrap_counter ^= 1;
92 : : }
93 : :
94 : 0 : PMD_INIT_LOG(DEBUG, "vq->vq_free_cnt=%d "
95 : : "vq->vq_avail_idx=%d "
96 : : "vq->vq_used_cons_idx=%d "
97 : : "vq->vq_packed.cached_flags=0x%x "
98 : : "vq->vq_packed.used_wrap_counter=%d",
99 : : vq->vq_free_cnt,
100 : : vq->vq_avail_idx,
101 : : vq->vq_used_cons_idx,
102 : : vq->vq_packed.cached_flags,
103 : : vq->vq_packed.used_wrap_counter);
104 : :
105 : 0 : result = cvq->hdr_mz->addr;
106 : 0 : return result;
107 : : }
108 : :
109 : : static struct virtio_pmd_ctrl *
110 : 0 : virtio_send_command_split(struct virtcrypto_ctl *cvq,
111 : : struct virtio_pmd_ctrl *ctrl,
112 : : int *dlen, int dnum)
113 : : {
114 : 0 : struct virtqueue *vq = virtcrypto_cq_to_vq(cvq);
115 : : struct virtio_pmd_ctrl *result;
116 : : uint32_t head, i;
117 : : int k, sum = 0;
118 : :
119 : 0 : head = vq->vq_desc_head_idx;
120 : :
121 : : /*
122 : : * Format is enforced in qemu code:
123 : : * One TX packet for header;
124 : : * At least one TX packet per argument;
125 : : * One RX packet for ACK.
126 : : */
127 : 0 : vq->vq_split.ring.desc[head].flags = VRING_DESC_F_NEXT;
128 : 0 : vq->vq_split.ring.desc[head].addr = cvq->hdr_mem;
129 : 0 : vq->vq_split.ring.desc[head].len = sizeof(struct virtio_crypto_op_ctrl_req);
130 : 0 : vq->vq_free_cnt--;
131 : 0 : i = vq->vq_split.ring.desc[head].next;
132 : :
133 [ # # ]: 0 : for (k = 0; k < dnum; k++) {
134 : 0 : vq->vq_split.ring.desc[i].flags = VRING_DESC_F_NEXT;
135 : 0 : vq->vq_split.ring.desc[i].addr = cvq->hdr_mem
136 : : + sizeof(struct virtio_crypto_op_ctrl_req)
137 : 0 : + sizeof(ctrl->input) + sizeof(uint8_t) * sum;
138 : 0 : vq->vq_split.ring.desc[i].len = dlen[k];
139 : 0 : sum += dlen[k];
140 : 0 : vq->vq_free_cnt--;
141 : 0 : i = vq->vq_split.ring.desc[i].next;
142 : : }
143 : :
144 : 0 : vq->vq_split.ring.desc[i].flags = VRING_DESC_F_WRITE;
145 : 0 : vq->vq_split.ring.desc[i].addr = cvq->hdr_mem
146 : 0 : + sizeof(struct virtio_crypto_op_ctrl_req);
147 : 0 : vq->vq_split.ring.desc[i].len = sizeof(ctrl->input);
148 : 0 : vq->vq_free_cnt--;
149 : :
150 [ # # ]: 0 : vq->vq_desc_head_idx = vq->vq_split.ring.desc[i].next;
151 : :
152 : : vq_update_avail_ring(vq, head);
153 : : vq_update_avail_idx(vq);
154 : :
155 : 0 : PMD_INIT_LOG(DEBUG, "vq->vq_queue_index = %d", vq->vq_queue_index);
156 : :
157 : 0 : cvq->notify_queue(vq, cvq->notify_cookie);
158 : :
159 [ # # ]: 0 : while (virtqueue_nused(vq) == 0)
160 : 0 : usleep(100);
161 : :
162 [ # # ]: 0 : while (virtqueue_nused(vq)) {
163 : : uint32_t idx, desc_idx, used_idx;
164 : : struct vring_used_elem *uep;
165 : :
166 : 0 : used_idx = (uint32_t)(vq->vq_used_cons_idx
167 : 0 : & (vq->vq_nentries - 1));
168 : 0 : uep = &vq->vq_split.ring.used->ring[used_idx];
169 : 0 : idx = (uint32_t)uep->id;
170 : : desc_idx = idx;
171 : :
172 [ # # ]: 0 : while (vq->vq_split.ring.desc[desc_idx].flags &
173 : : VRING_DESC_F_NEXT) {
174 : 0 : desc_idx = vq->vq_split.ring.desc[desc_idx].next;
175 : 0 : vq->vq_free_cnt++;
176 : : }
177 : :
178 : 0 : vq->vq_split.ring.desc[desc_idx].next = vq->vq_desc_head_idx;
179 : 0 : vq->vq_desc_head_idx = idx;
180 : :
181 : 0 : vq->vq_used_cons_idx++;
182 : 0 : vq->vq_free_cnt++;
183 : : }
184 : :
185 : 0 : PMD_INIT_LOG(DEBUG, "vq->vq_free_cnt=%d vq->vq_desc_head_idx=%d",
186 : : vq->vq_free_cnt, vq->vq_desc_head_idx);
187 : :
188 : 0 : result = cvq->hdr_mz->addr;
189 : 0 : return result;
190 : : }
191 : :
192 : : int
193 : 0 : virtio_crypto_send_command(struct virtcrypto_ctl *cvq, struct virtio_pmd_ctrl *ctrl,
194 : : int *dlen, int dnum)
195 : : {
196 : : struct virtio_pmd_ctrl *result;
197 : : struct virtqueue *vq;
198 : : uint8_t status = ~0;
199 : :
200 : 0 : ctrl->input.status = status;
201 : :
202 [ # # ]: 0 : if (!cvq) {
203 : 0 : PMD_INIT_LOG(ERR, "Control queue is not supported.");
204 : 0 : return -1;
205 : : }
206 : :
207 : 0 : rte_spinlock_lock(&cvq->lock);
208 : 0 : vq = virtcrypto_cq_to_vq(cvq);
209 : :
210 : 0 : PMD_INIT_LOG(DEBUG, "vq->vq_desc_head_idx = %d, status = %d, "
211 : : "vq->hw->cvq = %p vq = %p",
212 : : vq->vq_desc_head_idx, status, vq->hw->cvq, vq);
213 : :
214 [ # # # # ]: 0 : if (vq->vq_free_cnt < dnum + 2 || dnum < 1) {
215 : : rte_spinlock_unlock(&cvq->lock);
216 : 0 : return -1;
217 : : }
218 : :
219 [ # # ]: 0 : memcpy(cvq->hdr_mz->addr, ctrl, sizeof(struct virtio_pmd_ctrl));
220 : :
221 [ # # ]: 0 : if (vtpci_with_packed_queue(vq->hw))
222 : 0 : result = virtio_send_command_packed(cvq, ctrl, dlen, dnum);
223 : : else
224 : 0 : result = virtio_send_command_split(cvq, ctrl, dlen, dnum);
225 : :
226 : : rte_spinlock_unlock(&cvq->lock);
227 : 0 : return result->input.status;
228 : : }
|