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