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 <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>
This commit is contained in:
Shijith Thotton 2017-03-25 11:54:36 +05:30 committed by Ferruh Yigit
parent 1d395422f8
commit 990c41eea8
4 changed files with 177 additions and 0 deletions

View 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);

View 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--;
}

View File

@ -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
*

View 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;