Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 ZTE Corporation
3 : : */
4 : :
5 : : #include <stdint.h>
6 : : #include <rte_malloc.h>
7 : : #include <rte_mbuf.h>
8 : :
9 : : #include "zxdh_queue.h"
10 : : #include "zxdh_logs.h"
11 : : #include "zxdh_pci.h"
12 : : #include "zxdh_common.h"
13 : : #include "zxdh_msg.h"
14 : :
15 : : #define ZXDH_MBUF_MIN_SIZE sizeof(struct zxdh_net_hdr_dl)
16 : : #define ZXDH_MBUF_SIZE_4K 4096
17 : : #define ZXDH_RX_FREE_THRESH 32
18 : : #define ZXDH_TX_FREE_THRESH 32
19 : :
20 : : struct rte_mbuf *
21 : 0 : zxdh_queue_detach_unused(struct zxdh_virtqueue *vq)
22 : : {
23 : : struct rte_mbuf *cookie = NULL;
24 : : int32_t idx = 0;
25 : :
26 [ # # ]: 0 : if (vq == NULL)
27 : : return NULL;
28 : :
29 [ # # ]: 0 : for (idx = 0; idx < vq->vq_nentries; idx++) {
30 : 0 : cookie = vq->vq_descx[idx].cookie;
31 [ # # ]: 0 : if (cookie != NULL) {
32 : 0 : vq->vq_descx[idx].cookie = NULL;
33 : 0 : return cookie;
34 : : }
35 : : }
36 : : return NULL;
37 : : }
38 : :
39 : : static void
40 : 0 : zxdh_clear_channel(struct rte_eth_dev *dev, uint16_t lch)
41 : : {
42 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
43 : : uint16_t pch;
44 : : uint32_t var, addr, widx, bidx;
45 : :
46 [ # # ]: 0 : if (hw->channel_context[lch].valid == 0)
47 : : return;
48 : : /* get coi table offset and index */
49 : 0 : pch = hw->channel_context[lch].ph_chno;
50 : 0 : widx = pch / 32;
51 : 0 : bidx = pch % 32;
52 : 0 : addr = ZXDH_QUERES_SHARE_BASE + (widx * sizeof(uint32_t));
53 : 0 : var = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr);
54 : 0 : var &= ~(1 << bidx);
55 : 0 : zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);
56 : 0 : hw->channel_context[lch].valid = 0;
57 : 0 : hw->channel_context[lch].ph_chno = 0;
58 : 0 : PMD_DRV_LOG(DEBUG, " phyque %d release end ", pch);
59 : : }
60 : :
61 : : static int32_t
62 : 0 : zxdh_release_channel(struct rte_eth_dev *dev)
63 : : {
64 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
65 : 0 : u_int16_t rxq_num = hw->rx_qnum;
66 : 0 : u_int16_t txq_num = hw->tx_qnum;
67 : : uint16_t lch, i;
68 : : int32_t ret = 0;
69 : :
70 [ # # ]: 0 : if (hw->queue_set_flag == 1) {
71 [ # # ]: 0 : for (i = 0; i < rxq_num; i++) {
72 : 0 : lch = i * 2;
73 : 0 : PMD_DRV_LOG(DEBUG, "free success!");
74 [ # # ]: 0 : if (hw->channel_context[lch].valid == 0)
75 : 0 : continue;
76 : 0 : PMD_DRV_LOG(DEBUG, "phyque %d no need to release backend do it",
77 : : hw->channel_context[lch].ph_chno);
78 : 0 : hw->channel_context[lch].valid = 0;
79 : 0 : hw->channel_context[lch].ph_chno = 0;
80 : : }
81 [ # # ]: 0 : for (i = 0; i < txq_num; i++) {
82 : 0 : lch = i * 2 + 1;
83 : 0 : PMD_DRV_LOG(DEBUG, "free success!");
84 [ # # ]: 0 : if (hw->channel_context[lch].valid == 0)
85 : 0 : continue;
86 : 0 : PMD_DRV_LOG(DEBUG, "phyque %d no need to release backend do it",
87 : : hw->channel_context[lch].ph_chno);
88 : 0 : hw->channel_context[lch].valid = 0;
89 : 0 : hw->channel_context[lch].ph_chno = 0;
90 : : }
91 : 0 : hw->queue_set_flag = 0;
92 : 0 : return 0;
93 : : }
94 : 0 : ret = zxdh_timedlock(hw, 1000);
95 [ # # ]: 0 : if (ret) {
96 : 0 : PMD_DRV_LOG(ERR, "Acquiring hw lock got failed, timeout");
97 : 0 : return -1;
98 : : }
99 : :
100 [ # # ]: 0 : for (i = 0 ; i < rxq_num ; i++) {
101 : 0 : lch = i * 2;
102 : 0 : zxdh_clear_channel(dev, lch);
103 : : }
104 [ # # ]: 0 : for (i = 0; i < txq_num ; i++) {
105 : 0 : lch = i * 2 + 1;
106 : 0 : zxdh_clear_channel(dev, lch);
107 : : }
108 : 0 : zxdh_release_lock(hw);
109 : :
110 : 0 : return 0;
111 : : }
112 : :
113 : : int32_t
114 : 0 : zxdh_get_queue_type(uint16_t vtpci_queue_idx)
115 : : {
116 [ # # ]: 0 : if (vtpci_queue_idx % 2 == 0)
117 : : return ZXDH_VTNET_RQ;
118 : : else
119 : 0 : return ZXDH_VTNET_TQ;
120 : : }
121 : :
122 : : int32_t
123 : 0 : zxdh_free_queues(struct rte_eth_dev *dev)
124 : : {
125 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
126 : : struct zxdh_virtqueue *vq = NULL;
127 : 0 : u_int16_t rxq_num = hw->rx_qnum;
128 : 0 : u_int16_t txq_num = hw->tx_qnum;
129 : : uint16_t i = 0;
130 : :
131 [ # # ]: 0 : if (hw->vqs == NULL)
132 : : return 0;
133 : :
134 [ # # ]: 0 : for (i = 0; i < rxq_num; i++) {
135 : 0 : vq = hw->vqs[i * 2];
136 [ # # ]: 0 : if (vq == NULL)
137 : 0 : continue;
138 : :
139 : 0 : ZXDH_VTPCI_OPS(hw)->del_queue(hw, vq);
140 : 0 : rte_memzone_free(vq->rxq.mz);
141 : 0 : rte_free(vq);
142 : 0 : hw->vqs[i * 2] = NULL;
143 : 0 : PMD_MSG_LOG(DEBUG, "Release to queue %d success!", i * 2);
144 : : }
145 [ # # ]: 0 : for (i = 0; i < txq_num; i++) {
146 : 0 : vq = hw->vqs[i * 2 + 1];
147 [ # # ]: 0 : if (vq == NULL)
148 : 0 : continue;
149 : :
150 : 0 : ZXDH_VTPCI_OPS(hw)->del_queue(hw, vq);
151 : 0 : rte_memzone_free(vq->txq.mz);
152 : 0 : rte_memzone_free(vq->txq.zxdh_net_hdr_mz);
153 : 0 : rte_free(vq);
154 : 0 : hw->vqs[i * 2 + 1] = NULL;
155 : 0 : PMD_DRV_LOG(DEBUG, "Release to queue %d success!", i * 2 + 1);
156 : : }
157 : :
158 [ # # ]: 0 : if (zxdh_release_channel(dev) < 0) {
159 : 0 : PMD_DRV_LOG(ERR, "Failed to clear coi table");
160 : 0 : return -1;
161 : : }
162 : :
163 : 0 : rte_free(hw->vqs);
164 : 0 : hw->vqs = NULL;
165 : :
166 : 0 : return 0;
167 : : }
168 : :
169 : : static int
170 : 0 : zxdh_check_mempool(struct rte_mempool *mp, uint16_t offset, uint16_t min_length)
171 : : {
172 : : uint16_t data_room_size;
173 : :
174 [ # # ]: 0 : if (mp == NULL)
175 : : return -EINVAL;
176 : : data_room_size = rte_pktmbuf_data_room_size(mp);
177 [ # # ]: 0 : if (data_room_size < offset + min_length) {
178 : 0 : PMD_RX_LOG(ERR,
179 : : "%s mbuf_data_room_size %u < %u (%u + %u)",
180 : : mp->name, data_room_size,
181 : : offset + min_length, offset, min_length);
182 : 0 : return -EINVAL;
183 : : }
184 : : return 0;
185 : : }
186 : :
187 : : int32_t
188 : 0 : zxdh_dev_rx_queue_setup(struct rte_eth_dev *dev,
189 : : uint16_t queue_idx,
190 : : uint16_t nb_desc,
191 : : uint32_t socket_id __rte_unused,
192 : : const struct rte_eth_rxconf *rx_conf,
193 : : struct rte_mempool *mp)
194 : : {
195 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
196 : 0 : uint16_t vtpci_logic_qidx = 2 * queue_idx + ZXDH_RQ_QUEUE_IDX;
197 : 0 : struct zxdh_virtqueue *vq = hw->vqs[vtpci_logic_qidx];
198 : : int32_t ret = 0;
199 : :
200 [ # # ]: 0 : if (rx_conf->rx_deferred_start) {
201 : 0 : PMD_RX_LOG(ERR, "Rx deferred start is not supported");
202 : 0 : return -EINVAL;
203 : : }
204 : 0 : uint16_t rx_free_thresh = rx_conf->rx_free_thresh;
205 : :
206 [ # # ]: 0 : if (rx_free_thresh == 0)
207 : 0 : rx_free_thresh = RTE_MIN(vq->vq_nentries / 4, ZXDH_RX_FREE_THRESH);
208 : :
209 : : /* rx_free_thresh must be multiples of four. */
210 [ # # ]: 0 : if (rx_free_thresh & 0x3) {
211 : 0 : PMD_RX_LOG(ERR, "(rx_free_thresh=%u port=%u queue=%u)",
212 : : rx_free_thresh, dev->data->port_id, queue_idx);
213 : 0 : return -EINVAL;
214 : : }
215 : : /* rx_free_thresh must be less than the number of RX entries */
216 [ # # ]: 0 : if (rx_free_thresh >= vq->vq_nentries) {
217 : 0 : PMD_RX_LOG(ERR, "RX entries (%u). (rx_free_thresh=%u port=%u queue=%u)",
218 : : vq->vq_nentries, rx_free_thresh, dev->data->port_id, queue_idx);
219 : 0 : return -EINVAL;
220 : : }
221 : 0 : vq->vq_free_thresh = rx_free_thresh;
222 : : nb_desc = ZXDH_QUEUE_DEPTH;
223 : :
224 : 0 : vq->vq_free_cnt = RTE_MIN(vq->vq_free_cnt, nb_desc);
225 : 0 : struct zxdh_virtnet_rx *rxvq = &vq->rxq;
226 : :
227 : 0 : rxvq->queue_id = vtpci_logic_qidx;
228 : :
229 : : int mbuf_min_size = ZXDH_MBUF_MIN_SIZE;
230 : :
231 [ # # ]: 0 : if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
232 : : mbuf_min_size = ZXDH_MBUF_SIZE_4K;
233 : :
234 : 0 : ret = zxdh_check_mempool(mp, RTE_PKTMBUF_HEADROOM, mbuf_min_size);
235 [ # # ]: 0 : if (ret != 0) {
236 : 0 : PMD_RX_LOG(ERR,
237 : : "rxq setup but mpool size too small(<%d) failed", mbuf_min_size);
238 : 0 : return -EINVAL;
239 : : }
240 : 0 : rxvq->mpool = mp;
241 [ # # ]: 0 : if (queue_idx < dev->data->nb_rx_queues)
242 : 0 : dev->data->rx_queues[queue_idx] = rxvq;
243 : :
244 : : return 0;
245 : : }
246 : :
247 : : int32_t
248 : 0 : zxdh_dev_tx_queue_setup(struct rte_eth_dev *dev,
249 : : uint16_t queue_idx,
250 : : uint16_t nb_desc,
251 : : uint32_t socket_id __rte_unused,
252 : : const struct rte_eth_txconf *tx_conf)
253 : : {
254 : 0 : uint16_t vtpci_logic_qidx = 2 * queue_idx + ZXDH_TQ_QUEUE_IDX;
255 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
256 : 0 : struct zxdh_virtqueue *vq = hw->vqs[vtpci_logic_qidx];
257 : : struct zxdh_virtnet_tx *txvq = NULL;
258 : : uint16_t tx_free_thresh = 0;
259 : :
260 [ # # ]: 0 : if (tx_conf->tx_deferred_start) {
261 : 0 : PMD_TX_LOG(ERR, "Tx deferred start is not supported");
262 : 0 : return -EINVAL;
263 : : }
264 : :
265 : : nb_desc = ZXDH_QUEUE_DEPTH;
266 : :
267 : 0 : vq->vq_free_cnt = RTE_MIN(vq->vq_free_cnt, nb_desc);
268 : :
269 : 0 : txvq = &vq->txq;
270 : 0 : txvq->queue_id = vtpci_logic_qidx;
271 : :
272 : 0 : tx_free_thresh = tx_conf->tx_free_thresh;
273 [ # # ]: 0 : if (tx_free_thresh == 0)
274 : 0 : tx_free_thresh = RTE_MIN(vq->vq_nentries / 4, ZXDH_TX_FREE_THRESH);
275 : :
276 : : /* tx_free_thresh must be less than the number of TX entries minus 3 */
277 [ # # ]: 0 : if (tx_free_thresh >= (vq->vq_nentries - 3)) {
278 : 0 : PMD_TX_LOG(ERR, "TX entries - 3 (%u). (tx_free_thresh=%u port=%u queue=%u)",
279 : : vq->vq_nentries - 3, tx_free_thresh, dev->data->port_id, queue_idx);
280 : 0 : return -EINVAL;
281 : : }
282 : :
283 : 0 : vq->vq_free_thresh = tx_free_thresh;
284 : :
285 [ # # ]: 0 : if (queue_idx < dev->data->nb_tx_queues)
286 : 0 : dev->data->tx_queues[queue_idx] = txvq;
287 : :
288 : : return 0;
289 : : }
290 : :
291 : : int32_t
292 : 0 : zxdh_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
293 : : {
294 : 0 : struct zxdh_virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
295 [ # # ]: 0 : struct zxdh_virtqueue *vq = rxvq->vq;
296 : :
297 : : zxdh_queue_enable_intr(vq);
298 : 0 : return 0;
299 : : }
300 : :
301 : : int32_t
302 : 0 : zxdh_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
303 : : {
304 : 0 : struct zxdh_virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
305 [ # # ]: 0 : struct zxdh_virtqueue *vq = rxvq->vq;
306 : :
307 : : zxdh_queue_disable_intr(vq);
308 : 0 : return 0;
309 : : }
310 : :
311 : 0 : int32_t zxdh_enqueue_recv_refill_packed(struct zxdh_virtqueue *vq,
312 : : struct rte_mbuf **cookie, uint16_t num)
313 : : {
314 : 0 : struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
315 : : struct zxdh_vq_desc_extra *dxp;
316 : 0 : uint16_t flags = vq->vq_packed.cached_flags;
317 : : int32_t i;
318 : : uint16_t idx;
319 : :
320 [ # # ]: 0 : for (i = 0; i < num; i++) {
321 : 0 : idx = vq->vq_avail_idx;
322 : 0 : dxp = &vq->vq_descx[idx];
323 : 0 : dxp->cookie = (void *)cookie[i];
324 : 0 : dxp->ndescs = 1;
325 : : /* rx pkt fill in data_off */
326 : 0 : start_dp[idx].addr = rte_mbuf_iova_get(cookie[i]) + RTE_PKTMBUF_HEADROOM;
327 : 0 : start_dp[idx].len = cookie[i]->buf_len - RTE_PKTMBUF_HEADROOM;
328 : :
329 : : zxdh_queue_store_flags_packed(&start_dp[idx], flags);
330 [ # # ]: 0 : if (++vq->vq_avail_idx >= vq->vq_nentries) {
331 : 0 : vq->vq_avail_idx -= vq->vq_nentries;
332 : 0 : vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
333 : : flags = vq->vq_packed.cached_flags;
334 : : }
335 : : }
336 : 0 : vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - num);
337 : 0 : return 0;
338 : : }
339 : :
340 : 0 : int32_t zxdh_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t logic_qidx)
341 : : {
342 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
343 : 0 : struct zxdh_virtqueue *vq = hw->vqs[logic_qidx];
344 : : struct zxdh_virtnet_rx *rxvq = &vq->rxq;
345 : : uint16_t desc_idx;
346 : : int32_t error = 0;
347 : :
348 : : /* Allocate blank mbufs for the each rx descriptor */
349 : 0 : memset(&rxvq->fake_mbuf, 0, sizeof(rxvq->fake_mbuf));
350 [ # # ]: 0 : for (desc_idx = 0; desc_idx < ZXDH_MBUF_BURST_SZ; desc_idx++)
351 : 0 : vq->sw_ring[vq->vq_nentries + desc_idx] = &rxvq->fake_mbuf;
352 : :
353 [ # # ]: 0 : while (!zxdh_queue_full(vq)) {
354 : : uint16_t free_cnt = vq->vq_free_cnt;
355 : :
356 : 0 : free_cnt = RTE_MIN(ZXDH_MBUF_BURST_SZ, free_cnt);
357 : 0 : struct rte_mbuf *new_pkts[free_cnt];
358 : :
359 [ # # ]: 0 : if (likely(rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt) == 0)) {
360 : 0 : error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
361 [ # # ]: 0 : if (unlikely(error)) {
362 : : int32_t i;
363 [ # # ]: 0 : for (i = 0; i < free_cnt; i++)
364 : 0 : rte_pktmbuf_free(new_pkts[i]);
365 : : }
366 : : } else {
367 : 0 : PMD_DRV_LOG(ERR, "port %d rxq %d allocated bufs from %s failed",
368 : : hw->port_id, logic_qidx, rxvq->mpool->name);
369 : 0 : break;
370 : : }
371 : : }
372 : 0 : return 0;
373 : : }
374 : :
375 : 0 : void zxdh_queue_rxvq_flush(struct zxdh_virtqueue *vq)
376 : : {
377 : : struct zxdh_vq_desc_extra *dxp = NULL;
378 : : uint16_t i = 0;
379 : 0 : struct zxdh_vring_packed_desc *descs = vq->vq_packed.ring.desc;
380 : : int32_t cnt = 0;
381 : :
382 : 0 : i = vq->vq_used_cons_idx;
383 [ # # ]: 0 : while (zxdh_desc_used(&descs[i], vq) && cnt++ < vq->vq_nentries) {
384 : 0 : dxp = &vq->vq_descx[descs[i].id];
385 [ # # ]: 0 : if (dxp->cookie != NULL) {
386 : 0 : rte_pktmbuf_free(dxp->cookie);
387 : 0 : dxp->cookie = NULL;
388 : : }
389 : 0 : vq->vq_free_cnt++;
390 : 0 : vq->vq_used_cons_idx++;
391 [ # # ]: 0 : if (vq->vq_used_cons_idx >= vq->vq_nentries) {
392 : 0 : vq->vq_used_cons_idx -= vq->vq_nentries;
393 : 0 : vq->vq_packed.used_wrap_counter ^= 1;
394 : : }
395 : 0 : i = vq->vq_used_cons_idx;
396 : : }
397 : 0 : }
|