[dpdk-dev] [PATCH v3 13/46] net/liquidio: add APIs to allocate and free IQ

Shijith Thotton shijith.thotton at caviumnetworks.com
Sat Mar 25 07:24:24 CET 2017


Instruction queue (IQ) is used to send control and data packets to
device from host. IQ 0 is used to send device configuration commands
during initialization and later re-allocated as per application
requirement.

Signed-off-by: Shijith Thotton <shijith.thotton at caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.jacob at caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles at caviumnetworks.com>
Signed-off-by: Venkat Koppula <venkat.koppula at caviumnetworks.com>
Signed-off-by: Srisivasubramanian S <ssrinivasan at caviumnetworks.com>
Signed-off-by: Mallesham Jatharakonda <mjatharakonda at oneconvergence.com>
---
 drivers/net/liquidio/Makefile           |   1 +
 drivers/net/liquidio/base/lio_hw_defs.h |  12 ++
 drivers/net/liquidio/lio_ethdev.c       |   8 ++
 drivers/net/liquidio/lio_rxtx.c         | 206 ++++++++++++++++++++++++++++++++
 drivers/net/liquidio/lio_rxtx.h         |  57 +++++++++
 drivers/net/liquidio/lio_struct.h       | 112 ++++++++++++++++-
 6 files changed, 395 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/liquidio/lio_rxtx.c
 create mode 100644 drivers/net/liquidio/lio_rxtx.h

diff --git a/drivers/net/liquidio/Makefile b/drivers/net/liquidio/Makefile
index 451f49d..de2ef9b 100644
--- a/drivers/net/liquidio/Makefile
+++ b/drivers/net/liquidio/Makefile
@@ -51,6 +51,7 @@ VPATH += $(RTE_SDK)/drivers/net/liquidio/base
 # all source are stored in SRCS-y
 #
 SRCS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += lio_ethdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += lio_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += lio_23xx_vf.c
 SRCS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += lio_mbox.c
 
diff --git a/drivers/net/liquidio/base/lio_hw_defs.h b/drivers/net/liquidio/base/lio_hw_defs.h
index 9282068..726ce6b 100644
--- a/drivers/net/liquidio/base/lio_hw_defs.h
+++ b/drivers/net/liquidio/base/lio_hw_defs.h
@@ -76,6 +76,18 @@ enum lio_card_type {
 
 #define LIO_23XX_NAME "23xx"
 
+#define LIO_NUM_DEF_TX_DESCS_CFG(cfg)					\
+		((cfg)->default_config->num_def_tx_descs)
+
+#define LIO_IQ_INSTR_TYPE(cfg)		((cfg)->default_config->iq.instr_type)
+
+/* The following config values are fixed and should not be modified. */
+
+/* Maximum number of Instruction queues */
+#define LIO_MAX_INSTR_QUEUES(lio_dev)		CN23XX_MAX_RINGS_PER_VF
+
+#define LIO_MAX_POSSIBLE_INSTR_QUEUES		CN23XX_MAX_INPUT_QUEUES
+
 #define LIO_DEVICE_NAME_LEN		32
 #define LIO_BASE_MAJOR_VERSION		1
 #define LIO_BASE_MINOR_VERSION		5
diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c
index 5aae105..5d7d5a7 100644
--- a/drivers/net/liquidio/lio_ethdev.c
+++ b/drivers/net/liquidio/lio_ethdev.c
@@ -39,6 +39,7 @@
 #include "lio_logs.h"
 #include "lio_23xx_vf.h"
 #include "lio_ethdev.h"
+#include "lio_rxtx.h"
 
 static void
 lio_check_pf_hs_response(void *lio_dev)
@@ -127,6 +128,11 @@
 		goto error;
 	}
 
+	if (lio_setup_instr_queue0(lio_dev)) {
+		lio_dev_err(lio_dev, "Failed to setup instruction queue 0\n");
+		goto error;
+	}
+
 	dpdk_queues = (int)lio_dev->sriov_info.rings_per_vf;
 
 	lio_dev->max_tx_queues = dpdk_queues;
@@ -137,6 +143,8 @@
 error:
 	if (lio_dev->mbox[0])
 		lio_dev->fn_list.free_mbox(lio_dev);
+	if (lio_dev->instr_queue[0])
+		lio_free_instr_queue0(lio_dev);
 
 	return -1;
 }
diff --git a/drivers/net/liquidio/lio_rxtx.c b/drivers/net/liquidio/lio_rxtx.c
new file mode 100644
index 0000000..de98fc6
--- /dev/null
+++ b/drivers/net/liquidio/lio_rxtx.c
@@ -0,0 +1,206 @@
+/*
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Cavium, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+
+#include "lio_logs.h"
+#include "lio_struct.h"
+#include "lio_ethdev.h"
+#include "lio_rxtx.h"
+
+static void
+lio_dma_zone_free(struct lio_device *lio_dev, const struct rte_memzone *mz)
+{
+	const struct rte_memzone *mz_tmp;
+	int ret = 0;
+
+	if (mz == NULL) {
+		lio_dev_err(lio_dev, "Memzone NULL\n");
+		return;
+	}
+
+	mz_tmp = rte_memzone_lookup(mz->name);
+	if (mz_tmp == NULL) {
+		lio_dev_err(lio_dev, "Memzone %s Not Found\n", mz->name);
+		return;
+	}
+
+	ret = rte_memzone_free(mz);
+	if (ret)
+		lio_dev_err(lio_dev, "Memzone free Failed ret %d\n", ret);
+}
+
+/**
+ *  lio_init_instr_queue()
+ *  @param lio_dev	- pointer to the lio device structure.
+ *  @param txpciq	- queue to be initialized.
+ *
+ *  Called at driver init time for each input queue. iq_conf has the
+ *  configuration parameters for the queue.
+ *
+ *  @return  Success: 0	Failure: -1
+ */
+static int
+lio_init_instr_queue(struct lio_device *lio_dev,
+		     union octeon_txpciq txpciq,
+		     uint32_t num_descs, unsigned int socket_id)
+{
+	uint32_t iq_no = (uint32_t)txpciq.s.q_no;
+	struct lio_instr_queue *iq;
+	uint32_t instr_type;
+	uint32_t q_size;
+
+	instr_type = LIO_IQ_INSTR_TYPE(lio_dev);
+
+	q_size = instr_type * num_descs;
+	iq = lio_dev->instr_queue[iq_no];
+	iq->iq_mz = rte_eth_dma_zone_reserve(lio_dev->eth_dev,
+					     "instr_queue", iq_no, q_size,
+					     RTE_CACHE_LINE_SIZE,
+					     socket_id);
+	if (iq->iq_mz == NULL) {
+		lio_dev_err(lio_dev, "Cannot allocate memory for instr queue %d\n",
+			    iq_no);
+		return -1;
+	}
+
+	iq->base_addr_dma = iq->iq_mz->phys_addr;
+	iq->base_addr = (uint8_t *)iq->iq_mz->addr;
+
+	iq->max_count = num_descs;
+
+	/* Initialize a list to holds requests that have been posted to Octeon
+	 * but has yet to be fetched by octeon
+	 */
+	iq->request_list = rte_zmalloc_socket("request_list",
+					      sizeof(*iq->request_list) *
+							num_descs,
+					      RTE_CACHE_LINE_SIZE,
+					      socket_id);
+	if (iq->request_list == NULL) {
+		lio_dev_err(lio_dev, "Alloc failed for IQ[%d] nr free list\n",
+			    iq_no);
+		lio_dma_zone_free(lio_dev, iq->iq_mz);
+		return -1;
+	}
+
+	lio_dev_dbg(lio_dev, "IQ[%d]: base: %p basedma: %lx count: %d\n",
+		    iq_no, iq->base_addr, (unsigned long)iq->base_addr_dma,
+		    iq->max_count);
+
+	iq->lio_dev = lio_dev;
+	iq->txpciq.txpciq64 = txpciq.txpciq64;
+	iq->fill_cnt = 0;
+	iq->host_write_index = 0;
+	iq->lio_read_index = 0;
+	iq->flush_index = 0;
+
+	rte_atomic64_set(&iq->instr_pending, 0);
+
+	/* Initialize the spinlock for this instruction queue */
+	rte_spinlock_init(&iq->lock);
+	rte_spinlock_init(&iq->post_lock);
+
+	rte_atomic64_clear(&iq->iq_flush_running);
+
+	lio_dev->io_qmask.iq |= (1ULL << iq_no);
+
+	/* Set the 32B/64B mode for each input queue */
+	lio_dev->io_qmask.iq64B |= ((instr_type == 64) << iq_no);
+	iq->iqcmd_64B = (instr_type == 64);
+
+	return 0;
+}
+
+int
+lio_setup_instr_queue0(struct lio_device *lio_dev)
+{
+	union octeon_txpciq txpciq;
+	uint32_t num_descs = 0;
+	uint32_t iq_no = 0;
+
+	num_descs = LIO_NUM_DEF_TX_DESCS_CFG(lio_dev);
+
+	lio_dev->num_iqs = 0;
+
+	lio_dev->instr_queue[0] = rte_zmalloc(NULL,
+					sizeof(struct lio_instr_queue), 0);
+	if (lio_dev->instr_queue[0] == NULL)
+		return -ENOMEM;
+
+	lio_dev->instr_queue[0]->q_index = 0;
+	lio_dev->instr_queue[0]->app_ctx = (void *)(size_t)0;
+	txpciq.txpciq64 = 0;
+	txpciq.s.q_no = iq_no;
+	txpciq.s.pkind = lio_dev->pfvf_hsword.pkind;
+	txpciq.s.use_qpg = 0;
+	txpciq.s.qpg = 0;
+	if (lio_init_instr_queue(lio_dev, txpciq, num_descs, SOCKET_ID_ANY)) {
+		rte_free(lio_dev->instr_queue[0]);
+		lio_dev->instr_queue[0] = NULL;
+		return -1;
+	}
+
+	lio_dev->num_iqs++;
+
+	return 0;
+}
+
+/**
+ *  lio_delete_instr_queue()
+ *  @param lio_dev	- pointer to the lio device structure.
+ *  @param iq_no	- queue to be deleted.
+ *
+ *  Called at driver unload time for each input queue. Deletes all
+ *  allocated resources for the input queue.
+ */
+static void
+lio_delete_instr_queue(struct lio_device *lio_dev, uint32_t iq_no)
+{
+	struct lio_instr_queue *iq = lio_dev->instr_queue[iq_no];
+
+	rte_free(iq->request_list);
+	iq->request_list = NULL;
+	lio_dma_zone_free(lio_dev, iq->iq_mz);
+}
+
+void
+lio_free_instr_queue0(struct lio_device *lio_dev)
+{
+	lio_delete_instr_queue(lio_dev, 0);
+	rte_free(lio_dev->instr_queue[0]);
+	lio_dev->instr_queue[0] = NULL;
+	lio_dev->num_iqs--;
+}
diff --git a/drivers/net/liquidio/lio_rxtx.h b/drivers/net/liquidio/lio_rxtx.h
new file mode 100644
index 0000000..33f178b
--- /dev/null
+++ b/drivers/net/liquidio/lio_rxtx.h
@@ -0,0 +1,57 @@
+/*
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Cavium, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LIO_RXTX_H_
+#define _LIO_RXTX_H_
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include <rte_spinlock.h>
+#include <rte_memory.h>
+
+#include "lio_struct.h"
+
+struct lio_request_list {
+	uint32_t reqtype;
+	void *buf;
+};
+
+/** Setup instruction queue zero for the device
+ *  @param lio_dev which lio device to setup
+ *
+ *  @return 0 if success. -1 if fails
+ */
+int lio_setup_instr_queue0(struct lio_device *lio_dev);
+void lio_free_instr_queue0(struct lio_device *lio_dev);
+#endif	/* _LIO_RXTX_H_ */
diff --git a/drivers/net/liquidio/lio_struct.h b/drivers/net/liquidio/lio_struct.h
index e8b6e1d..29059a5 100644
--- a/drivers/net/liquidio/lio_struct.h
+++ b/drivers/net/liquidio/lio_struct.h
@@ -50,7 +50,110 @@ struct lio_version {
 	uint16_t reserved;
 };
 
-struct lio_device;
+/** The txpciq info passed to host from the firmware */
+union octeon_txpciq {
+	uint64_t txpciq64;
+
+	struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+		uint64_t q_no : 8;
+		uint64_t port : 8;
+		uint64_t pkind : 6;
+		uint64_t use_qpg : 1;
+		uint64_t qpg : 11;
+		uint64_t aura_num : 10;
+		uint64_t reserved : 20;
+#else
+		uint64_t reserved : 20;
+		uint64_t aura_num : 10;
+		uint64_t qpg : 11;
+		uint64_t use_qpg : 1;
+		uint64_t pkind : 6;
+		uint64_t port : 8;
+		uint64_t q_no : 8;
+#endif
+	} s;
+};
+
+/** The instruction (input) queue.
+ *  The input queue is used to post raw (instruction) mode data or packet
+ *  data to Octeon device from the host. Each input queue for
+ *  a LIO device has one such structure to represent it.
+ */
+struct lio_instr_queue {
+	/** A spinlock to protect access to the input ring.  */
+	rte_spinlock_t lock;
+
+	rte_spinlock_t post_lock;
+
+	struct lio_device *lio_dev;
+
+	uint32_t pkt_in_done;
+
+	rte_atomic64_t iq_flush_running;
+
+	/** Flag that indicates if the queue uses 64 byte commands. */
+	uint32_t iqcmd_64B:1;
+
+	/** Queue info. */
+	union octeon_txpciq txpciq;
+
+	uint32_t rsvd:17;
+
+	uint32_t status:8;
+
+	/** Maximum no. of instructions in this queue. */
+	uint32_t max_count;
+
+	/** Index in input ring where the driver should write the next packet */
+	uint32_t host_write_index;
+
+	/** Index in input ring where Octeon is expected to read the next
+	 *  packet.
+	 */
+	uint32_t lio_read_index;
+
+	/** This index aids in finding the window in the queue where Octeon
+	 *  has read the commands.
+	 */
+	uint32_t flush_index;
+
+	/** This field keeps track of the instructions pending in this queue. */
+	rte_atomic64_t instr_pending;
+
+	/** Pointer to the Virtual Base addr of the input ring. */
+	uint8_t *base_addr;
+
+	struct lio_request_list *request_list;
+
+	/** Octeon doorbell register for the ring. */
+	void *doorbell_reg;
+
+	/** Octeon instruction count register for this ring. */
+	void *inst_cnt_reg;
+
+	/** Number of instructions pending to be posted to Octeon. */
+	uint32_t fill_cnt;
+
+	/** DMA mapped base address of the input descriptor ring. */
+	uint64_t base_addr_dma;
+
+	/** Application context */
+	void *app_ctx;
+
+	/* network stack queue index */
+	int q_index;
+
+	/* Memory zone */
+	const struct rte_memzone *iq_mz;
+};
+
+struct lio_io_enable {
+	uint64_t iq;
+	uint64_t oq;
+	uint64_t iq64B;
+};
+
 struct lio_fn_list {
 	int (*setup_mbox)(struct lio_device *);
 	void (*free_mbox)(struct lio_device *);
@@ -170,6 +273,13 @@ struct lio_device {
 
 	struct lio_fn_list fn_list;
 
+	uint32_t num_iqs;
+
+	/** The input instruction queues */
+	struct lio_instr_queue *instr_queue[LIO_MAX_POSSIBLE_INSTR_QUEUES];
+
+	struct lio_io_enable io_qmask;
+
 	struct lio_sriov_info sriov_info;
 
 	struct lio_pf_vf_hs_word pfvf_hsword;
-- 
1.8.3.1



More information about the dev mailing list