1*aaf4363eSJerin Jacob /* SPDX-License-Identifier: BSD-3-Clause 2*aaf4363eSJerin Jacob * Copyright(c) 2017 Cavium, Inc 3445371e8SJerin Jacob */ 4*aaf4363eSJerin Jacob 5445371e8SJerin Jacob #include <stdbool.h> 6445371e8SJerin Jacob #include <string.h> 7445371e8SJerin Jacob #include <stdio.h> 8445371e8SJerin Jacob 9445371e8SJerin Jacob #include <rte_eal.h> 10445371e8SJerin Jacob #include <rte_cycles.h> 11445371e8SJerin Jacob #include <rte_malloc.h> 12445371e8SJerin Jacob #include <rte_memory.h> 13c752998bSGaetan Rivet #include <rte_bus_pci.h> 14445371e8SJerin Jacob #include <rte_spinlock.h> 15445371e8SJerin Jacob 16445371e8SJerin Jacob #include "../octeontx_logs.h" 17445371e8SJerin Jacob #include "octeontx_io.h" 18445371e8SJerin Jacob #include "octeontx_pkovf.h" 19445371e8SJerin Jacob 20445371e8SJerin Jacob struct octeontx_pko_iomem { 21445371e8SJerin Jacob uint8_t *va; 22df6e0a06SSantosh Shukla rte_iova_t iova; 23445371e8SJerin Jacob size_t size; 24445371e8SJerin Jacob }; 25445371e8SJerin Jacob 26445371e8SJerin Jacob #define PKO_IOMEM_NULL (struct octeontx_pko_iomem){0, 0, 0} 27445371e8SJerin Jacob 28445371e8SJerin Jacob struct octeontx_pko_fc_ctl_s { 29445371e8SJerin Jacob int64_t buf_cnt; 30445371e8SJerin Jacob int64_t padding[(PKO_DQ_FC_STRIDE / 8) - 1]; 31445371e8SJerin Jacob }; 32445371e8SJerin Jacob 33445371e8SJerin Jacob struct octeontx_pkovf { 34445371e8SJerin Jacob uint8_t *bar0; 35445371e8SJerin Jacob uint8_t *bar2; 36445371e8SJerin Jacob uint16_t domain; 37445371e8SJerin Jacob uint16_t vfid; 38445371e8SJerin Jacob }; 39445371e8SJerin Jacob 40445371e8SJerin Jacob struct octeontx_pko_vf_ctl_s { 41445371e8SJerin Jacob rte_spinlock_t lock; 42445371e8SJerin Jacob 43445371e8SJerin Jacob struct octeontx_pko_iomem fc_iomem; 44445371e8SJerin Jacob struct octeontx_pko_fc_ctl_s *fc_ctl; 45445371e8SJerin Jacob struct octeontx_pkovf pko[PKO_VF_MAX]; 46445371e8SJerin Jacob struct { 47445371e8SJerin Jacob uint64_t chanid; 48445371e8SJerin Jacob } dq_map[PKO_VF_MAX * PKO_VF_NUM_DQ]; 49445371e8SJerin Jacob }; 50445371e8SJerin Jacob 51445371e8SJerin Jacob static struct octeontx_pko_vf_ctl_s pko_vf_ctl; 52445371e8SJerin Jacob 53cad78ca2SJerin Jacob static void * 54cad78ca2SJerin Jacob octeontx_pko_dq_vf_bar0(uint16_t txq) 55cad78ca2SJerin Jacob { 56cad78ca2SJerin Jacob int vf_ix; 57cad78ca2SJerin Jacob 58cad78ca2SJerin Jacob vf_ix = txq / PKO_VF_NUM_DQ; 59cad78ca2SJerin Jacob return pko_vf_ctl.pko[vf_ix].bar0; 60cad78ca2SJerin Jacob } 61cad78ca2SJerin Jacob 62cad78ca2SJerin Jacob static int 63cad78ca2SJerin Jacob octeontx_pko_dq_gdq(uint16_t txq) 64cad78ca2SJerin Jacob { 65cad78ca2SJerin Jacob return txq % PKO_VF_NUM_DQ; 66cad78ca2SJerin Jacob } 67cad78ca2SJerin Jacob 68cad78ca2SJerin Jacob /** 69cad78ca2SJerin Jacob * Open a PKO DQ. 70cad78ca2SJerin Jacob */ 71cad78ca2SJerin Jacob static inline 72cad78ca2SJerin Jacob int octeontx_pko_dq_open(uint16_t txq) 73cad78ca2SJerin Jacob { 74cad78ca2SJerin Jacob unsigned int reg_off; 75cad78ca2SJerin Jacob uint8_t *vf_bar0; 76cad78ca2SJerin Jacob uint64_t rtn; 77cad78ca2SJerin Jacob int gdq; 78cad78ca2SJerin Jacob 79cad78ca2SJerin Jacob vf_bar0 = octeontx_pko_dq_vf_bar0(txq); 80cad78ca2SJerin Jacob gdq = octeontx_pko_dq_gdq(txq); 81cad78ca2SJerin Jacob 82cad78ca2SJerin Jacob if (unlikely(gdq < 0 || vf_bar0 == NULL)) 83cad78ca2SJerin Jacob return -EINVAL; 84cad78ca2SJerin Jacob *(volatile int64_t*)(pko_vf_ctl.fc_ctl + txq) = 85cad78ca2SJerin Jacob PKO_DQ_FC_DEPTH_PAGES - PKO_DQ_FC_SKID; 86cad78ca2SJerin Jacob 87cad78ca2SJerin Jacob rte_wmb(); 88cad78ca2SJerin Jacob 89cad78ca2SJerin Jacob octeontx_write64(PKO_DQ_FC_DEPTH_PAGES, 90cad78ca2SJerin Jacob vf_bar0 + PKO_VF_DQ_FC_STATUS(gdq)); 91cad78ca2SJerin Jacob 92cad78ca2SJerin Jacob /* Set the register to return descriptor (packet) count as DEPTH */ 93cad78ca2SJerin Jacob /* KIND=1, NCB_QUERY_RSP=0 */ 94cad78ca2SJerin Jacob octeontx_write64(1ull << PKO_DQ_KIND_BIT, 95cad78ca2SJerin Jacob vf_bar0 + PKO_VF_DQ_WM_CTL(gdq)); 96cad78ca2SJerin Jacob reg_off = PKO_VF_DQ_OP_OPEN(gdq); 97cad78ca2SJerin Jacob 98cad78ca2SJerin Jacob rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0); 99cad78ca2SJerin Jacob 100cad78ca2SJerin Jacob /* PKO_DQOP_E::OPEN */ 101cad78ca2SJerin Jacob if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x1) 102cad78ca2SJerin Jacob return -EIO; 103cad78ca2SJerin Jacob 104cad78ca2SJerin Jacob switch (rtn >> PKO_DQ_STATUS_BIT) { 105cad78ca2SJerin Jacob case 0xC: /* DQALREADYCREATED */ 106cad78ca2SJerin Jacob case 0x0: /* PASS */ 107cad78ca2SJerin Jacob break; 108cad78ca2SJerin Jacob default: 109cad78ca2SJerin Jacob return -EIO; 110cad78ca2SJerin Jacob } 111cad78ca2SJerin Jacob 112cad78ca2SJerin Jacob /* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */ 113cad78ca2SJerin Jacob octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq)); 114cad78ca2SJerin Jacob 115cad78ca2SJerin Jacob return rtn & ((1ull << PKO_DQ_OP_BIT) - 1); 116cad78ca2SJerin Jacob } 117cad78ca2SJerin Jacob 118cad78ca2SJerin Jacob /** 119cad78ca2SJerin Jacob * Close a PKO DQ 120cad78ca2SJerin Jacob * Flush all packets pending. 121cad78ca2SJerin Jacob */ 122cad78ca2SJerin Jacob static inline 123cad78ca2SJerin Jacob int octeontx_pko_dq_close(uint16_t txq) 124cad78ca2SJerin Jacob { 125cad78ca2SJerin Jacob unsigned int reg_off; 126cad78ca2SJerin Jacob uint8_t *vf_bar0; 127cad78ca2SJerin Jacob uint64_t rtn; 128cad78ca2SJerin Jacob int res; 129cad78ca2SJerin Jacob 130cad78ca2SJerin Jacob vf_bar0 = octeontx_pko_dq_vf_bar0(txq); 131cad78ca2SJerin Jacob res = octeontx_pko_dq_gdq(txq); 132cad78ca2SJerin Jacob 133cad78ca2SJerin Jacob if (unlikely(res < 0 || vf_bar0 == NULL)) 134cad78ca2SJerin Jacob return -EINVAL; 135cad78ca2SJerin Jacob 136cad78ca2SJerin Jacob reg_off = PKO_VF_DQ_OP_CLOSE(res); 137cad78ca2SJerin Jacob 138cad78ca2SJerin Jacob rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0); 139cad78ca2SJerin Jacob 140cad78ca2SJerin Jacob /* PKO_DQOP_E::CLOSE */ 141cad78ca2SJerin Jacob if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x2) 142cad78ca2SJerin Jacob return -EIO; 143cad78ca2SJerin Jacob 144cad78ca2SJerin Jacob switch (rtn >> PKO_DQ_STATUS_BIT) { 145cad78ca2SJerin Jacob case 0xD: /* DQNOTCREATED */ 146cad78ca2SJerin Jacob case 0x0: /* PASS */ 147cad78ca2SJerin Jacob break; 148cad78ca2SJerin Jacob default: 149cad78ca2SJerin Jacob return -EIO; 150cad78ca2SJerin Jacob } 151cad78ca2SJerin Jacob 152cad78ca2SJerin Jacob res = rtn & ((1ull << PKO_DQ_OP_BIT) - 1); /* DEPTH */ 153cad78ca2SJerin Jacob return res; 154cad78ca2SJerin Jacob } 155cad78ca2SJerin Jacob 156cad78ca2SJerin Jacob /* Flush all packets pending on a DQ */ 157cad78ca2SJerin Jacob static inline 158cad78ca2SJerin Jacob int octeontx_pko_dq_drain(uint16_t txq) 159cad78ca2SJerin Jacob { 160cad78ca2SJerin Jacob unsigned int gdq; 161cad78ca2SJerin Jacob uint8_t *vf_bar0; 162cad78ca2SJerin Jacob uint64_t reg; 163cad78ca2SJerin Jacob int res, timo = PKO_DQ_DRAIN_TO; 164cad78ca2SJerin Jacob 165cad78ca2SJerin Jacob vf_bar0 = octeontx_pko_dq_vf_bar0(txq); 166cad78ca2SJerin Jacob res = octeontx_pko_dq_gdq(txq); 167cad78ca2SJerin Jacob gdq = res; 168cad78ca2SJerin Jacob 169cad78ca2SJerin Jacob /* DRAIN=1, DRAIN_NULL_LINK=0, SW_XOFF=1 */ 170cad78ca2SJerin Jacob octeontx_write64(0x3, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq)); 171cad78ca2SJerin Jacob /* Wait until buffers leave DQs */ 172cad78ca2SJerin Jacob reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq)); 173cad78ca2SJerin Jacob while (reg && timo > 0) { 174cad78ca2SJerin Jacob rte_delay_us(100); 175cad78ca2SJerin Jacob timo--; 176cad78ca2SJerin Jacob reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq)); 177cad78ca2SJerin Jacob } 178cad78ca2SJerin Jacob /* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */ 179cad78ca2SJerin Jacob octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq)); 180cad78ca2SJerin Jacob 181cad78ca2SJerin Jacob return reg; 182cad78ca2SJerin Jacob } 183cad78ca2SJerin Jacob 184cad78ca2SJerin Jacob static inline int 185cad78ca2SJerin Jacob octeontx_pko_dq_range_lookup(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid, 186cad78ca2SJerin Jacob unsigned int dq_num, unsigned int dq_from) 187cad78ca2SJerin Jacob { 188cad78ca2SJerin Jacob unsigned int dq, dq_cnt; 189cad78ca2SJerin Jacob unsigned int dq_base; 190cad78ca2SJerin Jacob 191cad78ca2SJerin Jacob dq_cnt = 0; 192cad78ca2SJerin Jacob dq = dq_from; 193cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 194cad78ca2SJerin Jacob dq_base = dq; 195cad78ca2SJerin Jacob dq_cnt = 0; 196cad78ca2SJerin Jacob while (ctl->dq_map[dq].chanid == ~chanid && 197cad78ca2SJerin Jacob dq < RTE_DIM(ctl->dq_map)) { 198cad78ca2SJerin Jacob dq_cnt++; 199cad78ca2SJerin Jacob if (dq_cnt == dq_num) 200cad78ca2SJerin Jacob return dq_base; 201cad78ca2SJerin Jacob dq++; 202cad78ca2SJerin Jacob } 203cad78ca2SJerin Jacob dq++; 204cad78ca2SJerin Jacob } 205cad78ca2SJerin Jacob return -1; 206cad78ca2SJerin Jacob } 207cad78ca2SJerin Jacob 208cad78ca2SJerin Jacob static inline void 209cad78ca2SJerin Jacob octeontx_pko_dq_range_assign(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid, 210cad78ca2SJerin Jacob unsigned int dq_base, unsigned int dq_num) 211cad78ca2SJerin Jacob { 212cad78ca2SJerin Jacob unsigned int dq, dq_cnt; 213cad78ca2SJerin Jacob 214cad78ca2SJerin Jacob dq_cnt = 0; 215cad78ca2SJerin Jacob while (dq_cnt < dq_num) { 216cad78ca2SJerin Jacob dq = dq_base + dq_cnt; 217cad78ca2SJerin Jacob 218cad78ca2SJerin Jacob octeontx_log_dbg("DQ# %u assigned to CHAN# %" PRIx64 "", dq, 219cad78ca2SJerin Jacob chanid); 220cad78ca2SJerin Jacob 221cad78ca2SJerin Jacob ctl->dq_map[dq].chanid = ~chanid; 222cad78ca2SJerin Jacob dq_cnt++; 223cad78ca2SJerin Jacob } 224cad78ca2SJerin Jacob } 225cad78ca2SJerin Jacob 226cad78ca2SJerin Jacob static inline int 227cad78ca2SJerin Jacob octeontx_pko_dq_claim(struct octeontx_pko_vf_ctl_s *ctl, unsigned int dq_base, 228cad78ca2SJerin Jacob unsigned int dq_num, uint64_t chanid) 229cad78ca2SJerin Jacob { 230cad78ca2SJerin Jacob const uint64_t null_chanid = ~0ull; 231cad78ca2SJerin Jacob int dq; 232cad78ca2SJerin Jacob 233cad78ca2SJerin Jacob rte_spinlock_lock(&ctl->lock); 234cad78ca2SJerin Jacob 235cad78ca2SJerin Jacob dq = octeontx_pko_dq_range_lookup(ctl, null_chanid, dq_num, dq_base); 236cad78ca2SJerin Jacob if (dq < 0 || (unsigned int)dq != dq_base) { 237cad78ca2SJerin Jacob rte_spinlock_unlock(&ctl->lock); 238cad78ca2SJerin Jacob return -1; 239cad78ca2SJerin Jacob } 240cad78ca2SJerin Jacob octeontx_pko_dq_range_assign(ctl, chanid, dq_base, dq_num); 241cad78ca2SJerin Jacob 242cad78ca2SJerin Jacob rte_spinlock_unlock(&ctl->lock); 243cad78ca2SJerin Jacob 244cad78ca2SJerin Jacob return 0; 245cad78ca2SJerin Jacob } 246cad78ca2SJerin Jacob 247cad78ca2SJerin Jacob static inline int 248cad78ca2SJerin Jacob octeontx_pko_dq_free(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid) 249cad78ca2SJerin Jacob { 250cad78ca2SJerin Jacob const uint64_t null_chanid = ~0ull; 251cad78ca2SJerin Jacob unsigned int dq = 0, dq_cnt = 0; 252cad78ca2SJerin Jacob 253cad78ca2SJerin Jacob rte_spinlock_lock(&ctl->lock); 254cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 255cad78ca2SJerin Jacob if (ctl->dq_map[dq].chanid == ~chanid) { 256cad78ca2SJerin Jacob ctl->dq_map[dq].chanid = ~null_chanid; 257cad78ca2SJerin Jacob dq_cnt++; 258cad78ca2SJerin Jacob } 259cad78ca2SJerin Jacob dq++; 260cad78ca2SJerin Jacob } 261cad78ca2SJerin Jacob rte_spinlock_unlock(&ctl->lock); 262cad78ca2SJerin Jacob 263cad78ca2SJerin Jacob return dq_cnt > 0 ? 0 : -EINVAL; 264cad78ca2SJerin Jacob } 265cad78ca2SJerin Jacob 266cad78ca2SJerin Jacob int 267cad78ca2SJerin Jacob octeontx_pko_channel_open(int dq_base, int dq_num, int chanid) 268cad78ca2SJerin Jacob { 269cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 270cad78ca2SJerin Jacob int res; 271cad78ca2SJerin Jacob 272cad78ca2SJerin Jacob res = octeontx_pko_dq_claim(ctl, dq_base, dq_num, chanid); 273cad78ca2SJerin Jacob if (res < 0) 274cad78ca2SJerin Jacob return -1; 275cad78ca2SJerin Jacob 276cad78ca2SJerin Jacob return 0; 277cad78ca2SJerin Jacob } 278cad78ca2SJerin Jacob 279cad78ca2SJerin Jacob int 280cad78ca2SJerin Jacob octeontx_pko_channel_close(int chanid) 281cad78ca2SJerin Jacob { 282cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 283cad78ca2SJerin Jacob int res; 284cad78ca2SJerin Jacob 285cad78ca2SJerin Jacob res = octeontx_pko_dq_free(ctl, chanid); 286cad78ca2SJerin Jacob if (res < 0) 287cad78ca2SJerin Jacob return -1; 288cad78ca2SJerin Jacob 289cad78ca2SJerin Jacob return 0; 290cad78ca2SJerin Jacob } 291cad78ca2SJerin Jacob 292cad78ca2SJerin Jacob static inline int 293cad78ca2SJerin Jacob octeontx_pko_chan_start(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid) 294cad78ca2SJerin Jacob { 295cad78ca2SJerin Jacob unsigned int dq_vf; 296cad78ca2SJerin Jacob unsigned int dq, dq_cnt; 297cad78ca2SJerin Jacob 298cad78ca2SJerin Jacob dq_cnt = 0; 299cad78ca2SJerin Jacob dq = 0; 300cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 301cad78ca2SJerin Jacob dq_vf = dq / PKO_VF_NUM_DQ; 302cad78ca2SJerin Jacob 303cad78ca2SJerin Jacob if (!ctl->pko[dq_vf].bar0) { 304cad78ca2SJerin Jacob dq += PKO_VF_NUM_DQ; 305cad78ca2SJerin Jacob continue; 306cad78ca2SJerin Jacob } 307cad78ca2SJerin Jacob 308cad78ca2SJerin Jacob if (ctl->dq_map[dq].chanid != ~chanid) { 309cad78ca2SJerin Jacob dq++; 310cad78ca2SJerin Jacob continue; 311cad78ca2SJerin Jacob } 312cad78ca2SJerin Jacob 313cad78ca2SJerin Jacob if (octeontx_pko_dq_open(dq) < 0) 314cad78ca2SJerin Jacob break; 315cad78ca2SJerin Jacob 316cad78ca2SJerin Jacob dq_cnt++; 317cad78ca2SJerin Jacob dq++; 318cad78ca2SJerin Jacob } 319cad78ca2SJerin Jacob 320cad78ca2SJerin Jacob return dq_cnt; 321cad78ca2SJerin Jacob } 322cad78ca2SJerin Jacob 323cad78ca2SJerin Jacob int 324cad78ca2SJerin Jacob octeontx_pko_channel_start(int chanid) 325cad78ca2SJerin Jacob { 326cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 327cad78ca2SJerin Jacob int dq_cnt; 328cad78ca2SJerin Jacob 329cad78ca2SJerin Jacob dq_cnt = octeontx_pko_chan_start(ctl, chanid); 330cad78ca2SJerin Jacob if (dq_cnt < 0) 331cad78ca2SJerin Jacob return -1; 332cad78ca2SJerin Jacob 333cad78ca2SJerin Jacob return dq_cnt; 334cad78ca2SJerin Jacob } 335cad78ca2SJerin Jacob 336cad78ca2SJerin Jacob static inline int 337cad78ca2SJerin Jacob octeontx_pko_chan_stop(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid) 338cad78ca2SJerin Jacob { 339cad78ca2SJerin Jacob unsigned int dq, dq_cnt, dq_vf; 340cad78ca2SJerin Jacob int res; 341cad78ca2SJerin Jacob 342cad78ca2SJerin Jacob dq_cnt = 0; 343cad78ca2SJerin Jacob dq = 0; 344cad78ca2SJerin Jacob while (dq < RTE_DIM(ctl->dq_map)) { 345cad78ca2SJerin Jacob dq_vf = dq / PKO_VF_NUM_DQ; 346cad78ca2SJerin Jacob 347cad78ca2SJerin Jacob if (!ctl->pko[dq_vf].bar0) { 348cad78ca2SJerin Jacob dq += PKO_VF_NUM_DQ; 349cad78ca2SJerin Jacob continue; 350cad78ca2SJerin Jacob } 351cad78ca2SJerin Jacob 352cad78ca2SJerin Jacob if (ctl->dq_map[dq].chanid != ~chanid) { 353cad78ca2SJerin Jacob dq++; 354cad78ca2SJerin Jacob continue; 355cad78ca2SJerin Jacob } 356cad78ca2SJerin Jacob 357cad78ca2SJerin Jacob res = octeontx_pko_dq_drain(dq); 358cad78ca2SJerin Jacob if (res > 0) 359cad78ca2SJerin Jacob octeontx_log_err("draining DQ%d, buffers left: %x", 360cad78ca2SJerin Jacob dq, res); 361cad78ca2SJerin Jacob 362cad78ca2SJerin Jacob res = octeontx_pko_dq_close(dq); 363cad78ca2SJerin Jacob if (res < 0) 364cad78ca2SJerin Jacob octeontx_log_err("closing DQ%d failed\n", dq); 365cad78ca2SJerin Jacob 366cad78ca2SJerin Jacob dq_cnt++; 367cad78ca2SJerin Jacob dq++; 368cad78ca2SJerin Jacob } 369cad78ca2SJerin Jacob return dq_cnt; 370cad78ca2SJerin Jacob } 371cad78ca2SJerin Jacob 372cad78ca2SJerin Jacob int 373cad78ca2SJerin Jacob octeontx_pko_channel_stop(int chanid) 374cad78ca2SJerin Jacob { 375cad78ca2SJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 376cad78ca2SJerin Jacob 377cad78ca2SJerin Jacob octeontx_pko_chan_stop(ctl, chanid); 378cad78ca2SJerin Jacob return 0; 379cad78ca2SJerin Jacob } 380cad78ca2SJerin Jacob 3813813a10aSJerin Jacob static inline int 3823813a10aSJerin Jacob octeontx_pko_channel_query(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid, 3833813a10aSJerin Jacob void *out, size_t out_elem_size, 3843813a10aSJerin Jacob size_t dq_num, octeontx_pko_dq_getter_t getter) 3853813a10aSJerin Jacob { 3863813a10aSJerin Jacob octeontx_dq_t curr; 3873813a10aSJerin Jacob unsigned int dq_vf; 3883813a10aSJerin Jacob unsigned int dq; 3893813a10aSJerin Jacob 3903813a10aSJerin Jacob RTE_SET_USED(out_elem_size); 3913813a10aSJerin Jacob memset(&curr, 0, sizeof(octeontx_dq_t)); 3923813a10aSJerin Jacob 3933813a10aSJerin Jacob dq_vf = dq_num / PKO_VF_NUM_DQ; 3943813a10aSJerin Jacob dq = dq_num % PKO_VF_NUM_DQ; 3953813a10aSJerin Jacob 3963813a10aSJerin Jacob if (!ctl->pko[dq_vf].bar0) 3973813a10aSJerin Jacob return -EINVAL; 3983813a10aSJerin Jacob 3993813a10aSJerin Jacob if (ctl->dq_map[dq_num].chanid != ~chanid) 4003813a10aSJerin Jacob return -EINVAL; 4013813a10aSJerin Jacob 4023813a10aSJerin Jacob uint8_t *iter = (uint8_t *)out; 4033813a10aSJerin Jacob curr.lmtline_va = ctl->pko[dq_vf].bar2; 4043813a10aSJerin Jacob curr.ioreg_va = (void *)((uintptr_t)ctl->pko[dq_vf].bar0 4053813a10aSJerin Jacob + PKO_VF_DQ_OP_SEND((dq), 0)); 4063813a10aSJerin Jacob curr.fc_status_va = ctl->fc_ctl + dq; 4073813a10aSJerin Jacob 4083813a10aSJerin Jacob octeontx_log_dbg("lmtline=%p ioreg_va=%p fc_status_va=%p", 4093813a10aSJerin Jacob curr.lmtline_va, curr.ioreg_va, 4103813a10aSJerin Jacob curr.fc_status_va); 4113813a10aSJerin Jacob 4123813a10aSJerin Jacob getter(&curr, (void *)iter); 4133813a10aSJerin Jacob return 0; 4143813a10aSJerin Jacob } 4153813a10aSJerin Jacob 4163813a10aSJerin Jacob int 4173813a10aSJerin Jacob octeontx_pko_channel_query_dqs(int chanid, void *out, size_t out_elem_size, 4183813a10aSJerin Jacob size_t dq_num, octeontx_pko_dq_getter_t getter) 4193813a10aSJerin Jacob { 4203813a10aSJerin Jacob struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl; 4213813a10aSJerin Jacob int dq_cnt; 4223813a10aSJerin Jacob 4233813a10aSJerin Jacob dq_cnt = octeontx_pko_channel_query(ctl, chanid, out, out_elem_size, 4243813a10aSJerin Jacob dq_num, getter); 4253813a10aSJerin Jacob if (dq_cnt < 0) 4263813a10aSJerin Jacob return -1; 4273813a10aSJerin Jacob 4283813a10aSJerin Jacob return dq_cnt; 4293813a10aSJerin Jacob } 4303813a10aSJerin Jacob 4313813a10aSJerin Jacob int 4323813a10aSJerin Jacob octeontx_pko_vf_count(void) 4333813a10aSJerin Jacob { 4343813a10aSJerin Jacob int vf_cnt; 4353813a10aSJerin Jacob 4363813a10aSJerin Jacob vf_cnt = 0; 4373813a10aSJerin Jacob while (pko_vf_ctl.pko[vf_cnt].bar0) 4383813a10aSJerin Jacob vf_cnt++; 4393813a10aSJerin Jacob 4403813a10aSJerin Jacob return vf_cnt; 4413813a10aSJerin Jacob } 4423813a10aSJerin Jacob 4433813a10aSJerin Jacob int 4443813a10aSJerin Jacob octeontx_pko_init_fc(const size_t pko_vf_count) 4453813a10aSJerin Jacob { 4463813a10aSJerin Jacob int dq_ix; 4473813a10aSJerin Jacob uint64_t reg; 4483813a10aSJerin Jacob uint8_t *vf_bar0; 4493813a10aSJerin Jacob size_t vf_idx; 4503813a10aSJerin Jacob size_t fc_mem_size; 4513813a10aSJerin Jacob 4523813a10aSJerin Jacob fc_mem_size = sizeof(struct octeontx_pko_fc_ctl_s) * 4533813a10aSJerin Jacob pko_vf_count * PKO_VF_NUM_DQ; 4543813a10aSJerin Jacob 4553813a10aSJerin Jacob pko_vf_ctl.fc_iomem.va = rte_malloc(NULL, fc_mem_size, 128); 4563813a10aSJerin Jacob if (unlikely(!pko_vf_ctl.fc_iomem.va)) { 4573813a10aSJerin Jacob octeontx_log_err("fc_iomem: not enough memory"); 4583813a10aSJerin Jacob return -ENOMEM; 4593813a10aSJerin Jacob } 4603813a10aSJerin Jacob 46187cf4c6cSThomas Monjalon pko_vf_ctl.fc_iomem.iova = rte_malloc_virt2iova((void *) 4623813a10aSJerin Jacob pko_vf_ctl.fc_iomem.va); 4633813a10aSJerin Jacob pko_vf_ctl.fc_iomem.size = fc_mem_size; 4643813a10aSJerin Jacob 4653813a10aSJerin Jacob pko_vf_ctl.fc_ctl = 4663813a10aSJerin Jacob (struct octeontx_pko_fc_ctl_s *)pko_vf_ctl.fc_iomem.va; 4673813a10aSJerin Jacob 4683813a10aSJerin Jacob /* Configure Flow-Control feature for all DQs of open VFs */ 4693813a10aSJerin Jacob for (vf_idx = 0; vf_idx < pko_vf_count; vf_idx++) { 4703813a10aSJerin Jacob dq_ix = vf_idx * PKO_VF_NUM_DQ; 4713813a10aSJerin Jacob 4723813a10aSJerin Jacob vf_bar0 = pko_vf_ctl.pko[vf_idx].bar0; 4733813a10aSJerin Jacob 4743813a10aSJerin Jacob reg = (pko_vf_ctl.fc_iomem.iova + 4753813a10aSJerin Jacob (sizeof(struct octeontx_pko_fc_ctl_s) * dq_ix)) & ~0x7F; 4763813a10aSJerin Jacob reg |= /* BASE */ 4773813a10aSJerin Jacob (0x2 << 3) | /* HYST_BITS */ 4783813a10aSJerin Jacob (((PKO_DQ_FC_STRIDE == PKO_DQ_FC_STRIDE_16) ? 1 : 0) << 2) | 4793813a10aSJerin Jacob (0x1 << 0); /* ENABLE */ 4803813a10aSJerin Jacob 4813813a10aSJerin Jacob octeontx_write64(reg, vf_bar0 + PKO_VF_DQ_FC_CONFIG); 4823813a10aSJerin Jacob 4833813a10aSJerin Jacob octeontx_log_dbg("PKO: bar0 %p VF_idx %d DQ_FC_CFG=%" PRIx64 "", 4843813a10aSJerin Jacob vf_bar0, (int)vf_idx, reg); 4853813a10aSJerin Jacob } 4863813a10aSJerin Jacob return 0; 4873813a10aSJerin Jacob } 4883813a10aSJerin Jacob 4893813a10aSJerin Jacob void 4903813a10aSJerin Jacob octeontx_pko_fc_free(void) 4913813a10aSJerin Jacob { 4923813a10aSJerin Jacob rte_free(pko_vf_ctl.fc_iomem.va); 4933813a10aSJerin Jacob } 4943813a10aSJerin Jacob 495445371e8SJerin Jacob static void 496445371e8SJerin Jacob octeontx_pkovf_setup(void) 497445371e8SJerin Jacob { 498445371e8SJerin Jacob static bool init_once; 499445371e8SJerin Jacob 500445371e8SJerin Jacob if (!init_once) { 501445371e8SJerin Jacob unsigned int i; 502445371e8SJerin Jacob 503445371e8SJerin Jacob rte_spinlock_init(&pko_vf_ctl.lock); 504445371e8SJerin Jacob 505445371e8SJerin Jacob pko_vf_ctl.fc_iomem = PKO_IOMEM_NULL; 506445371e8SJerin Jacob pko_vf_ctl.fc_ctl = NULL; 507445371e8SJerin Jacob 508445371e8SJerin Jacob for (i = 0; i < PKO_VF_MAX; i++) { 509445371e8SJerin Jacob pko_vf_ctl.pko[i].bar0 = NULL; 510445371e8SJerin Jacob pko_vf_ctl.pko[i].bar2 = NULL; 511445371e8SJerin Jacob pko_vf_ctl.pko[i].domain = ~(uint16_t)0; 512445371e8SJerin Jacob pko_vf_ctl.pko[i].vfid = ~(uint16_t)0; 513445371e8SJerin Jacob } 514445371e8SJerin Jacob 515445371e8SJerin Jacob for (i = 0; i < (PKO_VF_MAX * PKO_VF_NUM_DQ); i++) 516445371e8SJerin Jacob pko_vf_ctl.dq_map[i].chanid = 0; 517445371e8SJerin Jacob 518445371e8SJerin Jacob init_once = true; 519445371e8SJerin Jacob } 520445371e8SJerin Jacob } 521445371e8SJerin Jacob 522445371e8SJerin Jacob /* PKOVF pcie device*/ 523445371e8SJerin Jacob static int 524445371e8SJerin Jacob pkovf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 525445371e8SJerin Jacob { 526445371e8SJerin Jacob uint64_t val; 527445371e8SJerin Jacob uint16_t vfid; 528445371e8SJerin Jacob uint16_t domain; 529445371e8SJerin Jacob uint8_t *bar0; 530445371e8SJerin Jacob uint8_t *bar2; 531445371e8SJerin Jacob struct octeontx_pkovf *res; 532445371e8SJerin Jacob 533445371e8SJerin Jacob RTE_SET_USED(pci_drv); 534445371e8SJerin Jacob 535445371e8SJerin Jacob /* For secondary processes, the primary has done all the work */ 536445371e8SJerin Jacob if (rte_eal_process_type() != RTE_PROC_PRIMARY) 537445371e8SJerin Jacob return 0; 538445371e8SJerin Jacob 539445371e8SJerin Jacob if (pci_dev->mem_resource[0].addr == NULL || 540445371e8SJerin Jacob pci_dev->mem_resource[2].addr == NULL) { 541445371e8SJerin Jacob octeontx_log_err("Empty bars %p %p", 542445371e8SJerin Jacob pci_dev->mem_resource[0].addr, 543445371e8SJerin Jacob pci_dev->mem_resource[2].addr); 544445371e8SJerin Jacob return -ENODEV; 545445371e8SJerin Jacob } 546445371e8SJerin Jacob bar0 = pci_dev->mem_resource[0].addr; 547445371e8SJerin Jacob bar2 = pci_dev->mem_resource[2].addr; 548445371e8SJerin Jacob 549445371e8SJerin Jacob octeontx_pkovf_setup(); 550445371e8SJerin Jacob 551445371e8SJerin Jacob /* get vfid and domain */ 552445371e8SJerin Jacob val = octeontx_read64(bar0 + PKO_VF_DQ_FC_CONFIG); 553445371e8SJerin Jacob domain = (val >> 7) & 0xffff; 554445371e8SJerin Jacob vfid = (val >> 23) & 0xffff; 555445371e8SJerin Jacob 556445371e8SJerin Jacob if (unlikely(vfid >= PKO_VF_MAX)) { 557445371e8SJerin Jacob octeontx_log_err("pko: Invalid vfid %d", vfid); 558445371e8SJerin Jacob return -EINVAL; 559445371e8SJerin Jacob } 560445371e8SJerin Jacob 561445371e8SJerin Jacob res = &pko_vf_ctl.pko[vfid]; 562445371e8SJerin Jacob res->vfid = vfid; 563445371e8SJerin Jacob res->domain = domain; 564445371e8SJerin Jacob res->bar0 = bar0; 565445371e8SJerin Jacob res->bar2 = bar2; 566445371e8SJerin Jacob 567445371e8SJerin Jacob octeontx_log_dbg("Domain=%d group=%d", res->domain, res->vfid); 568445371e8SJerin Jacob return 0; 569445371e8SJerin Jacob } 570445371e8SJerin Jacob 571445371e8SJerin Jacob #define PCI_VENDOR_ID_CAVIUM 0x177D 572445371e8SJerin Jacob #define PCI_DEVICE_ID_OCTEONTX_PKO_VF 0xA049 573445371e8SJerin Jacob 574445371e8SJerin Jacob static const struct rte_pci_id pci_pkovf_map[] = { 575445371e8SJerin Jacob { 576445371e8SJerin Jacob RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 577445371e8SJerin Jacob PCI_DEVICE_ID_OCTEONTX_PKO_VF) 578445371e8SJerin Jacob }, 579445371e8SJerin Jacob { 580445371e8SJerin Jacob .vendor_id = 0, 581445371e8SJerin Jacob }, 582445371e8SJerin Jacob }; 583445371e8SJerin Jacob 584445371e8SJerin Jacob static struct rte_pci_driver pci_pkovf = { 585445371e8SJerin Jacob .id_table = pci_pkovf_map, 586445371e8SJerin Jacob .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 587445371e8SJerin Jacob .probe = pkovf_probe, 588445371e8SJerin Jacob }; 589445371e8SJerin Jacob 590445371e8SJerin Jacob RTE_PMD_REGISTER_PCI(octeontx_pkovf, pci_pkovf); 591