uboot/drivers/net/octeontx2/nix.c
<<
>>
Prefs
   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