1 /* 2 * BSD LICENSE 3 * 4 * Copyright (C) Cavium, Inc. 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, Inc 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 = nicvf_log2_u32(len) - len_shift; 452 453 assert(val >= NICVF_QSIZE_MIN_VAL); 454 assert(val <= NICVF_QSIZE_MAX_VAL); 455 return val; 456 } 457 458 int 459 nicvf_qset_rbdr_config(struct nicvf *nic, uint16_t qidx) 460 { 461 int ret; 462 uint64_t head, tail; 463 struct nicvf_rbdr *rbdr = nic->rbdr; 464 struct rbdr_cfg rbdr_cfg = {.value = 0}; 465 466 ret = nicvf_qset_rbdr_reclaim(nic, qidx); 467 if (ret) 468 return ret; 469 470 /* Set descriptor base address */ 471 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_BASE, qidx, rbdr->phys); 472 473 /* Enable RBDR & set queue size */ 474 rbdr_cfg.ena = 1; 475 rbdr_cfg.reset = 0; 476 rbdr_cfg.ldwb = 0; 477 rbdr_cfg.qsize = nicvf_qsize_regbit(rbdr->qlen_mask + 1, 478 RBDR_SIZE_SHIFT); 479 rbdr_cfg.avg_con = 0; 480 rbdr_cfg.lines = rbdr->buffsz / 128; 481 482 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_CFG, qidx, rbdr_cfg.value); 483 484 /* Verify proper RBDR reset */ 485 head = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_HEAD, qidx); 486 tail = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_TAIL, qidx); 487 488 if (head | tail) 489 return NICVF_ERR_RBDR_RESET; 490 491 return NICVF_OK; 492 } 493 494 uint32_t 495 nicvf_qsize_rbdr_roundup(uint32_t val) 496 { 497 uint32_t list[] = {RBDR_QUEUE_SZ_8K, RBDR_QUEUE_SZ_16K, 498 RBDR_QUEUE_SZ_32K, RBDR_QUEUE_SZ_64K, 499 RBDR_QUEUE_SZ_128K, RBDR_QUEUE_SZ_256K, 500 RBDR_QUEUE_SZ_512K}; 501 return nicvf_roundup_list(val, list, NICVF_ARRAY_SIZE(list)); 502 } 503 504 int 505 nicvf_qset_rbdr_precharge(void *dev, struct nicvf *nic, 506 uint16_t ridx, rbdr_pool_get_handler handler, 507 uint32_t max_buffs) 508 { 509 struct rbdr_entry_t *desc, *desc0; 510 struct nicvf_rbdr *rbdr = nic->rbdr; 511 uint32_t count; 512 nicvf_iova_addr_t phy; 513 514 assert(rbdr != NULL); 515 desc = rbdr->desc; 516 count = 0; 517 /* Don't fill beyond max numbers of desc */ 518 while (count < rbdr->qlen_mask) { 519 if (count >= max_buffs) 520 break; 521 desc0 = desc + count; 522 phy = handler(dev, nic); 523 if (phy) { 524 desc0->full_addr = phy; 525 count++; 526 } else { 527 break; 528 } 529 } 530 nicvf_smp_wmb(); 531 nicvf_queue_reg_write(nic, NIC_QSET_RBDR_0_1_DOOR, ridx, count); 532 rbdr->tail = nicvf_queue_reg_read(nic, 533 NIC_QSET_RBDR_0_1_TAIL, ridx) >> 3; 534 rbdr->next_tail = rbdr->tail; 535 nicvf_smp_rmb(); 536 return 0; 537 } 538 539 int 540 nicvf_qset_rbdr_active(struct nicvf *nic, uint16_t qidx) 541 { 542 return nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_STATUS0, qidx); 543 } 544 545 int 546 nicvf_qset_sq_reclaim(struct nicvf *nic, uint16_t qidx) 547 { 548 uint64_t head, tail; 549 struct sq_cfg sq_cfg; 550 551 sq_cfg.value = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CFG, qidx); 552 553 /* Disable send queue */ 554 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, 0); 555 556 /* Check if SQ is stopped */ 557 if (sq_cfg.ena && nicvf_qset_poll_reg(nic, qidx, NIC_QSET_SQ_0_7_STATUS, 558 NICVF_SQ_STATUS_STOPPED_BIT, 1, 0x01)) 559 return NICVF_ERR_SQ_DISABLE; 560 561 /* Reset send queue */ 562 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, NICVF_SQ_RESET); 563 head = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_HEAD, qidx) >> 4; 564 tail = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_TAIL, qidx) >> 4; 565 if (head | tail) 566 return NICVF_ERR_SQ_RESET; 567 568 return 0; 569 } 570 571 int 572 nicvf_qset_sq_config(struct nicvf *nic, uint16_t qidx, struct nicvf_txq *txq) 573 { 574 int ret; 575 struct sq_cfg sq_cfg = {.value = 0}; 576 577 ret = nicvf_qset_sq_reclaim(nic, qidx); 578 if (ret) 579 return ret; 580 581 /* Send a mailbox msg to PF to config SQ */ 582 if (nicvf_mbox_sq_config(nic, qidx)) 583 return NICVF_ERR_SQ_PF_CFG; 584 585 /* Set queue base address */ 586 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_BASE, qidx, txq->phys); 587 588 /* Enable send queue & set queue size */ 589 sq_cfg.cq_limit = 0; 590 sq_cfg.ena = 1; 591 sq_cfg.reset = 0; 592 sq_cfg.ldwb = 0; 593 sq_cfg.qsize = nicvf_qsize_regbit(txq->qlen_mask + 1, SND_QSIZE_SHIFT); 594 sq_cfg.tstmp_bgx_intf = 0; 595 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, sq_cfg.value); 596 597 /* Ring doorbell so that H/W restarts processing SQEs */ 598 nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_DOOR, qidx, 0); 599 600 return 0; 601 } 602 603 uint32_t 604 nicvf_qsize_sq_roundup(uint32_t val) 605 { 606 uint32_t list[] = {SND_QUEUE_SZ_1K, SND_QUEUE_SZ_2K, 607 SND_QUEUE_SZ_4K, SND_QUEUE_SZ_8K, 608 SND_QUEUE_SZ_16K, SND_QUEUE_SZ_32K, 609 SND_QUEUE_SZ_64K}; 610 return nicvf_roundup_list(val, list, NICVF_ARRAY_SIZE(list)); 611 } 612 613 int 614 nicvf_qset_rq_reclaim(struct nicvf *nic, uint16_t qidx) 615 { 616 /* Disable receive queue */ 617 nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, 0); 618 return nicvf_mbox_rq_sync(nic); 619 } 620 621 int 622 nicvf_qset_rq_config(struct nicvf *nic, uint16_t qidx, struct nicvf_rxq *rxq) 623 { 624 struct pf_rq_cfg pf_rq_cfg = {.value = 0}; 625 struct rq_cfg rq_cfg = {.value = 0}; 626 627 if (nicvf_qset_rq_reclaim(nic, qidx)) 628 return NICVF_ERR_RQ_CLAIM; 629 630 pf_rq_cfg.strip_pre_l2 = 0; 631 /* First cache line of RBDR data will be allocated into L2C */ 632 pf_rq_cfg.caching = RQ_CACHE_ALLOC_FIRST; 633 pf_rq_cfg.cq_qs = nic->vf_id; 634 pf_rq_cfg.cq_idx = qidx; 635 pf_rq_cfg.rbdr_cont_qs = nic->vf_id; 636 pf_rq_cfg.rbdr_cont_idx = 0; 637 pf_rq_cfg.rbdr_strt_qs = nic->vf_id; 638 pf_rq_cfg.rbdr_strt_idx = 0; 639 640 /* Send a mailbox msg to PF to config RQ */ 641 if (nicvf_mbox_rq_config(nic, qidx, &pf_rq_cfg)) 642 return NICVF_ERR_RQ_PF_CFG; 643 644 /* Select Rx backpressure */ 645 if (nicvf_mbox_rq_bp_config(nic, qidx, rxq->rx_drop_en)) 646 return NICVF_ERR_RQ_BP_CFG; 647 648 /* Send a mailbox msg to PF to config RQ drop */ 649 if (nicvf_mbox_rq_drop_config(nic, qidx, rxq->rx_drop_en)) 650 return NICVF_ERR_RQ_DROP_CFG; 651 652 /* Enable Receive queue */ 653 rq_cfg.ena = 1; 654 nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, rq_cfg.value); 655 656 return 0; 657 } 658 659 int 660 nicvf_qset_cq_reclaim(struct nicvf *nic, uint16_t qidx) 661 { 662 uint64_t tail, head; 663 664 /* Disable completion queue */ 665 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, 0); 666 if (nicvf_qset_poll_reg(nic, qidx, NIC_QSET_CQ_0_7_CFG, 42, 1, 0)) 667 return NICVF_ERR_CQ_DISABLE; 668 669 /* Reset completion queue */ 670 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, NICVF_CQ_RESET); 671 tail = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_TAIL, qidx) >> 9; 672 head = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, qidx) >> 9; 673 if (head | tail) 674 return NICVF_ERR_CQ_RESET; 675 676 /* Disable timer threshold (doesn't get reset upon CQ reset) */ 677 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG2, qidx, 0); 678 return 0; 679 } 680 681 int 682 nicvf_qset_cq_config(struct nicvf *nic, uint16_t qidx, struct nicvf_rxq *rxq) 683 { 684 int ret; 685 struct cq_cfg cq_cfg = {.value = 0}; 686 687 ret = nicvf_qset_cq_reclaim(nic, qidx); 688 if (ret) 689 return ret; 690 691 /* Set completion queue base address */ 692 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_BASE, qidx, rxq->phys); 693 694 cq_cfg.ena = 1; 695 cq_cfg.reset = 0; 696 /* Writes of CQE will be allocated into L2C */ 697 cq_cfg.caching = 1; 698 cq_cfg.qsize = nicvf_qsize_regbit(rxq->qlen_mask + 1, CMP_QSIZE_SHIFT); 699 cq_cfg.avg_con = 0; 700 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, cq_cfg.value); 701 702 /* Set threshold value for interrupt generation */ 703 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_THRESH, qidx, 0); 704 nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG2, qidx, 0); 705 return 0; 706 } 707 708 uint32_t 709 nicvf_qsize_cq_roundup(uint32_t val) 710 { 711 uint32_t list[] = {CMP_QUEUE_SZ_1K, CMP_QUEUE_SZ_2K, 712 CMP_QUEUE_SZ_4K, CMP_QUEUE_SZ_8K, 713 CMP_QUEUE_SZ_16K, CMP_QUEUE_SZ_32K, 714 CMP_QUEUE_SZ_64K}; 715 return nicvf_roundup_list(val, list, NICVF_ARRAY_SIZE(list)); 716 } 717 718 719 void 720 nicvf_vlan_hw_strip(struct nicvf *nic, bool enable) 721 { 722 uint64_t val; 723 724 val = nicvf_reg_read(nic, NIC_VNIC_RQ_GEN_CFG); 725 if (enable) 726 val |= (STRIP_FIRST_VLAN << 25); 727 else 728 val &= ~((STRIP_SECOND_VLAN | STRIP_FIRST_VLAN) << 25); 729 730 nicvf_reg_write(nic, NIC_VNIC_RQ_GEN_CFG, val); 731 } 732 733 void 734 nicvf_apad_config(struct nicvf *nic, bool enable) 735 { 736 uint64_t val; 737 738 /* APAD always enabled in this device */ 739 if (!(nic->hwcap & NICVF_CAP_DISABLE_APAD)) 740 return; 741 742 val = nicvf_reg_read(nic, NIC_VNIC_RQ_GEN_CFG); 743 if (enable) 744 val &= ~(1ULL << NICVF_QS_RQ_DIS_APAD_SHIFT); 745 else 746 val |= (1ULL << NICVF_QS_RQ_DIS_APAD_SHIFT); 747 748 nicvf_reg_write(nic, NIC_VNIC_RQ_GEN_CFG, val); 749 } 750 751 void 752 nicvf_rss_set_key(struct nicvf *nic, uint8_t *key) 753 { 754 int idx; 755 uint64_t addr, val; 756 uint64_t *keyptr = (uint64_t *)key; 757 758 addr = NIC_VNIC_RSS_KEY_0_4; 759 for (idx = 0; idx < RSS_HASH_KEY_SIZE; idx++) { 760 val = nicvf_cpu_to_be_64(*keyptr); 761 nicvf_reg_write(nic, addr, val); 762 addr += sizeof(uint64_t); 763 keyptr++; 764 } 765 } 766 767 void 768 nicvf_rss_get_key(struct nicvf *nic, uint8_t *key) 769 { 770 int idx; 771 uint64_t addr, val; 772 uint64_t *keyptr = (uint64_t *)key; 773 774 addr = NIC_VNIC_RSS_KEY_0_4; 775 for (idx = 0; idx < RSS_HASH_KEY_SIZE; idx++) { 776 val = nicvf_reg_read(nic, addr); 777 *keyptr = nicvf_be_to_cpu_64(val); 778 addr += sizeof(uint64_t); 779 keyptr++; 780 } 781 } 782 783 void 784 nicvf_rss_set_cfg(struct nicvf *nic, uint64_t val) 785 { 786 nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, val); 787 } 788 789 uint64_t 790 nicvf_rss_get_cfg(struct nicvf *nic) 791 { 792 return nicvf_reg_read(nic, NIC_VNIC_RSS_CFG); 793 } 794 795 int 796 nicvf_rss_reta_update(struct nicvf *nic, uint8_t *tbl, uint32_t max_count) 797 { 798 uint32_t idx; 799 struct nicvf_rss_reta_info *rss = &nic->rss_info; 800 801 /* result will be stored in nic->rss_info.rss_size */ 802 if (nicvf_mbox_get_rss_size(nic)) 803 return NICVF_ERR_RSS_GET_SZ; 804 805 assert(rss->rss_size > 0); 806 rss->hash_bits = (uint8_t)nicvf_log2_u32(rss->rss_size); 807 for (idx = 0; idx < rss->rss_size && idx < max_count; idx++) 808 rss->ind_tbl[idx] = tbl[idx]; 809 810 if (nicvf_mbox_config_rss(nic)) 811 return NICVF_ERR_RSS_TBL_UPDATE; 812 813 return NICVF_OK; 814 } 815 816 int 817 nicvf_rss_reta_query(struct nicvf *nic, uint8_t *tbl, uint32_t max_count) 818 { 819 uint32_t idx; 820 struct nicvf_rss_reta_info *rss = &nic->rss_info; 821 822 /* result will be stored in nic->rss_info.rss_size */ 823 if (nicvf_mbox_get_rss_size(nic)) 824 return NICVF_ERR_RSS_GET_SZ; 825 826 assert(rss->rss_size > 0); 827 rss->hash_bits = (uint8_t)nicvf_log2_u32(rss->rss_size); 828 829 for (idx = 0; idx < rss->rss_size && idx < max_count; idx++) 830 tbl[idx] = rss->ind_tbl[idx]; 831 832 return NICVF_OK; 833 } 834 835 int 836 nicvf_rss_config(struct nicvf *nic, uint32_t qcnt, uint64_t cfg) 837 { 838 uint32_t idx; 839 uint8_t default_reta[NIC_MAX_RSS_IDR_TBL_SIZE]; 840 uint8_t default_key[RSS_HASH_KEY_BYTE_SIZE] = { 841 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 842 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 843 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 844 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 845 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD 846 }; 847 848 if (nic->cpi_alg != CPI_ALG_NONE) 849 return -EINVAL; 850 851 if (cfg == 0) 852 return -EINVAL; 853 854 /* Update default RSS key and cfg */ 855 nicvf_rss_set_key(nic, default_key); 856 nicvf_rss_set_cfg(nic, cfg); 857 858 /* Update default RSS RETA */ 859 for (idx = 0; idx < NIC_MAX_RSS_IDR_TBL_SIZE; idx++) 860 default_reta[idx] = idx % qcnt; 861 862 return nicvf_rss_reta_update(nic, default_reta, 863 NIC_MAX_RSS_IDR_TBL_SIZE); 864 } 865 866 int 867 nicvf_rss_term(struct nicvf *nic) 868 { 869 uint32_t idx; 870 uint8_t disable_rss[NIC_MAX_RSS_IDR_TBL_SIZE]; 871 872 nicvf_rss_set_cfg(nic, 0); 873 /* Redirect the output to 0th queue */ 874 for (idx = 0; idx < NIC_MAX_RSS_IDR_TBL_SIZE; idx++) 875 disable_rss[idx] = 0; 876 877 return nicvf_rss_reta_update(nic, disable_rss, 878 NIC_MAX_RSS_IDR_TBL_SIZE); 879 } 880 881 int 882 nicvf_loopback_config(struct nicvf *nic, bool enable) 883 { 884 if (enable && nic->loopback_supported == 0) 885 return NICVF_ERR_LOOPBACK_CFG; 886 887 return nicvf_mbox_loopback_config(nic, enable); 888 } 889 890 void 891 nicvf_hw_get_stats(struct nicvf *nic, struct nicvf_hw_stats *stats) 892 { 893 stats->rx_bytes = NICVF_GET_RX_STATS(RX_OCTS); 894 stats->rx_ucast_frames = NICVF_GET_RX_STATS(RX_UCAST); 895 stats->rx_bcast_frames = NICVF_GET_RX_STATS(RX_BCAST); 896 stats->rx_mcast_frames = NICVF_GET_RX_STATS(RX_MCAST); 897 stats->rx_fcs_errors = NICVF_GET_RX_STATS(RX_FCS); 898 stats->rx_l2_errors = NICVF_GET_RX_STATS(RX_L2ERR); 899 stats->rx_drop_red = NICVF_GET_RX_STATS(RX_RED); 900 stats->rx_drop_red_bytes = NICVF_GET_RX_STATS(RX_RED_OCTS); 901 stats->rx_drop_overrun = NICVF_GET_RX_STATS(RX_ORUN); 902 stats->rx_drop_overrun_bytes = NICVF_GET_RX_STATS(RX_ORUN_OCTS); 903 stats->rx_drop_bcast = NICVF_GET_RX_STATS(RX_DRP_BCAST); 904 stats->rx_drop_mcast = NICVF_GET_RX_STATS(RX_DRP_MCAST); 905 stats->rx_drop_l3_bcast = NICVF_GET_RX_STATS(RX_DRP_L3BCAST); 906 stats->rx_drop_l3_mcast = NICVF_GET_RX_STATS(RX_DRP_L3MCAST); 907 908 stats->tx_bytes_ok = NICVF_GET_TX_STATS(TX_OCTS); 909 stats->tx_ucast_frames_ok = NICVF_GET_TX_STATS(TX_UCAST); 910 stats->tx_bcast_frames_ok = NICVF_GET_TX_STATS(TX_BCAST); 911 stats->tx_mcast_frames_ok = NICVF_GET_TX_STATS(TX_MCAST); 912 stats->tx_drops = NICVF_GET_TX_STATS(TX_DROP); 913 } 914 915 void 916 nicvf_hw_get_rx_qstats(struct nicvf *nic, struct nicvf_hw_rx_qstats *qstats, 917 uint16_t qidx) 918 { 919 qstats->q_rx_bytes = 920 nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_STATUS0, qidx); 921 qstats->q_rx_packets = 922 nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_STATUS1, qidx); 923 } 924 925 void 926 nicvf_hw_get_tx_qstats(struct nicvf *nic, struct nicvf_hw_tx_qstats *qstats, 927 uint16_t qidx) 928 { 929 qstats->q_tx_bytes = 930 nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS0, qidx); 931 qstats->q_tx_packets = 932 nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS1, qidx); 933 } 934