Imported Upstream version 16.11
[deb_dpdk.git] / 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 }