[dpdk-dev] [PATCH v7 10/12] net/octeontx_ep: added dev start and stop
From: Nalla Pradeep <hidden>
Date: 2021-01-29 12:46:46
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Dev start and stop operations are added. To accomplish this internal functions to enable or disable io queues are incorporated. Signed-off-by: Nalla Pradeep <redacted> --- drivers/net/octeontx_ep/otx2_ep_vf.c | 107 ++++++++++++++++++++ drivers/net/octeontx_ep/otx_ep_common.h | 8 ++ drivers/net/octeontx_ep/otx_ep_ethdev.c | 44 ++++++++ drivers/net/octeontx_ep/otx_ep_vf.c | 128 ++++++++++++++++++++++++ drivers/net/octeontx_ep/otx_ep_vf.h | 4 + 5 files changed, 291 insertions(+)
diff --git a/drivers/net/octeontx_ep/otx2_ep_vf.c b/drivers/net/octeontx_ep/otx2_ep_vf.c
index 84de89ef7..64cd8731d 100644
--- a/drivers/net/octeontx_ep/otx2_ep_vf.c
+++ b/drivers/net/octeontx_ep/otx2_ep_vf.c@@ -188,6 +188,104 @@ otx2_vf_setup_oq_regs(struct otx_ep_device *otx_ep, uint32_t oq_no) rte_read32(droq->pkts_sent_reg)); } +static int +otx2_vf_enable_iq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + uint64_t loop = SDP_VF_BUSY_LOOP_COUNT; + uint64_t reg_val = 0ull; + + /* Resetting doorbells during IQ enabling also to handle abrupt + * guest reboot. IQ reset does not clear the doorbells. + */ + otx2_write64(0xFFFFFFFF, otx_ep->hw_addr + + SDP_VF_R_IN_INSTR_DBELL(q_no)); + + while (((otx2_read64(otx_ep->hw_addr + + SDP_VF_R_IN_INSTR_DBELL(q_no))) != 0ull) && loop--) { + rte_delay_ms(1); + } + + if (!loop) { + otx_ep_err("INSTR DBELL not coming back to 0\n"); + return -EIO; + } + + reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no)); + reg_val |= 0x1ull; + + otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no)); + + otx2_info("IQ[%d] enable done", q_no); + + return 0; +} + +static int +otx2_vf_enable_oq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + uint64_t reg_val = 0ull; + + reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no)); + reg_val |= 0x1ull; + otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no)); + + otx2_info("OQ[%d] enable done", q_no); + + return 0; +} + +static int +otx2_vf_enable_io_queues(struct otx_ep_device *otx_ep) +{ + uint32_t q_no = 0; + int ret; + + for (q_no = 0; q_no < otx_ep->nb_tx_queues; q_no++) { + ret = otx2_vf_enable_iq(otx_ep, q_no); + if (ret) + return ret; + } + + for (q_no = 0; q_no < otx_ep->nb_rx_queues; q_no++) + otx2_vf_enable_oq(otx_ep, q_no); + + return 0; +} + +static void +otx2_vf_disable_iq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + uint64_t reg_val = 0ull; + + /* Reset the doorbell register for this Input Queue. */ + reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no)); + reg_val &= ~0x1ull; + + otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no)); +} + +static void +otx2_vf_disable_oq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + volatile uint64_t reg_val = 0ull; + + reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no)); + reg_val &= ~0x1ull; + + otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no)); +} + +static void +otx2_vf_disable_io_queues(struct otx_ep_device *otx_ep) +{ + uint32_t q_no = 0; + + for (q_no = 0; q_no < otx_ep->sriov_info.rings_per_vf; q_no++) { + otx2_vf_disable_iq(otx_ep, q_no); + otx2_vf_disable_oq(otx_ep, q_no); + } +} + static const struct otx_ep_config default_otx2_ep_conf = { /* IQ attributes */ .iq = {
@@ -247,5 +345,14 @@ otx2_ep_vf_setup_device(struct otx_ep_device *otx_ep) otx_ep->fn_list.setup_device_regs = otx2_vf_setup_device_regs; + otx_ep->fn_list.enable_io_queues = otx2_vf_enable_io_queues; + otx_ep->fn_list.disable_io_queues = otx2_vf_disable_io_queues; + + otx_ep->fn_list.enable_iq = otx2_vf_enable_iq; + otx_ep->fn_list.disable_iq = otx2_vf_disable_iq; + + otx_ep->fn_list.enable_oq = otx2_vf_enable_oq; + otx_ep->fn_list.disable_oq = otx2_vf_disable_oq; + return 0; }
diff --git a/drivers/net/octeontx_ep/otx_ep_common.h b/drivers/net/octeontx_ep/otx_ep_common.h
index 25d18834b..cb42e3de0 100644
--- a/drivers/net/octeontx_ep/otx_ep_common.h
+++ b/drivers/net/octeontx_ep/otx_ep_common.h@@ -19,6 +19,7 @@ #define OTX_EP_PCI_RING_ALIGN 65536 #define SDP_PKIND 40 #define SDP_OTX2_PKIND 57 +#define OTX_EP_BUSY_LOOP_COUNT (10000) #define OTX_EP_MAX_IOQS_PER_VF 8 #define otx_ep_info(fmt, args...) \
@@ -374,7 +375,14 @@ struct otx_ep_fn_list { void (*setup_device_regs)(struct otx_ep_device *otx_ep); + int (*enable_io_queues)(struct otx_ep_device *otx_ep); void (*disable_io_queues)(struct otx_ep_device *otx_ep); + + int (*enable_iq)(struct otx_ep_device *otx_ep, uint32_t q_no); + void (*disable_iq)(struct otx_ep_device *otx_ep, uint32_t q_no); + + int (*enable_oq)(struct otx_ep_device *otx_ep, uint32_t q_no); + void (*disable_oq)(struct otx_ep_device *otx_ep, uint32_t q_no); }; /* OTX_EP EP VF device data structure */
diff --git a/drivers/net/octeontx_ep/otx_ep_ethdev.c b/drivers/net/octeontx_ep/otx_ep_ethdev.c
index 58bf6e6ae..84dd1e96a 100644
--- a/drivers/net/octeontx_ep/otx_ep_ethdev.c
+++ b/drivers/net/octeontx_ep/otx_ep_ethdev.c@@ -51,6 +51,46 @@ otx_ep_dev_info_get(struct rte_eth_dev *eth_dev, return 0; } +static int +otx_ep_dev_start(struct rte_eth_dev *eth_dev) +{ + struct otx_ep_device *otx_epvf; + unsigned int q; + int ret; + + otx_epvf = (struct otx_ep_device *)OTX_EP_DEV(eth_dev); + /* Enable IQ/OQ for this device */ + ret = otx_epvf->fn_list.enable_io_queues(otx_epvf); + if (ret) { + otx_ep_err("IOQ enable failed\n"); + return ret; + } + + for (q = 0; q < otx_epvf->nb_rx_queues; q++) { + rte_write32(otx_epvf->droq[q]->nb_desc, + otx_epvf->droq[q]->pkts_credit_reg); + + rte_wmb(); + otx_ep_info("OQ[%d] dbells [%d]\n", q, + rte_read32(otx_epvf->droq[q]->pkts_credit_reg)); + } + + otx_ep_info("dev started\n"); + + return 0; +} + +/* Stop device and disable input/output functions */ +static int +otx_ep_dev_stop(struct rte_eth_dev *eth_dev) +{ + struct otx_ep_device *otx_epvf = OTX_EP_DEV(eth_dev); + + otx_epvf->fn_list.disable_io_queues(otx_epvf); + + return 0; +} + static int otx_ep_chip_specific_setup(struct otx_ep_device *otx_epvf) {
@@ -292,6 +332,8 @@ otx_ep_tx_queue_release(void *txq) /* Define our ethernet definitions */ static const struct eth_dev_ops otx_ep_eth_dev_ops = { .dev_configure = otx_ep_dev_configure, + .dev_start = otx_ep_dev_start, + .dev_stop = otx_ep_dev_stop, .rx_queue_setup = otx_ep_rx_queue_setup, .rx_queue_release = otx_ep_rx_queue_release, .tx_queue_setup = otx_ep_tx_queue_setup,
@@ -309,6 +351,8 @@ otx_epdev_exit(struct rte_eth_dev *eth_dev) otx_epvf = OTX_EP_DEV(eth_dev); + otx_epvf->fn_list.disable_io_queues(otx_epvf); + num_queues = otx_epvf->nb_rx_queues; for (q = 0; q < num_queues; q++) { if (otx_ep_delete_oqs(otx_epvf, q)) {
diff --git a/drivers/net/octeontx_ep/otx_ep_vf.c b/drivers/net/octeontx_ep/otx_ep_vf.c
index 0a27b556c..c39a7010c 100644
--- a/drivers/net/octeontx_ep/otx_ep_vf.c
+++ b/drivers/net/octeontx_ep/otx_ep_vf.c@@ -202,6 +202,124 @@ otx_ep_setup_oq_regs(struct otx_ep_device *otx_ep, uint32_t oq_no) } } +static int +otx_ep_enable_iq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + uint64_t loop = OTX_EP_BUSY_LOOP_COUNT; + uint64_t reg_val = 0ull; + + /* Resetting doorbells during IQ enabling also to handle abrupt + * guest reboot. IQ reset does not clear the doorbells. + */ + otx_ep_write64(0xFFFFFFFF, otx_ep->hw_addr, + OTX_EP_R_IN_INSTR_DBELL(q_no)); + + while (((rte_read64(otx_ep->hw_addr + + OTX_EP_R_IN_INSTR_DBELL(q_no))) != 0ull) && loop--) { + rte_delay_ms(1); + } + + if (loop == 0) { + otx_ep_err("dbell reset failed\n"); + return -EIO; + } + + + reg_val = rte_read64(otx_ep->hw_addr + OTX_EP_R_IN_ENABLE(q_no)); + reg_val |= 0x1ull; + + otx_ep_write64(reg_val, otx_ep->hw_addr, OTX_EP_R_IN_ENABLE(q_no)); + + otx_ep_info("IQ[%d] enable done\n", q_no); + + return 0; +} + +static int +otx_ep_enable_oq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + uint64_t reg_val = 0ull; + uint64_t loop = OTX_EP_BUSY_LOOP_COUNT; + + /* Resetting doorbells during IQ enabling also to handle abrupt + * guest reboot. IQ reset does not clear the doorbells. + */ + otx_ep_write64(0xFFFFFFFF, otx_ep->hw_addr, + OTX_EP_R_OUT_SLIST_DBELL(q_no)); + while (((rte_read64(otx_ep->hw_addr + + OTX_EP_R_OUT_SLIST_DBELL(q_no))) != 0ull) && loop--) { + rte_delay_ms(1); + } + if (loop == 0) { + otx_ep_err("dbell reset failed\n"); + return -EIO; + } + + + reg_val = rte_read64(otx_ep->hw_addr + OTX_EP_R_OUT_ENABLE(q_no)); + reg_val |= 0x1ull; + otx_ep_write64(reg_val, otx_ep->hw_addr, OTX_EP_R_OUT_ENABLE(q_no)); + + otx_ep_info("OQ[%d] enable done\n", q_no); + + return 0; +} + +static int +otx_ep_enable_io_queues(struct otx_ep_device *otx_ep) +{ + uint32_t q_no = 0; + int ret; + + for (q_no = 0; q_no < otx_ep->nb_tx_queues; q_no++) { + ret = otx_ep_enable_iq(otx_ep, q_no); + if (ret) + return ret; + } + + for (q_no = 0; q_no < otx_ep->nb_rx_queues; q_no++) { + ret = otx_ep_enable_oq(otx_ep, q_no); + if (ret) + return ret; + } + + return 0; +} + +static void +otx_ep_disable_iq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + uint64_t reg_val = 0ull; + + /* Reset the doorbell register for this Input Queue. */ + reg_val = rte_read64(otx_ep->hw_addr + OTX_EP_R_IN_ENABLE(q_no)); + reg_val &= ~0x1ull; + + otx_ep_write64(reg_val, otx_ep->hw_addr, OTX_EP_R_IN_ENABLE(q_no)); +} + +static void +otx_ep_disable_oq(struct otx_ep_device *otx_ep, uint32_t q_no) +{ + uint64_t reg_val = 0ull; + + reg_val = rte_read64(otx_ep->hw_addr + OTX_EP_R_OUT_ENABLE(q_no)); + reg_val &= ~0x1ull; + + otx_ep_write64(reg_val, otx_ep->hw_addr, OTX_EP_R_OUT_ENABLE(q_no)); +} + +static void +otx_ep_disable_io_queues(struct otx_ep_device *otx_ep) +{ + uint32_t q_no = 0; + + for (q_no = 0; q_no < otx_ep->sriov_info.rings_per_vf; q_no++) { + otx_ep_disable_iq(otx_ep, q_no); + otx_ep_disable_oq(otx_ep, q_no); + } +} + /* OTX_EP default configuration */ static const struct otx_ep_config default_otx_ep_conf = { /* IQ attributes */
@@ -264,5 +382,15 @@ otx_ep_vf_setup_device(struct otx_ep_device *otx_ep) otx_ep->fn_list.setup_device_regs = otx_ep_setup_device_regs; + otx_ep->fn_list.enable_io_queues = otx_ep_enable_io_queues; + otx_ep->fn_list.disable_io_queues = otx_ep_disable_io_queues; + + otx_ep->fn_list.enable_iq = otx_ep_enable_iq; + otx_ep->fn_list.disable_iq = otx_ep_disable_iq; + + otx_ep->fn_list.enable_oq = otx_ep_enable_oq; + otx_ep->fn_list.disable_oq = otx_ep_disable_oq; + + return 0; }
diff --git a/drivers/net/octeontx_ep/otx_ep_vf.h b/drivers/net/octeontx_ep/otx_ep_vf.h
index c6115d37c..f05843557 100644
--- a/drivers/net/octeontx_ep/otx_ep_vf.h
+++ b/drivers/net/octeontx_ep/otx_ep_vf.h@@ -8,6 +8,7 @@ /* OTX_EP VF IQ Registers */ #define OTX_EP_R_IN_CONTROL_START (0x10000) +#define OTX_EP_R_IN_ENABLE_START (0x10010) #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)
@@ -17,6 +18,9 @@ #define OTX_EP_R_IN_CONTROL(ring) \ (OTX_EP_R_IN_CONTROL_START + ((ring) * OTX_EP_RING_OFFSET)) +#define OTX_EP_R_IN_ENABLE(ring) \ + (OTX_EP_R_IN_ENABLE_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))
--
2.17.1