From 61950624542e03a3e46ebac70d5ea2c9a7a5ece8 Mon Sep 17 00:00:00 2001 From: Nalla Pradeep Date: Fri, 29 Jan 2021 04:45:07 -0800 Subject: [PATCH] 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 Reviewed-by: Ferruh Yigit --- drivers/net/octeontx_ep/otx2_ep_vf.c | 120 ++++++++++++++++++++++++ drivers/net/octeontx_ep/otx_ep_common.h | 72 ++++++++++++++ drivers/net/octeontx_ep/otx_ep_vf.c | 120 ++++++++++++++++++++++++ drivers/net/octeontx_ep/otx_ep_vf.h | 49 ++++++++++ 4 files changed, 361 insertions(+) diff --git a/drivers/net/octeontx_ep/otx2_ep_vf.c b/drivers/net/octeontx_ep/otx2_ep_vf.c index 6368ddc80d..84de89ef7f 100644 --- a/drivers/net/octeontx_ep/otx2_ep_vf.c +++ b/drivers/net/octeontx_ep/otx2_ep_vf.c @@ -71,6 +71,123 @@ otx2_vf_setup_device_regs(struct otx_ep_device *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 = { @@ -125,6 +242,9 @@ otx2_ep_vf_setup_device(struct otx_ep_device *otx_ep) 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; diff --git a/drivers/net/octeontx_ep/otx_ep_common.h b/drivers/net/octeontx_ep/otx_ep_common.h index 493dbf8e13..25d18834b7 100644 --- a/drivers/net/octeontx_ep/otx_ep_common.h +++ b/drivers/net/octeontx_ep/otx_ep_common.h @@ -36,6 +36,33 @@ "%s():%u " fmt "\n", \ __func__, __LINE__, ##args) +/* Input Request Header format */ +union otx_ep_instr_irh { + uint64_t u64; + struct { + /* Request ID */ + uint64_t rid:16; + + /* PCIe port to use for response */ + uint64_t pcie_port:3; + + /* Scatter indicator 1=scatter */ + uint64_t scatter:1; + + /* Size of Expected result OR no. of entries in scatter list */ + uint64_t rlenssz:14; + + /* Desired destination port for result */ + uint64_t dport:6; + + /* Opcode Specific parameters */ + uint64_t param:8; + + /* Opcode for the return packet */ + uint64_t opcode:16; + } s; +}; + #define otx_ep_write64(value, base_addr, reg_off) \ {\ typeof(value) val = (value); \ @@ -45,6 +72,33 @@ rte_write64(val, ((base_addr) + off)); \ } +/* Instruction Header - for OCTEON-TX models */ +typedef union otx_ep_instr_ih { + uint64_t u64; + struct { + /** Data Len */ + uint64_t tlen:16; + + /** Reserved */ + uint64_t rsvd:20; + + /** PKIND for OTX_EP */ + uint64_t pkind:6; + + /** Front Data size */ + uint64_t fsz:6; + + /** No. of entries in gather list */ + uint64_t gsz:14; + + /** Gather indicator 1=gather*/ + uint64_t gather:1; + + /** Reserved3 */ + uint64_t reserved3:1; + } s; +} otx_ep_instr_ih_t; + /* OTX_EP IQ request list */ struct otx_ep_instr_list { void *buf; @@ -246,6 +300,16 @@ struct otx_ep_droq { /* The size of each buffer pointed by the buffer pointer. */ uint32_t buffer_size; + /** Pointer to the mapped packet credit register. + * Host writes number of info/buffer ptrs available to this register + */ + void *pkts_credit_reg; + + /** Pointer to the mapped packet sent register. OCTEON TX2 writes the + * number of packets DMA'ed to host memory in this register. + */ + void *pkts_sent_reg; + /* Statistics for this DROQ. */ struct otx_ep_droq_stats stats; @@ -263,6 +327,7 @@ struct otx_ep_droq { /* Memory zone **/ const struct rte_memzone *desc_ring_mz; + const struct rte_memzone *info_mz; }; #define OTX_EP_DROQ_SIZE (sizeof(struct otx_ep_droq)) @@ -371,6 +436,13 @@ int otx_ep_delete_oqs(struct otx_ep_device *otx_ep, uint32_t oq_no); #define OTX_EP_MAX_PKT_SZ 64000U #define OTX_EP_MAX_MAC_ADDRS 1 +#define OTX_EP_CLEAR_ISIZE_BSIZE 0x7FFFFFULL +#define OTX_EP_CLEAR_OUT_INT_LVLS 0x3FFFFFFFFFFFFFULL +#define OTX_EP_CLEAR_IN_INT_LVLS 0xFFFFFFFF +#define OTX_EP_CLEAR_SDP_IN_INT_LVLS 0x3FFFFFFFFFFFFFUL +#define OTX_EP_DROQ_BUFSZ_MASK 0xFFFF +#define OTX_EP_CLEAR_SLIST_DBELL 0xFFFFFFFF +#define OTX_EP_CLEAR_SDP_OUT_PKT_CNT 0xFFFFFFFFF extern int otx_net_ep_logtype; #endif /* _OTX_EP_COMMON_H_ */ diff --git a/drivers/net/octeontx_ep/otx_ep_vf.c b/drivers/net/octeontx_ep/otx_ep_vf.c index 22eee9100b..075e4d07df 100644 --- a/drivers/net/octeontx_ep/otx_ep_vf.c +++ b/drivers/net/octeontx_ep/otx_ep_vf.c @@ -85,6 +85,123 @@ otx_ep_setup_device_regs(struct otx_ep_device *otx_ep) otx_ep_setup_global_output_regs(otx_ep); } +static void +otx_ep_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 = rte_read64(otx_ep->hw_addr + OTX_EP_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 & OTX_EP_R_IN_CTL_IDLE)) { + do { + reg_val = rte_read64(otx_ep->hw_addr + + OTX_EP_R_IN_CONTROL(iq_no)); + } while (!(reg_val & OTX_EP_R_IN_CTL_IDLE)); + } + + /* Write the start of the input queue's ring and its size */ + otx_ep_write64(iq->base_addr_dma, otx_ep->hw_addr, + OTX_EP_R_IN_INSTR_BADDR(iq_no)); + otx_ep_write64(iq->nb_desc, otx_ep->hw_addr, + OTX_EP_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 + + OTX_EP_R_IN_INSTR_DBELL(iq_no); + iq->inst_cnt_reg = (uint8_t *)otx_ep->hw_addr + + OTX_EP_R_IN_CNTS(iq_no); + + otx_ep_dbg("InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p\n", + 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 + */ + /* reg_val = rte_read64(otx_ep->hw_addr + + * OTX_EP_R_IN_INT_LEVELS(iq_no)); + */ + otx_ep_write64(OTX_EP_CLEAR_IN_INT_LVLS, otx_ep->hw_addr, + OTX_EP_R_IN_INT_LEVELS(iq_no)); +} + +static void +otx_ep_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 + */ + otx_ep_write64(0ULL, otx_ep->hw_addr, OTX_EP_R_OUT_ENABLE(oq_no)); + + reg_val = rte_read64(otx_ep->hw_addr + OTX_EP_R_OUT_CONTROL(oq_no)); + + while (!(reg_val & OTX_EP_R_OUT_CTL_IDLE)) { + reg_val = rte_read64(otx_ep->hw_addr + + OTX_EP_R_OUT_CONTROL(oq_no)); + } + + otx_ep_write64(droq->desc_ring_dma, otx_ep->hw_addr, + OTX_EP_R_OUT_SLIST_BADDR(oq_no)); + otx_ep_write64(droq->nb_desc, otx_ep->hw_addr, + OTX_EP_R_OUT_SLIST_RSIZE(oq_no)); + + oq_ctl = rte_read64(otx_ep->hw_addr + OTX_EP_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); + + otx_ep_write64(oq_ctl, otx_ep->hw_addr, OTX_EP_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 + + OTX_EP_R_OUT_CNTS(oq_no); + droq->pkts_credit_reg = (uint8_t *)otx_ep->hw_addr + + OTX_EP_R_OUT_SLIST_DBELL(oq_no); + + otx_ep_write64(OTX_EP_CLEAR_OUT_INT_LVLS, otx_ep->hw_addr, + OTX_EP_R_OUT_INT_LEVELS(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("OTX_EP_R[%d]_credit:%x\n", 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("OTX_EP_R[%d]_sent: %x\n", 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 default configuration */ static const struct otx_ep_config default_otx_ep_conf = { /* IQ attributes */ @@ -142,6 +259,9 @@ otx_ep_vf_setup_device(struct otx_ep_device *otx_ep) otx_ep_info("OTX_EP RPVF: %d\n", otx_ep->sriov_info.rings_per_vf); + otx_ep->fn_list.setup_iq_regs = otx_ep_setup_iq_regs; + otx_ep->fn_list.setup_oq_regs = otx_ep_setup_oq_regs; + otx_ep->fn_list.setup_device_regs = otx_ep_setup_device_regs; return 0; diff --git a/drivers/net/octeontx_ep/otx_ep_vf.h b/drivers/net/octeontx_ep/otx_ep_vf.h index d17c87909a..c6115d37c0 100644 --- a/drivers/net/octeontx_ep/otx_ep_vf.h +++ b/drivers/net/octeontx_ep/otx_ep_vf.h @@ -8,9 +8,30 @@ /* OTX_EP VF IQ Registers */ #define OTX_EP_R_IN_CONTROL_START (0x10000) +#define OTX_EP_R_IN_INSTR_BADDR_START (0x10020) +#define OTX_EP_R_IN_INSTR_RSIZE_START (0x10030) +#define OTX_EP_R_IN_INSTR_DBELL_START (0x10040) +#define OTX_EP_R_IN_CNTS_START (0x10050) +#define OTX_EP_R_IN_INT_LEVELS_START (0x10060) + #define OTX_EP_R_IN_CONTROL(ring) \ (OTX_EP_R_IN_CONTROL_START + ((ring) * OTX_EP_RING_OFFSET)) +#define OTX_EP_R_IN_INSTR_BADDR(ring) \ + (OTX_EP_R_IN_INSTR_BADDR_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_IN_INSTR_RSIZE(ring) \ + (OTX_EP_R_IN_INSTR_RSIZE_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_IN_INSTR_DBELL(ring) \ + (OTX_EP_R_IN_INSTR_DBELL_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_IN_CNTS(ring) \ + (OTX_EP_R_IN_CNTS_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_IN_INT_LEVELS(ring) \ + (OTX_EP_R_IN_INT_LEVELS_START + ((ring) * OTX_EP_RING_OFFSET)) + /* OTX_EP VF IQ Masks */ #define OTX_EP_R_IN_CTL_RPVF_MASK (0xF) #define OTX_EP_R_IN_CTL_RPVF_POS (48) @@ -20,10 +41,38 @@ #define OTX_EP_R_IN_CTL_IS_64B (0x1ull << 24) #define OTX_EP_R_IN_CTL_ESR (0x1ull << 1) /* OTX_EP VF OQ Registers */ +#define OTX_EP_R_OUT_CNTS_START (0x10100) +#define OTX_EP_R_OUT_INT_LEVELS_START (0x10110) +#define OTX_EP_R_OUT_SLIST_BADDR_START (0x10120) +#define OTX_EP_R_OUT_SLIST_RSIZE_START (0x10130) +#define OTX_EP_R_OUT_SLIST_DBELL_START (0x10140) #define OTX_EP_R_OUT_CONTROL_START (0x10150) +#define OTX_EP_R_OUT_ENABLE_START (0x10160) + #define OTX_EP_R_OUT_CONTROL(ring) \ (OTX_EP_R_OUT_CONTROL_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_OUT_ENABLE(ring) \ + (OTX_EP_R_OUT_ENABLE_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_OUT_SLIST_BADDR(ring) \ + (OTX_EP_R_OUT_SLIST_BADDR_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_OUT_SLIST_RSIZE(ring) \ + (OTX_EP_R_OUT_SLIST_RSIZE_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_OUT_SLIST_DBELL(ring) \ + (OTX_EP_R_OUT_SLIST_DBELL_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_OUT_CNTS(ring) \ + (OTX_EP_R_OUT_CNTS_START + ((ring) * OTX_EP_RING_OFFSET)) + +#define OTX_EP_R_OUT_INT_LEVELS(ring) \ + (OTX_EP_R_OUT_INT_LEVELS_START + ((ring) * OTX_EP_RING_OFFSET)) + /* OTX_EP VF OQ Masks */ + +#define OTX_EP_R_OUT_CTL_IDLE (1ull << 36) #define OTX_EP_R_OUT_CTL_ES_I (1ull << 34) #define OTX_EP_R_OUT_CTL_NSR_I (1ull << 33) #define OTX_EP_R_OUT_CTL_ROR_I (1ull << 32) -- 2.20.1