net/liquidio: add APIs to allocate and free IQ
authorShijith Thotton <shijith.thotton@caviumnetworks.com>
Sat, 25 Mar 2017 06:24:24 +0000 (11:54 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 4 Apr 2017 16:59:48 +0000 (18:59 +0200)
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@caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Venkat Koppula <venkat.koppula@caviumnetworks.com>
Signed-off-by: Srisivasubramanian S <ssrinivasan@caviumnetworks.com>
Signed-off-by: Mallesham Jatharakonda <mjatharakonda@oneconvergence.com>
drivers/net/liquidio/Makefile
drivers/net/liquidio/base/lio_hw_defs.h
drivers/net/liquidio/lio_ethdev.c
drivers/net/liquidio/lio_rxtx.c [new file with mode: 0644]
drivers/net/liquidio/lio_rxtx.h [new file with mode: 0644]
drivers/net/liquidio/lio_struct.h

index 451f49d..de2ef9b 100644 (file)
@@ -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
 
index 9282068..726ce6b 100644 (file)
@@ -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
index 5aae105..5d7d5a7 100644 (file)
@@ -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 @@ lio_first_time_init(struct lio_device *lio_dev,
                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 @@ lio_first_time_init(struct lio_device *lio_dev,
 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 (file)
index 0000000..de98fc6
--- /dev/null
@@ -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 (file)
index 0000000..33f178b
--- /dev/null
@@ -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_ */
index e8b6e1d..29059a5 100644 (file)
@@ -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;