1445371e8SJerin Jacob /* 2445371e8SJerin Jacob * BSD LICENSE 3445371e8SJerin Jacob * 4445371e8SJerin Jacob * Copyright (C) Cavium Inc. 2017. All rights reserved. 5445371e8SJerin Jacob * 6445371e8SJerin Jacob * Redistribution and use in source and binary forms, with or without 7445371e8SJerin Jacob * modification, are permitted provided that the following conditions 8445371e8SJerin Jacob * are met: 9445371e8SJerin Jacob * 10445371e8SJerin Jacob * * Redistributions of source code must retain the above copyright 11445371e8SJerin Jacob * notice, this list of conditions and the following disclaimer. 12445371e8SJerin Jacob * * Redistributions in binary form must reproduce the above copyright 13445371e8SJerin Jacob * notice, this list of conditions and the following disclaimer in 14445371e8SJerin Jacob * the documentation and/or other materials provided with the 15445371e8SJerin Jacob * distribution. 16445371e8SJerin Jacob * * Neither the name of Cavium networks nor the names of its 17445371e8SJerin Jacob * contributors may be used to endorse or promote products derived 18445371e8SJerin Jacob * from this software without specific prior written permission. 19445371e8SJerin Jacob * 20445371e8SJerin Jacob * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21445371e8SJerin Jacob * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22445371e8SJerin Jacob * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23445371e8SJerin Jacob * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24445371e8SJerin Jacob * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25445371e8SJerin Jacob * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26445371e8SJerin Jacob * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27445371e8SJerin Jacob * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28445371e8SJerin Jacob * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29445371e8SJerin Jacob * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30445371e8SJerin Jacob * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31445371e8SJerin Jacob */ 32445371e8SJerin Jacob #include <stdbool.h> 33445371e8SJerin Jacob #include <string.h> 34445371e8SJerin Jacob #include <stdio.h> 35445371e8SJerin Jacob 36445371e8SJerin Jacob #include <rte_eal.h> 37445371e8SJerin Jacob #include <rte_cycles.h> 38445371e8SJerin Jacob #include <rte_malloc.h> 39445371e8SJerin Jacob #include <rte_memory.h> 40445371e8SJerin Jacob #include <rte_pci.h> 41445371e8SJerin Jacob #include <rte_spinlock.h> 42445371e8SJerin Jacob 43445371e8SJerin Jacob #include "../octeontx_logs.h" 44445371e8SJerin Jacob #include "octeontx_io.h" 45445371e8SJerin Jacob #include "octeontx_pkovf.h" 46445371e8SJerin Jacob 47445371e8SJerin Jacob struct octeontx_pko_iomem { 48445371e8SJerin Jacob uint8_t *va; 49445371e8SJerin Jacob phys_addr_t iova; 50445371e8SJerin Jacob size_t size; 51445371e8SJerin Jacob }; 52445371e8SJerin Jacob 53445371e8SJerin Jacob #define PKO_IOMEM_NULL (struct octeontx_pko_iomem){0, 0, 0} 54445371e8SJerin Jacob 55445371e8SJerin Jacob struct octeontx_pko_fc_ctl_s { 56445371e8SJerin Jacob int64_t buf_cnt; 57445371e8SJerin Jacob int64_t padding[(PKO_DQ_FC_STRIDE / 8) - 1]; 58445371e8SJerin Jacob }; 59445371e8SJerin Jacob 60445371e8SJerin Jacob struct octeontx_pkovf { 61445371e8SJerin Jacob uint8_t *bar0; 62445371e8SJerin Jacob uint8_t *bar2; 63445371e8SJerin Jacob uint16_t domain; 64445371e8SJerin Jacob uint16_t vfid; 65445371e8SJerin Jacob }; 66445371e8SJerin Jacob 67445371e8SJerin Jacob struct octeontx_pko_vf_ctl_s { 68445371e8SJerin Jacob rte_spinlock_t lock; 69445371e8SJerin Jacob 70445371e8SJerin Jacob struct octeontx_pko_iomem fc_iomem; 71445371e8SJerin Jacob struct octeontx_pko_fc_ctl_s *fc_ctl; 72445371e8SJerin Jacob struct octeontx_pkovf pko[PKO_VF_MAX]; 73445371e8SJerin Jacob struct { 74445371e8SJerin Jacob uint64_t chanid; 75445371e8SJerin Jacob } dq_map[PKO_VF_MAX * PKO_VF_NUM_DQ]; 76445371e8SJerin Jacob }; 77445371e8SJerin Jacob 78445371e8SJerin Jacob static struct octeontx_pko_vf_ctl_s pko_vf_ctl; 79445371e8SJerin Jacob 80*cad78ca2SJerin Jacob static void * 81*cad78ca2SJerin Jacob octeontx_pko_dq_vf_bar0(uint16_t txq) 82*cad78ca2SJerin Jacob { 83*cad78ca2SJerin Jacob int vf_ix; 84*cad78ca2SJerin Jacob 85*cad78ca2SJerin Jacob vf_ix = txq / PKO_VF_NUM_DQ; 86*cad78ca2SJerin Jacob return pko_vf_ctl.pko[vf_ix].bar0; 87*cad78ca2SJerin Jacob } 88*cad78ca2SJerin Jacob 89*cad78ca2SJerin Jacob static int 90*cad78ca2SJerin Jacob octeontx_pko_dq_gdq(uint16_t txq) 91*cad78ca2SJerin Jacob { 92*cad78ca2SJerin Jacob return txq % PKO_VF_NUM_DQ; 93*cad78ca2SJerin Jacob } 94*cad78ca2SJerin Jacob 95*cad78ca2SJerin Jacob /** 96*cad78ca2SJerin Jacob * Open a PKO DQ. 97*cad78ca2SJerin Jacob */ 98*cad78ca2SJerin Jacob static inline 99*cad78ca2SJerin Jacob int octeontx_pko_dq_open(uint16_t txq) 100*cad78ca2SJerin Jacob { 101*cad78ca2SJerin Jacob unsigned int reg_off; 102*cad78ca2SJerin Jacob uint8_t *vf_bar0; 103*cad78ca2SJerin Jacob uint64_t rtn; 104*cad78ca2SJerin Jacob int gdq; 105*cad78ca2SJerin Jacob 106*cad78ca2SJerin Jacob vf_bar0 = octeontx_pko_dq_vf_bar0(txq); 107*cad78ca2SJerin Jacob gdq = octeontx_pko_dq_gdq(txq); 108*cad78ca2SJerin Jacob 109*cad78ca2SJerin Jacob if (unlikely(gdq < 0 || vf_bar0 == NULL)) 110*cad78ca2SJerin Jacob return -EINVAL; 111*cad78ca2SJerin Jacob *(volatile int64_t*)(pko_vf_ctl.fc_ctl + txq) = 112*cad78ca2SJerin Jacob PKO_DQ_FC_DEPTH_PAGES - PKO_DQ_FC_SKID; 113*cad78ca2SJerin Jacob 114*cad78ca2SJerin Jacob rte_wmb(); 115*cad78ca2SJerin Jacob 116*cad78ca2SJerin Jacob octeontx_write64(PKO_DQ_FC_DEPTH_PAGES, 117*cad78ca2SJerin Jacob vf_bar0 + PKO_VF_DQ_FC_STATUS(gdq)); 118*cad78ca2SJerin Jacob 119*cad78ca2SJerin Jacob /* Set the register to return descriptor (packet) count as DEPTH */ 120*cad78ca2SJerin Jacob /* KIND=1, NCB_QUERY_RSP=0 */ 121*cad78ca2SJerin Jacob octeontx_write64(1ull << PKO_DQ_KIND_BIT, 122*cad78ca2SJerin Jacob vf_bar0 + PKO_VF_DQ_WM_CTL(gdq)); 123*cad78ca2SJerin Jacob reg_off = PKO_VF_DQ_OP_OPEN(gdq); 124*cad78ca2SJerin Jacob 125*cad78ca2SJerin Jacob rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0); 126*cad78ca2SJerin Jacob 127*cad78ca2SJerin Jacob /* PKO_DQOP_E::OPEN */ 128*cad78ca2SJerin Jacob if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x1) 129*cad78ca2SJerin Jacob return -EIO; 130*cad78ca2SJerin Jacob 131*cad78ca2SJerin Jacob switch (rtn >> PKO_DQ_STATUS_BIT) { 132*cad78ca2SJerin Jacob case 0xC: /* DQALREADYCREATED */ 133*cad78ca2SJerin Jacob case 0x0: /* PASS */ 134*cad78ca2SJerin Jacob break; 135*cad78ca2SJerin Jacob default: 136*cad78ca2SJerin Jacob return -EIO; 137*cad78ca2SJerin Jacob } 138*cad78ca2SJerin Jacob 139*cad78ca2SJerin Jacob /* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */ 140*cad78ca2SJerin Jacob octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq)); 141*cad78ca2SJerin Jacob 142*cad78ca2SJerin Jacob return rtn & ((1ull << PKO_DQ_OP_BIT) - 1); 143*cad78ca2SJerin Jacob } 144*cad78ca2SJerin Jacob 145*cad78ca2SJerin Jacob /** 146*cad78ca2SJerin Jacob * Close a PKO DQ 147*cad78ca2SJerin Jacob * Flush all packets pending. 148*cad78ca2SJerin Jacob */ 149*cad78ca2SJerin Jacob static inline 150*cad78ca2SJerin Jacob int octeontx_pko_dq_close(uint16_t txq) 151*cad78ca2SJerin Jacob { 152*cad78ca2SJerin Jacob unsigned int reg_off; 153*cad78ca2SJerin Jacob uint8_t *vf_bar0; 154*cad78ca2SJerin Jacob uint64_t rtn; 155*cad78ca2SJerin Jacob int res; 156*cad78ca2SJerin Jacob 157*cad78ca2SJerin Jacob vf_bar0 = octeontx_pko_dq_vf_bar0(txq); 158*cad78ca2SJerin Jacob res = octeontx_pko_dq_gdq(txq); 159*cad78ca2SJerin Jacob 160*cad78ca2SJerin Jacob if (unlikely(res < 0 || vf_bar0 == NULL)) 161*cad78ca2SJerin Jacob return -EINVAL; 162*cad78ca2SJerin Jacob 163*cad78ca2SJerin Jacob reg_off = PKO_VF_DQ_OP_CLOSE(res); 164*cad78ca2SJerin Jacob 165*cad78ca2SJerin Jacob rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0); 166*cad78ca2SJerin Jacob 167*cad78ca2SJerin Jacob /* PKO_DQOP_E::CLOSE */ 168*cad78ca2SJerin Jacob if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x2) 169*cad78ca2SJerin Jacob return -EIO; 170*cad78ca2SJerin Jacob 171*cad78ca2SJerin Jacob switch (rtn >> PKO_DQ_STATUS_BIT) { 172*cad78ca2SJerin Jacob case 0xD: /* DQNOTCREATED */ 173*cad78ca2SJerin Jacob case 0x0: /* PASS */ 174*cad78ca2SJerin Jacob break; 175*cad78ca2SJerin Jacob default: 176*cad78ca2SJerin Jacob return -EIO; 177*cad78ca2SJerin Jacob } 178*cad78ca2SJerin Jacob 179*cad78ca2SJerin Jacob res = rtn & ((1ull << PKO_DQ_OP_BIT) - 1); /* DEPTH */ 180*cad78ca2SJerin Jacob return res; 181*cad78ca2SJerin Jacob } 182*cad78ca2SJerin Jacob 183*cad78ca2SJerin Jacob /* Flush all packets pending on a DQ */ 184*cad78ca2SJerin Jacob static inline 185*cad78ca2SJerin Jacob int octeontx_pko_dq_drain(uint16_t txq) 186*cad78ca2SJerin Jacob { 187*cad78ca2SJerin Jacob unsigned int gdq; 188*cad78ca2SJerin Jacob uint8_t *vf_bar0; 189*cad78ca2SJerin Jacob uint64_t reg; 190*cad78ca2SJerin Jacob int res, timo = PKO_DQ_DRAIN_TO; 191*cad78ca2SJerin Jacob 192*cad78ca2SJerin Jacob vf_bar0 = octeontx_pko_dq_vf_bar0(txq); 193*cad78ca2SJerin Jacob res = octeontx_pko_dq_gdq(txq); 194*cad78ca2SJerin Jacob gdq = res; 195*cad78ca2SJerin Jacob 196*cad78ca2SJerin Jacob /* DRAIN=1, DRAIN_NULL_LINK=0, SW_XOFF=1 */ 197*cad78ca2SJerin Jacob octeontx_write64(0x3, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq)); 198*cad78ca2SJerin Jacob /* Wait until buffers leave DQs */ 199*cad78ca2SJerin Jacob reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq)); 200*cad78ca2SJerin Jacob while (reg && timo > 0) { 201*cad78ca2SJerin Jacob rte_delay_us(100); 202*cad78ca2SJerin Jacob timo--; 203*cad78ca2SJerin Jacob reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq)); 204*cad78ca2SJerin Jacob } 205*cad78ca2SJerin Jacob /* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */ 206*cad78ca2SJerin Jacob octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq)); 207*cad78ca2SJerin Jacob 208*cad78ca2SJerin Jacob return reg; 209*cad78ca2SJerin Jacob } 210*cad78ca2SJerin Jacob 211*cad78ca2SJerin Jacob static inline int 212*cad78ca2SJerin Jacob octeontx_pko_dq_range_lookup(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid, 213*cad78ca2SJerin Jacob unsigned int dq_num, unsigned int dq_from) 214*cad78ca2SJerin Jacob { 215*cad78ca2SJerin Jacob unsigned int dq, dq_cnt; 216*cad78ca2SJerin Jacob unsigned int dq_base; 217*cad78ca2SJerin Jacob 218*cad78ca2SJerin Jacob dq_cnt = 0; 219*cad78ca2SJerin Jacob dq = dq_from; 220*cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 221*cad78ca2SJerin Jacob dq_base = dq; 222*cad78ca2SJerin Jacob dq_cnt = 0; 223*cad78ca2SJerin Jacob while (ctl->dq_map[dq].chanid == ~chanid && 224*cad78ca2SJerin Jacob dq < RTE_DIM(ctl->dq_map)) { 225*cad78ca2SJerin Jacob dq_cnt++; 226*cad78ca2SJerin Jacob if (dq_cnt == dq_num) 227*cad78ca2SJerin Jacob return dq_base; 228*cad78ca2SJerin Jacob dq++; 229*cad78ca2SJerin Jacob } 230*cad78ca2SJerin Jacob dq++; 231*cad78ca2SJerin Jacob } 232*cad78ca2SJerin Jacob return -1; 233*cad78ca2SJerin Jacob } 234*cad78ca2SJerin Jacob 235*cad78ca2SJerin Jacob static inline void 236*cad78ca2SJerin Jacob octeontx_pko_dq_range_assign(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid, 237*cad78ca2SJerin Jacob unsigned int dq_base, unsigned int dq_num) 238*cad78ca2SJerin Jacob { 239*cad78ca2SJerin Jacob unsigned int dq, dq_cnt; 240*cad78ca2SJerin Jacob 241*cad78ca2SJerin Jacob dq_cnt = 0; 242*cad78ca2SJerin Jacob while (dq_cnt < dq_num) { 243*cad78ca2SJerin Jacob dq = dq_base + dq_cnt; 244*cad78ca2SJerin Jacob 245*cad78ca2SJerin Jacob octeontx_log_dbg("DQ# %u assigned to CHAN# %" PRIx64 "", dq, 246*cad78ca2SJerin Jacob chanid); 247*cad78ca2SJerin Jacob 248*cad78ca2SJerin Jacob ctl->dq_map[dq].chanid = ~chanid; 249*cad78ca2SJerin Jacob dq_cnt++; 250*cad78ca2SJerin Jacob } 251*cad78ca2SJerin Jacob } 252*cad78ca2SJerin Jacob 253*cad78ca2SJerin Jacob static inline int 254*cad78ca2SJerin Jacob octeontx_pko_dq_claim(struct octeontx_pko_vf_ctl_s *ctl, unsigned int dq_base, 255*cad78ca2SJerin Jacob unsigned int dq_num, uint64_t chanid) 256*cad78ca2SJerin Jacob { 257*cad78ca2SJerin Jacob const uint64_t null_chanid = ~0ull; 258*cad78ca2SJerin Jacob int dq; 259*cad78ca2SJerin Jacob 260*cad78ca2SJerin Jacob rte_spinlock_lock(&ctl->lock); 261*cad78ca2SJerin Jacob 262*cad78ca2SJerin Jacob dq = octeontx_pko_dq_range_lookup(ctl, null_chanid, dq_num, dq_base); 263*cad78ca2SJerin Jacob if (dq < 0 || (unsigned int)dq != dq_base) { 264*cad78ca2SJerin Jacob rte_spinlock_unlock(&ctl->lock); 265*cad78ca2SJerin Jacob return -1; 266*cad78ca2SJerin Jacob } 267*cad78ca2SJerin Jacob octeontx_pko_dq_range_assign(ctl, chanid, dq_base, dq_num); 268*cad78ca2SJerin Jacob 269*cad78ca2SJerin Jacob rte_spinlock_unlock(&ctl->lock); 270*cad78ca2SJerin Jacob 271*cad78ca2SJerin Jacob return 0; 272*cad78ca2SJerin Jacob } 273*cad78ca2SJerin Jacob 274*cad78ca2SJerin Jacob static inline int 275*cad78ca2SJerin Jacob octeontx_pko_dq_free(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid) 276*cad78ca2SJerin Jacob { 277*cad78ca2SJerin Jacob const uint64_t null_chanid = ~0ull; 278*cad78ca2SJerin Jacob unsigned int dq = 0, dq_cnt = 0; 279*cad78ca2SJerin Jacob 280*cad78ca2SJerin Jacob rte_spinlock_lock(&ctl->lock); 281*cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 282*cad78ca2SJerin Jacob if (ctl->dq_map[dq].chanid == ~chanid) { 283*cad78ca2SJerin Jacob ctl->dq_map[dq].chanid = ~null_chanid; 284*cad78ca2SJerin Jacob dq_cnt++; 285*cad78ca2SJerin Jacob } 286*cad78ca2SJerin Jacob dq++; 287*cad78ca2SJerin Jacob } 288*cad78ca2SJerin Jacob rte_spinlock_unlock(&ctl->lock); 289*cad78ca2SJerin Jacob 290*cad78ca2SJerin Jacob return dq_cnt > 0 ? 0 : -EINVAL; 291*cad78ca2SJerin Jacob } 292*cad78ca2SJerin Jacob 293*cad78ca2SJerin Jacob int 294*cad78ca2SJerin Jacob octeontx_pko_channel_open(int dq_base, int dq_num, int chanid) 295*cad78ca2SJerin Jacob { 296*cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 297*cad78ca2SJerin Jacob int res; 298*cad78ca2SJerin Jacob 299*cad78ca2SJerin Jacob res = octeontx_pko_dq_claim(ctl, dq_base, dq_num, chanid); 300*cad78ca2SJerin Jacob if (res < 0) 301*cad78ca2SJerin Jacob return -1; 302*cad78ca2SJerin Jacob 303*cad78ca2SJerin Jacob return 0; 304*cad78ca2SJerin Jacob } 305*cad78ca2SJerin Jacob 306*cad78ca2SJerin Jacob int 307*cad78ca2SJerin Jacob octeontx_pko_channel_close(int chanid) 308*cad78ca2SJerin Jacob { 309*cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 310*cad78ca2SJerin Jacob int res; 311*cad78ca2SJerin Jacob 312*cad78ca2SJerin Jacob res = octeontx_pko_dq_free(ctl, chanid); 313*cad78ca2SJerin Jacob if (res < 0) 314*cad78ca2SJerin Jacob return -1; 315*cad78ca2SJerin Jacob 316*cad78ca2SJerin Jacob return 0; 317*cad78ca2SJerin Jacob } 318*cad78ca2SJerin Jacob 319*cad78ca2SJerin Jacob static inline int 320*cad78ca2SJerin Jacob octeontx_pko_chan_start(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid) 321*cad78ca2SJerin Jacob { 322*cad78ca2SJerin Jacob unsigned int dq_vf; 323*cad78ca2SJerin Jacob unsigned int dq, dq_cnt; 324*cad78ca2SJerin Jacob 325*cad78ca2SJerin Jacob dq_cnt = 0; 326*cad78ca2SJerin Jacob dq = 0; 327*cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 328*cad78ca2SJerin Jacob dq_vf = dq / PKO_VF_NUM_DQ; 329*cad78ca2SJerin Jacob 330*cad78ca2SJerin Jacob if (!ctl->pko[dq_vf].bar0) { 331*cad78ca2SJerin Jacob dq += PKO_VF_NUM_DQ; 332*cad78ca2SJerin Jacob continue; 333*cad78ca2SJerin Jacob } 334*cad78ca2SJerin Jacob 335*cad78ca2SJerin Jacob if (ctl->dq_map[dq].chanid != ~chanid) { 336*cad78ca2SJerin Jacob dq++; 337*cad78ca2SJerin Jacob continue; 338*cad78ca2SJerin Jacob } 339*cad78ca2SJerin Jacob 340*cad78ca2SJerin Jacob if (octeontx_pko_dq_open(dq) < 0) 341*cad78ca2SJerin Jacob break; 342*cad78ca2SJerin Jacob 343*cad78ca2SJerin Jacob dq_cnt++; 344*cad78ca2SJerin Jacob dq++; 345*cad78ca2SJerin Jacob } 346*cad78ca2SJerin Jacob 347*cad78ca2SJerin Jacob return dq_cnt; 348*cad78ca2SJerin Jacob } 349*cad78ca2SJerin Jacob 350*cad78ca2SJerin Jacob int 351*cad78ca2SJerin Jacob octeontx_pko_channel_start(int chanid) 352*cad78ca2SJerin Jacob { 353*cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 354*cad78ca2SJerin Jacob int dq_cnt; 355*cad78ca2SJerin Jacob 356*cad78ca2SJerin Jacob dq_cnt = octeontx_pko_chan_start(ctl, chanid); 357*cad78ca2SJerin Jacob if (dq_cnt < 0) 358*cad78ca2SJerin Jacob return -1; 359*cad78ca2SJerin Jacob 360*cad78ca2SJerin Jacob return dq_cnt; 361*cad78ca2SJerin Jacob } 362*cad78ca2SJerin Jacob 363*cad78ca2SJerin Jacob static inline int 364*cad78ca2SJerin Jacob octeontx_pko_chan_stop(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid) 365*cad78ca2SJerin Jacob { 366*cad78ca2SJerin Jacob unsigned int dq, dq_cnt, dq_vf; 367*cad78ca2SJerin Jacob int res; 368*cad78ca2SJerin Jacob 369*cad78ca2SJerin Jacob dq_cnt = 0; 370*cad78ca2SJerin Jacob dq = 0; 371*cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 372*cad78ca2SJerin Jacob dq_vf = dq / PKO_VF_NUM_DQ; 373*cad78ca2SJerin Jacob 374*cad78ca2SJerin Jacob if (!ctl->pko[dq_vf].bar0) { 375*cad78ca2SJerin Jacob dq += PKO_VF_NUM_DQ; 376*cad78ca2SJerin Jacob continue; 377*cad78ca2SJerin Jacob } 378*cad78ca2SJerin Jacob 379*cad78ca2SJerin Jacob if (ctl->dq_map[dq].chanid != ~chanid) { 380*cad78ca2SJerin Jacob dq++; 381*cad78ca2SJerin Jacob continue; 382*cad78ca2SJerin Jacob } 383*cad78ca2SJerin Jacob 384*cad78ca2SJerin Jacob res = octeontx_pko_dq_drain(dq); 385*cad78ca2SJerin Jacob if (res > 0) 386*cad78ca2SJerin Jacob octeontx_log_err("draining DQ%d, buffers left: %x", 387*cad78ca2SJerin Jacob dq, res); 388*cad78ca2SJerin Jacob 389*cad78ca2SJerin Jacob res = octeontx_pko_dq_close(dq); 390*cad78ca2SJerin Jacob if (res < 0) 391*cad78ca2SJerin Jacob octeontx_log_err("closing DQ%d failed\n", dq); 392*cad78ca2SJerin Jacob 393*cad78ca2SJerin Jacob dq_cnt++; 394*cad78ca2SJerin Jacob dq++; 395*cad78ca2SJerin Jacob } 396*cad78ca2SJerin Jacob return dq_cnt; 397*cad78ca2SJerin Jacob } 398*cad78ca2SJerin Jacob 399*cad78ca2SJerin Jacob int 400*cad78ca2SJerin Jacob octeontx_pko_channel_stop(int chanid) 401*cad78ca2SJerin Jacob { 402*cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 403*cad78ca2SJerin Jacob 404*cad78ca2SJerin Jacob octeontx_pko_chan_stop(ctl, chanid); 405*cad78ca2SJerin Jacob return 0; 406*cad78ca2SJerin Jacob } 407*cad78ca2SJerin Jacob 408445371e8SJerin Jacob static void 409445371e8SJerin Jacob octeontx_pkovf_setup(void) 410445371e8SJerin Jacob { 411445371e8SJerin Jacob static bool init_once; 412445371e8SJerin Jacob 413445371e8SJerin Jacob if (!init_once) { 414445371e8SJerin Jacob unsigned int i; 415445371e8SJerin Jacob 416445371e8SJerin Jacob rte_spinlock_init(&pko_vf_ctl.lock); 417445371e8SJerin Jacob 418445371e8SJerin Jacob pko_vf_ctl.fc_iomem = PKO_IOMEM_NULL; 419445371e8SJerin Jacob pko_vf_ctl.fc_ctl = NULL; 420445371e8SJerin Jacob 421445371e8SJerin Jacob for (i = 0; i < PKO_VF_MAX; i++) { 422445371e8SJerin Jacob pko_vf_ctl.pko[i].bar0 = NULL; 423445371e8SJerin Jacob pko_vf_ctl.pko[i].bar2 = NULL; 424445371e8SJerin Jacob pko_vf_ctl.pko[i].domain = ~(uint16_t)0; 425445371e8SJerin Jacob pko_vf_ctl.pko[i].vfid = ~(uint16_t)0; 426445371e8SJerin Jacob } 427445371e8SJerin Jacob 428445371e8SJerin Jacob for (i = 0; i < (PKO_VF_MAX * PKO_VF_NUM_DQ); i++) 429445371e8SJerin Jacob pko_vf_ctl.dq_map[i].chanid = 0; 430445371e8SJerin Jacob 431445371e8SJerin Jacob init_once = true; 432445371e8SJerin Jacob } 433445371e8SJerin Jacob } 434445371e8SJerin Jacob 435445371e8SJerin Jacob /* PKOVF pcie device*/ 436445371e8SJerin Jacob static int 437445371e8SJerin Jacob pkovf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 438445371e8SJerin Jacob { 439445371e8SJerin Jacob uint64_t val; 440445371e8SJerin Jacob uint16_t vfid; 441445371e8SJerin Jacob uint16_t domain; 442445371e8SJerin Jacob uint8_t *bar0; 443445371e8SJerin Jacob uint8_t *bar2; 444445371e8SJerin Jacob struct octeontx_pkovf *res; 445445371e8SJerin Jacob 446445371e8SJerin Jacob RTE_SET_USED(pci_drv); 447445371e8SJerin Jacob 448445371e8SJerin Jacob /* For secondary processes, the primary has done all the work */ 449445371e8SJerin Jacob if (rte_eal_process_type() != RTE_PROC_PRIMARY) 450445371e8SJerin Jacob return 0; 451445371e8SJerin Jacob 452445371e8SJerin Jacob if (pci_dev->mem_resource[0].addr == NULL || 453445371e8SJerin Jacob pci_dev->mem_resource[2].addr == NULL) { 454445371e8SJerin Jacob octeontx_log_err("Empty bars %p %p", 455445371e8SJerin Jacob pci_dev->mem_resource[0].addr, 456445371e8SJerin Jacob pci_dev->mem_resource[2].addr); 457445371e8SJerin Jacob return -ENODEV; 458445371e8SJerin Jacob } 459445371e8SJerin Jacob bar0 = pci_dev->mem_resource[0].addr; 460445371e8SJerin Jacob bar2 = pci_dev->mem_resource[2].addr; 461445371e8SJerin Jacob 462445371e8SJerin Jacob octeontx_pkovf_setup(); 463445371e8SJerin Jacob 464445371e8SJerin Jacob /* get vfid and domain */ 465445371e8SJerin Jacob val = octeontx_read64(bar0 + PKO_VF_DQ_FC_CONFIG); 466445371e8SJerin Jacob domain = (val >> 7) & 0xffff; 467445371e8SJerin Jacob vfid = (val >> 23) & 0xffff; 468445371e8SJerin Jacob 469445371e8SJerin Jacob if (unlikely(vfid >= PKO_VF_MAX)) { 470445371e8SJerin Jacob octeontx_log_err("pko: Invalid vfid %d", vfid); 471445371e8SJerin Jacob return -EINVAL; 472445371e8SJerin Jacob } 473445371e8SJerin Jacob 474445371e8SJerin Jacob res = &pko_vf_ctl.pko[vfid]; 475445371e8SJerin Jacob res->vfid = vfid; 476445371e8SJerin Jacob res->domain = domain; 477445371e8SJerin Jacob res->bar0 = bar0; 478445371e8SJerin Jacob res->bar2 = bar2; 479445371e8SJerin Jacob 480445371e8SJerin Jacob octeontx_log_dbg("Domain=%d group=%d", res->domain, res->vfid); 481445371e8SJerin Jacob return 0; 482445371e8SJerin Jacob } 483445371e8SJerin Jacob 484445371e8SJerin Jacob #define PCI_VENDOR_ID_CAVIUM 0x177D 485445371e8SJerin Jacob #define PCI_DEVICE_ID_OCTEONTX_PKO_VF 0xA049 486445371e8SJerin Jacob 487445371e8SJerin Jacob static const struct rte_pci_id pci_pkovf_map[] = { 488445371e8SJerin Jacob { 489445371e8SJerin Jacob RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 490445371e8SJerin Jacob PCI_DEVICE_ID_OCTEONTX_PKO_VF) 491445371e8SJerin Jacob }, 492445371e8SJerin Jacob { 493445371e8SJerin Jacob .vendor_id = 0, 494445371e8SJerin Jacob }, 495445371e8SJerin Jacob }; 496445371e8SJerin Jacob 497445371e8SJerin Jacob static struct rte_pci_driver pci_pkovf = { 498445371e8SJerin Jacob .id_table = pci_pkovf_map, 499445371e8SJerin Jacob .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 500445371e8SJerin Jacob .probe = pkovf_probe, 501445371e8SJerin Jacob }; 502445371e8SJerin Jacob 503445371e8SJerin Jacob RTE_PMD_REGISTER_PCI(octeontx_pkovf, pci_pkovf); 504