From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 40160A10D6 for ; Wed, 28 Aug 2019 13:24:18 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 32AB41C207; Wed, 28 Aug 2019 13:23:19 +0200 (CEST) Received: from inva020.nxp.com (inva020.nxp.com [92.121.34.13]) by dpdk.org (Postfix) with ESMTP id 3D9351C138 for ; Wed, 28 Aug 2019 13:23:06 +0200 (CEST) Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id ED8F21A010D; Wed, 28 Aug 2019 13:23:05 +0200 (CEST) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id D12711A0004; Wed, 28 Aug 2019 13:23:02 +0200 (CEST) Received: from GDB1.ap.freescale.net (GDB1.ap.freescale.net [10.232.132.179]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 7E994402E3; Wed, 28 Aug 2019 19:22:58 +0800 (SGT) From: Gagandeep Singh To: dev@dpdk.org, ferruh.yigit@intel.com Cc: thomas@monjalon.net, Gagandeep Singh , Akhil Goyal Date: Wed, 28 Aug 2019 16:38:43 +0530 Message-Id: <20190828110849.14759-8-g.singh@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828110849.14759-1-g.singh@nxp.com> References: <20190826130246.30485-1-g.singh@nxp.com> <20190828110849.14759-1-g.singh@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Subject: [dpdk-dev] [PATCH v2 07/13] net/ppfe: add device start stop operations X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds device start, stop and close operations. Signed-off-by: Gagandeep Singh Signed-off-by: Akhil Goyal Acked-by: Nipun Gupta --- drivers/net/ppfe/Makefile | 2 +- drivers/net/ppfe/pfe_eth.h | 1 + drivers/net/ppfe/pfe_hif.c | 136 +++++++++++++ drivers/net/ppfe/pfe_hif.h | 41 ++++ drivers/net/ppfe/pfe_hif_lib.c | 350 ++++++++++++++++++++++++++++++++- drivers/net/ppfe/pfe_hif_lib.h | 11 ++ drivers/net/ppfe/pfe_mod.h | 1 + drivers/net/ppfe/ppfe_ethdev.c | 187 ++++++++++++++++++ 8 files changed, 727 insertions(+), 2 deletions(-) diff --git a/drivers/net/ppfe/Makefile b/drivers/net/ppfe/Makefile index 4f7889e25..5c724ace0 100644 --- a/drivers/net/ppfe/Makefile +++ b/drivers/net/ppfe/Makefile @@ -30,7 +30,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PPFE_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 diff --git a/drivers/net/ppfe/pfe_eth.h b/drivers/net/ppfe/pfe_eth.h index a8ce3e314..79245c306 100644 --- a/drivers/net/ppfe/pfe_eth.h +++ b/drivers/net/ppfe/pfe_eth.h @@ -53,6 +53,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; diff --git a/drivers/net/ppfe/pfe_hif.c b/drivers/net/ppfe/pfe_hif.c index 908700bc1..3a044bc04 100644 --- a/drivers/net/ppfe/pfe_hif.c +++ b/drivers/net/ppfe/pfe_hif.c @@ -41,6 +41,142 @@ static void 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) { diff --git a/drivers/net/ppfe/pfe_hif.h b/drivers/net/ppfe/pfe_hif.h index fa3c08cc7..483db75da 100644 --- a/drivers/net/ppfe/pfe_hif.h +++ b/drivers/net/ppfe/pfe_hif.h @@ -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 ppfe_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); diff --git a/drivers/net/ppfe/pfe_hif_lib.c b/drivers/net/ppfe/pfe_hif_lib.c index c6c25458f..4c19108eb 100644 --- a/drivers/net/ppfe/pfe_hif_lib.c +++ b/drivers/net/ppfe/pfe_hif_lib.c @@ -5,10 +5,358 @@ #include "pfe_logs.h" #include "pfe_mod.h" -int pfe_hif_lib_init(__rte_unused struct pfe *pfe) +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 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; } diff --git a/drivers/net/ppfe/pfe_hif_lib.h b/drivers/net/ppfe/pfe_hif_lib.h index 2db7338c2..03e492559 100644 --- a/drivers/net/ppfe/pfe_hif_lib.h +++ b/drivers/net/ppfe/pfe_hif_lib.h @@ -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_ */ diff --git a/drivers/net/ppfe/pfe_mod.h b/drivers/net/ppfe/pfe_mod.h index f83c98b32..deb19f82b 100644 --- a/drivers/net/ppfe/pfe_mod.h +++ b/drivers/net/ppfe/pfe_mod.h @@ -22,6 +22,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; diff --git a/drivers/net/ppfe/ppfe_ethdev.c b/drivers/net/ppfe/ppfe_ethdev.c index 8764d5d15..bb4d40077 100644 --- a/drivers/net/ppfe/ppfe_ethdev.c +++ b/drivers/net/ppfe/ppfe_ethdev.c @@ -64,6 +64,131 @@ pfe_soc_version_get(void) fclose(svr_file); } +/* pfe_eth_start + */ +static int pfe_eth_start(struct pfe_eth_priv_s *priv) +{ + gpi_enable(priv->GPI_baseaddr); + gemac_enable(priv->EMAC_baseaddr); + + return 0; +} + +/* pfe_eth_flush_txQ + */ +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); + } + } +} + + +/* pfe_eth_flush_tx + */ +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); +} + +/* pfe_eth_event_handler + */ +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; +} + +/* pfe_eth_open + */ +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) { @@ -98,6 +223,7 @@ pfe_eth_close_cdev(struct pfe_eth_priv_s *priv) } } + /* pfe_eth_exit */ static void @@ -112,6 +238,65 @@ pfe_eth_exit(struct rte_eth_dev *dev, struct pfe *pfe) pfe->nb_devs--; } +/* pfe_eth_stop + */ +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); +} + +/* pfe_eth_close + * + */ +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 void +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 = PPFE_MAX_MACS; + dev_info->max_rx_pktlen = JUMBO_FRAME_SIZE; + 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; +} + +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, +}; + /* pfe_eth_init_one */ static int pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id) @@ -187,6 +372,8 @@ static int 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; -- 2.17.1