1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2018 Marvell International Ltd. 4 */ 5 6#include <dm.h> 7#include <errno.h> 8#include <log.h> 9#include <malloc.h> 10#include <memalign.h> 11#include <misc.h> 12#include <net.h> 13#include <pci.h> 14#include <watchdog.h> 15 16#include <asm/arch/board.h> 17#include <asm/arch/csrs/csrs-lmt.h> 18#include <asm/io.h> 19#include <asm/types.h> 20 21#include <linux/delay.h> 22#include <linux/log2.h> 23#include <linux/types.h> 24 25#include "nix.h" 26#include "lmt.h" 27#include "cgx.h" 28 29/** 30 * NIX needs a lot of memory areas. Rather than handle all the failure cases, 31 * we'll use a wrapper around alloc that prints an error if a memory 32 * allocation fails. 33 * 34 * @param num_elements 35 * Number of elements to allocate 36 * @param elem_size Size of each element 37 * @param msg Text string to show when allocation fails 38 * 39 * Return: A valid memory location or NULL on failure 40 */ 41static void *nix_memalloc(int num_elements, size_t elem_size, const char *msg) 42{ 43 size_t alloc_size = num_elements * elem_size; 44 void *base = memalign(CONFIG_SYS_CACHELINE_SIZE, alloc_size); 45 46 if (!base) 47 printf("NIX: Mem alloc failed for %s (%d * %zu = %zu bytes)\n", 48 msg ? msg : __func__, num_elements, elem_size, 49 alloc_size); 50 else 51 memset(base, 0, alloc_size); 52 53 debug("NIX: Memory alloc for %s (%d * %zu = %zu bytes) at %p\n", 54 msg ? msg : __func__, num_elements, elem_size, alloc_size, base); 55 return base; 56} 57 58int npc_lf_setup(struct nix *nix) 59{ 60 int err; 61 62 err = npc_lf_admin_setup(nix); 63 if (err) { 64 printf("%s: Error setting up npc lf admin\n", __func__); 65 return err; 66 } 67 68 return 0; 69} 70 71static int npa_setup_pool(struct npa *npa, u32 pool_id, 72 size_t buffer_size, u32 queue_length, void *buffers[]) 73{ 74 struct { 75 union npa_lf_aura_op_free0 f0; 76 union npa_lf_aura_op_free1 f1; 77 } aura_descr; 78 int index; 79 80 for (index = 0; index < queue_length; index++) { 81 buffers[index] = memalign(CONFIG_SYS_CACHELINE_SIZE, 82 buffer_size); 83 if (!buffers[index]) { 84 printf("%s: Out of memory %d, size: %zu\n", 85 __func__, index, buffer_size); 86 return -ENOMEM; 87 } 88 debug("%s: allocating buffer %d, addr %p size: %zu\n", 89 __func__, index, buffers[index], buffer_size); 90 91 /* Add the newly obtained pointer to the pool. 128 bit 92 * writes only. 93 */ 94 aura_descr.f0.s.addr = (u64)buffers[index]; 95 aura_descr.f1.u = 0; 96 aura_descr.f1.s.aura = pool_id; 97 st128(npa->npa_base + NPA_LF_AURA_OP_FREE0(), 98 aura_descr.f0.u, aura_descr.f1.u); 99 } 100 101 return 0; 102} 103 104int npa_lf_setup(struct nix *nix) 105{ 106 struct rvu_pf *rvu = dev_get_priv(nix->dev); 107 struct nix_af *nix_af = nix->nix_af; 108 struct npa *npa; 109 union npa_af_const npa_af_const; 110 union npa_aura_s *aura; 111 union npa_pool_s *pool; 112 union rvu_func_addr_s block_addr; 113 int idx; 114 int stack_page_pointers; 115 int stack_page_bytes; 116 int err; 117 118 npa = (struct npa *)calloc(1, sizeof(struct npa)); 119 if (!npa) { 120 printf("%s: out of memory for npa instance\n", __func__); 121 return -ENOMEM; 122 } 123 block_addr.u = 0; 124 block_addr.s.block = RVU_BLOCK_ADDR_E_NPA; 125 npa->npa_base = rvu->pf_base + block_addr.u; 126 npa->npa_af = nix_af->npa_af; 127 nix->npa = npa; 128 129 npa_af_const.u = npa_af_reg_read(npa->npa_af, NPA_AF_CONST()); 130 stack_page_pointers = npa_af_const.s.stack_page_ptrs; 131 stack_page_bytes = npa_af_const.s.stack_page_bytes; 132 133 npa->stack_pages[NPA_POOL_RX] = (RQ_QLEN + stack_page_pointers - 1) / 134 stack_page_pointers; 135 npa->stack_pages[NPA_POOL_TX] = (SQ_QLEN + stack_page_pointers - 1) / 136 stack_page_pointers; 137 npa->stack_pages[NPA_POOL_SQB] = (SQB_QLEN + stack_page_pointers - 1) / 138 stack_page_pointers; 139 npa->pool_stack_pointers = stack_page_pointers; 140 141 npa->q_len[NPA_POOL_RX] = RQ_QLEN; 142 npa->q_len[NPA_POOL_TX] = SQ_QLEN; 143 npa->q_len[NPA_POOL_SQB] = SQB_QLEN; 144 145 npa->buf_size[NPA_POOL_RX] = MAX_MTU + CONFIG_SYS_CACHELINE_SIZE; 146 npa->buf_size[NPA_POOL_TX] = MAX_MTU + CONFIG_SYS_CACHELINE_SIZE; 147 npa->buf_size[NPA_POOL_SQB] = nix_af->sqb_size; 148 149 npa->aura_ctx = nix_memalloc(NPA_POOL_COUNT, 150 sizeof(union npa_aura_s), 151 "aura context"); 152 if (!npa->aura_ctx) { 153 printf("%s: Out of memory for aura context\n", __func__); 154 return -ENOMEM; 155 } 156 157 for (idx = 0; idx < NPA_POOL_COUNT; idx++) { 158 npa->pool_ctx[idx] = nix_memalloc(1, 159 sizeof(union npa_pool_s), 160 "pool context"); 161 if (!npa->pool_ctx[idx]) { 162 printf("%s: Out of memory for pool context\n", 163 __func__); 164 return -ENOMEM; 165 } 166 npa->pool_stack[idx] = nix_memalloc(npa->stack_pages[idx], 167 stack_page_bytes, 168 "pool stack"); 169 if (!npa->pool_stack[idx]) { 170 printf("%s: Out of memory for pool stack\n", __func__); 171 return -ENOMEM; 172 } 173 } 174 175 err = npa_lf_admin_setup(npa, nix->lf, (dma_addr_t)npa->aura_ctx); 176 if (err) { 177 printf("%s: Error setting up NPA LF admin for lf %d\n", 178 __func__, nix->lf); 179 return err; 180 } 181 182 /* Set up the auras */ 183 for (idx = 0; idx < NPA_POOL_COUNT; idx++) { 184 aura = npa->aura_ctx + (idx * sizeof(union npa_aura_s)); 185 pool = npa->pool_ctx[idx]; 186 debug("%s aura %p pool %p\n", __func__, aura, pool); 187 memset(aura, 0, sizeof(union npa_aura_s)); 188 aura->s.fc_ena = 0; 189 aura->s.pool_addr = (u64)npa->pool_ctx[idx]; 190 debug("%s aura.s.pool_addr %llx pool_addr %p\n", __func__, 191 aura->s.pool_addr, npa->pool_ctx[idx]); 192 aura->s.shift = 64 - __builtin_clzll(npa->q_len[idx]) - 8; 193 aura->s.count = npa->q_len[idx]; 194 aura->s.limit = npa->q_len[idx]; 195 aura->s.ena = 1; 196 err = npa_attach_aura(nix_af, nix->lf, aura, idx); 197 if (err) 198 return err; 199 200 memset(pool, 0, sizeof(*pool)); 201 pool->s.fc_ena = 0; 202 pool->s.nat_align = 1; 203 pool->s.stack_base = (u64)(npa->pool_stack[idx]); 204 debug("%s pool.s.stack_base %llx stack_base %p\n", __func__, 205 pool->s.stack_base, npa->pool_stack[idx]); 206 pool->s.buf_size = 207 npa->buf_size[idx] / CONFIG_SYS_CACHELINE_SIZE; 208 pool->s.stack_max_pages = npa->stack_pages[idx]; 209 pool->s.shift = 210 64 - __builtin_clzll(npa->pool_stack_pointers) - 8; 211 pool->s.ptr_start = 0; 212 pool->s.ptr_end = (1ULL << 40) - 1; 213 pool->s.ena = 1; 214 err = npa_attach_pool(nix_af, nix->lf, pool, idx); 215 if (err) 216 return err; 217 } 218 219 for (idx = 0; idx < NPA_POOL_COUNT; idx++) { 220 npa->buffers[idx] = nix_memalloc(npa->q_len[idx], 221 sizeof(void *), 222 "buffers"); 223 if (!npa->buffers[idx]) { 224 printf("%s: Out of memory\n", __func__); 225 return -ENOMEM; 226 } 227 } 228 229 for (idx = 0; idx < NPA_POOL_COUNT; idx++) { 230 err = npa_setup_pool(npa, idx, npa->buf_size[idx], 231 npa->q_len[idx], npa->buffers[idx]); 232 if (err) { 233 printf("%s: Error setting up pool %d\n", 234 __func__, idx); 235 return err; 236 } 237 } 238 return 0; 239} 240 241int npa_lf_shutdown(struct nix *nix) 242{ 243 struct npa *npa = nix->npa; 244 int err; 245 int pool; 246 247 err = npa_lf_admin_shutdown(nix->nix_af, nix->lf, NPA_POOL_COUNT); 248 if (err) { 249 printf("%s: Error %d shutting down NPA LF admin\n", 250 __func__, err); 251 return err; 252 } 253 free(npa->aura_ctx); 254 npa->aura_ctx = NULL; 255 256 for (pool = 0; pool < NPA_POOL_COUNT; pool++) { 257 free(npa->pool_ctx[pool]); 258 npa->pool_ctx[pool] = NULL; 259 free(npa->pool_stack[pool]); 260 npa->pool_stack[pool] = NULL; 261 free(npa->buffers[pool]); 262 npa->buffers[pool] = NULL; 263 } 264 265 return 0; 266} 267 268int nix_lf_setup(struct nix *nix) 269{ 270 struct nix_af *nix_af = nix->nix_af; 271 int idx; 272 int err = -1; 273 274 /* Alloc NIX RQ HW context memory */ 275 nix->rq_ctx_base = nix_memalloc(nix->rq_cnt, nix_af->rq_ctx_sz, 276 "RQ CTX"); 277 if (!nix->rq_ctx_base) 278 goto error; 279 memset(nix->rq_ctx_base, 0, nix_af->rq_ctx_sz); 280 281 /* Alloc NIX SQ HW context memory */ 282 nix->sq_ctx_base = nix_memalloc(nix->sq_cnt, nix_af->sq_ctx_sz, 283 "SQ CTX"); 284 if (!nix->sq_ctx_base) 285 goto error; 286 memset(nix->sq_ctx_base, 0, nix_af->sq_ctx_sz); 287 288 /* Alloc NIX CQ HW context memory */ 289 nix->cq_ctx_base = nix_memalloc(nix->cq_cnt, nix_af->cq_ctx_sz, 290 "CQ CTX"); 291 if (!nix->cq_ctx_base) 292 goto error; 293 memset(nix->cq_ctx_base, 0, nix_af->cq_ctx_sz * NIX_CQ_COUNT); 294 /* Alloc NIX CQ Ring memory */ 295 for (idx = 0; idx < NIX_CQ_COUNT; idx++) { 296 err = qmem_alloc(&nix->cq[idx], CQ_ENTRIES, CQ_ENTRY_SIZE); 297 if (err) 298 goto error; 299 } 300 301 /* Alloc memory for Qints HW contexts */ 302 nix->qint_base = nix_memalloc(nix_af->qints, nix_af->qint_ctx_sz, 303 "Qint CTX"); 304 if (!nix->qint_base) 305 goto error; 306 /* Alloc memory for CQints HW contexts */ 307 nix->cint_base = nix_memalloc(nix_af->cints, nix_af->cint_ctx_sz, 308 "Cint CTX"); 309 if (!nix->cint_base) 310 goto error; 311 /* Alloc NIX RSS HW context memory and config the base */ 312 nix->rss_base = nix_memalloc(nix->rss_grps, nix_af->rsse_ctx_sz, 313 "RSS CTX"); 314 if (!nix->rss_base) 315 goto error; 316 317 err = nix_lf_admin_setup(nix); 318 if (err) { 319 printf("%s: Error setting up LF\n", __func__); 320 goto error; 321 } 322 323 return 0; 324 325error: 326 if (nix->rq_ctx_base) 327 free(nix->rq_ctx_base); 328 nix->rq_ctx_base = NULL; 329 if (nix->rq_ctx_base) 330 free(nix->rq_ctx_base); 331 nix->rq_ctx_base = NULL; 332 if (nix->sq_ctx_base) 333 free(nix->sq_ctx_base); 334 nix->sq_ctx_base = NULL; 335 if (nix->cq_ctx_base) 336 free(nix->cq_ctx_base); 337 nix->cq_ctx_base = NULL; 338 339 for (idx = 0; idx < NIX_CQ_COUNT; idx++) 340 qmem_free(&nix->cq[idx]); 341 342 return err; 343} 344 345int nix_lf_shutdown(struct nix *nix) 346{ 347 struct nix_af *nix_af = nix->nix_af; 348 int index; 349 int err; 350 351 err = nix_lf_admin_shutdown(nix_af, nix->lf, nix->cq_cnt, 352 nix->rq_cnt, nix->sq_cnt); 353 if (err) { 354 printf("%s: Error shutting down LF admin\n", __func__); 355 return err; 356 } 357 358 if (nix->rq_ctx_base) 359 free(nix->rq_ctx_base); 360 nix->rq_ctx_base = NULL; 361 if (nix->rq_ctx_base) 362 free(nix->rq_ctx_base); 363 nix->rq_ctx_base = NULL; 364 if (nix->sq_ctx_base) 365 free(nix->sq_ctx_base); 366 nix->sq_ctx_base = NULL; 367 if (nix->cq_ctx_base) 368 free(nix->cq_ctx_base); 369 nix->cq_ctx_base = NULL; 370 371 for (index = 0; index < NIX_CQ_COUNT; index++) 372 qmem_free(&nix->cq[index]); 373 374 debug("%s: nix lf %d reset --\n", __func__, nix->lf); 375 return 0; 376} 377 378struct nix *nix_lf_alloc(struct udevice *dev) 379{ 380 union rvu_func_addr_s block_addr; 381 struct nix *nix; 382 struct rvu_pf *rvu = dev_get_priv(dev); 383 struct rvu_af *rvu_af = dev_get_priv(rvu->afdev); 384 union rvu_pf_func_s pf_func; 385 int err; 386 387 debug("%s(%s )\n", __func__, dev->name); 388 389 nix = (struct nix *)calloc(1, sizeof(*nix)); 390 if (!nix) { 391 printf("%s: Out of memory for nix instance\n", __func__); 392 return NULL; 393 } 394 nix->nix_af = rvu_af->nix_af; 395 396 block_addr.u = 0; 397 block_addr.s.block = RVU_BLOCK_ADDR_E_NIXX(0); 398 nix->nix_base = rvu->pf_base + block_addr.u; 399 block_addr.u = 0; 400 block_addr.s.block = RVU_BLOCK_ADDR_E_NPC; 401 nix->npc_base = rvu->pf_base + block_addr.u; 402 block_addr.u = 0; 403 block_addr.s.block = RVU_BLOCK_ADDR_E_LMT; 404 nix->lmt_base = rvu->pf_base + block_addr.u; 405 406 pf_func.u = 0; 407 pf_func.s.pf = rvu->pfid; 408 nix->pf_func = pf_func.u; 409 nix->lf = rvu->nix_lfid; 410 nix->pf = rvu->pfid; 411 nix->dev = dev; 412 nix->sq_cnt = 1; 413 nix->rq_cnt = 1; 414 nix->rss_grps = 1; 415 nix->cq_cnt = 2; 416 nix->xqe_sz = NIX_CQE_SIZE_W16; 417 418 nix->lmac = nix_get_cgx_lmac(nix->pf); 419 if (!nix->lmac) { 420 printf("%s: Error: could not find lmac for pf %d\n", 421 __func__, nix->pf); 422 free(nix); 423 return NULL; 424 } 425 nix->lmac->link_num = 426 NIX_LINK_E_CGXX_LMACX(nix->lmac->cgx->cgx_id, 427 nix->lmac->lmac_id); 428 nix->lmac->chan_num = 429 NIX_CHAN_E_CGXX_LMACX_CHX(nix->lmac->cgx->cgx_id, 430 nix->lmac->lmac_id, 0); 431 /* This is rx pkind in 1:1 mapping to NIX_LINK_E */ 432 nix->lmac->pknd = nix->lmac->link_num; 433 434 cgx_lmac_set_pkind(nix->lmac, nix->lmac->lmac_id, nix->lmac->pknd); 435 debug("%s(%s CGX%x LMAC%x)\n", __func__, dev->name, 436 nix->lmac->cgx->cgx_id, nix->lmac->lmac_id); 437 debug("%s(%s Link %x Chan %x Pknd %x)\n", __func__, dev->name, 438 nix->lmac->link_num, nix->lmac->chan_num, nix->lmac->pknd); 439 440 err = npa_lf_setup(nix); 441 if (err) 442 return NULL; 443 444 err = npc_lf_setup(nix); 445 if (err) 446 return NULL; 447 448 err = nix_lf_setup(nix); 449 if (err) 450 return NULL; 451 452 return nix; 453} 454 455u64 npa_aura_op_alloc(struct npa *npa, u64 aura_id) 456{ 457 union npa_lf_aura_op_allocx op_allocx; 458 459 op_allocx.u = atomic_fetch_and_add64_nosync(npa->npa_base + 460 NPA_LF_AURA_OP_ALLOCX(0), aura_id); 461 return op_allocx.s.addr; 462} 463 464u64 nix_cq_op_status(struct nix *nix, u64 cq_id) 465{ 466 union nixx_lf_cq_op_status op_status; 467 s64 *reg = nix->nix_base + NIXX_LF_CQ_OP_STATUS(); 468 469 op_status.u = atomic_fetch_and_add64_nosync(reg, cq_id << 32); 470 return op_status.u; 471} 472 473/* TX */ 474static inline void nix_write_lmt(struct nix *nix, void *buffer, 475 int num_words) 476{ 477 int i; 478 479 u64 *lmt_ptr = lmt_store_ptr(nix); 480 u64 *ptr = buffer; 481 482 debug("%s lmt_ptr %p %p\n", __func__, nix->lmt_base, lmt_ptr); 483 for (i = 0; i < num_words; i++) { 484 debug("%s data %llx lmt_ptr %p\n", __func__, ptr[i], 485 lmt_ptr + i); 486 lmt_ptr[i] = ptr[i]; 487 } 488} 489 490void nix_cqe_tx_pkt_handler(struct nix *nix, void *cqe) 491{ 492 union nix_cqe_hdr_s *txcqe = (union nix_cqe_hdr_s *)cqe; 493 494 debug("%s: txcqe: %p\n", __func__, txcqe); 495 496 if (txcqe->s.cqe_type != NIX_XQE_TYPE_E_SEND) { 497 printf("%s: Error: Unsupported CQ header type %d\n", 498 __func__, txcqe->s.cqe_type); 499 return; 500 } 501 nix_pf_reg_write(nix, NIXX_LF_CQ_OP_DOOR(), 502 (NIX_CQ_TX << 32) | 1); 503} 504 505void nix_lf_flush_tx(struct udevice *dev) 506{ 507 struct rvu_pf *rvu = dev_get_priv(dev); 508 struct nix *nix = rvu->nix; 509 union nixx_lf_cq_op_status op_status; 510 u32 head, tail; 511 void *cq_tx_base = nix->cq[NIX_CQ_TX].base; 512 union nix_cqe_hdr_s *cqe; 513 514 /* ack tx cqe entries */ 515 op_status.u = nix_cq_op_status(nix, NIX_CQ_TX); 516 head = op_status.s.head; 517 tail = op_status.s.tail; 518 head &= (nix->cq[NIX_CQ_TX].qsize - 1); 519 tail &= (nix->cq[NIX_CQ_TX].qsize - 1); 520 521 debug("%s cq tx head %d tail %d\n", __func__, head, tail); 522 while (head != tail) { 523 cqe = cq_tx_base + head * nix->cq[NIX_CQ_TX].entry_sz; 524 nix_cqe_tx_pkt_handler(nix, cqe); 525 op_status.u = nix_cq_op_status(nix, NIX_CQ_TX); 526 head = op_status.s.head; 527 tail = op_status.s.tail; 528 head &= (nix->cq[NIX_CQ_TX].qsize - 1); 529 tail &= (nix->cq[NIX_CQ_TX].qsize - 1); 530 debug("%s cq tx head %d tail %d\n", __func__, head, tail); 531 } 532} 533 534int nix_lf_xmit(struct udevice *dev, void *pkt, int pkt_len) 535{ 536 struct rvu_pf *rvu = dev_get_priv(dev); 537 struct nix *nix = rvu->nix; 538 struct nix_tx_dr tx_dr; 539 int dr_sz = (sizeof(struct nix_tx_dr) + 15) / 16 - 1; 540 s64 result; 541 void *packet; 542 543 nix_lf_flush_tx(dev); 544 memset((void *)&tx_dr, 0, sizeof(struct nix_tx_dr)); 545 /* Dump TX packet in to NPA buffer */ 546 packet = (void *)npa_aura_op_alloc(nix->npa, NPA_POOL_TX); 547 if (!packet) { 548 printf("%s TX buffers unavailable\n", __func__); 549 return -1; 550 } 551 memcpy(packet, pkt, pkt_len); 552 debug("%s TX buffer %p\n", __func__, packet); 553 554 tx_dr.hdr.s.aura = NPA_POOL_TX; 555 tx_dr.hdr.s.df = 0; 556 tx_dr.hdr.s.pnc = 1; 557 tx_dr.hdr.s.sq = 0; 558 tx_dr.hdr.s.total = pkt_len; 559 tx_dr.hdr.s.sizem1 = dr_sz - 2; /* FIXME - for now hdr+sg+sg1addr */ 560 debug("%s dr_sz %d\n", __func__, dr_sz); 561 562 tx_dr.tx_sg.s.segs = 1; 563 tx_dr.tx_sg.s.subdc = NIX_SUBDC_E_SG; 564 tx_dr.tx_sg.s.seg1_size = pkt_len; 565 tx_dr.tx_sg.s.ld_type = NIX_SENDLDTYPE_E_LDT; 566 tx_dr.sg1_addr = (dma_addr_t)packet; 567 568#define DEBUG_PKT 569#ifdef DEBUG_PKT 570 debug("TX PKT Data\n"); 571 for (int i = 0; i < pkt_len; i++) { 572 if (i && (i % 8 == 0)) 573 debug("\n"); 574 debug("%02x ", *((u8 *)pkt + i)); 575 } 576 debug("\n"); 577#endif 578 do { 579 nix_write_lmt(nix, &tx_dr, (dr_sz - 1) * 2); 580 __iowmb(); 581 result = lmt_submit((u64)(nix->nix_base + 582 NIXX_LF_OP_SENDX(0))); 583 schedule(); 584 } while (result == 0); 585 586 return 0; 587} 588 589/* RX */ 590void nix_lf_flush_rx(struct udevice *dev) 591{ 592 struct rvu_pf *rvu = dev_get_priv(dev); 593 struct nix *nix = rvu->nix; 594 union nixx_lf_cq_op_status op_status; 595 void *cq_rx_base = nix->cq[NIX_CQ_RX].base; 596 struct nix_rx_dr *rx_dr; 597 union nix_rx_parse_s *rxparse; 598 u32 head, tail; 599 u32 rx_cqe_sz = nix->cq[NIX_CQ_RX].entry_sz; 600 u64 *seg; 601 602 /* flush rx cqe entries */ 603 op_status.u = nix_cq_op_status(nix, NIX_CQ_RX); 604 head = op_status.s.head; 605 tail = op_status.s.tail; 606 head &= (nix->cq[NIX_CQ_RX].qsize - 1); 607 tail &= (nix->cq[NIX_CQ_RX].qsize - 1); 608 609 debug("%s cq rx head %d tail %d\n", __func__, head, tail); 610 while (head != tail) { 611 rx_dr = (struct nix_rx_dr *)cq_rx_base + head * rx_cqe_sz; 612 rxparse = &rx_dr->rx_parse; 613 614 debug("%s: rx parse: %p\n", __func__, rxparse); 615 debug("%s: rx parse: desc_sizem1 %x pkt_lenm1 %x\n", 616 __func__, rxparse->s.desc_sizem1, rxparse->s.pkt_lenm1); 617 618 seg = (dma_addr_t *)(&rx_dr->rx_sg + 1); 619 620 st128(nix->npa->npa_base + NPA_LF_AURA_OP_FREE0(), 621 seg[0], (1ULL << 63) | NPA_POOL_RX); 622 623 debug("%s return %llx to NPA\n", __func__, seg[0]); 624 nix_pf_reg_write(nix, NIXX_LF_CQ_OP_DOOR(), 625 (NIX_CQ_RX << 32) | 1); 626 627 op_status.u = nix_cq_op_status(nix, NIX_CQ_RX); 628 head = op_status.s.head; 629 tail = op_status.s.tail; 630 head &= (nix->cq[NIX_CQ_RX].qsize - 1); 631 tail &= (nix->cq[NIX_CQ_RX].qsize - 1); 632 debug("%s cq rx head %d tail %d\n", __func__, head, tail); 633 } 634} 635 636int nix_lf_free_pkt(struct udevice *dev, uchar *pkt, int pkt_len) 637{ 638 struct rvu_pf *rvu = dev_get_priv(dev); 639 struct nix *nix = rvu->nix; 640 641 /* Return rx packet to NPA */ 642 debug("%s return %p to NPA\n", __func__, pkt); 643 st128(nix->npa->npa_base + NPA_LF_AURA_OP_FREE0(), (u64)pkt, 644 (1ULL << 63) | NPA_POOL_RX); 645 nix_pf_reg_write(nix, NIXX_LF_CQ_OP_DOOR(), 646 (NIX_CQ_RX << 32) | 1); 647 648 nix_lf_flush_tx(dev); 649 return 0; 650} 651 652int nix_lf_recv(struct udevice *dev, int flags, uchar **packetp) 653{ 654 struct rvu_pf *rvu = dev_get_priv(dev); 655 struct nix *nix = rvu->nix; 656 union nixx_lf_cq_op_status op_status; 657 void *cq_rx_base = nix->cq[NIX_CQ_RX].base; 658 struct nix_rx_dr *rx_dr; 659 union nix_rx_parse_s *rxparse; 660 void *pkt, *cqe; 661 int pkt_len = 0; 662 u64 *addr; 663 u32 head, tail; 664 665 /* fetch rx cqe entries */ 666 op_status.u = nix_cq_op_status(nix, NIX_CQ_RX); 667 head = op_status.s.head; 668 tail = op_status.s.tail; 669 head &= (nix->cq[NIX_CQ_RX].qsize - 1); 670 tail &= (nix->cq[NIX_CQ_RX].qsize - 1); 671 debug("%s cq rx head %d tail %d\n", __func__, head, tail); 672 if (head == tail) 673 return -EAGAIN; 674 675 debug("%s: rx_base %p head %d sz %d\n", __func__, cq_rx_base, head, 676 nix->cq[NIX_CQ_RX].entry_sz); 677 cqe = cq_rx_base + head * nix->cq[NIX_CQ_RX].entry_sz; 678 rx_dr = (struct nix_rx_dr *)cqe; 679 rxparse = &rx_dr->rx_parse; 680 681 debug("%s: rx completion: %p\n", __func__, cqe); 682 debug("%s: rx dr: %p\n", __func__, rx_dr); 683 debug("%s: rx parse: %p\n", __func__, rxparse); 684 debug("%s: rx parse: desc_sizem1 %x pkt_lenm1 %x\n", 685 __func__, rxparse->s.desc_sizem1, rxparse->s.pkt_lenm1); 686 debug("%s: rx parse: pkind %x chan %x\n", 687 __func__, rxparse->s.pkind, rxparse->s.chan); 688 689 if (rx_dr->hdr.s.cqe_type != NIX_XQE_TYPE_E_RX) { 690 printf("%s: Error: Unsupported CQ header type in Rx %d\n", 691 __func__, rx_dr->hdr.s.cqe_type); 692 return -1; 693 } 694 695 pkt_len = rxparse->s.pkt_lenm1 + 1; 696 addr = (dma_addr_t *)(&rx_dr->rx_sg + 1); 697 pkt = (void *)addr[0]; 698 699 debug("%s: segs: %d (%d@0x%llx, %d@0x%llx, %d@0x%llx)\n", __func__, 700 rx_dr->rx_sg.s.segs, rx_dr->rx_sg.s.seg1_size, addr[0], 701 rx_dr->rx_sg.s.seg2_size, addr[1], 702 rx_dr->rx_sg.s.seg3_size, addr[2]); 703 if (pkt_len < rx_dr->rx_sg.s.seg1_size + rx_dr->rx_sg.s.seg2_size + 704 rx_dr->rx_sg.s.seg3_size) { 705 debug("%s: Error: rx buffer size too small\n", __func__); 706 return -1; 707 } 708 709 __iowmb(); 710#define DEBUG_PKT 711#ifdef DEBUG_PKT 712 debug("RX PKT Data\n"); 713 for (int i = 0; i < pkt_len; i++) { 714 if (i && (i % 8 == 0)) 715 debug("\n"); 716 debug("%02x ", *((u8 *)pkt + i)); 717 } 718 debug("\n"); 719#endif 720 721 *packetp = (uchar *)pkt; 722 723 return pkt_len; 724} 725 726int nix_lf_setup_mac(struct udevice *dev) 727{ 728 struct rvu_pf *rvu = dev_get_priv(dev); 729 struct nix *nix = rvu->nix; 730 struct eth_pdata *pdata = dev_get_plat(dev); 731 732 /* If lower level firmware fails to set proper MAC 733 * u-boot framework updates MAC to random address. 734 * Use this hook to update mac address in cgx lmac 735 * and call mac filter setup to update new address. 736 */ 737 if (memcmp(nix->lmac->mac_addr, pdata->enetaddr, ARP_HLEN)) { 738 memcpy(nix->lmac->mac_addr, pdata->enetaddr, 6); 739 eth_env_set_enetaddr_by_index("eth", dev_seq(rvu->dev), 740 pdata->enetaddr); 741 cgx_lmac_mac_filter_setup(nix->lmac); 742 /* Update user given MAC address to ATF for update 743 * in sh_fwdata to use in Linux. 744 */ 745 cgx_intf_set_macaddr(dev); 746 debug("%s: lMAC %pM\n", __func__, nix->lmac->mac_addr); 747 debug("%s: pMAC %pM\n", __func__, pdata->enetaddr); 748 } 749 debug("%s: setupMAC %pM\n", __func__, pdata->enetaddr); 750 return 0; 751} 752 753void nix_lf_halt(struct udevice *dev) 754{ 755 struct rvu_pf *rvu = dev_get_priv(dev); 756 struct nix *nix = rvu->nix; 757 758 cgx_lmac_rx_tx_enable(nix->lmac, nix->lmac->lmac_id, false); 759 760 mdelay(1); 761 762 /* Flush tx and rx descriptors */ 763 nix_lf_flush_rx(dev); 764 nix_lf_flush_tx(dev); 765} 766 767int nix_lf_init(struct udevice *dev) 768{ 769 struct rvu_pf *rvu = dev_get_priv(dev); 770 struct nix *nix = rvu->nix; 771 struct lmac *lmac = nix->lmac; 772 int ret; 773 u64 link_sts; 774 u8 link, speed; 775 u16 errcode; 776 777 printf("Waiting for CGX%d LMAC%d [%s] link status...", 778 lmac->cgx->cgx_id, lmac->lmac_id, 779 lmac_type_to_str[lmac->lmac_type]); 780 781 if (lmac->init_pend) { 782 /* Bring up LMAC */ 783 ret = cgx_lmac_link_enable(lmac, lmac->lmac_id, 784 true, &link_sts); 785 lmac->init_pend = 0; 786 } else { 787 ret = cgx_lmac_link_status(lmac, lmac->lmac_id, &link_sts); 788 } 789 790 if (ret) { 791 printf(" [Down]\n"); 792 return -1; 793 } 794 795 link = link_sts & 0x1; 796 speed = (link_sts >> 2) & 0xf; 797 errcode = (link_sts >> 6) & 0x2ff; 798 debug("%s: link %x speed %x errcode %x\n", 799 __func__, link, speed, errcode); 800 801 /* Print link status */ 802 printf(" [%s]\n", link ? lmac_speed_to_str[speed] : "Down"); 803 if (!link) 804 return -1; 805 806 if (!lmac->init_pend) 807 cgx_lmac_rx_tx_enable(lmac, lmac->lmac_id, true); 808 809 return 0; 810} 811 812void nix_get_cgx_lmac_id(struct udevice *dev, int *cgxid, int *lmacid) 813{ 814 struct rvu_pf *rvu = dev_get_priv(dev); 815 struct nix *nix = rvu->nix; 816 struct lmac *lmac = nix->lmac; 817 818 *cgxid = lmac->cgx->cgx_id; 819 *lmacid = lmac->lmac_id; 820} 821 822void nix_print_mac_info(struct udevice *dev) 823{ 824 struct rvu_pf *rvu = dev_get_priv(dev); 825 struct nix *nix = rvu->nix; 826 struct lmac *lmac = nix->lmac; 827 828 printf(" CGX%d LMAC%d [%s]", lmac->cgx->cgx_id, lmac->lmac_id, 829 lmac_type_to_str[lmac->lmac_type]); 830} 831