net/liquidio: add APIs for SG list
authorShijith Thotton <shijith.thotton@caviumnetworks.com>
Sat, 25 Mar 2017 06:24:36 +0000 (11:54 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 4 Apr 2017 16:59:48 +0000 (18:59 +0200)
Add APIs to setup and free Scatter-Gather list. SG list is used while
sending packets with multiple segments.

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/lio_ethdev.c
drivers/net/liquidio/lio_rxtx.c
drivers/net/liquidio/lio_rxtx.h
drivers/net/liquidio/lio_struct.h

index 9e2d3f8..77106f6 100644 (file)
@@ -202,6 +202,15 @@ lio_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t q_no,
                return retval;
        }
 
+       retval = lio_setup_sglists(lio_dev, q_no, fw_mapped_iq,
+                               lio_dev->instr_queue[fw_mapped_iq]->max_count,
+                               socket_id);
+
+       if (retval) {
+               lio_delete_instruction_queue(lio_dev, fw_mapped_iq);
+               return retval;
+       }
+
        eth_dev->data->tx_queues[q_no] = lio_dev->instr_queue[fw_mapped_iq];
 
        return 0;
@@ -334,6 +343,20 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev)
        /* Copy the permanent MAC address */
        ether_addr_copy((struct ether_addr *)mac, &eth_dev->data->mac_addrs[0]);
 
+       lio_dev->glist_lock =
+           rte_zmalloc(NULL, sizeof(*lio_dev->glist_lock) * num_iqueues, 0);
+       if (lio_dev->glist_lock == NULL)
+               return -ENOMEM;
+
+       lio_dev->glist_head =
+               rte_zmalloc(NULL, sizeof(*lio_dev->glist_head) * num_iqueues,
+                           0);
+       if (lio_dev->glist_head == NULL) {
+               rte_free(lio_dev->glist_lock);
+               lio_dev->glist_lock = NULL;
+               return -ENOMEM;
+       }
+
        lio_dev->port_configured = 1;
 
        lio_free_soft_command(sc);
index b0dfc9b..50deaba 100644 (file)
@@ -40,6 +40,8 @@
 #include "lio_ethdev.h"
 #include "lio_rxtx.h"
 
+#define LIO_MAX_SG 12
+
 static void
 lio_droq_compute_max_packet_bufs(struct lio_droq *droq)
 {
@@ -1272,3 +1274,108 @@ lio_process_ordered_list(struct lio_device *lio_dev)
 
        return 0;
 }
+
+static inline struct lio_stailq_node *
+list_delete_first_node(struct lio_stailq_head *head)
+{
+       struct lio_stailq_node *node;
+
+       if (STAILQ_EMPTY(head))
+               node = NULL;
+       else
+               node = STAILQ_FIRST(head);
+
+       if (node)
+               STAILQ_REMOVE(head, node, lio_stailq_node, entries);
+
+       return node;
+}
+
+static void
+lio_delete_sglist(struct lio_instr_queue *txq)
+{
+       struct lio_device *lio_dev = txq->lio_dev;
+       int iq_no = txq->q_index;
+       struct lio_gather *g;
+
+       if (lio_dev->glist_head == NULL)
+               return;
+
+       do {
+               g = (struct lio_gather *)list_delete_first_node(
+                                               &lio_dev->glist_head[iq_no]);
+               if (g) {
+                       if (g->sg)
+                               rte_free(
+                                   (void *)((unsigned long)g->sg - g->adjust));
+                       rte_free(g);
+               }
+       } while (g);
+}
+
+/**
+ * \brief Setup gather lists
+ * @param lio per-network private data
+ */
+int
+lio_setup_sglists(struct lio_device *lio_dev, int iq_no,
+                 int fw_mapped_iq, int num_descs, unsigned int socket_id)
+{
+       struct lio_gather *g;
+       int i;
+
+       rte_spinlock_init(&lio_dev->glist_lock[iq_no]);
+
+       STAILQ_INIT(&lio_dev->glist_head[iq_no]);
+
+       for (i = 0; i < num_descs; i++) {
+               g = rte_zmalloc_socket(NULL, sizeof(*g), RTE_CACHE_LINE_SIZE,
+                                      socket_id);
+               if (g == NULL) {
+                       lio_dev_err(lio_dev,
+                                   "lio_gather memory allocation failed for qno %d\n",
+                                   iq_no);
+                       break;
+               }
+
+               g->sg_size =
+                   ((ROUNDUP4(LIO_MAX_SG) >> 2) * LIO_SG_ENTRY_SIZE);
+
+               g->sg = rte_zmalloc_socket(NULL, g->sg_size + 8,
+                                          RTE_CACHE_LINE_SIZE, socket_id);
+               if (g->sg == NULL) {
+                       lio_dev_err(lio_dev,
+                                   "sg list memory allocation failed for qno %d\n",
+                                   iq_no);
+                       rte_free(g);
+                       break;
+               }
+
+               /* The gather component should be aligned on 64-bit boundary */
+               if (((unsigned long)g->sg) & 7) {
+                       g->adjust = 8 - (((unsigned long)g->sg) & 7);
+                       g->sg =
+                           (struct lio_sg_entry *)((unsigned long)g->sg +
+                                                      g->adjust);
+               }
+
+               STAILQ_INSERT_TAIL(&lio_dev->glist_head[iq_no], &g->list,
+                                  entries);
+       }
+
+       if (i != num_descs) {
+               lio_delete_sglist(lio_dev->instr_queue[fw_mapped_iq]);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void
+lio_delete_instruction_queue(struct lio_device *lio_dev, int iq_no)
+{
+       lio_delete_instr_queue(lio_dev, iq_no);
+       rte_free(lio_dev->instr_queue[iq_no]);
+       lio_dev->instr_queue[iq_no] = NULL;
+       lio_dev->num_iqs--;
+}
index 86d5864..10bca4c 100644 (file)
 
 #include "lio_struct.h"
 
+#ifndef ROUNDUP4
+#define ROUNDUP4(val) (((val) + 3) & 0xfffffffc)
+#endif
+
 #define LIO_STQUEUE_FIRST_ENTRY(ptr, type, elem)       \
        (type *)((char *)((ptr)->stqh_first) - offsetof(type, elem))
 
@@ -548,9 +552,12 @@ uint16_t lio_dev_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
                           uint16_t budget);
 void lio_delete_droq_queue(struct lio_device *lio_dev, int oq_no);
 
+int lio_setup_sglists(struct lio_device *lio_dev, int iq_no,
+                     int fw_mapped_iq, int num_descs, unsigned int socket_id);
 int lio_setup_iq(struct lio_device *lio_dev, int q_index,
                 union octeon_txpciq iq_no, uint32_t num_descs, void *app_ctx,
                 unsigned int socket_id);
+void lio_delete_instruction_queue(struct lio_device *lio_dev, int iq_no);
 /** Setup instruction queue zero for the device
  *  @param lio_dev which lio device to setup
  *
index 7a7a4a6..4d67eb6 100644 (file)
@@ -298,6 +298,41 @@ struct lio_instr_queue {
        const struct rte_memzone *iq_mz;
 };
 
+/* The Scatter-Gather List Entry. The scatter or gather component used with
+ * input instruction has this format.
+ */
+struct lio_sg_entry {
+       /** The first 64 bit gives the size of data in each dptr. */
+       union {
+               uint16_t size[4];
+               uint64_t size64;
+       } u;
+
+       /** The 4 dptr pointers for this entry. */
+       uint64_t ptr[4];
+};
+
+#define LIO_SG_ENTRY_SIZE      (sizeof(struct lio_sg_entry))
+
+/** Structure of a node in list of gather components maintained by
+ *  driver for each network device.
+ */
+struct lio_gather {
+       /** List manipulation. Next and prev pointers. */
+       struct lio_stailq_node list;
+
+       /** Size of the gather component at sg in bytes. */
+       int sg_size;
+
+       /** Number of bytes that sg was adjusted to make it 8B-aligned. */
+       int adjust;
+
+       /** Gather component that can accommodate max sized fragment list
+        *  received from the IP layer.
+        */
+       struct lio_sg_entry *sg;
+};
+
 struct lio_io_enable {
        uint64_t iq;
        uint64_t oq;
@@ -516,6 +551,11 @@ struct lio_device {
 
        uint32_t num_iqs;
 
+       /** Guards each glist */
+       rte_spinlock_t *glist_lock;
+       /** Array of gather component linked lists */
+       struct lio_stailq_head *glist_head;
+
        /* The pool containing pre allocated buffers used for soft commands */
        struct rte_mempool *sc_buf_pool;