net/liquidio: add API to setup Rx queue
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:
parent
c6186279df
commit
191447ce23
@ -78,6 +78,8 @@ enum lio_card_type {
|
||||
|
||||
#define LIO_DEV_RUNNING 0xc
|
||||
|
||||
#define LIO_OQ_REFILL_THRESHOLD_CFG(cfg) \
|
||||
((cfg)->default_config->oq.refill_threshold)
|
||||
#define LIO_NUM_DEF_TX_DESCS_CFG(cfg) \
|
||||
((cfg)->default_config->num_def_tx_descs)
|
||||
|
||||
@ -89,6 +91,7 @@ enum lio_card_type {
|
||||
#define LIO_MAX_INSTR_QUEUES(lio_dev) CN23XX_MAX_RINGS_PER_VF
|
||||
|
||||
#define LIO_MAX_POSSIBLE_INSTR_QUEUES CN23XX_MAX_INPUT_QUEUES
|
||||
#define LIO_MAX_POSSIBLE_OUTPUT_QUEUES CN23XX_MAX_OUTPUT_QUEUES
|
||||
|
||||
#define LIO_DEVICE_NAME_LEN 32
|
||||
#define LIO_BASE_MAJOR_VERSION 1
|
||||
|
@ -55,6 +55,72 @@ lio_hweight64(uint64_t w)
|
||||
return (res + (res >> 32)) & 0x00000000000000FFul;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup our receive queue/ringbuffer. This is the
|
||||
* queue the Octeon uses to send us packets and
|
||||
* responses. We are given a memory pool for our
|
||||
* packet buffers that are used to populate the receive
|
||||
* queue.
|
||||
*
|
||||
* @param eth_dev
|
||||
* Pointer to the structure rte_eth_dev
|
||||
* @param q_no
|
||||
* Queue number
|
||||
* @param num_rx_descs
|
||||
* Number of entries in the queue
|
||||
* @param socket_id
|
||||
* Where to allocate memory
|
||||
* @param rx_conf
|
||||
* Pointer to the struction rte_eth_rxconf
|
||||
* @param mp
|
||||
* Pointer to the packet pool
|
||||
*
|
||||
* @return
|
||||
* - On success, return 0
|
||||
* - On failure, return -1
|
||||
*/
|
||||
static int
|
||||
lio_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t q_no,
|
||||
uint16_t num_rx_descs, unsigned int socket_id,
|
||||
const struct rte_eth_rxconf *rx_conf __rte_unused,
|
||||
struct rte_mempool *mp)
|
||||
{
|
||||
struct lio_device *lio_dev = LIO_DEV(eth_dev);
|
||||
struct rte_pktmbuf_pool_private *mbp_priv;
|
||||
uint32_t fw_mapped_oq;
|
||||
uint16_t buf_size;
|
||||
|
||||
if (q_no >= lio_dev->nb_rx_queues) {
|
||||
lio_dev_err(lio_dev, "Invalid rx queue number %u\n", q_no);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lio_dev_dbg(lio_dev, "setting up rx queue %u\n", q_no);
|
||||
|
||||
fw_mapped_oq = lio_dev->linfo.rxpciq[q_no].s.q_no;
|
||||
|
||||
if ((lio_dev->droq[fw_mapped_oq]) &&
|
||||
(num_rx_descs != lio_dev->droq[fw_mapped_oq]->max_count)) {
|
||||
lio_dev_err(lio_dev,
|
||||
"Reconfiguring Rx descs not supported. Configure descs to same value %u or restart application\n",
|
||||
lio_dev->droq[fw_mapped_oq]->max_count);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
mbp_priv = rte_mempool_get_priv(mp);
|
||||
buf_size = mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM;
|
||||
|
||||
if (lio_setup_droq(lio_dev, fw_mapped_oq, num_rx_descs, buf_size, mp,
|
||||
socket_id)) {
|
||||
lio_dev_err(lio_dev, "droq allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
eth_dev->data->rx_queues[q_no] = lio_dev->droq[fw_mapped_oq];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lio_dev_configure(struct rte_eth_dev *eth_dev)
|
||||
{
|
||||
struct lio_device *lio_dev = LIO_DEV(eth_dev);
|
||||
@ -199,6 +265,7 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev)
|
||||
/* Define our ethernet definitions */
|
||||
static const struct eth_dev_ops liovf_eth_dev_ops = {
|
||||
.dev_configure = lio_dev_configure,
|
||||
.rx_queue_setup = lio_dev_rx_queue_setup,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -62,6 +62,174 @@ lio_dma_zone_free(struct lio_device *lio_dev, const struct rte_memzone *mz)
|
||||
lio_dev_err(lio_dev, "Memzone free Failed ret %d\n", ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the space for descriptor ring for the droq.
|
||||
*
|
||||
* @param lio_dev - pointer to the lio device structure
|
||||
* @param q_no - droq no.
|
||||
*/
|
||||
static void
|
||||
lio_delete_droq(struct lio_device *lio_dev, uint32_t q_no)
|
||||
{
|
||||
struct lio_droq *droq = lio_dev->droq[q_no];
|
||||
|
||||
lio_dev_dbg(lio_dev, "OQ[%d]\n", q_no);
|
||||
|
||||
rte_free(droq->recv_buf_list);
|
||||
droq->recv_buf_list = NULL;
|
||||
lio_dma_zone_free(lio_dev, droq->info_mz);
|
||||
lio_dma_zone_free(lio_dev, droq->desc_ring_mz);
|
||||
|
||||
memset(droq, 0, LIO_DROQ_SIZE);
|
||||
}
|
||||
|
||||
static void *
|
||||
lio_alloc_info_buffer(struct lio_device *lio_dev,
|
||||
struct lio_droq *droq, unsigned int socket_id)
|
||||
{
|
||||
droq->info_mz = rte_eth_dma_zone_reserve(lio_dev->eth_dev,
|
||||
"info_list", droq->q_no,
|
||||
(droq->max_count *
|
||||
LIO_DROQ_INFO_SIZE),
|
||||
RTE_CACHE_LINE_SIZE,
|
||||
socket_id);
|
||||
|
||||
if (droq->info_mz == NULL)
|
||||
return NULL;
|
||||
|
||||
droq->info_list_dma = droq->info_mz->phys_addr;
|
||||
droq->info_alloc_size = droq->info_mz->len;
|
||||
droq->info_base_addr = (size_t)droq->info_mz->addr;
|
||||
|
||||
return droq->info_mz->addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates space for the descriptor ring for the droq and
|
||||
* sets the base addr, num desc etc in Octeon registers.
|
||||
*
|
||||
* @param lio_dev - pointer to the lio device structure
|
||||
* @param q_no - droq no.
|
||||
* @param app_ctx - pointer to application context
|
||||
* @return Success: 0 Failure: -1
|
||||
*/
|
||||
static int
|
||||
lio_init_droq(struct lio_device *lio_dev, uint32_t q_no,
|
||||
uint32_t num_descs, uint32_t desc_size,
|
||||
struct rte_mempool *mpool, unsigned int socket_id)
|
||||
{
|
||||
uint32_t c_refill_threshold;
|
||||
uint32_t desc_ring_size;
|
||||
struct lio_droq *droq;
|
||||
|
||||
lio_dev_dbg(lio_dev, "OQ[%d]\n", q_no);
|
||||
|
||||
droq = lio_dev->droq[q_no];
|
||||
droq->lio_dev = lio_dev;
|
||||
droq->q_no = q_no;
|
||||
droq->mpool = mpool;
|
||||
|
||||
c_refill_threshold = LIO_OQ_REFILL_THRESHOLD_CFG(lio_dev);
|
||||
|
||||
droq->max_count = num_descs;
|
||||
droq->buffer_size = desc_size;
|
||||
|
||||
desc_ring_size = droq->max_count * LIO_DROQ_DESC_SIZE;
|
||||
droq->desc_ring_mz = rte_eth_dma_zone_reserve(lio_dev->eth_dev,
|
||||
"droq", q_no,
|
||||
desc_ring_size,
|
||||
RTE_CACHE_LINE_SIZE,
|
||||
socket_id);
|
||||
|
||||
if (droq->desc_ring_mz == NULL) {
|
||||
lio_dev_err(lio_dev,
|
||||
"Output queue %d ring alloc failed\n", q_no);
|
||||
return -1;
|
||||
}
|
||||
|
||||
droq->desc_ring_dma = droq->desc_ring_mz->phys_addr;
|
||||
droq->desc_ring = (struct lio_droq_desc *)droq->desc_ring_mz->addr;
|
||||
|
||||
lio_dev_dbg(lio_dev, "droq[%d]: desc_ring: virt: 0x%p, dma: %lx\n",
|
||||
q_no, droq->desc_ring, (unsigned long)droq->desc_ring_dma);
|
||||
lio_dev_dbg(lio_dev, "droq[%d]: num_desc: %d\n", q_no,
|
||||
droq->max_count);
|
||||
|
||||
droq->info_list = lio_alloc_info_buffer(lio_dev, droq, socket_id);
|
||||
if (droq->info_list == NULL) {
|
||||
lio_dev_err(lio_dev, "Cannot allocate memory for info list.\n");
|
||||
goto init_droq_fail;
|
||||
}
|
||||
|
||||
droq->recv_buf_list = rte_zmalloc_socket("recv_buf_list",
|
||||
(droq->max_count *
|
||||
LIO_DROQ_RECVBUF_SIZE),
|
||||
RTE_CACHE_LINE_SIZE,
|
||||
socket_id);
|
||||
if (droq->recv_buf_list == NULL) {
|
||||
lio_dev_err(lio_dev,
|
||||
"Output queue recv buf list alloc failed\n");
|
||||
goto init_droq_fail;
|
||||
}
|
||||
|
||||
droq->refill_threshold = c_refill_threshold;
|
||||
|
||||
rte_spinlock_init(&droq->lock);
|
||||
|
||||
lio_dev->io_qmask.oq |= (1ULL << q_no);
|
||||
|
||||
return 0;
|
||||
|
||||
init_droq_fail:
|
||||
lio_delete_droq(lio_dev, q_no);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
lio_setup_droq(struct lio_device *lio_dev, int oq_no, int num_descs,
|
||||
int desc_size, struct rte_mempool *mpool, unsigned int socket_id)
|
||||
{
|
||||
struct lio_droq *droq;
|
||||
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
if (lio_dev->droq[oq_no]) {
|
||||
lio_dev_dbg(lio_dev, "Droq %d in use\n", oq_no);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate the DS for the new droq. */
|
||||
droq = rte_zmalloc_socket("ethdev RX queue", sizeof(*droq),
|
||||
RTE_CACHE_LINE_SIZE, socket_id);
|
||||
if (droq == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
lio_dev->droq[oq_no] = droq;
|
||||
|
||||
/* Initialize the Droq */
|
||||
if (lio_init_droq(lio_dev, oq_no, num_descs, desc_size, mpool,
|
||||
socket_id)) {
|
||||
lio_dev_err(lio_dev, "Droq[%u] Initialization Failed\n", oq_no);
|
||||
rte_free(lio_dev->droq[oq_no]);
|
||||
lio_dev->droq[oq_no] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lio_dev->num_oqs++;
|
||||
|
||||
lio_dev_dbg(lio_dev, "Total number of OQ: %d\n", lio_dev->num_oqs);
|
||||
|
||||
/* Send credit for octeon output queues. credits are always
|
||||
* sent after the output queue is enabled.
|
||||
*/
|
||||
rte_write32(lio_dev->droq[oq_no]->max_count,
|
||||
lio_dev->droq[oq_no]->pkts_credit_reg);
|
||||
rte_wmb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lio_init_instr_queue()
|
||||
* @param lio_dev - pointer to the lio device structure.
|
||||
|
@ -50,6 +50,58 @@
|
||||
#define lio_uptime \
|
||||
(size_t)(rte_get_timer_cycles() / rte_get_timer_hz())
|
||||
|
||||
/** Descriptor format.
|
||||
* The descriptor ring is made of descriptors which have 2 64-bit values:
|
||||
* -# Physical (bus) address of the data buffer.
|
||||
* -# Physical (bus) address of a lio_droq_info structure.
|
||||
* The device DMA's incoming packets and its information at the address
|
||||
* given by these descriptor fields.
|
||||
*/
|
||||
struct lio_droq_desc {
|
||||
/** The buffer pointer */
|
||||
uint64_t buffer_ptr;
|
||||
|
||||
/** The Info pointer */
|
||||
uint64_t info_ptr;
|
||||
};
|
||||
|
||||
#define LIO_DROQ_DESC_SIZE (sizeof(struct lio_droq_desc))
|
||||
|
||||
/** Information about packet DMA'ed by Octeon.
|
||||
* The format of the information available at Info Pointer after Octeon
|
||||
* has posted a packet. Not all descriptors have valid information. Only
|
||||
* the Info field of the first descriptor for a packet has information
|
||||
* about the packet.
|
||||
*/
|
||||
struct lio_droq_info {
|
||||
/** The Output Receive Header. */
|
||||
union octeon_rh rh;
|
||||
|
||||
/** The Length of the packet. */
|
||||
uint64_t length;
|
||||
};
|
||||
|
||||
#define LIO_DROQ_INFO_SIZE (sizeof(struct lio_droq_info))
|
||||
|
||||
/** Pointer to data buffer.
|
||||
* Driver keeps a pointer to the data buffer that it made available to
|
||||
* the Octeon device. Since the descriptor ring keeps physical (bus)
|
||||
* addresses, this field is required for the driver to keep track of
|
||||
* the virtual address pointers.
|
||||
*/
|
||||
struct lio_recv_buffer {
|
||||
/** Packet buffer, including meta data. */
|
||||
void *buffer;
|
||||
|
||||
/** Data in the packet buffer. */
|
||||
uint8_t *data;
|
||||
|
||||
};
|
||||
|
||||
#define LIO_DROQ_RECVBUF_SIZE (sizeof(struct lio_recv_buffer))
|
||||
|
||||
#define LIO_DROQ_SIZE (sizeof(struct lio_droq))
|
||||
|
||||
#define LIO_IQ_SEND_OK 0
|
||||
#define LIO_IQ_SEND_STOP 1
|
||||
#define LIO_IQ_SEND_FAILED -1
|
||||
@ -458,6 +510,10 @@ lio_incr_index(uint32_t index, uint32_t count, uint32_t max)
|
||||
return index;
|
||||
}
|
||||
|
||||
int lio_setup_droq(struct lio_device *lio_dev, int q_no, int num_descs,
|
||||
int desc_size, struct rte_mempool *mpool,
|
||||
unsigned int socket_id);
|
||||
|
||||
/** Setup instruction queue zero for the device
|
||||
* @param lio_dev which lio device to setup
|
||||
*
|
||||
|
@ -56,6 +56,150 @@ struct lio_version {
|
||||
uint16_t reserved;
|
||||
};
|
||||
|
||||
/** The Descriptor Ring Output Queue structure.
|
||||
* This structure has all the information required to implement a
|
||||
* DROQ.
|
||||
*/
|
||||
struct lio_droq {
|
||||
/** A spinlock to protect access to this ring. */
|
||||
rte_spinlock_t lock;
|
||||
|
||||
uint32_t q_no;
|
||||
|
||||
uint32_t pkt_count;
|
||||
|
||||
struct lio_device *lio_dev;
|
||||
|
||||
/** The 8B aligned descriptor ring starts at this address. */
|
||||
struct lio_droq_desc *desc_ring;
|
||||
|
||||
/** Index in the ring where the driver should read the next packet */
|
||||
uint32_t read_idx;
|
||||
|
||||
/** Index in the ring where Octeon will write the next packet */
|
||||
uint32_t write_idx;
|
||||
|
||||
/** Index in the ring where the driver will refill the descriptor's
|
||||
* buffer
|
||||
*/
|
||||
uint32_t refill_idx;
|
||||
|
||||
/** Packets pending to be processed */
|
||||
rte_atomic64_t pkts_pending;
|
||||
|
||||
/** Number of descriptors in this ring. */
|
||||
uint32_t max_count;
|
||||
|
||||
/** The number of descriptors pending refill. */
|
||||
uint32_t refill_count;
|
||||
|
||||
uint32_t refill_threshold;
|
||||
|
||||
/** The 8B aligned info ptrs begin from this address. */
|
||||
struct lio_droq_info *info_list;
|
||||
|
||||
/** The receive buffer list. This list has the virtual addresses of the
|
||||
* buffers.
|
||||
*/
|
||||
struct lio_recv_buffer *recv_buf_list;
|
||||
|
||||
/** The size of each buffer pointed by the buffer pointer. */
|
||||
uint32_t buffer_size;
|
||||
|
||||
/** Pointer to the mapped packet credit register.
|
||||
* Host writes number of info/buffer ptrs available to this register
|
||||
*/
|
||||
void *pkts_credit_reg;
|
||||
|
||||
/** Pointer to the mapped packet sent register.
|
||||
* Octeon writes the number of packets DMA'ed to host memory
|
||||
* in this register.
|
||||
*/
|
||||
void *pkts_sent_reg;
|
||||
|
||||
/** DMA mapped address of the DROQ descriptor ring. */
|
||||
size_t desc_ring_dma;
|
||||
|
||||
/** Info ptr list are allocated at this virtual address. */
|
||||
size_t info_base_addr;
|
||||
|
||||
/** DMA mapped address of the info list */
|
||||
size_t info_list_dma;
|
||||
|
||||
/** Allocated size of info list. */
|
||||
uint32_t info_alloc_size;
|
||||
|
||||
/** Memory zone **/
|
||||
const struct rte_memzone *desc_ring_mz;
|
||||
const struct rte_memzone *info_mz;
|
||||
struct rte_mempool *mpool;
|
||||
};
|
||||
|
||||
/** Receive Header */
|
||||
union octeon_rh {
|
||||
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
|
||||
uint64_t rh64;
|
||||
struct {
|
||||
uint64_t opcode : 4;
|
||||
uint64_t subcode : 8;
|
||||
uint64_t len : 3; /** additional 64-bit words */
|
||||
uint64_t reserved : 17;
|
||||
uint64_t ossp : 32; /** opcode/subcode specific parameters */
|
||||
} r;
|
||||
struct {
|
||||
uint64_t opcode : 4;
|
||||
uint64_t subcode : 8;
|
||||
uint64_t len : 3; /** additional 64-bit words */
|
||||
uint64_t extra : 28;
|
||||
uint64_t vlan : 12;
|
||||
uint64_t priority : 3;
|
||||
uint64_t csum_verified : 3; /** checksum verified. */
|
||||
uint64_t has_hwtstamp : 1; /** Has hardware timestamp.1 = yes.*/
|
||||
uint64_t encap_on : 1;
|
||||
uint64_t has_hash : 1; /** Has hash (rth or rss). 1 = yes. */
|
||||
} r_dh;
|
||||
struct {
|
||||
uint64_t opcode : 4;
|
||||
uint64_t subcode : 8;
|
||||
uint64_t len : 3; /** additional 64-bit words */
|
||||
uint64_t reserved : 8;
|
||||
uint64_t extra : 25;
|
||||
uint64_t gmxport : 16;
|
||||
} r_nic_info;
|
||||
#else
|
||||
uint64_t rh64;
|
||||
struct {
|
||||
uint64_t ossp : 32; /** opcode/subcode specific parameters */
|
||||
uint64_t reserved : 17;
|
||||
uint64_t len : 3; /** additional 64-bit words */
|
||||
uint64_t subcode : 8;
|
||||
uint64_t opcode : 4;
|
||||
} r;
|
||||
struct {
|
||||
uint64_t has_hash : 1; /** Has hash (rth or rss). 1 = yes. */
|
||||
uint64_t encap_on : 1;
|
||||
uint64_t has_hwtstamp : 1; /** 1 = has hwtstamp */
|
||||
uint64_t csum_verified : 3; /** checksum verified. */
|
||||
uint64_t priority : 3;
|
||||
uint64_t vlan : 12;
|
||||
uint64_t extra : 28;
|
||||
uint64_t len : 3; /** additional 64-bit words */
|
||||
uint64_t subcode : 8;
|
||||
uint64_t opcode : 4;
|
||||
} r_dh;
|
||||
struct {
|
||||
uint64_t gmxport : 16;
|
||||
uint64_t extra : 25;
|
||||
uint64_t reserved : 8;
|
||||
uint64_t len : 3; /** additional 64-bit words */
|
||||
uint64_t subcode : 8;
|
||||
uint64_t opcode : 4;
|
||||
} r_nic_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define OCTEON_RH_SIZE (sizeof(union octeon_rh))
|
||||
|
||||
/** The txpciq info passed to host from the firmware */
|
||||
union octeon_txpciq {
|
||||
uint64_t txpciq64;
|
||||
@ -380,6 +524,11 @@ struct lio_device {
|
||||
/** The singly-linked tail queues of instruction response */
|
||||
struct lio_response_list response_list;
|
||||
|
||||
uint32_t num_oqs;
|
||||
|
||||
/** The DROQ output queues */
|
||||
struct lio_droq *droq[LIO_MAX_POSSIBLE_OUTPUT_QUEUES];
|
||||
|
||||
struct lio_io_enable io_qmask;
|
||||
|
||||
struct lio_sriov_info sriov_info;
|
||||
|
Loading…
Reference in New Issue
Block a user