From 990c41eea8eb32a3ebe7b9cda62618cbeb1b4b70 Mon Sep 17 00:00:00 2001 From: Shijith Thotton Date: Sat, 25 Mar 2017 11:54:36 +0530 Subject: [PATCH] net/liquidio: add APIs for SG list Add APIs to setup and free Scatter-Gather list. SG list is used while sending packets with multiple segments. Signed-off-by: Shijith Thotton Signed-off-by: Jerin Jacob Signed-off-by: Derek Chickles Signed-off-by: Venkat Koppula Signed-off-by: Srisivasubramanian S Signed-off-by: Mallesham Jatharakonda --- drivers/net/liquidio/lio_ethdev.c | 23 +++++++ drivers/net/liquidio/lio_rxtx.c | 107 ++++++++++++++++++++++++++++++ drivers/net/liquidio/lio_rxtx.h | 7 ++ drivers/net/liquidio/lio_struct.h | 40 +++++++++++ 4 files changed, 177 insertions(+) diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c index 9e2d3f8ef4..77106f6dbc 100644 --- a/drivers/net/liquidio/lio_ethdev.c +++ b/drivers/net/liquidio/lio_ethdev.c @@ -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, ð_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); diff --git a/drivers/net/liquidio/lio_rxtx.c b/drivers/net/liquidio/lio_rxtx.c index b0dfc9bfd1..50deaba6e0 100644 --- a/drivers/net/liquidio/lio_rxtx.c +++ b/drivers/net/liquidio/lio_rxtx.c @@ -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--; +} diff --git a/drivers/net/liquidio/lio_rxtx.h b/drivers/net/liquidio/lio_rxtx.h index 86d5864230..10bca4c9b3 100644 --- a/drivers/net/liquidio/lio_rxtx.h +++ b/drivers/net/liquidio/lio_rxtx.h @@ -42,6 +42,10 @@ #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 * diff --git a/drivers/net/liquidio/lio_struct.h b/drivers/net/liquidio/lio_struct.h index 7a7a4a6f75..4d67eb684f 100644 --- a/drivers/net/liquidio/lio_struct.h +++ b/drivers/net/liquidio/lio_struct.h @@ -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; -- 2.20.1