]> git.proxmox.com Git - ceph.git/blob - ceph/src/dpdk/drivers/net/thunderx/base/nicvf_hw.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / dpdk / drivers / net / thunderx / base / nicvf_hw.c
1 /*
2 * BSD LICENSE
3 *
4 * Copyright (C) Cavium networks Ltd. 2016.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Cavium networks nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <unistd.h>
34 #include <math.h>
35 #include <errno.h>
36 #include <stdarg.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <assert.h>
42
43 #include "nicvf_plat.h"
44
45 struct nicvf_reg_info {
46 uint32_t offset;
47 const char *name;
48 };
49
50 #define NICVF_REG_POLL_ITER_NR (10)
51 #define NICVF_REG_POLL_DELAY_US (2000)
52 #define NICVF_REG_INFO(reg) {reg, #reg}
53
54 static const struct nicvf_reg_info nicvf_reg_tbl[] = {
55 NICVF_REG_INFO(NIC_VF_CFG),
56 NICVF_REG_INFO(NIC_VF_PF_MAILBOX_0_1),
57 NICVF_REG_INFO(NIC_VF_INT),
58 NICVF_REG_INFO(NIC_VF_INT_W1S),
59 NICVF_REG_INFO(NIC_VF_ENA_W1C),
60 NICVF_REG_INFO(NIC_VF_ENA_W1S),
61 NICVF_REG_INFO(NIC_VNIC_RSS_CFG),
62 NICVF_REG_INFO(NIC_VNIC_RQ_GEN_CFG),
63 };
64
65 static const struct nicvf_reg_info nicvf_multi_reg_tbl[] = {
66 {NIC_VNIC_RSS_KEY_0_4 + 0, "NIC_VNIC_RSS_KEY_0"},
67 {NIC_VNIC_RSS_KEY_0_4 + 8, "NIC_VNIC_RSS_KEY_1"},
68 {NIC_VNIC_RSS_KEY_0_4 + 16, "NIC_VNIC_RSS_KEY_2"},
69 {NIC_VNIC_RSS_KEY_0_4 + 24, "NIC_VNIC_RSS_KEY_3"},
70 {NIC_VNIC_RSS_KEY_0_4 + 32, "NIC_VNIC_RSS_KEY_4"},
71 {NIC_VNIC_TX_STAT_0_4 + 0, "NIC_VNIC_STAT_TX_OCTS"},
72 {NIC_VNIC_TX_STAT_0_4 + 8, "NIC_VNIC_STAT_TX_UCAST"},
73 {NIC_VNIC_TX_STAT_0_4 + 16, "NIC_VNIC_STAT_TX_BCAST"},
74 {NIC_VNIC_TX_STAT_0_4 + 24, "NIC_VNIC_STAT_TX_MCAST"},
75 {NIC_VNIC_TX_STAT_0_4 + 32, "NIC_VNIC_STAT_TX_DROP"},
76 {NIC_VNIC_RX_STAT_0_13 + 0, "NIC_VNIC_STAT_RX_OCTS"},
77 {NIC_VNIC_RX_STAT_0_13 + 8, "NIC_VNIC_STAT_RX_UCAST"},
78 {NIC_VNIC_RX_STAT_0_13 + 16, "NIC_VNIC_STAT_RX_BCAST"},
79 {NIC_VNIC_RX_STAT_0_13 + 24, "NIC_VNIC_STAT_RX_MCAST"},
80 {NIC_VNIC_RX_STAT_0_13 + 32, "NIC_VNIC_STAT_RX_RED"},
81 {NIC_VNIC_RX_STAT_0_13 + 40, "NIC_VNIC_STAT_RX_RED_OCTS"},
82 {NIC_VNIC_RX_STAT_0_13 + 48, "NIC_VNIC_STAT_RX_ORUN"},
83 {NIC_VNIC_RX_STAT_0_13 + 56, "NIC_VNIC_STAT_RX_ORUN_OCTS"},
84 {NIC_VNIC_RX_STAT_0_13 + 64, "NIC_VNIC_STAT_RX_FCS"},
85 {NIC_VNIC_RX_STAT_0_13 + 72, "NIC_VNIC_STAT_RX_L2ERR"},
86 {NIC_VNIC_RX_STAT_0_13 + 80, "NIC_VNIC_STAT_RX_DRP_BCAST"},
87 {NIC_VNIC_RX_STAT_0_13 + 88, "NIC_VNIC_STAT_RX_DRP_MCAST"},
88 {NIC_VNIC_RX_STAT_0_13 + 96, "NIC_VNIC_STAT_RX_DRP_L3BCAST"},
89 {NIC_VNIC_RX_STAT_0_13 + 104, "NIC_VNIC_STAT_RX_DRP_L3MCAST"},
90 };
91
92 static const struct nicvf_reg_info nicvf_qset_cq_reg_tbl[] = {
93 NICVF_REG_INFO(NIC_QSET_CQ_0_7_CFG),
94 NICVF_REG_INFO(NIC_QSET_CQ_0_7_CFG2),
95 NICVF_REG_INFO(NIC_QSET_CQ_0_7_THRESH),
96 NICVF_REG_INFO(NIC_QSET_CQ_0_7_BASE),
97 NICVF_REG_INFO(NIC_QSET_CQ_0_7_HEAD),
98 NICVF_REG_INFO(NIC_QSET_CQ_0_7_TAIL),
99 NICVF_REG_INFO(NIC_QSET_CQ_0_7_DOOR),
100 NICVF_REG_INFO(NIC_QSET_CQ_0_7_STATUS),
101 NICVF_REG_INFO(NIC_QSET_CQ_0_7_STATUS2),
102 NICVF_REG_INFO(NIC_QSET_CQ_0_7_DEBUG),
103 };
104
105 static const struct nicvf_reg_info nicvf_qset_rq_reg_tbl[] = {
106 NICVF_REG_INFO(NIC_QSET_RQ_0_7_CFG),
107 NICVF_REG_INFO(NIC_QSET_RQ_0_7_STATUS0),
108 NICVF_REG_INFO(NIC_QSET_RQ_0_7_STATUS1),
109 };
110
111 static const struct nicvf_reg_info nicvf_qset_sq_reg_tbl[] = {
112 NICVF_REG_INFO(NIC_QSET_SQ_0_7_CFG),
113 NICVF_REG_INFO(NIC_QSET_SQ_0_7_THRESH),
114 NICVF_REG_INFO(NIC_QSET_SQ_0_7_BASE),
115 NICVF_REG_INFO(NIC_QSET_SQ_0_7_HEAD),
116 NICVF_REG_INFO(NIC_QSET_SQ_0_7_TAIL),
117 NICVF_REG_INFO(NIC_QSET_SQ_0_7_DOOR),
118 NICVF_REG_INFO(NIC_QSET_SQ_0_7_STATUS),
119 NICVF_REG_INFO(NIC_QSET_SQ_0_7_DEBUG),
120 NICVF_REG_INFO(NIC_QSET_SQ_0_7_STATUS0),
121 NICVF_REG_INFO(NIC_QSET_SQ_0_7_STATUS1),
122 };
123
124 static const struct nicvf_reg_info nicvf_qset_rbdr_reg_tbl[] = {
125 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_CFG),
126 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_THRESH),
127 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_BASE),
128 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_HEAD),
129 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_TAIL),
130 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_DOOR),
131 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_STATUS0),
132 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_STATUS1),
133 NICVF_REG_INFO(NIC_QSET_RBDR_0_1_PRFCH_STATUS),
134 };
135
136 int
137 nicvf_base_init(struct nicvf *nic)
138 {
139 nic->hwcap = 0;
140 if (nic->subsystem_device_id == 0)
141 return NICVF_ERR_BASE_INIT;
142
143 if (nicvf_hw_version(nic) == PCI_SUB_DEVICE_ID_CN88XX_PASS2_NICVF)
144 nic->hwcap |= NICVF_CAP_TUNNEL_PARSING | NICVF_CAP_CQE_RX2;
145
146 if (nicvf_hw_version(nic) == PCI_SUB_DEVICE_ID_CN81XX_NICVF)
147 nic->hwcap |= NICVF_CAP_TUNNEL_PARSING | NICVF_CAP_CQE_RX2;
148
149 if (nicvf_hw_version(nic) == PCI_SUB_DEVICE_ID_CN83XX_NICVF)
150 nic->hwcap |= NICVF_CAP_TUNNEL_PARSING | NICVF_CAP_CQE_RX2 |
151 NICVF_CAP_DISABLE_APAD;
152
153 return NICVF_OK;
154 }
155
156 /* dump on stdout if data is NULL */
157 int
158 nicvf_reg_dump(struct nicvf *nic, uint64_t *data)
159 {
160 uint32_t i, q;
161 bool dump_stdout;
162
163 dump_stdout = data ? 0 : 1;
164
165 for (i = 0; i < NICVF_ARRAY_SIZE(nicvf_reg_tbl); i++)
166 if (dump_stdout)
167 nicvf_log("%24s = 0x%" PRIx64 "\n",
168 nicvf_reg_tbl[i].name,
169 nicvf_reg_read(nic, nicvf_reg_tbl[i].offset));
170 else
171 *data++ = nicvf_reg_read(nic, nicvf_reg_tbl[i].offset);
172
173 for (i = 0; i < NICVF_ARRAY_SIZE(nicvf_multi_reg_tbl); i++)
174 if (dump_stdout)
175 nicvf_log("%24s = 0x%" PRIx64 "\n",
176 nicvf_multi_reg_tbl[i].name,
177 nicvf_reg_read(nic,
178 nicvf_multi_reg_tbl[i].offset));
179 else
180 *data++ = nicvf_reg_read(nic,
181 nicvf_multi_reg_tbl[i].offset);
182
183 for (q = 0; q < MAX_CMP_QUEUES_PER_QS; q++)
184 for (i = 0; i < NICVF_ARRAY_SIZE(nicvf_qset_cq_reg_tbl); i++)
185 if (dump_stdout)
186 nicvf_log("%30s(%d) = 0x%" PRIx64 "\n",
187 nicvf_qset_cq_reg_tbl[i].name, q,
188 nicvf_queue_reg_read(nic,
189 nicvf_qset_cq_reg_tbl[i].offset, q));
190 else
191 *data++ = nicvf_queue_reg_read(nic,
192 nicvf_qset_cq_reg_tbl[i].offset, q);
193
194 for (q = 0; q < MAX_RCV_QUEUES_PER_QS; q++)
195 for (i = 0; i < NICVF_ARRAY_SIZE(nicvf_qset_rq_reg_tbl); i++)
196 if (dump_stdout)
197 nicvf_log("%30s(%d) = 0x%" PRIx64 "\n",
198 nicvf_qset_rq_reg_tbl[i].name, q,
199 nicvf_queue_reg_read(nic,
200 nicvf_qset_rq_reg_tbl[i].offset, q));
201 else
202 *data++ = nicvf_queue_reg_read(nic,
203 nicvf_qset_rq_reg_tbl[i].offset, q);
204
205 for (q = 0; q < MAX_SND_QUEUES_PER_QS; q++)
206 for (i = 0; i < NICVF_ARRAY_SIZE(nicvf_qset_sq_reg_tbl); i++)
207 if (dump_stdout)
208 nicvf_log("%30s(%d) = 0x%" PRIx64 "\n",
209 nicvf_qset_sq_reg_tbl[i].name, q,
210 nicvf_queue_reg_read(nic,
211 nicvf_qset_sq_reg_tbl[i].offset, q));
212 else
213 *data++ = nicvf_queue_reg_read(nic,
214 nicvf_qset_sq_reg_tbl[i].offset, q);
215
216 for (q = 0; q < MAX_RCV_BUF_DESC_RINGS_PER_QS; q++)
217 for (i = 0; i < NICVF_ARRAY_SIZE(nicvf_qset_rbdr_reg_tbl); i++)
218 if (dump_stdout)
219 nicvf_log("%30s(%d) = 0x%" PRIx64 "\n",
220 nicvf_qset_rbdr_reg_tbl[i].name, q,
221 nicvf_queue_reg_read(nic,
222 nicvf_qset_rbdr_reg_tbl[i].offset, q));
223 else
224 *data++ = nicvf_queue_reg_read(nic,
225 nicvf_qset_rbdr_reg_tbl[i].offset, q);
226 return 0;
227 }
228
229 int
230 nicvf_reg_get_count(void)
231 {
232 int nr_regs;
233
234 nr_regs = NICVF_ARRAY_SIZE(nicvf_reg_tbl);
235 nr_regs += NICVF_ARRAY_SIZE(nicvf_multi_reg_tbl);
236 nr_regs += NICVF_ARRAY_SIZE(nicvf_qset_cq_reg_tbl) *
237 MAX_CMP_QUEUES_PER_QS;
238 nr_regs += NICVF_ARRAY_SIZE(nicvf_qset_rq_reg_tbl) *
239 MAX_RCV_QUEUES_PER_QS;
240 nr_regs += NICVF_ARRAY_SIZE(nicvf_qset_sq_reg_tbl) *
241 MAX_SND_QUEUES_PER_QS;
242 nr_regs += NICVF_ARRAY_SIZE(nicvf_qset_rbdr_reg_tbl) *
243 MAX_RCV_BUF_DESC_RINGS_PER_QS;
244
245 return nr_regs;
246 }
247
248 static int
249 nicvf_qset_config_internal(struct nicvf *nic, bool enable)
250 {
251 int ret;
252 struct pf_qs_cfg pf_qs_cfg = {.value = 0};
253
254 pf_qs_cfg.ena = enable ? 1 : 0;
255 pf_qs_cfg.vnic = nic->vf_id;
256 ret = nicvf_mbox_qset_config(nic, &pf_qs_cfg);
257 return ret ? NICVF_ERR_SET_QS : 0;
258 }
259
260 /* Requests PF to assign and enable Qset */
261 int
262 nicvf_qset_config(struct nicvf *nic)
263 {
264 /* Enable Qset */
265 return nicvf_qset_config_internal(nic, true);
266 }
267
268 int
269 nicvf_qset_reclaim(struct nicvf *nic)
270 {
271 /* Disable Qset */
272 return nicvf_qset_config_internal(nic, false);
273 }
274
275 static int
276 cmpfunc(const void *a, const void *b)
277 {
278 return (*(const uint32_t *)a - *(const uint32_t *)b);
279 }
280
281 static uint32_t
282 nicvf_roundup_list(uint32_t val, uint32_t list[], uint32_t entries)
283 {
284 uint32_t i;
285
286 qsort(list, entries, sizeof(uint32_t), cmpfunc);
287 for (i = 0; i < entries; i++)
288 if (val <= list[i])
289 break;
290 /* Not in the list */
291 if (i >= entries)
292 return 0;
293 else
294 return list[i];
295 }
296
297 static void
298 nicvf_handle_qset_err_intr(struct nicvf *nic)
299 {
300 uint16_t qidx;
301 uint64_t status;
302
303 nicvf_log("%s (VF%d)\n", __func__, nic->vf_id);
304 nicvf_reg_dump(nic, NULL);
305
306 for (qidx = 0; qidx < MAX_CMP_QUEUES_PER_QS; qidx++) {
307 status = nicvf_queue_reg_read(
308 nic, NIC_QSET_CQ_0_7_STATUS, qidx);
309 if (!(status & NICVF_CQ_ERR_MASK))
310 continue;
311
312 if (status & NICVF_CQ_WR_FULL)
313 nicvf_log("[%d]NICVF_CQ_WR_FULL\n", qidx);
314 if (status & NICVF_CQ_WR_DISABLE)
315 nicvf_log("[%d]NICVF_CQ_WR_DISABLE\n", qidx);
316 if (status & NICVF_CQ_WR_FAULT)
317 nicvf_log("[%d]NICVF_CQ_WR_FAULT\n", qidx);
318 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_STATUS, qidx, 0);
319 }
320
321 for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) {
322 status = nicvf_queue_reg_read(
323 nic, NIC_QSET_SQ_0_7_STATUS, qidx);
324 if (!(status & NICVF_SQ_ERR_MASK))
325 continue;
326
327 if (status & NICVF_SQ_ERR_STOPPED)
328 nicvf_log("[%d]NICVF_SQ_ERR_STOPPED\n", qidx);
329 if (status & NICVF_SQ_ERR_SEND)
330 nicvf_log("[%d]NICVF_SQ_ERR_SEND\n", qidx);
331 if (status & NICVF_SQ_ERR_DPE)
332 nicvf_log("[%d]NICVF_SQ_ERR_DPE\n", qidx);
333 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_STATUS, qidx, 0);
334 }
335
336 for (qidx = 0; qidx < MAX_RCV_BUF_DESC_RINGS_PER_QS; qidx++) {
337 status = nicvf_queue_reg_read(nic,
338 NIC_QSET_RBDR_0_1_STATUS0, qidx);
339 status &= NICVF_RBDR_FIFO_STATE_MASK;
340 status >>= NICVF_RBDR_FIFO_STATE_SHIFT;
341
342 if (status == RBDR_FIFO_STATE_FAIL)
343 nicvf_log("[%d]RBDR_FIFO_STATE_FAIL\n", qidx);
344 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_STATUS0, qidx, 0);
345 }
346
347 nicvf_disable_all_interrupts(nic);
348 abort();
349 }
350
351 /*
352 * Handle poll mode driver interested "mbox" and "queue-set error" interrupts.
353 * This function is not re-entrant.
354 * The caller should provide proper serialization.
355 */
356 int
357 nicvf_reg_poll_interrupts(struct nicvf *nic)
358 {
359 int msg = 0;
360 uint64_t intr;
361
362 intr = nicvf_reg_read(nic, NIC_VF_INT);
363 if (intr & NICVF_INTR_MBOX_MASK) {
364 nicvf_reg_write(nic, NIC_VF_INT, NICVF_INTR_MBOX_MASK);
365 msg = nicvf_handle_mbx_intr(nic);
366 }
367 if (intr & NICVF_INTR_QS_ERR_MASK) {
368 nicvf_reg_write(nic, NIC_VF_INT, NICVF_INTR_QS_ERR_MASK);
369 nicvf_handle_qset_err_intr(nic);
370 }
371 return msg;
372 }
373
374 static int
375 nicvf_qset_poll_reg(struct nicvf *nic, uint16_t qidx, uint32_t offset,
376 uint32_t bit_pos, uint32_t bits, uint64_t val)
377 {
378 uint64_t bit_mask;
379 uint64_t reg_val;
380 int timeout = NICVF_REG_POLL_ITER_NR;
381
382 bit_mask = (1ULL << bits) - 1;
383 bit_mask = (bit_mask << bit_pos);
384
385 while (timeout) {
386 reg_val = nicvf_queue_reg_read(nic, offset, qidx);
387 if (((reg_val & bit_mask) >> bit_pos) == val)
388 return NICVF_OK;
389 nicvf_delay_us(NICVF_REG_POLL_DELAY_US);
390 timeout--;
391 }
392 return NICVF_ERR_REG_POLL;
393 }
394
395 int
396 nicvf_qset_rbdr_reclaim(struct nicvf *nic, uint16_t qidx)
397 {
398 uint64_t status;
399 int timeout = NICVF_REG_POLL_ITER_NR;
400 struct nicvf_rbdr *rbdr = nic->rbdr;
401
402 /* Save head and tail pointers for freeing up buffers */
403 if (rbdr) {
404 rbdr->head = nicvf_queue_reg_read(nic,
405 NIC_QSET_RBDR_0_1_HEAD, qidx) >> 3;
406 rbdr->tail = nicvf_queue_reg_read(nic,
407 NIC_QSET_RBDR_0_1_TAIL, qidx) >> 3;
408 rbdr->next_tail = rbdr->tail;
409 }
410
411 /* Reset RBDR */
412 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_CFG, qidx,
413 NICVF_RBDR_RESET);
414
415 /* Disable RBDR */
416 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_CFG, qidx, 0);
417 if (nicvf_qset_poll_reg(nic, qidx, NIC_QSET_RBDR_0_1_STATUS0,
418 62, 2, 0x00))
419 return NICVF_ERR_RBDR_DISABLE;
420
421 while (1) {
422 status = nicvf_queue_reg_read(nic,
423 NIC_QSET_RBDR_0_1_PRFCH_STATUS, qidx);
424 if ((status & 0xFFFFFFFF) == ((status >> 32) & 0xFFFFFFFF))
425 break;
426 nicvf_delay_us(NICVF_REG_POLL_DELAY_US);
427 timeout--;
428 if (!timeout)
429 return NICVF_ERR_RBDR_PREFETCH;
430 }
431
432 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_CFG, qidx,
433 NICVF_RBDR_RESET);
434 if (nicvf_qset_poll_reg(nic, qidx,
435 NIC_QSET_RBDR_0_1_STATUS0, 62, 2, 0x02))
436 return NICVF_ERR_RBDR_RESET1;
437
438 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_CFG, qidx, 0x00);
439 if (nicvf_qset_poll_reg(nic, qidx,
440 NIC_QSET_RBDR_0_1_STATUS0, 62, 2, 0x00))
441 return NICVF_ERR_RBDR_RESET2;
442
443 return NICVF_OK;
444 }
445
446 static int
447 nicvf_qsize_regbit(uint32_t len, uint32_t len_shift)
448 {
449 int val;
450
451 val = ((uint32_t)log2(len) - len_shift);
452 assert(val >= NICVF_QSIZE_MIN_VAL);
453 assert(val <= NICVF_QSIZE_MAX_VAL);
454 return val;
455 }
456
457 int
458 nicvf_qset_rbdr_config(struct nicvf *nic, uint16_t qidx)
459 {
460 int ret;
461 uint64_t head, tail;
462 struct nicvf_rbdr *rbdr = nic->rbdr;
463 struct rbdr_cfg rbdr_cfg = {.value = 0};
464
465 ret = nicvf_qset_rbdr_reclaim(nic, qidx);
466 if (ret)
467 return ret;
468
469 /* Set descriptor base address */
470 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_BASE, qidx, rbdr->phys);
471
472 /* Enable RBDR & set queue size */
473 rbdr_cfg.ena = 1;
474 rbdr_cfg.reset = 0;
475 rbdr_cfg.ldwb = 0;
476 rbdr_cfg.qsize = nicvf_qsize_regbit(rbdr->qlen_mask + 1,
477 RBDR_SIZE_SHIFT);
478 rbdr_cfg.avg_con = 0;
479 rbdr_cfg.lines = rbdr->buffsz / 128;
480
481 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_CFG, qidx, rbdr_cfg.value);
482
483 /* Verify proper RBDR reset */
484 head = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_HEAD, qidx);
485 tail = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_TAIL, qidx);
486
487 if (head | tail)
488 return NICVF_ERR_RBDR_RESET;
489
490 return NICVF_OK;
491 }
492
493 uint32_t
494 nicvf_qsize_rbdr_roundup(uint32_t val)
495 {
496 uint32_t list[] = {RBDR_QUEUE_SZ_8K, RBDR_QUEUE_SZ_16K,
497 RBDR_QUEUE_SZ_32K, RBDR_QUEUE_SZ_64K,
498 RBDR_QUEUE_SZ_128K, RBDR_QUEUE_SZ_256K,
499 RBDR_QUEUE_SZ_512K};
500 return nicvf_roundup_list(val, list, NICVF_ARRAY_SIZE(list));
501 }
502
503 int
504 nicvf_qset_rbdr_precharge(void *dev, struct nicvf *nic,
505 uint16_t ridx, rbdr_pool_get_handler handler,
506 uint32_t max_buffs)
507 {
508 struct rbdr_entry_t *desc, *desc0;
509 struct nicvf_rbdr *rbdr = nic->rbdr;
510 uint32_t count;
511 nicvf_phys_addr_t phy;
512
513 assert(rbdr != NULL);
514 desc = rbdr->desc;
515 count = 0;
516 /* Don't fill beyond max numbers of desc */
517 while (count < rbdr->qlen_mask) {
518 if (count >= max_buffs)
519 break;
520 desc0 = desc + count;
521 phy = handler(dev, nic);
522 if (phy) {
523 desc0->full_addr = phy;
524 count++;
525 } else {
526 break;
527 }
528 }
529 nicvf_smp_wmb();
530 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_DOOR, ridx, count);
531 rbdr->tail = nicvf_queue_reg_read(nic,
532 NIC_QSET_RBDR_0_1_TAIL, ridx) >> 3;
533 rbdr->next_tail = rbdr->tail;
534 nicvf_smp_rmb();
535 return 0;
536 }
537
538 int
539 nicvf_qset_rbdr_active(struct nicvf *nic, uint16_t qidx)
540 {
541 return nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_STATUS0, qidx);
542 }
543
544 int
545 nicvf_qset_sq_reclaim(struct nicvf *nic, uint16_t qidx)
546 {
547 uint64_t head, tail;
548 struct sq_cfg sq_cfg;
549
550 sq_cfg.value = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CFG, qidx);
551
552 /* Disable send queue */
553 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, 0);
554
555 /* Check if SQ is stopped */
556 if (sq_cfg.ena && nicvf_qset_poll_reg(nic, qidx, NIC_QSET_SQ_0_7_STATUS,
557 NICVF_SQ_STATUS_STOPPED_BIT, 1, 0x01))
558 return NICVF_ERR_SQ_DISABLE;
559
560 /* Reset send queue */
561 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, NICVF_SQ_RESET);
562 head = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_HEAD, qidx) >> 4;
563 tail = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_TAIL, qidx) >> 4;
564 if (head | tail)
565 return NICVF_ERR_SQ_RESET;
566
567 return 0;
568 }
569
570 int
571 nicvf_qset_sq_config(struct nicvf *nic, uint16_t qidx, struct nicvf_txq *txq)
572 {
573 int ret;
574 struct sq_cfg sq_cfg = {.value = 0};
575
576 ret = nicvf_qset_sq_reclaim(nic, qidx);
577 if (ret)
578 return ret;
579
580 /* Send a mailbox msg to PF to config SQ */
581 if (nicvf_mbox_sq_config(nic, qidx))
582 return NICVF_ERR_SQ_PF_CFG;
583
584 /* Set queue base address */
585 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_BASE, qidx, txq->phys);
586
587 /* Enable send queue & set queue size */
588 sq_cfg.ena = 1;
589 sq_cfg.reset = 0;
590 sq_cfg.ldwb = 0;
591 sq_cfg.qsize = nicvf_qsize_regbit(txq->qlen_mask + 1, SND_QSIZE_SHIFT);
592 sq_cfg.tstmp_bgx_intf = 0;
593 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, sq_cfg.value);
594
595 /* Ring doorbell so that H/W restarts processing SQEs */
596 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_DOOR, qidx, 0);
597
598 return 0;
599 }
600
601 uint32_t
602 nicvf_qsize_sq_roundup(uint32_t val)
603 {
604 uint32_t list[] = {SND_QUEUE_SZ_1K, SND_QUEUE_SZ_2K,
605 SND_QUEUE_SZ_4K, SND_QUEUE_SZ_8K,
606 SND_QUEUE_SZ_16K, SND_QUEUE_SZ_32K,
607 SND_QUEUE_SZ_64K};
608 return nicvf_roundup_list(val, list, NICVF_ARRAY_SIZE(list));
609 }
610
611 int
612 nicvf_qset_rq_reclaim(struct nicvf *nic, uint16_t qidx)
613 {
614 /* Disable receive queue */
615 nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, 0);
616 return nicvf_mbox_rq_sync(nic);
617 }
618
619 int
620 nicvf_qset_rq_config(struct nicvf *nic, uint16_t qidx, struct nicvf_rxq *rxq)
621 {
622 struct pf_rq_cfg pf_rq_cfg = {.value = 0};
623 struct rq_cfg rq_cfg = {.value = 0};
624
625 if (nicvf_qset_rq_reclaim(nic, qidx))
626 return NICVF_ERR_RQ_CLAIM;
627
628 pf_rq_cfg.strip_pre_l2 = 0;
629 /* First cache line of RBDR data will be allocated into L2C */
630 pf_rq_cfg.caching = RQ_CACHE_ALLOC_FIRST;
631 pf_rq_cfg.cq_qs = nic->vf_id;
632 pf_rq_cfg.cq_idx = qidx;
633 pf_rq_cfg.rbdr_cont_qs = nic->vf_id;
634 pf_rq_cfg.rbdr_cont_idx = 0;
635 pf_rq_cfg.rbdr_strt_qs = nic->vf_id;
636 pf_rq_cfg.rbdr_strt_idx = 0;
637
638 /* Send a mailbox msg to PF to config RQ */
639 if (nicvf_mbox_rq_config(nic, qidx, &pf_rq_cfg))
640 return NICVF_ERR_RQ_PF_CFG;
641
642 /* Select Rx backpressure */
643 if (nicvf_mbox_rq_bp_config(nic, qidx, rxq->rx_drop_en))
644 return NICVF_ERR_RQ_BP_CFG;
645
646 /* Send a mailbox msg to PF to config RQ drop */
647 if (nicvf_mbox_rq_drop_config(nic, qidx, rxq->rx_drop_en))
648 return NICVF_ERR_RQ_DROP_CFG;
649
650 /* Enable Receive queue */
651 rq_cfg.ena = 1;
652 nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, rq_cfg.value);
653
654 return 0;
655 }
656
657 int
658 nicvf_qset_cq_reclaim(struct nicvf *nic, uint16_t qidx)
659 {
660 uint64_t tail, head;
661
662 /* Disable completion queue */
663 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, 0);
664 if (nicvf_qset_poll_reg(nic, qidx, NIC_QSET_CQ_0_7_CFG, 42, 1, 0))
665 return NICVF_ERR_CQ_DISABLE;
666
667 /* Reset completion queue */
668 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, NICVF_CQ_RESET);
669 tail = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_TAIL, qidx) >> 9;
670 head = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, qidx) >> 9;
671 if (head | tail)
672 return NICVF_ERR_CQ_RESET;
673
674 /* Disable timer threshold (doesn't get reset upon CQ reset) */
675 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG2, qidx, 0);
676 return 0;
677 }
678
679 int
680 nicvf_qset_cq_config(struct nicvf *nic, uint16_t qidx, struct nicvf_rxq *rxq)
681 {
682 int ret;
683 struct cq_cfg cq_cfg = {.value = 0};
684
685 ret = nicvf_qset_cq_reclaim(nic, qidx);
686 if (ret)
687 return ret;
688
689 /* Set completion queue base address */
690 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_BASE, qidx, rxq->phys);
691
692 cq_cfg.ena = 1;
693 cq_cfg.reset = 0;
694 /* Writes of CQE will be allocated into L2C */
695 cq_cfg.caching = 1;
696 cq_cfg.qsize = nicvf_qsize_regbit(rxq->qlen_mask + 1, CMP_QSIZE_SHIFT);
697 cq_cfg.avg_con = 0;
698 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, cq_cfg.value);
699
700 /* Set threshold value for interrupt generation */
701 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_THRESH, qidx, 0);
702 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG2, qidx, 0);
703 return 0;
704 }
705
706 uint32_t
707 nicvf_qsize_cq_roundup(uint32_t val)
708 {
709 uint32_t list[] = {CMP_QUEUE_SZ_1K, CMP_QUEUE_SZ_2K,
710 CMP_QUEUE_SZ_4K, CMP_QUEUE_SZ_8K,
711 CMP_QUEUE_SZ_16K, CMP_QUEUE_SZ_32K,
712 CMP_QUEUE_SZ_64K};
713 return nicvf_roundup_list(val, list, NICVF_ARRAY_SIZE(list));
714 }
715
716
717 void
718 nicvf_vlan_hw_strip(struct nicvf *nic, bool enable)
719 {
720 uint64_t val;
721
722 val = nicvf_reg_read(nic, NIC_VNIC_RQ_GEN_CFG);
723 if (enable)
724 val |= (STRIP_FIRST_VLAN << 25);
725 else
726 val &= ~((STRIP_SECOND_VLAN | STRIP_FIRST_VLAN) << 25);
727
728 nicvf_reg_write(nic, NIC_VNIC_RQ_GEN_CFG, val);
729 }
730
731 void
732 nicvf_apad_config(struct nicvf *nic, bool enable)
733 {
734 uint64_t val;
735
736 /* APAD always enabled in this device */
737 if (!(nic->hwcap & NICVF_CAP_DISABLE_APAD))
738 return;
739
740 val = nicvf_reg_read(nic, NIC_VNIC_RQ_GEN_CFG);
741 if (enable)
742 val &= ~(1ULL << NICVF_QS_RQ_DIS_APAD_SHIFT);
743 else
744 val |= (1ULL << NICVF_QS_RQ_DIS_APAD_SHIFT);
745
746 nicvf_reg_write(nic, NIC_VNIC_RQ_GEN_CFG, val);
747 }
748
749 void
750 nicvf_rss_set_key(struct nicvf *nic, uint8_t *key)
751 {
752 int idx;
753 uint64_t addr, val;
754 uint64_t *keyptr = (uint64_t *)key;
755
756 addr = NIC_VNIC_RSS_KEY_0_4;
757 for (idx = 0; idx < RSS_HASH_KEY_SIZE; idx++) {
758 val = nicvf_cpu_to_be_64(*keyptr);
759 nicvf_reg_write(nic, addr, val);
760 addr += sizeof(uint64_t);
761 keyptr++;
762 }
763 }
764
765 void
766 nicvf_rss_get_key(struct nicvf *nic, uint8_t *key)
767 {
768 int idx;
769 uint64_t addr, val;
770 uint64_t *keyptr = (uint64_t *)key;
771
772 addr = NIC_VNIC_RSS_KEY_0_4;
773 for (idx = 0; idx < RSS_HASH_KEY_SIZE; idx++) {
774 val = nicvf_reg_read(nic, addr);
775 *keyptr = nicvf_be_to_cpu_64(val);
776 addr += sizeof(uint64_t);
777 keyptr++;
778 }
779 }
780
781 void
782 nicvf_rss_set_cfg(struct nicvf *nic, uint64_t val)
783 {
784 nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, val);
785 }
786
787 uint64_t
788 nicvf_rss_get_cfg(struct nicvf *nic)
789 {
790 return nicvf_reg_read(nic, NIC_VNIC_RSS_CFG);
791 }
792
793 int
794 nicvf_rss_reta_update(struct nicvf *nic, uint8_t *tbl, uint32_t max_count)
795 {
796 uint32_t idx;
797 struct nicvf_rss_reta_info *rss = &nic->rss_info;
798
799 /* result will be stored in nic->rss_info.rss_size */
800 if (nicvf_mbox_get_rss_size(nic))
801 return NICVF_ERR_RSS_GET_SZ;
802
803 assert(rss->rss_size > 0);
804 rss->hash_bits = (uint8_t)log2(rss->rss_size);
805 for (idx = 0; idx < rss->rss_size && idx < max_count; idx++)
806 rss->ind_tbl[idx] = tbl[idx];
807
808 if (nicvf_mbox_config_rss(nic))
809 return NICVF_ERR_RSS_TBL_UPDATE;
810
811 return NICVF_OK;
812 }
813
814 int
815 nicvf_rss_reta_query(struct nicvf *nic, uint8_t *tbl, uint32_t max_count)
816 {
817 uint32_t idx;
818 struct nicvf_rss_reta_info *rss = &nic->rss_info;
819
820 /* result will be stored in nic->rss_info.rss_size */
821 if (nicvf_mbox_get_rss_size(nic))
822 return NICVF_ERR_RSS_GET_SZ;
823
824 assert(rss->rss_size > 0);
825 rss->hash_bits = (uint8_t)log2(rss->rss_size);
826 for (idx = 0; idx < rss->rss_size && idx < max_count; idx++)
827 tbl[idx] = rss->ind_tbl[idx];
828
829 return NICVF_OK;
830 }
831
832 int
833 nicvf_rss_config(struct nicvf *nic, uint32_t qcnt, uint64_t cfg)
834 {
835 uint32_t idx;
836 uint8_t default_reta[NIC_MAX_RSS_IDR_TBL_SIZE];
837 uint8_t default_key[RSS_HASH_KEY_BYTE_SIZE] = {
838 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
839 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
840 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
841 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
842 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD
843 };
844
845 if (nic->cpi_alg != CPI_ALG_NONE)
846 return -EINVAL;
847
848 if (cfg == 0)
849 return -EINVAL;
850
851 /* Update default RSS key and cfg */
852 nicvf_rss_set_key(nic, default_key);
853 nicvf_rss_set_cfg(nic, cfg);
854
855 /* Update default RSS RETA */
856 for (idx = 0; idx < NIC_MAX_RSS_IDR_TBL_SIZE; idx++)
857 default_reta[idx] = idx % qcnt;
858
859 return nicvf_rss_reta_update(nic, default_reta,
860 NIC_MAX_RSS_IDR_TBL_SIZE);
861 }
862
863 int
864 nicvf_rss_term(struct nicvf *nic)
865 {
866 uint32_t idx;
867 uint8_t disable_rss[NIC_MAX_RSS_IDR_TBL_SIZE];
868
869 nicvf_rss_set_cfg(nic, 0);
870 /* Redirect the output to 0th queue */
871 for (idx = 0; idx < NIC_MAX_RSS_IDR_TBL_SIZE; idx++)
872 disable_rss[idx] = 0;
873
874 return nicvf_rss_reta_update(nic, disable_rss,
875 NIC_MAX_RSS_IDR_TBL_SIZE);
876 }
877
878 int
879 nicvf_loopback_config(struct nicvf *nic, bool enable)
880 {
881 if (enable && nic->loopback_supported == 0)
882 return NICVF_ERR_LOOPBACK_CFG;
883
884 return nicvf_mbox_loopback_config(nic, enable);
885 }
886
887 void
888 nicvf_hw_get_stats(struct nicvf *nic, struct nicvf_hw_stats *stats)
889 {
890 stats->rx_bytes = NICVF_GET_RX_STATS(RX_OCTS);
891 stats->rx_ucast_frames = NICVF_GET_RX_STATS(RX_UCAST);
892 stats->rx_bcast_frames = NICVF_GET_RX_STATS(RX_BCAST);
893 stats->rx_mcast_frames = NICVF_GET_RX_STATS(RX_MCAST);
894 stats->rx_fcs_errors = NICVF_GET_RX_STATS(RX_FCS);
895 stats->rx_l2_errors = NICVF_GET_RX_STATS(RX_L2ERR);
896 stats->rx_drop_red = NICVF_GET_RX_STATS(RX_RED);
897 stats->rx_drop_red_bytes = NICVF_GET_RX_STATS(RX_RED_OCTS);
898 stats->rx_drop_overrun = NICVF_GET_RX_STATS(RX_ORUN);
899 stats->rx_drop_overrun_bytes = NICVF_GET_RX_STATS(RX_ORUN_OCTS);
900 stats->rx_drop_bcast = NICVF_GET_RX_STATS(RX_DRP_BCAST);
901 stats->rx_drop_mcast = NICVF_GET_RX_STATS(RX_DRP_MCAST);
902 stats->rx_drop_l3_bcast = NICVF_GET_RX_STATS(RX_DRP_L3BCAST);
903 stats->rx_drop_l3_mcast = NICVF_GET_RX_STATS(RX_DRP_L3MCAST);
904
905 stats->tx_bytes_ok = NICVF_GET_TX_STATS(TX_OCTS);
906 stats->tx_ucast_frames_ok = NICVF_GET_TX_STATS(TX_UCAST);
907 stats->tx_bcast_frames_ok = NICVF_GET_TX_STATS(TX_BCAST);
908 stats->tx_mcast_frames_ok = NICVF_GET_TX_STATS(TX_MCAST);
909 stats->tx_drops = NICVF_GET_TX_STATS(TX_DROP);
910 }
911
912 void
913 nicvf_hw_get_rx_qstats(struct nicvf *nic, struct nicvf_hw_rx_qstats *qstats,
914 uint16_t qidx)
915 {
916 qstats->q_rx_bytes =
917 nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_STATUS0, qidx);
918 qstats->q_rx_packets =
919 nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_STATUS1, qidx);
920 }
921
922 void
923 nicvf_hw_get_tx_qstats(struct nicvf *nic, struct nicvf_hw_tx_qstats *qstats,
924 uint16_t qidx)
925 {
926 qstats->q_tx_bytes =
927 nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS0, qidx);
928 qstats->q_tx_packets =
929 nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS1, qidx);
930 }