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