Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include "base/hinic3_compat.h"
6 : : #include "base/hinic3_cmd.h"
7 : : #include "base/hinic3_cmdq.h"
8 : : #include "base/hinic3_hw_comm.h"
9 : : #include "base/hinic3_nic_cfg.h"
10 : : #include "hinic3_nic_io.h"
11 : : #include "hinic3_rx.h"
12 : : #include "hinic3_tx.h"
13 : :
14 : : #define HINIC3_DEAULT_TX_CI_PENDING_LIMIT 3
15 : : #define HINIC3_DEAULT_TX_CI_COALESCING_TIME 16
16 : : #define HINIC3_DEAULT_DROP_THD_ON 0xFFFF
17 : : #define HINIC3_DEAULT_DROP_THD_OFF 0
18 : :
19 : : #define WQ_PREFETCH_MAX 6
20 : : #define WQ_PREFETCH_MIN 1
21 : : #define WQ_PREFETCH_THRESHOLD 256
22 : :
23 : : #define HINIC3_Q_CTXT_MAX \
24 : : ((uint16_t)(((HINIC3_CMDQ_BUF_SIZE - 8) - RTE_PKTMBUF_HEADROOM) / 64))
25 : :
26 : : enum hinic3_qp_ctxt_type {
27 : : HINIC3_QP_CTXT_TYPE_SQ,
28 : : HINIC3_QP_CTXT_TYPE_RQ,
29 : : };
30 : :
31 : : struct hinic3_qp_ctxt_header {
32 : : uint16_t num_queues;
33 : : uint16_t queue_type;
34 : : uint16_t start_qid;
35 : : uint16_t rsvd;
36 : : };
37 : :
38 : : struct hinic3_sq_ctxt {
39 : : uint32_t ci_pi;
40 : : uint32_t drop_mode_sp; /**< Packet drop mode and special flags. */
41 : : uint32_t wq_pfn_hi_owner; /**< High PFN and ownership flag. */
42 : : uint32_t wq_pfn_lo; /**< Low bits of work queue PFN. */
43 : :
44 : : uint32_t rsvd0; /**< Reserved field 0. */
45 : : uint32_t pkt_drop_thd; /**< Packet drop threshold. */
46 : : uint32_t global_sq_id;
47 : : uint32_t vlan_ceq_attr; /**< VLAN and CEQ attributes. */
48 : :
49 : : uint32_t pref_cache; /**< Cache prefetch settings for the queue. */
50 : : uint32_t pref_ci_owner; /**< Prefetch settings for CI and ownership. */
51 : : uint32_t pref_wq_pfn_hi_ci; /**< Prefetch settings for high PFN and CI. */
52 : : uint32_t pref_wq_pfn_lo; /**< Prefetch settings for low PFN. */
53 : :
54 : : uint32_t rsvd8; /**< Reserved field 8. */
55 : : uint32_t rsvd9; /**< Reserved field 9. */
56 : : uint32_t wq_block_pfn_hi; /**< High bits of work queue block PFN. */
57 : : uint32_t wq_block_pfn_lo; /**< Low bits of work queue block PFN. */
58 : : };
59 : :
60 : : struct hinic3_rq_ctxt {
61 : : uint32_t ci_pi;
62 : : uint32_t ceq_attr; /**< Completion event queue attributes. */
63 : : uint32_t wq_pfn_hi_type_owner; /**< High PFN, WQE type and ownership flag. */
64 : : uint32_t wq_pfn_lo; /**< Low bits of work queue PFN. */
65 : :
66 : : uint32_t rsvd[3]; /**< Reserved field. */
67 : : uint32_t cqe_sge_len; /**< CQE scatter/gather element length. */
68 : :
69 : : uint32_t pref_cache; /**< Cache prefetch settings for the queue. */
70 : : uint32_t pref_ci_owner; /**< Prefetch settings for CI and ownership. */
71 : : uint32_t pref_wq_pfn_hi_ci; /**< Prefetch settings for high PFN and CI. */
72 : : uint32_t pref_wq_pfn_lo; /**< Prefetch settings for low PFN. */
73 : :
74 : : uint32_t pi_paddr_hi; /**< High 32-bits of PI DMA address. */
75 : : uint32_t pi_paddr_lo; /**< Low 32-bits of PI DMA address. */
76 : : uint32_t wq_block_pfn_hi; /**< High bits of work queue block PFN. */
77 : : uint32_t wq_block_pfn_lo; /**< Low bits of work queue block PFN. */
78 : : };
79 : :
80 : : struct hinic3_sq_ctxt_block {
81 : : struct hinic3_qp_ctxt_header cmdq_hdr;
82 : : struct hinic3_sq_ctxt sq_ctxt[HINIC3_Q_CTXT_MAX];
83 : : };
84 : :
85 : : struct hinic3_rq_ctxt_block {
86 : : struct hinic3_qp_ctxt_header cmdq_hdr;
87 : : struct hinic3_rq_ctxt rq_ctxt[HINIC3_Q_CTXT_MAX];
88 : : };
89 : :
90 : : struct hinic3_clean_queue_ctxt {
91 : : struct hinic3_qp_ctxt_header cmdq_hdr;
92 : : uint32_t rsvd;
93 : : };
94 : :
95 : : #define SQ_CTXT_SIZE(num_sqs) \
96 : : ((uint16_t)(sizeof(struct hinic3_qp_ctxt_header) + \
97 : : (num_sqs) * sizeof(struct hinic3_sq_ctxt)))
98 : :
99 : : #define RQ_CTXT_SIZE(num_rqs) \
100 : : ((uint16_t)(sizeof(struct hinic3_qp_ctxt_header) + \
101 : : (num_rqs) * sizeof(struct hinic3_rq_ctxt)))
102 : :
103 : : #define CI_IDX_HIGH_SHIFH 12
104 : :
105 : : #define CI_HIGN_IDX(val) ((val) >> CI_IDX_HIGH_SHIFH)
106 : :
107 : : #define SQ_CTXT_PI_IDX_SHIFT 0
108 : : #define SQ_CTXT_CI_IDX_SHIFT 16
109 : :
110 : : #define SQ_CTXT_PI_IDX_MASK 0xFFFFU
111 : : #define SQ_CTXT_CI_IDX_MASK 0xFFFFU
112 : :
113 : : #define SQ_CTXT_CI_PI_SET(val, member) \
114 : : (((val) & SQ_CTXT_##member##_MASK) << SQ_CTXT_##member##_SHIFT)
115 : :
116 : : #define SQ_CTXT_MODE_SP_FLAG_SHIFT 0
117 : : #define SQ_CTXT_MODE_PKT_DROP_SHIFT 1
118 : :
119 : : #define SQ_CTXT_MODE_SP_FLAG_MASK 0x1U
120 : : #define SQ_CTXT_MODE_PKT_DROP_MASK 0x1U
121 : :
122 : : #define SQ_CTXT_MODE_SET(val, member) \
123 : : (((val) & SQ_CTXT_MODE_##member##_MASK) \
124 : : << SQ_CTXT_MODE_##member##_SHIFT)
125 : :
126 : : #define SQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0
127 : : #define SQ_CTXT_WQ_PAGE_OWNER_SHIFT 23
128 : :
129 : : #define SQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU
130 : : #define SQ_CTXT_WQ_PAGE_OWNER_MASK 0x1U
131 : :
132 : : #define SQ_CTXT_WQ_PAGE_SET(val, member) \
133 : : (((val) & SQ_CTXT_WQ_PAGE_##member##_MASK) \
134 : : << SQ_CTXT_WQ_PAGE_##member##_SHIFT)
135 : :
136 : : #define SQ_CTXT_PKT_DROP_THD_ON_SHIFT 0
137 : : #define SQ_CTXT_PKT_DROP_THD_OFF_SHIFT 16
138 : :
139 : : #define SQ_CTXT_PKT_DROP_THD_ON_MASK 0xFFFFU
140 : : #define SQ_CTXT_PKT_DROP_THD_OFF_MASK 0xFFFFU
141 : :
142 : : #define SQ_CTXT_PKT_DROP_THD_SET(val, member) \
143 : : (((val) & SQ_CTXT_PKT_DROP_##member##_MASK) \
144 : : << SQ_CTXT_PKT_DROP_##member##_SHIFT)
145 : :
146 : : #define SQ_CTXT_GLOBAL_SQ_ID_SHIFT 0
147 : :
148 : : #define SQ_CTXT_GLOBAL_SQ_ID_MASK 0x1FFFU
149 : :
150 : : #define SQ_CTXT_GLOBAL_QUEUE_ID_SET(val, member) \
151 : : (((val) & SQ_CTXT_##member##_MASK) << SQ_CTXT_##member##_SHIFT)
152 : :
153 : : #define SQ_CTXT_VLAN_TAG_SHIFT 0
154 : : #define SQ_CTXT_VLAN_TYPE_SEL_SHIFT 16
155 : : #define SQ_CTXT_VLAN_INSERT_MODE_SHIFT 19
156 : : #define SQ_CTXT_VLAN_CEQ_EN_SHIFT 23
157 : :
158 : : #define SQ_CTXT_VLAN_TAG_MASK 0xFFFFU
159 : : #define SQ_CTXT_VLAN_TYPE_SEL_MASK 0x7U
160 : : #define SQ_CTXT_VLAN_INSERT_MODE_MASK 0x3U
161 : : #define SQ_CTXT_VLAN_CEQ_EN_MASK 0x1U
162 : :
163 : : #define SQ_CTXT_VLAN_CEQ_SET(val, member) \
164 : : (((val) & SQ_CTXT_VLAN_##member##_MASK) \
165 : : << SQ_CTXT_VLAN_##member##_SHIFT)
166 : :
167 : : #define SQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0
168 : : #define SQ_CTXT_PREF_CACHE_MAX_SHIFT 14
169 : : #define SQ_CTXT_PREF_CACHE_MIN_SHIFT 25
170 : :
171 : : #define SQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU
172 : : #define SQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU
173 : : #define SQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU
174 : :
175 : : #define SQ_CTXT_PREF_CI_HI_SHIFT 0
176 : : #define SQ_CTXT_PREF_OWNER_SHIFT 4
177 : :
178 : : #define SQ_CTXT_PREF_CI_HI_MASK 0xFU
179 : : #define SQ_CTXT_PREF_OWNER_MASK 0x1U
180 : :
181 : : #define SQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0
182 : : #define SQ_CTXT_PREF_CI_LOW_SHIFT 20
183 : :
184 : : #define SQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU
185 : : #define SQ_CTXT_PREF_CI_LOW_MASK 0xFFFU
186 : :
187 : : #define SQ_CTXT_PREF_SET(val, member) \
188 : : (((val) & SQ_CTXT_PREF_##member##_MASK) \
189 : : << SQ_CTXT_PREF_##member##_SHIFT)
190 : :
191 : : #define SQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0
192 : :
193 : : #define SQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU
194 : :
195 : : #define SQ_CTXT_WQ_BLOCK_SET(val, member) \
196 : : (((val) & SQ_CTXT_WQ_BLOCK_##member##_MASK) \
197 : : << SQ_CTXT_WQ_BLOCK_##member##_SHIFT)
198 : :
199 : : #define RQ_CTXT_PI_IDX_SHIFT 0
200 : : #define RQ_CTXT_CI_IDX_SHIFT 16
201 : :
202 : : #define RQ_CTXT_PI_IDX_MASK 0xFFFFU
203 : : #define RQ_CTXT_CI_IDX_MASK 0xFFFFU
204 : :
205 : : #define RQ_CTXT_CI_PI_SET(val, member) \
206 : : (((val) & RQ_CTXT_##member##_MASK) << RQ_CTXT_##member##_SHIFT)
207 : :
208 : : #define RQ_CTXT_CEQ_ATTR_INTR_SHIFT 21
209 : : #define RQ_CTXT_CEQ_ATTR_INTR_ARM_SHIFT 30
210 : : #define RQ_CTXT_CEQ_ATTR_EN_SHIFT 31
211 : :
212 : : #define RQ_CTXT_CEQ_ATTR_INTR_MASK 0x3FFU
213 : : #define RQ_CTXT_CEQ_ATTR_INTR_ARM_MASK 0x1U
214 : : #define RQ_CTXT_CEQ_ATTR_EN_MASK 0x1U
215 : :
216 : : #define RQ_CTXT_CEQ_ATTR_SET(val, member) \
217 : : (((val) & RQ_CTXT_CEQ_ATTR_##member##_MASK) \
218 : : << RQ_CTXT_CEQ_ATTR_##member##_SHIFT)
219 : :
220 : : #define RQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0
221 : : #define RQ_CTXT_WQ_PAGE_WQE_TYPE_SHIFT 28
222 : : #define RQ_CTXT_WQ_PAGE_OWNER_SHIFT 31
223 : :
224 : : #define RQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU
225 : : #define RQ_CTXT_WQ_PAGE_WQE_TYPE_MASK 0x3U
226 : : #define RQ_CTXT_WQ_PAGE_OWNER_MASK 0x1U
227 : :
228 : : #define RQ_CTXT_WQ_PAGE_SET(val, member) \
229 : : (((val) & RQ_CTXT_WQ_PAGE_##member##_MASK) \
230 : : << RQ_CTXT_WQ_PAGE_##member##_SHIFT)
231 : :
232 : : #define RQ_CTXT_CQE_LEN_SHIFT 28
233 : :
234 : : #define RQ_CTXT_CQE_LEN_MASK 0x3U
235 : :
236 : : #define RQ_CTXT_CQE_LEN_SET(val, member) \
237 : : (((val) & RQ_CTXT_##member##_MASK) << RQ_CTXT_##member##_SHIFT)
238 : :
239 : : #define RQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0
240 : : #define RQ_CTXT_PREF_CACHE_MAX_SHIFT 14
241 : : #define RQ_CTXT_PREF_CACHE_MIN_SHIFT 25
242 : :
243 : : #define RQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU
244 : : #define RQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU
245 : : #define RQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU
246 : :
247 : : #define RQ_CTXT_PREF_CI_HI_SHIFT 0
248 : : #define RQ_CTXT_PREF_OWNER_SHIFT 4
249 : :
250 : : #define RQ_CTXT_PREF_CI_HI_MASK 0xFU
251 : : #define RQ_CTXT_PREF_OWNER_MASK 0x1U
252 : :
253 : : #define RQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0
254 : : #define RQ_CTXT_PREF_CI_LOW_SHIFT 20
255 : :
256 : : #define RQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU
257 : : #define RQ_CTXT_PREF_CI_LOW_MASK 0xFFFU
258 : :
259 : : #define RQ_CTXT_PREF_SET(val, member) \
260 : : (((val) & RQ_CTXT_PREF_##member##_MASK) \
261 : : << RQ_CTXT_PREF_##member##_SHIFT)
262 : :
263 : : #define RQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0
264 : :
265 : : #define RQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU
266 : :
267 : : #define RQ_CTXT_WQ_BLOCK_SET(val, member) \
268 : : (((val) & RQ_CTXT_WQ_BLOCK_##member##_MASK) \
269 : : << RQ_CTXT_WQ_BLOCK_##member##_SHIFT)
270 : :
271 : : #define SIZE_16BYTES(size) (RTE_ALIGN((size), 16) >> 4)
272 : :
273 : : #define WQ_PAGE_PFN_SHIFT 12
274 : : #define WQ_BLOCK_PFN_SHIFT 9
275 : :
276 : : #define WQ_PAGE_PFN(page_addr) ((page_addr) >> WQ_PAGE_PFN_SHIFT)
277 : : #define WQ_BLOCK_PFN(page_addr) ((page_addr) >> WQ_BLOCK_PFN_SHIFT)
278 : :
279 : : /**
280 : : * Prepare the command queue header and converted it to big-endian format.
281 : : *
282 : : * @param[out] qp_ctxt_hdr
283 : : * Pointer to command queue context header structure to be initialized.
284 : : * @param[in] ctxt_type
285 : : * Type of context (SQ/RQ) to be set in header.
286 : : * @param[in] num_queues
287 : : * Number of queues.
288 : : * @param[in] q_id
289 : : * Starting queue ID for this context.
290 : : */
291 : : static void
292 : 0 : hinic3_qp_prepare_cmdq_header(struct hinic3_qp_ctxt_header *qp_ctxt_hdr,
293 : : enum hinic3_qp_ctxt_type ctxt_type,
294 : : uint16_t num_queues, uint16_t q_id)
295 : : {
296 : 0 : qp_ctxt_hdr->queue_type = ctxt_type;
297 : 0 : qp_ctxt_hdr->num_queues = num_queues;
298 : 0 : qp_ctxt_hdr->start_qid = q_id;
299 : 0 : qp_ctxt_hdr->rsvd = 0;
300 : :
301 : : rte_atomic_thread_fence(rte_memory_order_seq_cst);
302 : :
303 : : hinic3_cpu_to_be32(qp_ctxt_hdr, sizeof(*qp_ctxt_hdr));
304 : 0 : }
305 : :
306 : : /**
307 : : * Initialize context structure for specified TXQ by configuring various queue
308 : : * parameters (e.g., ci, pi, work queue page addresses).
309 : : *
310 : : * @param[in] sq
311 : : * Pointer to TXQ structure.
312 : : * @param[in] sq_id
313 : : * ID of TXQ being configured.
314 : : * @param[out] sq_ctxt
315 : : * Pointer to structure that will hold TXQ context.
316 : : */
317 : : static void
318 : 0 : hinic3_sq_prepare_ctxt(struct hinic3_txq *sq, uint16_t sq_id,
319 : : struct hinic3_sq_ctxt *sq_ctxt)
320 : : {
321 : : uint64_t wq_page_addr, wq_page_pfn, wq_block_pfn;
322 : : uint32_t wq_page_pfn_hi, wq_page_pfn_lo, wq_block_pfn_hi, wq_block_pfn_lo;
323 : : uint16_t pi_start, ci_start;
324 : :
325 : 0 : ci_start = sq->cons_idx & sq->q_mask;
326 : 0 : pi_start = sq->prod_idx & sq->q_mask;
327 : :
328 : : /* Read the first page from hardware table. */
329 : 0 : wq_page_addr = sq->queue_buf_paddr;
330 : :
331 : 0 : wq_page_pfn = WQ_PAGE_PFN(wq_page_addr);
332 : 0 : wq_page_pfn_hi = upper_32_bits(wq_page_pfn);
333 : 0 : wq_page_pfn_lo = lower_32_bits(wq_page_pfn);
334 : :
335 : : /* Use 0-level CLA. */
336 : 0 : wq_block_pfn = WQ_BLOCK_PFN(wq_page_addr);
337 : 0 : wq_block_pfn_hi = upper_32_bits(wq_block_pfn);
338 : 0 : wq_block_pfn_lo = lower_32_bits(wq_block_pfn);
339 : :
340 : 0 : sq_ctxt->ci_pi = SQ_CTXT_CI_PI_SET(ci_start, CI_IDX) |
341 : 0 : SQ_CTXT_CI_PI_SET(pi_start, PI_IDX);
342 : :
343 : 0 : sq_ctxt->drop_mode_sp = SQ_CTXT_MODE_SET(0, SP_FLAG) |
344 : : SQ_CTXT_MODE_SET(0, PKT_DROP);
345 : :
346 : 0 : sq_ctxt->wq_pfn_hi_owner = SQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) |
347 : : SQ_CTXT_WQ_PAGE_SET(1, OWNER);
348 : :
349 : 0 : sq_ctxt->wq_pfn_lo = wq_page_pfn_lo;
350 : :
351 : 0 : sq_ctxt->pkt_drop_thd =
352 : : SQ_CTXT_PKT_DROP_THD_SET(HINIC3_DEAULT_DROP_THD_ON, THD_ON) |
353 : : SQ_CTXT_PKT_DROP_THD_SET(HINIC3_DEAULT_DROP_THD_OFF, THD_OFF);
354 : :
355 : 0 : sq_ctxt->global_sq_id =
356 : 0 : SQ_CTXT_GLOBAL_QUEUE_ID_SET(sq_id, GLOBAL_SQ_ID);
357 : :
358 : : /* Insert c-vlan in default. */
359 : 0 : sq_ctxt->vlan_ceq_attr = SQ_CTXT_VLAN_CEQ_SET(0, CEQ_EN) |
360 : : SQ_CTXT_VLAN_CEQ_SET(1, INSERT_MODE);
361 : :
362 : 0 : sq_ctxt->rsvd0 = 0;
363 : :
364 : 0 : sq_ctxt->pref_cache =
365 : : SQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) |
366 : : SQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) |
367 : : SQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD);
368 : :
369 : 0 : sq_ctxt->pref_ci_owner =
370 : 0 : SQ_CTXT_PREF_SET(CI_HIGN_IDX(ci_start), CI_HI) |
371 : : SQ_CTXT_PREF_SET(1, OWNER);
372 : :
373 : 0 : sq_ctxt->pref_wq_pfn_hi_ci =
374 : 0 : SQ_CTXT_PREF_SET(ci_start, CI_LOW) |
375 : : SQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI);
376 : :
377 : 0 : sq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo;
378 : :
379 : 0 : sq_ctxt->wq_block_pfn_hi =
380 : : SQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI);
381 : :
382 : 0 : sq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo;
383 : :
384 : : rte_atomic_thread_fence(rte_memory_order_seq_cst);
385 : :
386 : : hinic3_cpu_to_be32(sq_ctxt, sizeof(*sq_ctxt));
387 : 0 : }
388 : :
389 : : /**
390 : : * Initialize context structure for specified RXQ by configuring various queue
391 : : * parameters (e.g., ci, pi, work queue page addresses).
392 : : *
393 : : * @param[in] rq
394 : : * Pointer to RXQ structure.
395 : : * @param[out] rq_ctxt
396 : : * Pointer to structure that will hold RXQ context.
397 : : */
398 : : static void
399 : 0 : hinic3_rq_prepare_ctxt(struct hinic3_rxq *rq, struct hinic3_rq_ctxt *rq_ctxt)
400 : : {
401 : : uint64_t wq_page_addr, wq_page_pfn, wq_block_pfn;
402 : : uint32_t wq_page_pfn_hi, wq_page_pfn_lo, wq_block_pfn_hi, wq_block_pfn_lo;
403 : : uint16_t pi_start, ci_start;
404 : 0 : uint16_t wqe_type = rq->wqebb_shift - HINIC3_RQ_WQEBB_SHIFT;
405 : : uint8_t intr_disable;
406 : :
407 : : /* RQ depth is in unit of 8 Bytes. */
408 : 0 : ci_start = (uint16_t)((rq->cons_idx & rq->q_mask) << wqe_type);
409 : 0 : pi_start = (uint16_t)((rq->prod_idx & rq->q_mask) << wqe_type);
410 : :
411 : : /* Read the first page from hardware table. */
412 : 0 : wq_page_addr = rq->queue_buf_paddr;
413 : :
414 : 0 : wq_page_pfn = WQ_PAGE_PFN(wq_page_addr);
415 : 0 : wq_page_pfn_hi = upper_32_bits(wq_page_pfn);
416 : 0 : wq_page_pfn_lo = lower_32_bits(wq_page_pfn);
417 : :
418 : : /* Use 0-level CLA. */
419 : 0 : wq_block_pfn = WQ_BLOCK_PFN(wq_page_addr);
420 : 0 : wq_block_pfn_hi = upper_32_bits(wq_block_pfn);
421 : 0 : wq_block_pfn_lo = lower_32_bits(wq_block_pfn);
422 : :
423 : 0 : rq_ctxt->ci_pi = RQ_CTXT_CI_PI_SET(ci_start, CI_IDX) |
424 : 0 : RQ_CTXT_CI_PI_SET(pi_start, PI_IDX);
425 : :
426 : : /* RQ doesn't need ceq, msix_entry_idx set 1, but mask not enable. */
427 : 0 : intr_disable = rq->dp_intr_en ? 0 : 1;
428 : 0 : rq_ctxt->ceq_attr = RQ_CTXT_CEQ_ATTR_SET(intr_disable, EN) |
429 : 0 : RQ_CTXT_CEQ_ATTR_SET(0, INTR_ARM) |
430 : 0 : RQ_CTXT_CEQ_ATTR_SET(rq->msix_entry_idx, INTR);
431 : :
432 : : /* Use 32Byte WQE with SGE for CQE in default. */
433 : 0 : rq_ctxt->wq_pfn_hi_type_owner =
434 : 0 : RQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) |
435 : : RQ_CTXT_WQ_PAGE_SET(1, OWNER);
436 : :
437 [ # # # ]: 0 : switch (wqe_type) {
438 : : case HINIC3_EXTEND_RQ_WQE:
439 : : /* Use 32Byte WQE with SGE for CQE. */
440 : : rq_ctxt->wq_pfn_hi_type_owner |=
441 : : RQ_CTXT_WQ_PAGE_SET(0, WQE_TYPE);
442 : : break;
443 : 0 : case HINIC3_NORMAL_RQ_WQE:
444 : : /* Use 16Byte WQE with 32Bytes SGE for CQE. */
445 : 0 : rq_ctxt->wq_pfn_hi_type_owner |=
446 : : RQ_CTXT_WQ_PAGE_SET(2, WQE_TYPE);
447 : 0 : rq_ctxt->cqe_sge_len = RQ_CTXT_CQE_LEN_SET(1, CQE_LEN);
448 : 0 : break;
449 : 0 : default:
450 : 0 : PMD_DRV_LOG(INFO, "Invalid rq wqe type: %u", wqe_type);
451 : : }
452 : :
453 : 0 : rq_ctxt->wq_pfn_lo = wq_page_pfn_lo;
454 : :
455 : 0 : rq_ctxt->pref_cache =
456 : : RQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) |
457 : : RQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) |
458 : : RQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD);
459 : :
460 : 0 : rq_ctxt->pref_ci_owner =
461 : 0 : RQ_CTXT_PREF_SET(CI_HIGN_IDX(ci_start), CI_HI) |
462 : : RQ_CTXT_PREF_SET(1, OWNER);
463 : :
464 : 0 : rq_ctxt->pref_wq_pfn_hi_ci =
465 : 0 : RQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI) |
466 : : RQ_CTXT_PREF_SET(ci_start, CI_LOW);
467 : :
468 : 0 : rq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo;
469 : :
470 : 0 : rq_ctxt->pi_paddr_hi = upper_32_bits(rq->pi_dma_addr);
471 : 0 : rq_ctxt->pi_paddr_lo = lower_32_bits(rq->pi_dma_addr);
472 : :
473 : 0 : rq_ctxt->wq_block_pfn_hi =
474 : : RQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI);
475 : :
476 : 0 : rq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo;
477 : : rte_atomic_thread_fence(rte_memory_order_seq_cst);
478 : :
479 : : hinic3_cpu_to_be32(rq_ctxt, sizeof(*rq_ctxt));
480 : 0 : }
481 : :
482 : : /**
483 : : * Allocate a command buffer, prepare context for each SQ queue by setting
484 : : * various parameters, send context data to hardware. It processes SQ queues in
485 : : * batches, with each batch not exceeding `HINIC3_Q_CTXT_MAX` SQ contexts.
486 : : *
487 : : * @param[in] nic_dev
488 : : * Pointer to NIC device structure.
489 : : *
490 : : * @return
491 : : * 0 on success, a negative error code on failure.
492 : : * - -ENOMEM if the memory allocation for the command buffer fails.
493 : : * - -EFAULT if the hardware returns an error while processing the context data.
494 : : */
495 : : static int
496 : 0 : init_sq_ctxts(struct hinic3_nic_dev *nic_dev)
497 : : {
498 : : struct hinic3_sq_ctxt_block *sq_ctxt_block = NULL;
499 : : struct hinic3_sq_ctxt *sq_ctxt = NULL;
500 : : struct hinic3_cmd_buf *cmd_buf = NULL;
501 : : struct hinic3_txq *sq = NULL;
502 : 0 : uint64_t out_param = 0;
503 : : uint16_t q_id, curr_id, max_ctxts, i;
504 : : int err = 0;
505 : :
506 : 0 : cmd_buf = hinic3_alloc_cmd_buf(nic_dev->hwdev);
507 [ # # ]: 0 : if (!cmd_buf) {
508 : 0 : PMD_DRV_LOG(ERR, "Allocate cmd buf for sq ctx failed");
509 : 0 : return -ENOMEM;
510 : : }
511 : :
512 : : q_id = 0;
513 [ # # ]: 0 : while (q_id < nic_dev->num_sqs) {
514 : 0 : sq_ctxt_block = cmd_buf->buf;
515 : 0 : sq_ctxt = sq_ctxt_block->sq_ctxt;
516 : :
517 : 0 : max_ctxts = (nic_dev->num_sqs - q_id) > HINIC3_Q_CTXT_MAX
518 : : ? HINIC3_Q_CTXT_MAX
519 : 0 : : (nic_dev->num_sqs - q_id);
520 : :
521 : 0 : hinic3_qp_prepare_cmdq_header(&sq_ctxt_block->cmdq_hdr,
522 : : HINIC3_QP_CTXT_TYPE_SQ,
523 : : max_ctxts, q_id);
524 : :
525 [ # # ]: 0 : for (i = 0; i < max_ctxts; i++) {
526 : 0 : curr_id = q_id + i;
527 : 0 : sq = nic_dev->txqs[curr_id];
528 : 0 : hinic3_sq_prepare_ctxt(sq, curr_id, &sq_ctxt[i]);
529 : : }
530 : :
531 : 0 : cmd_buf->size = SQ_CTXT_SIZE(max_ctxts);
532 : : rte_atomic_thread_fence(rte_memory_order_seq_cst);
533 : 0 : err = hinic3_cmdq_direct_resp(nic_dev->hwdev, HINIC3_MOD_L2NIC,
534 : : HINIC3_UCODE_CMD_MODIFY_QUEUE_CTX,
535 : : cmd_buf, &out_param, 0);
536 [ # # # # ]: 0 : if (err || out_param != 0) {
537 : 0 : PMD_DRV_LOG(ERR,
538 : : "Set SQ ctxts failed, err: %d, out_param: %" PRIu64,
539 : : err, out_param);
540 : :
541 : : err = -EFAULT;
542 : 0 : break;
543 : : }
544 : :
545 : 0 : q_id += max_ctxts;
546 : : }
547 : :
548 : 0 : hinic3_free_cmd_buf(cmd_buf);
549 : 0 : return err;
550 : : }
551 : :
552 : : /**
553 : : * Initialize context for all RQ in device.
554 : : *
555 : : * @param[in] nic_dev
556 : : * Pointer to NIC device structure.
557 : : *
558 : : * @return
559 : : * 0 on success, a negative error code on failure.
560 : : * - -ENOMEM if the memory allocation for the command buffer fails.
561 : : * - -EFAULT if the hardware returns an error while processing the context data.
562 : : */
563 : : static int
564 : 0 : init_rq_ctxts(struct hinic3_nic_dev *nic_dev)
565 : : {
566 : : struct hinic3_rq_ctxt_block *rq_ctxt_block = NULL;
567 : : struct hinic3_rq_ctxt *rq_ctxt = NULL;
568 : : struct hinic3_cmd_buf *cmd_buf = NULL;
569 : : struct hinic3_rxq *rq = NULL;
570 : 0 : uint64_t out_param = 0;
571 : : uint16_t q_id, curr_id, max_ctxts, i;
572 : : int err = 0;
573 : :
574 : 0 : cmd_buf = hinic3_alloc_cmd_buf(nic_dev->hwdev);
575 [ # # ]: 0 : if (!cmd_buf) {
576 : 0 : PMD_DRV_LOG(ERR, "Allocate cmd buf for rq ctx failed");
577 : 0 : return -ENOMEM;
578 : : }
579 : :
580 : : q_id = 0;
581 [ # # ]: 0 : while (q_id < nic_dev->num_rqs) {
582 : 0 : rq_ctxt_block = cmd_buf->buf;
583 : 0 : rq_ctxt = rq_ctxt_block->rq_ctxt;
584 : :
585 : 0 : max_ctxts = (nic_dev->num_rqs - q_id) > HINIC3_Q_CTXT_MAX
586 : : ? HINIC3_Q_CTXT_MAX
587 : 0 : : (nic_dev->num_rqs - q_id);
588 : :
589 : 0 : hinic3_qp_prepare_cmdq_header(&rq_ctxt_block->cmdq_hdr,
590 : : HINIC3_QP_CTXT_TYPE_RQ,
591 : : max_ctxts, q_id);
592 : :
593 [ # # ]: 0 : for (i = 0; i < max_ctxts; i++) {
594 : 0 : curr_id = q_id + i;
595 : 0 : rq = nic_dev->rxqs[curr_id];
596 : 0 : hinic3_rq_prepare_ctxt(rq, &rq_ctxt[i]);
597 : : }
598 : :
599 : 0 : cmd_buf->size = RQ_CTXT_SIZE(max_ctxts);
600 : : rte_atomic_thread_fence(rte_memory_order_seq_cst);
601 : 0 : err = hinic3_cmdq_direct_resp(nic_dev->hwdev, HINIC3_MOD_L2NIC,
602 : : HINIC3_UCODE_CMD_MODIFY_QUEUE_CTX,
603 : : cmd_buf, &out_param, 0);
604 [ # # # # ]: 0 : if (err || out_param != 0) {
605 : 0 : PMD_DRV_LOG(ERR,
606 : : "Set RQ ctxts failed, err: %d, out_param: %" PRIu64,
607 : : err, out_param);
608 : : err = -EFAULT;
609 : 0 : break;
610 : : }
611 : :
612 : 0 : q_id += max_ctxts;
613 : : }
614 : :
615 : 0 : hinic3_free_cmd_buf(cmd_buf);
616 : 0 : return err;
617 : : }
618 : :
619 : : /**
620 : : * Allocate memory for command buffer, construct related command request, send a
621 : : * command to hardware to clean up queue offload context.
622 : : *
623 : : * @param[in] nic_dev
624 : : * Pointer to NIC device structure.
625 : : * @param[in] ctxt_type
626 : : * The type of queue context to clean.
627 : : * The queue context type that determines which queue type to clean up.
628 : : *
629 : : * @return
630 : : * 0 on success, non-zero on failure.
631 : : */
632 : : static int
633 : 0 : clean_queue_offload_ctxt(struct hinic3_nic_dev *nic_dev,
634 : : enum hinic3_qp_ctxt_type ctxt_type)
635 : : {
636 : : struct hinic3_clean_queue_ctxt *ctxt_block = NULL;
637 : : struct hinic3_cmd_buf *cmd_buf;
638 : 0 : uint64_t out_param = 0;
639 : : int err;
640 : :
641 : 0 : cmd_buf = hinic3_alloc_cmd_buf(nic_dev->hwdev);
642 [ # # ]: 0 : if (!cmd_buf) {
643 : 0 : PMD_DRV_LOG(ERR, "Allocate cmd buf for LRO/TSO space failed");
644 : 0 : return -ENOMEM;
645 : : }
646 : :
647 : : /* Construct related command request. */
648 : 0 : ctxt_block = cmd_buf->buf;
649 : : /* Assumed max_rqs must be equal to max_sqs. */
650 : 0 : ctxt_block->cmdq_hdr.num_queues = nic_dev->max_sqs;
651 : 0 : ctxt_block->cmdq_hdr.queue_type = ctxt_type;
652 : 0 : ctxt_block->cmdq_hdr.start_qid = 0;
653 : : /*
654 : : * Add a memory barrier to ensure that instructions are not out of order
655 : : * due to compilation optimization.
656 : : */
657 : : rte_atomic_thread_fence(rte_memory_order_seq_cst);
658 : :
659 : : hinic3_cpu_to_be32(ctxt_block, sizeof(*ctxt_block));
660 : :
661 : 0 : cmd_buf->size = sizeof(*ctxt_block);
662 : :
663 : : /* Send a command to hardware to clean up queue offload context. */
664 : 0 : err = hinic3_cmdq_direct_resp(nic_dev->hwdev, HINIC3_MOD_L2NIC,
665 : : HINIC3_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
666 : : cmd_buf, &out_param, 0);
667 [ # # # # ]: 0 : if ((err) || (out_param)) {
668 : 0 : PMD_DRV_LOG(ERR,
669 : : "Clean queue offload ctxts failed, err: %d, out_param: %" PRIu64,
670 : : err, out_param);
671 : : err = -EFAULT;
672 : : }
673 : :
674 : 0 : hinic3_free_cmd_buf(cmd_buf);
675 : 0 : return err;
676 : : }
677 : :
678 : : static int
679 : 0 : clean_qp_offload_ctxt(struct hinic3_nic_dev *nic_dev)
680 : : {
681 : : /* Clean LRO/TSO context space. */
682 [ # # # # ]: 0 : return (clean_queue_offload_ctxt(nic_dev, HINIC3_QP_CTXT_TYPE_SQ) ||
683 : 0 : clean_queue_offload_ctxt(nic_dev, HINIC3_QP_CTXT_TYPE_RQ));
684 : : }
685 : :
686 : : void
687 : 0 : hinic3_get_func_rx_buf_size(struct hinic3_nic_dev *nic_dev)
688 : : {
689 : : struct hinic3_rxq *rxq = NULL;
690 : : uint16_t q_id;
691 : : uint16_t buf_size = 0;
692 : :
693 [ # # ]: 0 : for (q_id = 0; q_id < nic_dev->num_rqs; q_id++) {
694 : 0 : rxq = nic_dev->rxqs[q_id];
695 : :
696 [ # # ]: 0 : if (rxq == NULL)
697 : 0 : continue;
698 : :
699 [ # # ]: 0 : if (q_id == 0)
700 : 0 : buf_size = rxq->buf_len;
701 : :
702 : 0 : buf_size = buf_size > rxq->buf_len ? rxq->buf_len : buf_size;
703 : : }
704 : :
705 : 0 : nic_dev->rx_buff_len = buf_size;
706 : 0 : }
707 : :
708 : : int
709 : 0 : hinic3_init_qp_ctxts(struct hinic3_nic_dev *nic_dev)
710 : : {
711 : : struct hinic3_hwdev *hwdev = NULL;
712 : : struct hinic3_sq_attr sq_attr;
713 : : uint32_t rq_depth = 0;
714 : : uint32_t sq_depth = 0;
715 : : uint16_t q_id;
716 : : int err;
717 : :
718 [ # # ]: 0 : if (!nic_dev)
719 : : return -EINVAL;
720 : :
721 : 0 : hwdev = nic_dev->hwdev;
722 : :
723 : 0 : err = init_sq_ctxts(nic_dev);
724 [ # # ]: 0 : if (err) {
725 : 0 : PMD_DRV_LOG(ERR, "Init SQ ctxts failed");
726 : 0 : return err;
727 : : }
728 : :
729 : 0 : err = init_rq_ctxts(nic_dev);
730 [ # # ]: 0 : if (err) {
731 : 0 : PMD_DRV_LOG(ERR, "Init RQ ctxts failed");
732 : 0 : return err;
733 : : }
734 : :
735 : 0 : err = clean_qp_offload_ctxt(nic_dev);
736 [ # # ]: 0 : if (err) {
737 : 0 : PMD_DRV_LOG(ERR, "Clean qp offload ctxts failed");
738 : 0 : return err;
739 : : }
740 : :
741 [ # # ]: 0 : if (nic_dev->num_rqs != 0)
742 : 0 : rq_depth = ((uint32_t)nic_dev->rxqs[0]->q_depth)
743 : 0 : << nic_dev->rxqs[0]->wqe_type;
744 : :
745 [ # # ]: 0 : if (nic_dev->num_sqs != 0)
746 : 0 : sq_depth = nic_dev->txqs[0]->q_depth;
747 : :
748 : 0 : err = hinic3_set_root_ctxt(hwdev, rq_depth, sq_depth,
749 : 0 : nic_dev->rx_buff_len);
750 [ # # ]: 0 : if (err) {
751 : 0 : PMD_DRV_LOG(ERR, "Set root context failed");
752 : 0 : return err;
753 : : }
754 : :
755 : : /* Configure CI tables for each SQ. */
756 [ # # ]: 0 : for (q_id = 0; q_id < nic_dev->num_sqs; q_id++) {
757 : 0 : sq_attr.ci_dma_base = nic_dev->txqs[q_id]->ci_dma_base >> 0x2;
758 : 0 : sq_attr.pending_limit = HINIC3_DEAULT_TX_CI_PENDING_LIMIT;
759 : 0 : sq_attr.coalescing_time = HINIC3_DEAULT_TX_CI_COALESCING_TIME;
760 : 0 : sq_attr.intr_en = 0;
761 : 0 : sq_attr.intr_idx = 0; /**< Tx doesn't need interrupt. */
762 : 0 : sq_attr.l2nic_sqn = q_id;
763 : 0 : sq_attr.dma_attr_off = 0;
764 : 0 : err = hinic3_set_ci_table(hwdev, &sq_attr);
765 [ # # ]: 0 : if (err) {
766 : 0 : PMD_DRV_LOG(ERR, "Set ci table failed");
767 : 0 : goto set_cons_idx_table_err;
768 : : }
769 : : }
770 : :
771 : : return 0;
772 : :
773 : : set_cons_idx_table_err:
774 : 0 : hinic3_clean_root_ctxt(hwdev);
775 : 0 : return err;
776 : : }
777 : :
778 : : void
779 : 0 : hinic3_free_qp_ctxts(struct hinic3_hwdev *hwdev)
780 : : {
781 [ # # ]: 0 : if (!hwdev)
782 : : return;
783 : :
784 : 0 : hinic3_clean_root_ctxt(hwdev);
785 : : }
786 : :
787 : : void
788 : 0 : hinic3_update_driver_feature(struct hinic3_nic_dev *nic_dev, uint64_t s_feature)
789 : : {
790 [ # # ]: 0 : if (!nic_dev)
791 : : return;
792 : :
793 : 0 : nic_dev->feature_cap = s_feature;
794 : :
795 : 0 : PMD_DRV_LOG(DEBUG, "Update nic feature to 0x%" PRIx64, nic_dev->feature_cap);
796 : : }
797 : :
798 : : uint64_t
799 : 0 : hinic3_get_driver_feature(struct hinic3_nic_dev *nic_dev)
800 : : {
801 : 0 : return nic_dev->feature_cap;
802 : : }
|