/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2018 Cavium, Inc */ #include "otx_zip.h" uint64_t zip_reg_read64(uint8_t *hw_addr, uint64_t offset) { uint8_t *base = hw_addr; return *(volatile uint64_t *)(base + offset); } void zip_reg_write64(uint8_t *hw_addr, uint64_t offset, uint64_t val) { uint8_t *base = hw_addr; *(uint64_t *)(base + offset) = val; } static void zip_q_enable(struct zipvf_qp *qp) { zip_vqx_ena_t que_ena; /*ZIP VFx command queue init*/ que_ena.u = 0ull; que_ena.s.ena = 1; zip_reg_write64(qp->vf->vbar0, ZIP_VQ_ENA, que_ena.u); rte_wmb(); } /* initialize given qp on zip device */ int zipvf_q_init(struct zipvf_qp *qp) { zip_vqx_sbuf_addr_t que_sbuf_addr; uint64_t size; void *cmdq_addr; uint64_t iova; struct zipvf_cmdq *cmdq = &qp->cmdq; struct zip_vf *vf = qp->vf; /* allocate and setup instruction queue */ size = ZIP_MAX_CMDQ_SIZE; size = ZIP_ALIGN_ROUNDUP(size, ZIP_CMDQ_ALIGN); cmdq_addr = rte_zmalloc(qp->name, size, ZIP_CMDQ_ALIGN); if (cmdq_addr == NULL) return -1; cmdq->sw_head = (uint64_t *)cmdq_addr; cmdq->va = (uint8_t *)cmdq_addr; iova = rte_mem_virt2iova(cmdq_addr); cmdq->iova = iova; que_sbuf_addr.u = 0ull; que_sbuf_addr.s.ptr = (cmdq->iova >> 7); zip_reg_write64(vf->vbar0, ZIP_VQ_SBUF_ADDR, que_sbuf_addr.u); zip_q_enable(qp); memset(cmdq->va, 0, ZIP_MAX_CMDQ_SIZE); rte_spinlock_init(&cmdq->qlock); return 0; } int zipvf_q_term(struct zipvf_qp *qp) { struct zipvf_cmdq *cmdq = &qp->cmdq; zip_vqx_ena_t que_ena; struct zip_vf *vf = qp->vf; if (cmdq->va != NULL) { memset(cmdq->va, 0, ZIP_MAX_CMDQ_SIZE); rte_free(cmdq->va); } /*Disabling the ZIP queue*/ que_ena.u = 0ull; zip_reg_write64(vf->vbar0, ZIP_VQ_ENA, que_ena.u); return 0; } void zipvf_push_command(struct zipvf_qp *qp, union zip_inst_s *cmd) { zip_quex_doorbell_t dbell; union zip_nptr_s ncp; uint64_t *ncb_ptr; struct zipvf_cmdq *cmdq = &qp->cmdq; void *reg_base = qp->vf->vbar0; /*Held queue lock*/ rte_spinlock_lock(&(cmdq->qlock)); /* Check space availability in zip cmd queue */ if ((((cmdq->sw_head - (uint64_t *)cmdq->va) * sizeof(uint64_t *)) + ZIP_CMD_SIZE) == (ZIP_MAX_CMDQ_SIZE - ZIP_MAX_NCBP_SIZE)) { /*Last buffer of the command queue*/ memcpy((uint8_t *)cmdq->sw_head, (uint8_t *)cmd, sizeof(union zip_inst_s)); /* move pointer to next loc in unit of 64-bit word */ cmdq->sw_head += ZIP_CMD_SIZE_WORDS; /* now, point the "Next-Chunk Buffer Ptr" to sw_head */ ncb_ptr = cmdq->sw_head; /* Pointing head again to cmdqueue base*/ cmdq->sw_head = (uint64_t *)cmdq->va; ncp.u = 0ull; ncp.s.addr = cmdq->iova; *ncb_ptr = ncp.u; } else { /*Enough buffers available in the command queue*/ memcpy((uint8_t *)cmdq->sw_head, (uint8_t *)cmd, sizeof(union zip_inst_s)); cmdq->sw_head += ZIP_CMD_SIZE_WORDS; } rte_wmb(); /* Ringing ZIP VF doorbell */ dbell.u = 0ull; dbell.s.dbell_cnt = 1; zip_reg_write64(reg_base, ZIP_VQ_DOORBELL, dbell.u); rte_spinlock_unlock(&(cmdq->qlock)); } int zipvf_create(struct rte_compressdev *compressdev) { struct rte_pci_device *pdev = RTE_DEV_TO_PCI(compressdev->device); struct zip_vf *zipvf = NULL; char *dev_name = compressdev->data->name; void *vbar0; uint64_t reg; if (pdev->mem_resource[0].phys_addr == 0ULL) return -EIO; vbar0 = pdev->mem_resource[0].addr; if (!vbar0) { ZIP_PMD_ERR("Failed to map BAR0 of %s", dev_name); return -ENODEV; } zipvf = (struct zip_vf *)(compressdev->data->dev_private); if (!zipvf) return -ENOMEM; zipvf->vbar0 = vbar0; reg = zip_reg_read64(zipvf->vbar0, ZIP_VF_PF_MBOXX(0)); /* Storing domain in local to ZIP VF */ zipvf->dom_sdom = reg; zipvf->pdev = pdev; zipvf->max_nb_queue_pairs = ZIP_MAX_VF_QUEUE; return 0; } int zipvf_destroy(struct rte_compressdev *compressdev) { struct zip_vf *vf = (struct zip_vf *)(compressdev->data->dev_private); /* Rewriting the domain_id in ZIP_VF_MBOX for app rerun */ zip_reg_write64(vf->vbar0, ZIP_VF_PF_MBOXX(0), vf->dom_sdom); return 0; }