net/pfe: add device start/stop
This patch adds device start, stop and close operations. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com> Acked-by: Nipun Gupta <nipun.gupta@nxp.com>
This commit is contained in:
parent
5253fe372e
commit
fe38ad9ba7
@ -31,7 +31,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PFE_PMD) += pfe_hif.c
|
||||
LDLIBS += -lrte_bus_vdev
|
||||
LDLIBS += -lrte_bus_dpaa
|
||||
LDLIBS += -lrte_common_dpaax
|
||||
LDLIBS += -lrte_eal
|
||||
LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool
|
||||
LDLIBS += -lrte_ethdev -lrte_kvargs
|
||||
|
||||
include $(RTE_SDK)/mk/rte.lib.mk
|
||||
|
@ -55,6 +55,7 @@ struct ls1012a_pfe_platform_data {
|
||||
|
||||
struct pfe_eth_priv_s {
|
||||
struct pfe *pfe;
|
||||
struct hif_client_s client;
|
||||
int low_tmu_q;
|
||||
int high_tmu_q;
|
||||
struct rte_eth_dev *ndev;
|
||||
|
@ -71,6 +71,126 @@ pfe_soc_version_get(void)
|
||||
fclose(svr_file);
|
||||
}
|
||||
|
||||
static int pfe_eth_start(struct pfe_eth_priv_s *priv)
|
||||
{
|
||||
gpi_enable(priv->GPI_baseaddr);
|
||||
gemac_enable(priv->EMAC_baseaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int
|
||||
__rte_unused from_tx, __rte_unused int n_desc)
|
||||
{
|
||||
struct rte_mbuf *mbuf;
|
||||
unsigned int flags;
|
||||
|
||||
/* Clean HIF and client queue */
|
||||
while ((mbuf = hif_lib_tx_get_next_complete(&priv->client,
|
||||
tx_q_num, &flags,
|
||||
HIF_TX_DESC_NT))) {
|
||||
if (mbuf) {
|
||||
mbuf->next = NULL;
|
||||
mbuf->nb_segs = 1;
|
||||
rte_pktmbuf_free(mbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pfe_eth_flush_tx(struct pfe_eth_priv_s *priv)
|
||||
{
|
||||
unsigned int ii;
|
||||
|
||||
for (ii = 0; ii < emac_txq_cnt; ii++)
|
||||
pfe_eth_flush_txQ(priv, ii, 0, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
pfe_eth_event_handler(void *data, int event, __rte_unused int qno)
|
||||
{
|
||||
struct pfe_eth_priv_s *priv = data;
|
||||
|
||||
switch (event) {
|
||||
case EVENT_TXDONE_IND:
|
||||
pfe_eth_flush_tx(priv);
|
||||
hif_lib_event_handler_start(&priv->client, EVENT_TXDONE_IND, 0);
|
||||
break;
|
||||
case EVENT_HIGH_RX_WM:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pfe_eth_open(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct pfe_eth_priv_s *priv = dev->data->dev_private;
|
||||
struct hif_client_s *client;
|
||||
struct hif_shm *hif_shm;
|
||||
int rc;
|
||||
|
||||
/* Register client driver with HIF */
|
||||
client = &priv->client;
|
||||
|
||||
if (client->pfe) {
|
||||
hif_shm = client->pfe->hif.shm;
|
||||
/* TODO please remove the below code of if block, once we add
|
||||
* the proper cleanup in eth_close
|
||||
*/
|
||||
if (!test_bit(PFE_CL_GEM0 + priv->id,
|
||||
&hif_shm->g_client_status[0])) {
|
||||
/* Register client driver with HIF */
|
||||
memset(client, 0, sizeof(*client));
|
||||
client->id = PFE_CL_GEM0 + priv->id;
|
||||
client->tx_qn = emac_txq_cnt;
|
||||
client->rx_qn = EMAC_RXQ_CNT;
|
||||
client->priv = priv;
|
||||
client->pfe = priv->pfe;
|
||||
client->port_id = dev->data->port_id;
|
||||
client->event_handler = pfe_eth_event_handler;
|
||||
|
||||
client->tx_qsize = EMAC_TXQ_DEPTH;
|
||||
client->rx_qsize = EMAC_RXQ_DEPTH;
|
||||
|
||||
rc = hif_lib_client_register(client);
|
||||
if (rc) {
|
||||
PFE_PMD_ERR("hif_lib_client_register(%d)"
|
||||
" failed", client->id);
|
||||
goto err0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Register client driver with HIF */
|
||||
memset(client, 0, sizeof(*client));
|
||||
client->id = PFE_CL_GEM0 + priv->id;
|
||||
client->tx_qn = emac_txq_cnt;
|
||||
client->rx_qn = EMAC_RXQ_CNT;
|
||||
client->priv = priv;
|
||||
client->pfe = priv->pfe;
|
||||
client->port_id = dev->data->port_id;
|
||||
client->event_handler = pfe_eth_event_handler;
|
||||
|
||||
client->tx_qsize = EMAC_TXQ_DEPTH;
|
||||
client->rx_qsize = EMAC_RXQ_DEPTH;
|
||||
|
||||
rc = hif_lib_client_register(client);
|
||||
if (rc) {
|
||||
PFE_PMD_ERR("hif_lib_client_register(%d) failed",
|
||||
client->id);
|
||||
goto err0;
|
||||
}
|
||||
}
|
||||
rc = pfe_eth_start(priv);
|
||||
|
||||
err0:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
pfe_eth_open_cdev(struct pfe_eth_priv_s *priv)
|
||||
{
|
||||
@ -105,11 +225,21 @@ pfe_eth_close_cdev(struct pfe_eth_priv_s *priv)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pfe_eth_stop(struct rte_eth_dev *dev/*, int wake*/)
|
||||
{
|
||||
struct pfe_eth_priv_s *priv = dev->data->dev_private;
|
||||
|
||||
gemac_disable(priv->EMAC_baseaddr);
|
||||
gpi_disable(priv->GPI_baseaddr);
|
||||
}
|
||||
|
||||
static void
|
||||
pfe_eth_exit(struct rte_eth_dev *dev, struct pfe *pfe)
|
||||
{
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
pfe_eth_stop(dev);
|
||||
/* Close the device file for link status */
|
||||
pfe_eth_close_cdev(dev->data->dev_private);
|
||||
|
||||
@ -118,6 +248,58 @@ pfe_eth_exit(struct rte_eth_dev *dev, struct pfe *pfe)
|
||||
pfe->nb_devs--;
|
||||
}
|
||||
|
||||
static void
|
||||
pfe_eth_close(struct rte_eth_dev *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (!g_pfe)
|
||||
return;
|
||||
|
||||
pfe_eth_exit(dev, g_pfe);
|
||||
|
||||
if (g_pfe->nb_devs == 0) {
|
||||
pfe_hif_exit(g_pfe);
|
||||
pfe_hif_lib_exit(g_pfe);
|
||||
rte_free(g_pfe);
|
||||
g_pfe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pfe_eth_configure(struct rte_eth_dev *dev __rte_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pfe_eth_info(struct rte_eth_dev *dev,
|
||||
struct rte_eth_dev_info *dev_info)
|
||||
{
|
||||
struct pfe_eth_priv_s *internals = dev->data->dev_private;
|
||||
|
||||
dev_info->if_index = internals->id;
|
||||
dev_info->max_mac_addrs = PFE_MAX_MACS;
|
||||
dev_info->max_rx_queues = dev->data->nb_rx_queues;
|
||||
dev_info->max_tx_queues = dev->data->nb_tx_queues;
|
||||
dev_info->min_rx_bufsize = HIF_RX_PKT_MIN_SIZE;
|
||||
if (pfe_svr == SVR_LS1012A_REV1)
|
||||
dev_info->max_rx_pktlen = MAX_MTU_ON_REV1 + PFE_ETH_OVERHEAD;
|
||||
else
|
||||
dev_info->max_rx_pktlen = JUMBO_FRAME_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct eth_dev_ops ops = {
|
||||
.dev_start = pfe_eth_open,
|
||||
.dev_stop = pfe_eth_stop,
|
||||
.dev_close = pfe_eth_close,
|
||||
.dev_configure = pfe_eth_configure,
|
||||
.dev_infos_get = pfe_eth_info,
|
||||
};
|
||||
|
||||
static int
|
||||
pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
|
||||
{
|
||||
@ -178,6 +360,8 @@ pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
|
||||
}
|
||||
|
||||
eth_dev->data->mtu = 1500;
|
||||
eth_dev->dev_ops = &ops;
|
||||
pfe_eth_stop(eth_dev);
|
||||
pfe_gemac_init(priv);
|
||||
|
||||
eth_dev->data->nb_rx_queues = 1;
|
||||
|
@ -43,6 +43,145 @@ pfe_hif_free_descr(struct pfe_hif *hif)
|
||||
rte_free(hif->descr_baseaddr_v);
|
||||
}
|
||||
|
||||
/*
|
||||
* pfe_hif_client_register
|
||||
*
|
||||
* This function used to register a client driver with the HIF driver.
|
||||
*
|
||||
* Return value:
|
||||
* 0 - on Successful registration
|
||||
*/
|
||||
static int
|
||||
pfe_hif_client_register(struct pfe_hif *hif, u32 client_id,
|
||||
struct hif_client_shm *client_shm)
|
||||
{
|
||||
struct hif_client *client = &hif->client[client_id];
|
||||
u32 i, cnt;
|
||||
struct rx_queue_desc *rx_qbase;
|
||||
struct tx_queue_desc *tx_qbase;
|
||||
struct hif_rx_queue *rx_queue;
|
||||
struct hif_tx_queue *tx_queue;
|
||||
int err = 0;
|
||||
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
rte_spinlock_lock(&hif->tx_lock);
|
||||
|
||||
if (test_bit(client_id, &hif->shm->g_client_status[0])) {
|
||||
PFE_PMD_ERR("client %d already registered", client_id);
|
||||
err = -1;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
memset(client, 0, sizeof(struct hif_client));
|
||||
|
||||
/* Initialize client Rx queues baseaddr, size */
|
||||
|
||||
cnt = CLIENT_CTRL_RX_Q_CNT(client_shm->ctrl);
|
||||
/* Check if client is requesting for more queues than supported */
|
||||
if (cnt > HIF_CLIENT_QUEUES_MAX)
|
||||
cnt = HIF_CLIENT_QUEUES_MAX;
|
||||
|
||||
client->rx_qn = cnt;
|
||||
rx_qbase = (struct rx_queue_desc *)client_shm->rx_qbase;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
rx_queue = &client->rx_q[i];
|
||||
rx_queue->base = rx_qbase + i * client_shm->rx_qsize;
|
||||
rx_queue->size = client_shm->rx_qsize;
|
||||
rx_queue->write_idx = 0;
|
||||
}
|
||||
|
||||
/* Initialize client Tx queues baseaddr, size */
|
||||
cnt = CLIENT_CTRL_TX_Q_CNT(client_shm->ctrl);
|
||||
|
||||
/* Check if client is requesting for more queues than supported */
|
||||
if (cnt > HIF_CLIENT_QUEUES_MAX)
|
||||
cnt = HIF_CLIENT_QUEUES_MAX;
|
||||
|
||||
client->tx_qn = cnt;
|
||||
tx_qbase = (struct tx_queue_desc *)client_shm->tx_qbase;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
tx_queue = &client->tx_q[i];
|
||||
tx_queue->base = tx_qbase + i * client_shm->tx_qsize;
|
||||
tx_queue->size = client_shm->tx_qsize;
|
||||
tx_queue->ack_idx = 0;
|
||||
}
|
||||
|
||||
set_bit(client_id, &hif->shm->g_client_status[0]);
|
||||
|
||||
unlock:
|
||||
rte_spinlock_unlock(&hif->tx_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* pfe_hif_client_unregister
|
||||
*
|
||||
* This function used to unregister a client from the HIF driver.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
pfe_hif_client_unregister(struct pfe_hif *hif, u32 client_id)
|
||||
{
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
/*
|
||||
* Mark client as no longer available (which prevents further packet
|
||||
* receive for this client)
|
||||
*/
|
||||
rte_spinlock_lock(&hif->tx_lock);
|
||||
|
||||
if (!test_bit(client_id, &hif->shm->g_client_status[0])) {
|
||||
PFE_PMD_ERR("client %d not registered", client_id);
|
||||
|
||||
rte_spinlock_unlock(&hif->tx_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
clear_bit(client_id, &hif->shm->g_client_status[0]);
|
||||
|
||||
rte_spinlock_unlock(&hif->tx_lock);
|
||||
}
|
||||
|
||||
void
|
||||
hif_process_client_req(struct pfe_hif *hif, int req,
|
||||
int data1, __rte_unused int data2)
|
||||
{
|
||||
unsigned int client_id = data1;
|
||||
|
||||
if (client_id >= HIF_CLIENTS_MAX) {
|
||||
PFE_PMD_ERR("client id %d out of bounds", client_id);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (req) {
|
||||
case REQUEST_CL_REGISTER:
|
||||
/* Request for register a client */
|
||||
PFE_PMD_INFO("register client_id %d", client_id);
|
||||
pfe_hif_client_register(hif, client_id, (struct
|
||||
hif_client_shm *)&hif->shm->client[client_id]);
|
||||
break;
|
||||
|
||||
case REQUEST_CL_UNREGISTER:
|
||||
PFE_PMD_INFO("unregister client_id %d", client_id);
|
||||
|
||||
/* Request for unregister a client */
|
||||
pfe_hif_client_unregister(hif, client_id);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
PFE_PMD_ERR("unsupported request %d", req);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process client Tx queues
|
||||
* Currently we don't have checking for tx pending
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined(LS1012A_PFE_RESET_WA)
|
||||
static void
|
||||
pfe_hif_disable_rx_desc(struct pfe_hif *hif)
|
||||
|
@ -14,6 +14,12 @@
|
||||
#define HIF_RX_DESC_NT 64
|
||||
#define HIF_TX_DESC_NT 2048
|
||||
|
||||
#define HIF_FIRST_BUFFER BIT(0)
|
||||
#define HIF_LAST_BUFFER BIT(1)
|
||||
#define HIF_DONT_DMA_MAP BIT(2)
|
||||
#define HIF_DATA_VALID BIT(3)
|
||||
#define HIF_TSO BIT(4)
|
||||
|
||||
enum {
|
||||
PFE_CL_GEM0 = 0,
|
||||
PFE_CL_GEM1,
|
||||
@ -63,6 +69,39 @@ struct hif_desc_sw {
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
struct hif_hdr {
|
||||
u8 client_id;
|
||||
u8 q_num;
|
||||
u16 client_ctrl;
|
||||
u16 client_ctrl1;
|
||||
};
|
||||
|
||||
struct __hif_hdr {
|
||||
union {
|
||||
struct hif_hdr hdr;
|
||||
u32 word[2];
|
||||
};
|
||||
};
|
||||
|
||||
struct hif_ipsec_hdr {
|
||||
u16 sa_handle[2];
|
||||
} __packed;
|
||||
|
||||
struct pfe_parse {
|
||||
unsigned int packet_type;
|
||||
uint16_t hash;
|
||||
uint16_t parse_incomplete;
|
||||
unsigned long long ol_flags;
|
||||
};
|
||||
|
||||
/* HIF_CTRL_TX... defines */
|
||||
#define HIF_CTRL_TX_CHECKSUM BIT(2)
|
||||
|
||||
/* HIF_CTRL_RX... defines */
|
||||
#define HIF_CTRL_RX_OFFSET_OFST (24)
|
||||
#define HIF_CTRL_RX_CHECKSUMMED BIT(2)
|
||||
#define HIF_CTRL_RX_CONTINUED BIT(1)
|
||||
|
||||
struct pfe_hif {
|
||||
/* To store registered clients in hif layer */
|
||||
struct hif_client client[HIF_CLIENTS_MAX];
|
||||
@ -99,6 +138,8 @@ struct pfe_hif {
|
||||
struct rte_device *dev;
|
||||
};
|
||||
|
||||
void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int
|
||||
data2);
|
||||
int pfe_hif_init(struct pfe *pfe);
|
||||
void pfe_hif_exit(struct pfe *pfe);
|
||||
void pfe_hif_rx_idle(struct pfe_hif *hif);
|
||||
|
@ -5,11 +5,371 @@
|
||||
#include "pfe_logs.h"
|
||||
#include "pfe_mod.h"
|
||||
|
||||
unsigned int emac_txq_cnt;
|
||||
|
||||
/*
|
||||
* @pfe_hal_lib.c
|
||||
* Common functions used by HIF client drivers
|
||||
*/
|
||||
|
||||
/*HIF shared memory Global variable */
|
||||
struct hif_shm ghif_shm;
|
||||
|
||||
/*This function sends indication to HIF driver
|
||||
*
|
||||
* @param[in] hif hif context
|
||||
*/
|
||||
static void
|
||||
hif_lib_indicate_hif(struct pfe_hif *hif, int req, int data1, int
|
||||
data2)
|
||||
{
|
||||
hif_process_client_req(hif, req, data1, data2);
|
||||
}
|
||||
|
||||
void
|
||||
hif_lib_indicate_client(struct hif_client_s *client, int event_type,
|
||||
int qno)
|
||||
{
|
||||
if (!client || event_type >= HIF_EVENT_MAX ||
|
||||
qno >= HIF_CLIENT_QUEUES_MAX)
|
||||
return;
|
||||
|
||||
if (!test_and_set_bit(qno, &client->queue_mask[event_type]))
|
||||
client->event_handler(client->priv, event_type, qno);
|
||||
}
|
||||
|
||||
/*This function releases Rx queue descriptors memory and pre-filled buffers
|
||||
*
|
||||
* @param[in] client hif_client context
|
||||
*/
|
||||
static void
|
||||
hif_lib_client_release_rx_buffers(struct hif_client_s *client)
|
||||
{
|
||||
struct rte_mempool *pool;
|
||||
struct rte_pktmbuf_pool_private *mb_priv;
|
||||
struct rx_queue_desc *desc;
|
||||
unsigned int qno, ii;
|
||||
void *buf;
|
||||
|
||||
pool = client->pfe->hif.shm->pool;
|
||||
mb_priv = rte_mempool_get_priv(pool);
|
||||
for (qno = 0; qno < client->rx_qn; qno++) {
|
||||
desc = client->rx_q[qno].base;
|
||||
|
||||
for (ii = 0; ii < client->rx_q[qno].size; ii++) {
|
||||
buf = (void *)desc->data;
|
||||
if (buf) {
|
||||
/* Data pointor to mbuf pointor calculation:
|
||||
* "Data - User private data - headroom - mbufsize"
|
||||
* Actual data pointor given to HIF BDs was
|
||||
* "mbuf->data_offset - PFE_PKT_HEADER_SZ"
|
||||
*/
|
||||
buf = buf + PFE_PKT_HEADER_SZ
|
||||
- sizeof(struct rte_mbuf)
|
||||
- RTE_PKTMBUF_HEADROOM
|
||||
- mb_priv->mbuf_priv_size;
|
||||
rte_pktmbuf_free((struct rte_mbuf *)buf);
|
||||
desc->ctrl = 0;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
rte_free(client->rx_qbase);
|
||||
}
|
||||
|
||||
/*This function allocates memory for the rxq descriptors and pre-fill rx queues
|
||||
* with buffers.
|
||||
* @param[in] client client context
|
||||
* @param[in] q_size size of the rxQ, all queues are of same size
|
||||
*/
|
||||
static int
|
||||
hif_lib_client_init_rx_buffers(struct hif_client_s *client,
|
||||
int q_size)
|
||||
{
|
||||
struct rx_queue_desc *desc;
|
||||
struct hif_client_rx_queue *queue;
|
||||
unsigned int ii, qno;
|
||||
|
||||
/*Allocate memory for the client queues */
|
||||
client->rx_qbase = rte_malloc(NULL, client->rx_qn * q_size *
|
||||
sizeof(struct rx_queue_desc), RTE_CACHE_LINE_SIZE);
|
||||
if (!client->rx_qbase)
|
||||
goto err;
|
||||
|
||||
for (qno = 0; qno < client->rx_qn; qno++) {
|
||||
queue = &client->rx_q[qno];
|
||||
|
||||
queue->base = client->rx_qbase + qno * q_size * sizeof(struct
|
||||
rx_queue_desc);
|
||||
queue->size = q_size;
|
||||
queue->read_idx = 0;
|
||||
queue->write_idx = 0;
|
||||
queue->queue_id = 0;
|
||||
queue->port_id = client->port_id;
|
||||
queue->priv = client->priv;
|
||||
PFE_PMD_DEBUG("rx queue: %d, base: %p, size: %d\n", qno,
|
||||
queue->base, queue->size);
|
||||
}
|
||||
|
||||
for (qno = 0; qno < client->rx_qn; qno++) {
|
||||
queue = &client->rx_q[qno];
|
||||
desc = queue->base;
|
||||
|
||||
for (ii = 0; ii < queue->size; ii++) {
|
||||
desc->ctrl = CL_DESC_OWN;
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hif_lib_client_cleanup_tx_queue(struct hif_client_tx_queue *queue)
|
||||
{
|
||||
/*
|
||||
* Check if there are any pending packets. Client must flush the tx
|
||||
* queues before unregistering, by calling by calling
|
||||
* hif_lib_tx_get_next_complete()
|
||||
*
|
||||
* Hif no longer calls since we are no longer registered
|
||||
*/
|
||||
if (queue->tx_pending)
|
||||
PFE_PMD_ERR("pending transmit packet");
|
||||
}
|
||||
|
||||
static void
|
||||
hif_lib_client_release_tx_buffers(struct hif_client_s *client)
|
||||
{
|
||||
unsigned int qno;
|
||||
|
||||
for (qno = 0; qno < client->tx_qn; qno++)
|
||||
hif_lib_client_cleanup_tx_queue(&client->tx_q[qno]);
|
||||
|
||||
rte_free(client->tx_qbase);
|
||||
}
|
||||
|
||||
static int
|
||||
hif_lib_client_init_tx_buffers(struct hif_client_s *client, int
|
||||
q_size)
|
||||
{
|
||||
struct hif_client_tx_queue *queue;
|
||||
unsigned int qno;
|
||||
|
||||
client->tx_qbase = rte_malloc(NULL, client->tx_qn * q_size *
|
||||
sizeof(struct tx_queue_desc), RTE_CACHE_LINE_SIZE);
|
||||
if (!client->tx_qbase)
|
||||
return 1;
|
||||
|
||||
for (qno = 0; qno < client->tx_qn; qno++) {
|
||||
queue = &client->tx_q[qno];
|
||||
|
||||
queue->base = client->tx_qbase + qno * q_size * sizeof(struct
|
||||
tx_queue_desc);
|
||||
queue->size = q_size;
|
||||
queue->read_idx = 0;
|
||||
queue->write_idx = 0;
|
||||
queue->tx_pending = 0;
|
||||
queue->nocpy_flag = 0;
|
||||
queue->prev_tmu_tx_pkts = 0;
|
||||
queue->done_tmu_tx_pkts = 0;
|
||||
queue->priv = client->priv;
|
||||
queue->queue_id = 0;
|
||||
queue->port_id = client->port_id;
|
||||
|
||||
PFE_PMD_DEBUG("tx queue: %d, base: %p, size: %d", qno,
|
||||
queue->base, queue->size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hif_lib_event_dummy(__rte_unused void *priv,
|
||||
__rte_unused int event_type, __rte_unused int qno)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pfe_hif_lib_init(__rte_unused struct pfe *pfe)
|
||||
hif_lib_client_register(struct hif_client_s *client)
|
||||
{
|
||||
struct hif_shm *hif_shm;
|
||||
struct hif_client_shm *client_shm;
|
||||
int err, i;
|
||||
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
/*Allocate memory before spin_lock*/
|
||||
if (hif_lib_client_init_rx_buffers(client, client->rx_qsize)) {
|
||||
err = -ENOMEM;
|
||||
goto err_rx;
|
||||
}
|
||||
|
||||
if (hif_lib_client_init_tx_buffers(client, client->tx_qsize)) {
|
||||
err = -ENOMEM;
|
||||
goto err_tx;
|
||||
}
|
||||
|
||||
rte_spinlock_lock(&client->pfe->hif.lock);
|
||||
if (!(client->pfe) || client->id >= HIF_CLIENTS_MAX ||
|
||||
client->pfe->hif_client[client->id]) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
hif_shm = client->pfe->hif.shm;
|
||||
|
||||
if (!client->event_handler)
|
||||
client->event_handler = hif_lib_event_dummy;
|
||||
|
||||
/*Initialize client specific shared memory */
|
||||
client_shm = (struct hif_client_shm *)&hif_shm->client[client->id];
|
||||
client_shm->rx_qbase = (unsigned long)client->rx_qbase;
|
||||
client_shm->rx_qsize = client->rx_qsize;
|
||||
client_shm->tx_qbase = (unsigned long)client->tx_qbase;
|
||||
client_shm->tx_qsize = client->tx_qsize;
|
||||
client_shm->ctrl = (client->tx_qn << CLIENT_CTRL_TX_Q_CNT_OFST) |
|
||||
(client->rx_qn << CLIENT_CTRL_RX_Q_CNT_OFST);
|
||||
|
||||
for (i = 0; i < HIF_EVENT_MAX; i++) {
|
||||
client->queue_mask[i] = 0; /*
|
||||
* By default all events are
|
||||
* unmasked
|
||||
*/
|
||||
}
|
||||
|
||||
/*Indicate to HIF driver*/
|
||||
hif_lib_indicate_hif(&client->pfe->hif, REQUEST_CL_REGISTER,
|
||||
client->id, 0);
|
||||
|
||||
PFE_PMD_DEBUG("client: %p, client_id: %d, tx_qsize: %d, rx_qsize: %d",
|
||||
client, client->id, client->tx_qsize, client->rx_qsize);
|
||||
|
||||
client->cpu_id = -1;
|
||||
|
||||
client->pfe->hif_client[client->id] = client;
|
||||
rte_spinlock_unlock(&client->pfe->hif.lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
rte_spinlock_unlock(&client->pfe->hif.lock);
|
||||
hif_lib_client_release_tx_buffers(client);
|
||||
|
||||
err_tx:
|
||||
hif_lib_client_release_rx_buffers(client);
|
||||
|
||||
err_rx:
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
hif_lib_client_unregister(struct hif_client_s *client)
|
||||
{
|
||||
struct pfe *pfe = client->pfe;
|
||||
u32 client_id = client->id;
|
||||
|
||||
PFE_PMD_INFO("client: %p, client_id: %d, txQ_depth: %d, rxQ_depth: %d",
|
||||
client, client->id, client->tx_qsize, client->rx_qsize);
|
||||
|
||||
rte_spinlock_lock(&pfe->hif.lock);
|
||||
hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_UNREGISTER, client->id, 0);
|
||||
|
||||
hif_lib_client_release_tx_buffers(client);
|
||||
hif_lib_client_release_rx_buffers(client);
|
||||
pfe->hif_client[client_id] = NULL;
|
||||
rte_spinlock_unlock(&pfe->hif.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hif_lib_event_handler_start(struct hif_client_s *client, int event,
|
||||
int qno)
|
||||
{
|
||||
struct hif_client_rx_queue *queue = &client->rx_q[qno];
|
||||
struct rx_queue_desc *desc = queue->base + queue->read_idx;
|
||||
|
||||
if (event >= HIF_EVENT_MAX || qno >= HIF_CLIENT_QUEUES_MAX) {
|
||||
PFE_PMD_WARN("Unsupported event : %d queue number : %d",
|
||||
event, qno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
test_and_clear_bit(qno, &client->queue_mask[event]);
|
||||
|
||||
switch (event) {
|
||||
case EVENT_RX_PKT_IND:
|
||||
if (!(desc->ctrl & CL_DESC_OWN))
|
||||
hif_lib_indicate_client(client,
|
||||
EVENT_RX_PKT_IND, qno);
|
||||
break;
|
||||
|
||||
case EVENT_HIGH_RX_WM:
|
||||
case EVENT_TXDONE_IND:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno,
|
||||
unsigned int *flags, __rte_unused int count)
|
||||
{
|
||||
struct hif_client_tx_queue *queue = &client->tx_q[qno];
|
||||
struct tx_queue_desc *desc = queue->base + queue->read_idx;
|
||||
|
||||
PFE_DP_LOG(DEBUG, "qno : %d rd_indx: %d pending:%d",
|
||||
qno, queue->read_idx, queue->tx_pending);
|
||||
|
||||
if (!queue->tx_pending)
|
||||
return NULL;
|
||||
|
||||
if (queue->nocpy_flag && !queue->done_tmu_tx_pkts) {
|
||||
u32 tmu_tx_pkts = 0;
|
||||
|
||||
if (queue->prev_tmu_tx_pkts > tmu_tx_pkts)
|
||||
queue->done_tmu_tx_pkts = UINT_MAX -
|
||||
queue->prev_tmu_tx_pkts + tmu_tx_pkts;
|
||||
else
|
||||
queue->done_tmu_tx_pkts = tmu_tx_pkts -
|
||||
queue->prev_tmu_tx_pkts;
|
||||
|
||||
queue->prev_tmu_tx_pkts = tmu_tx_pkts;
|
||||
|
||||
if (!queue->done_tmu_tx_pkts)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (desc->ctrl & CL_DESC_OWN)
|
||||
return NULL;
|
||||
|
||||
queue->read_idx = (queue->read_idx + 1) & (queue->size - 1);
|
||||
queue->tx_pending--;
|
||||
|
||||
*flags = CL_DESC_GET_FLAGS(desc->ctrl);
|
||||
|
||||
if (queue->done_tmu_tx_pkts && (*flags & HIF_LAST_BUFFER))
|
||||
queue->done_tmu_tx_pkts--;
|
||||
|
||||
return desc->data;
|
||||
}
|
||||
|
||||
int
|
||||
pfe_hif_lib_init(struct pfe *pfe)
|
||||
{
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
emac_txq_cnt = EMAC_TXQ_CNT;
|
||||
pfe->hif.shm = &ghif_shm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#ifndef _PFE_HIF_LIB_H_
|
||||
#define _PFE_HIF_LIB_H_
|
||||
|
||||
#include "pfe_hif.h"
|
||||
|
||||
#define HIF_CL_REQ_TIMEOUT 10
|
||||
#define GFP_DMA_PFE 0
|
||||
|
||||
@ -158,5 +160,14 @@ extern unsigned int emac_txq_cnt;
|
||||
|
||||
int pfe_hif_lib_init(struct pfe *pfe);
|
||||
void pfe_hif_lib_exit(struct pfe *pfe);
|
||||
int hif_lib_client_register(struct hif_client_s *client);
|
||||
int hif_lib_client_unregister(struct hif_client_s *client);
|
||||
void hif_lib_indicate_client(struct hif_client_s *client, int event, int data);
|
||||
int hif_lib_event_handler_start(struct hif_client_s *client, int event, int
|
||||
data);
|
||||
void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno,
|
||||
unsigned int *flags, int count);
|
||||
int pfe_hif_shm_init(struct hif_shm *hif_shm, struct rte_mempool *mb_pool);
|
||||
void pfe_hif_shm_clean(struct hif_shm *hif_shm);
|
||||
|
||||
#endif /* _PFE_HIF_LIB_H_ */
|
||||
|
@ -48,6 +48,7 @@ struct pfe {
|
||||
struct ls1012a_pfe_platform_data platform_data;
|
||||
struct pfe_hif hif;
|
||||
struct pfe_eth eth;
|
||||
struct hif_client_s *hif_client[HIF_CLIENTS_MAX];
|
||||
int mdio_muxval[PHYID_MAX_VAL];
|
||||
uint8_t nb_devs;
|
||||
uint8_t max_intf;
|
||||
|
Loading…
Reference in New Issue
Block a user