net/pfe: add device start/stop
authorGagandeep Singh <g.singh@nxp.com>
Thu, 10 Oct 2019 06:32:27 +0000 (12:02 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 23 Oct 2019 14:43:08 +0000 (16:43 +0200)
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>
drivers/net/pfe/Makefile
drivers/net/pfe/pfe_eth.h
drivers/net/pfe/pfe_ethdev.c
drivers/net/pfe/pfe_hif.c
drivers/net/pfe/pfe_hif.h
drivers/net/pfe/pfe_hif_lib.c
drivers/net/pfe/pfe_hif_lib.h
drivers/net/pfe/pfe_mod.h

index 5c317e1..91815fc 100644 (file)
@@ -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
index ab739f0..63e5aca 100644 (file)
@@ -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;
index ac1e608..08f3716 100644 (file)
@@ -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;
index 28530d1..39a6ec8 100644 (file)
@@ -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)
index fa3c08c..9c4e577 100644 (file)
 #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);
index 8f8121b..2012d89 100644 (file)
 #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;
 }
 
index 45fae7d..25c1a33 100644 (file)
@@ -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_ */
index 97fbb48..363feed 100644 (file)
@@ -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;