numam-dpdk/drivers/net/octeontx_ep/otx2_ep_vf.c
Nalla Pradeep 6195062454 net/octeontx_ep: set up IQ and OQ registers
Configuring hardware registers with command queue (IQ) and driver output
queue (OQ) parameters.
List of parameters configured for IQ after making sure it is idle
1. Base address
2. Instruction size
3. Disabling interrupts for fastpath

List of parameters configured for OQ after making sure it is idle
1. Base address
2. Output buffer size
3. Clear output queue doorbell
4. Disable interrupts for fastpath

Signed-off-by: Nalla Pradeep <pnalla@marvell.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
2021-01-29 18:16:12 +01:00

252 lines
7.1 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(C) 2021 Marvell.
*/
#include "otx2_common.h"
#include "otx_ep_common.h"
#include "otx2_ep_vf.h"
static void
otx2_vf_setup_global_iq_reg(struct otx_ep_device *otx_ep, int q_no)
{
volatile uint64_t reg_val = 0ull;
/* Select ES, RO, NS, RDSIZE,DPTR Format#0 for IQs
* IS_64B is by default enabled.
*/
reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
reg_val |= SDP_VF_R_IN_CTL_RDSIZE;
reg_val |= SDP_VF_R_IN_CTL_IS_64B;
reg_val |= SDP_VF_R_IN_CTL_ESR;
otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
}
static void
otx2_vf_setup_global_oq_reg(struct otx_ep_device *otx_ep, int q_no)
{
volatile uint64_t reg_val = 0ull;
reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
reg_val &= ~(SDP_VF_R_OUT_CTL_IMODE);
reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_P);
reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_P);
reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_I);
reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_I);
reg_val &= ~(SDP_VF_R_OUT_CTL_ES_I);
reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_D);
reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_D);
reg_val &= ~(SDP_VF_R_OUT_CTL_ES_D);
/* INFO/DATA ptr swap is required */
reg_val |= (SDP_VF_R_OUT_CTL_ES_P);
otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
}
static void
otx2_vf_setup_global_input_regs(struct otx_ep_device *otx_ep)
{
uint64_t q_no = 0ull;
for (q_no = 0; q_no < (otx_ep->sriov_info.rings_per_vf); q_no++)
otx2_vf_setup_global_iq_reg(otx_ep, q_no);
}
static void
otx2_vf_setup_global_output_regs(struct otx_ep_device *otx_ep)
{
uint32_t q_no;
for (q_no = 0; q_no < (otx_ep->sriov_info.rings_per_vf); q_no++)
otx2_vf_setup_global_oq_reg(otx_ep, q_no);
}
static void
otx2_vf_setup_device_regs(struct otx_ep_device *otx_ep)
{
otx2_vf_setup_global_input_regs(otx_ep);
otx2_vf_setup_global_output_regs(otx_ep);
}
static void
otx2_vf_setup_iq_regs(struct otx_ep_device *otx_ep, uint32_t iq_no)
{
struct otx_ep_instr_queue *iq = otx_ep->instr_queue[iq_no];
volatile uint64_t reg_val = 0ull;
reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(iq_no));
/* Wait till IDLE to set to 1, not supposed to configure BADDR
* as long as IDLE is 0
*/
if (!(reg_val & SDP_VF_R_IN_CTL_IDLE)) {
do {
reg_val = otx2_read64(otx_ep->hw_addr +
SDP_VF_R_IN_CONTROL(iq_no));
} while (!(reg_val & SDP_VF_R_IN_CTL_IDLE));
}
/* Write the start of the input queue's ring and its size */
otx2_write64(iq->base_addr_dma, otx_ep->hw_addr +
SDP_VF_R_IN_INSTR_BADDR(iq_no));
otx2_write64(iq->nb_desc, otx_ep->hw_addr +
SDP_VF_R_IN_INSTR_RSIZE(iq_no));
/* Remember the doorbell & instruction count register addr
* for this queue
*/
iq->doorbell_reg = (uint8_t *)otx_ep->hw_addr +
SDP_VF_R_IN_INSTR_DBELL(iq_no);
iq->inst_cnt_reg = (uint8_t *)otx_ep->hw_addr +
SDP_VF_R_IN_CNTS(iq_no);
otx_ep_dbg("InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p",
iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
do {
reg_val = rte_read32(iq->inst_cnt_reg);
rte_write32(reg_val, iq->inst_cnt_reg);
} while (reg_val != 0);
/* IN INTR_THRESHOLD is set to max(FFFFFFFF) which disable the IN INTR
* to raise
*/
otx2_write64(OTX_EP_CLEAR_SDP_IN_INT_LVLS,
otx_ep->hw_addr + SDP_VF_R_IN_INT_LEVELS(iq_no));
}
static void
otx2_vf_setup_oq_regs(struct otx_ep_device *otx_ep, uint32_t oq_no)
{
volatile uint64_t reg_val = 0ull;
uint64_t oq_ctl = 0ull;
struct otx_ep_droq *droq = otx_ep->droq[oq_no];
/* Wait on IDLE to set to 1, supposed to configure BADDR
* as log as IDLE is 0
*/
reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
while (!(reg_val & SDP_VF_R_OUT_CTL_IDLE)) {
reg_val = otx2_read64(otx_ep->hw_addr +
SDP_VF_R_OUT_CONTROL(oq_no));
}
otx2_write64(droq->desc_ring_dma, otx_ep->hw_addr +
SDP_VF_R_OUT_SLIST_BADDR(oq_no));
otx2_write64(droq->nb_desc, otx_ep->hw_addr +
SDP_VF_R_OUT_SLIST_RSIZE(oq_no));
oq_ctl = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
/* Clear the ISIZE and BSIZE (22-0) */
oq_ctl &= ~(OTX_EP_CLEAR_ISIZE_BSIZE);
/* Populate the BSIZE (15-0) */
oq_ctl |= (droq->buffer_size & OTX_EP_DROQ_BUFSZ_MASK);
otx2_write64(oq_ctl, otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
/* Mapped address of the pkt_sent and pkts_credit regs */
droq->pkts_sent_reg = (uint8_t *)otx_ep->hw_addr +
SDP_VF_R_OUT_CNTS(oq_no);
droq->pkts_credit_reg = (uint8_t *)otx_ep->hw_addr +
SDP_VF_R_OUT_SLIST_DBELL(oq_no);
rte_write64(OTX_EP_CLEAR_OUT_INT_LVLS,
otx_ep->hw_addr + SDP_VF_R_OUT_INT_LEVELS(oq_no));
/* Clear PKT_CNT register */
rte_write64(OTX_EP_CLEAR_SDP_OUT_PKT_CNT, (uint8_t *)otx_ep->hw_addr +
SDP_VF_R_OUT_PKT_CNT(oq_no));
/* Clear the OQ doorbell */
rte_write32(OTX_EP_CLEAR_SLIST_DBELL, droq->pkts_credit_reg);
while ((rte_read32(droq->pkts_credit_reg) != 0ull)) {
rte_write32(OTX_EP_CLEAR_SLIST_DBELL, droq->pkts_credit_reg);
rte_delay_ms(1);
}
otx_ep_dbg("SDP_R[%d]_credit:%x", oq_no,
rte_read32(droq->pkts_credit_reg));
/* Clear the OQ_OUT_CNTS doorbell */
reg_val = rte_read32(droq->pkts_sent_reg);
rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
otx_ep_dbg("SDP_R[%d]_sent: %x", oq_no,
rte_read32(droq->pkts_sent_reg));
while (((rte_read32(droq->pkts_sent_reg)) != 0ull)) {
reg_val = rte_read32(droq->pkts_sent_reg);
rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
rte_delay_ms(1);
}
otx_ep_dbg("SDP_R[%d]_sent: %x", oq_no,
rte_read32(droq->pkts_sent_reg));
}
static const struct otx_ep_config default_otx2_ep_conf = {
/* IQ attributes */
.iq = {
.max_iqs = OTX_EP_CFG_IO_QUEUES,
.instr_type = OTX_EP_64BYTE_INSTR,
.pending_list_size = (OTX_EP_MAX_IQ_DESCRIPTORS *
OTX_EP_CFG_IO_QUEUES),
},
/* OQ attributes */
.oq = {
.max_oqs = OTX_EP_CFG_IO_QUEUES,
.info_ptr = OTX_EP_OQ_INFOPTR_MODE,
.refill_threshold = OTX_EP_OQ_REFIL_THRESHOLD,
},
.num_iqdef_descs = OTX_EP_MAX_IQ_DESCRIPTORS,
.num_oqdef_descs = OTX_EP_MAX_OQ_DESCRIPTORS,
.oqdef_buf_size = OTX_EP_OQ_BUF_SIZE,
};
static const struct otx_ep_config*
otx2_ep_get_defconf(struct otx_ep_device *otx_ep_dev __rte_unused)
{
const struct otx_ep_config *default_conf = NULL;
default_conf = &default_otx2_ep_conf;
return default_conf;
}
int
otx2_ep_vf_setup_device(struct otx_ep_device *otx_ep)
{
uint64_t reg_val = 0ull;
/* If application doesn't provide its conf, use driver default conf */
if (otx_ep->conf == NULL) {
otx_ep->conf = otx2_ep_get_defconf(otx_ep);
if (otx_ep->conf == NULL) {
otx2_err("SDP VF default config not found");
return -ENOENT;
}
otx2_info("Default config is used");
}
/* Get IOQs (RPVF] count */
reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(0));
otx_ep->sriov_info.rings_per_vf = ((reg_val >> SDP_VF_R_IN_CTL_RPVF_POS)
& SDP_VF_R_IN_CTL_RPVF_MASK);
otx2_info("SDP RPVF: %d", otx_ep->sriov_info.rings_per_vf);
otx_ep->fn_list.setup_iq_regs = otx2_vf_setup_iq_regs;
otx_ep->fn_list.setup_oq_regs = otx2_vf_setup_oq_regs;
otx_ep->fn_list.setup_device_regs = otx2_vf_setup_device_regs;
return 0;
}