get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/60320/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 60320,
    "url": "http://patches.dpdk.org/api/patches/60320/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20191001110209.6047-10-g.singh@nxp.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20191001110209.6047-10-g.singh@nxp.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20191001110209.6047-10-g.singh@nxp.com",
    "date": "2019-10-01T11:02:04",
    "name": "[v3,09/14] net/ppfe: add burst enqueue and dequeue operations",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "0b4670441e1f9555e7834f83210ce2895431b266",
    "submitter": {
        "id": 1068,
        "url": "http://patches.dpdk.org/api/people/1068/?format=api",
        "name": "Gagandeep Singh",
        "email": "g.singh@nxp.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20191001110209.6047-10-g.singh@nxp.com/mbox/",
    "series": [
        {
            "id": 6647,
            "url": "http://patches.dpdk.org/api/series/6647/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=6647",
            "date": "2019-10-01T11:01:55",
            "name": "introduces ppfe network PMD",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/6647/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/60320/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/60320/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id A45231BEC1;\n\tTue,  1 Oct 2019 13:17:45 +0200 (CEST)",
            "from inva020.nxp.com (inva020.nxp.com [92.121.34.13])\n\tby dpdk.org (Postfix) with ESMTP id EE86E1B94D\n\tfor <dev@dpdk.org>; Tue,  1 Oct 2019 13:17:35 +0200 (CEST)",
            "from inva020.nxp.com (localhost [127.0.0.1])\n\tby inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id B4BD71A01DE;\n\tTue,  1 Oct 2019 13:17:35 +0200 (CEST)",
            "from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com\n\t[165.114.16.14])\n\tby inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 2719D1A0543;\n\tTue,  1 Oct 2019 13:17:33 +0200 (CEST)",
            "from GDB1.ap.freescale.net (GDB1.ap.freescale.net [10.232.132.179])\n\tby invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 9B7E4402C1;\n\tTue,  1 Oct 2019 19:17:29 +0800 (SGT)"
        ],
        "From": "Gagandeep Singh <g.singh@nxp.com>",
        "To": "dev@dpdk.org,\n\tferruh.yigit@intel.com",
        "Cc": "thomas@monjalon.net,\n\tGagandeep Singh <g.singh@nxp.com>",
        "Date": "Tue,  1 Oct 2019 16:32:04 +0530",
        "Message-Id": "<20191001110209.6047-10-g.singh@nxp.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20191001110209.6047-1-g.singh@nxp.com>",
        "References": "<20190826130246.30485-1-g.singh@nxp.com>\n\t<20191001110209.6047-1-g.singh@nxp.com>",
        "X-Virus-Scanned": "ClamAV using ClamSMTP",
        "Subject": "[dpdk-dev] [PATCH v3 09/14] net/ppfe: add burst enqueue and dequeue\n\toperations",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch add burst enqueue and dequeue operations\nto the ppfe PMD.\n\nSigned-off-by: Gagandeep Singh <g.singh@nxp.com>\nAcked-by: Nipun Gupta <nipun.gupta@nxp.com>\nAcked-by: Akhil Goyal <akhil.goyal@nxp.com>\n---\n drivers/net/ppfe/pfe_hif.c     | 360 ++++++++++++++++++++++++++++++++-\n drivers/net/ppfe/pfe_hif.h     |   8 +\n drivers/net/ppfe/pfe_hif_lib.c | 146 +++++++++++++\n drivers/net/ppfe/pfe_hif_lib.h |   8 +\n drivers/net/ppfe/pfe_mod.h     |   2 +\n drivers/net/ppfe/ppfe_ethdev.c | 140 +++++++++++++\n 6 files changed, 663 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/net/ppfe/pfe_hif.c b/drivers/net/ppfe/pfe_hif.c\nindex 024ca3d77..d7d22329c 100644\n--- a/drivers/net/ppfe/pfe_hif.c\n+++ b/drivers/net/ppfe/pfe_hif.c\n@@ -43,6 +43,38 @@ pfe_hif_free_descr(struct pfe_hif *hif)\n \trte_free(hif->descr_baseaddr_v);\n }\n \n+/* pfe_hif_release_buffers */\n+static void\n+pfe_hif_release_buffers(struct pfe_hif *hif)\n+{\n+\tstruct hif_desc\t*desc;\n+\tuint32_t i = 0;\n+\tstruct rte_mbuf *mbuf;\n+\tstruct rte_pktmbuf_pool_private *mb_priv;\n+\n+\thif->rx_base = hif->descr_baseaddr_v;\n+\n+\t/*Free Rx buffers */\n+\tdesc = hif->rx_base;\n+\tmb_priv = rte_mempool_get_priv(hif->shm->pool);\n+\tfor (i = 0; i < hif->rx_ring_size; i++) {\n+\t\tif (readl(&desc->data)) {\n+\t\t\tif (i < hif->shm->rx_buf_pool_cnt &&\n+\t\t\t    !hif->shm->rx_buf_pool[i]) {\n+\t\t\t\tmbuf = hif->rx_buf_vaddr[i] + PFE_PKT_HEADER_SZ\n+\t\t\t\t\t- sizeof(struct rte_mbuf)\n+\t\t\t\t\t- RTE_PKTMBUF_HEADROOM\n+\t\t\t\t\t- mb_priv->mbuf_priv_size;\n+\t\t\t\thif->shm->rx_buf_pool[i] = mbuf;\n+\t\t\t}\n+\t\t}\n+\t\twritel(0, &desc->data);\n+\t\twritel(0, &desc->status);\n+\t\twritel(0, &desc->ctrl);\n+\t\tdesc++;\n+\t}\n+}\n+\n /*\n  * pfe_hif_init_buffers\n  * This function initializes the HIF Rx/Tx ring descriptors and\n@@ -259,9 +291,332 @@ pfe_hif_client_unregister(struct pfe_hif *hif, u32 client_id)\n \trte_spinlock_unlock(&hif->tx_lock);\n }\n \n+/*\n+ * client_put_rxpacket-\n+ */\n+static struct rte_mbuf *\n+client_put_rxpacket(struct hif_rx_queue *queue,\n+\t\tvoid *pkt, u32 len,\n+\t\tu32 flags, u32 client_ctrl,\n+\t\tstruct rte_mempool *pool,\n+\t\tu32 *rem_len)\n+{\n+\tstruct rx_queue_desc *desc = queue->base + queue->write_idx;\n+\tstruct rte_mbuf *mbuf = NULL;\n+\n+\n+\tif (readl(&desc->ctrl) & CL_DESC_OWN) {\n+\t\tmbuf = rte_cpu_to_le_64(rte_pktmbuf_alloc(pool));\n+\t\tif (unlikely(!mbuf)) {\n+\t\t\tPFE_PMD_WARN(\"Buffer allocation failure\\n\");\n+\t\t\treturn NULL;\n+\t\t}\n+\n+\t\tdesc->data = pkt;\n+\t\tdesc->client_ctrl = client_ctrl;\n+\t\t/*\n+\t\t * Ensure everything else is written to DDR before\n+\t\t * writing bd->ctrl\n+\t\t */\n+\t\trte_wmb();\n+\t\twritel(CL_DESC_BUF_LEN(len) | flags, &desc->ctrl);\n+\t\tqueue->write_idx = (queue->write_idx + 1)\n+\t\t\t\t    & (queue->size - 1);\n+\n+\t\t*rem_len = mbuf->buf_len;\n+\t}\n+\n+\treturn mbuf;\n+}\n+\n+/*\n+ * pfe_hif_rx_process-\n+ * This function does pfe hif rx queue processing.\n+ * Dequeue packet from Rx queue and send it to corresponding client queue\n+ */\n+int\n+pfe_hif_rx_process(struct pfe *pfe, int budget)\n+{\n+\tstruct hif_desc\t*desc;\n+\tstruct hif_hdr *pkt_hdr;\n+\tstruct __hif_hdr hif_hdr;\n+\tvoid *free_buf;\n+\tint rtc, len, rx_processed = 0;\n+\tstruct __hif_desc local_desc;\n+\tint flags = 0, wait_for_last = 0, retry = 0;\n+\tunsigned int buf_size = 0;\n+\tstruct rte_mbuf *mbuf = NULL;\n+\tstruct pfe_hif *hif = &pfe->hif;\n+\n+\trte_spinlock_lock(&hif->lock);\n+\n+\trtc = hif->rxtoclean_index;\n+\n+\twhile (rx_processed < budget) {\n+\t\tdesc = hif->rx_base + rtc;\n+\n+\t\t__memcpy12(&local_desc, desc);\n+\n+\t\t/* ACK pending Rx interrupt */\n+\t\tif (local_desc.ctrl & BD_CTRL_DESC_EN) {\n+\t\t\tif (unlikely(wait_for_last))\n+\t\t\t\tcontinue;\n+\t\t\telse\n+\t\t\t\tbreak;\n+\t\t}\n+\n+\t\tlen = BD_BUF_LEN(local_desc.ctrl);\n+\t\tpkt_hdr = (struct hif_hdr *)hif->rx_buf_vaddr[rtc];\n+\n+\t\t/* Track last HIF header received */\n+\t\tif (!hif->started) {\n+\t\t\thif->started = 1;\n+\n+\t\t\t__memcpy8(&hif_hdr, pkt_hdr);\n+\n+\t\t\thif->qno = hif_hdr.hdr.q_num;\n+\t\t\thif->client_id = hif_hdr.hdr.client_id;\n+\t\t\thif->client_ctrl = (hif_hdr.hdr.client_ctrl1 << 16) |\n+\t\t\t\t\t\thif_hdr.hdr.client_ctrl;\n+\t\t\tflags = CL_DESC_FIRST;\n+\n+\t\t} else {\n+\t\t\tflags = 0;\n+\t\t}\n+\n+\t\tif (local_desc.ctrl & BD_CTRL_LIFM) {\n+\t\t\tflags |= CL_DESC_LAST;\n+\t\t\twait_for_last = 0;\n+\t\t} else {\n+\t\t\twait_for_last = 1;\n+\t\t}\n+\n+\t\t/* Check for valid client id and still registered */\n+\t\tif (hif->client_id >= HIF_CLIENTS_MAX ||\n+\t\t    !(test_bit(hif->client_id,\n+\t\t\t&hif->shm->g_client_status[0]))) {\n+\t\t\tPFE_PMD_INFO(\"packet with invalid client id %d qnum %d\",\n+\t\t\t\thif->client_id, hif->qno);\n+\n+\t\t\tfree_buf = hif->rx_buf_addr[rtc];\n+\n+\t\t\tgoto pkt_drop;\n+\t\t}\n+\n+\t\t/* Check to valid queue number */\n+\t\tif (hif->client[hif->client_id].rx_qn <= hif->qno) {\n+\t\t\tPFE_DP_LOG(DEBUG, \"packet with invalid queue: %d\",\n+\t\t\t\t\thif->qno);\n+\t\t\thif->qno = 0;\n+\t\t}\n+\n+retry:\n+\t\tmbuf =\n+\t\tclient_put_rxpacket(&hif->client[hif->client_id].rx_q[hif->qno],\n+\t\t\t\t    (void *)pkt_hdr, len, flags,\n+\t\t\t\t    hif->client_ctrl, hif->shm->pool,\n+\t\t\t\t    &buf_size);\n+\n+\t\tif (unlikely(!mbuf)) {\n+\t\t\tif (!retry) {\n+\t\t\t\tpfe_tx_do_cleanup(pfe);\n+\t\t\t\tretry = 1;\n+\t\t\t\tgoto retry;\n+\t\t\t}\n+\t\t\trx_processed = budget;\n+\n+\t\t\tif (flags & CL_DESC_FIRST)\n+\t\t\t\thif->started = 0;\n+\n+\t\t\tPFE_DP_LOG(DEBUG, \"No buffers\");\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tretry = 0;\n+\n+\t\tfree_buf = (void *)(size_t)rte_pktmbuf_iova(mbuf);\n+\t\tfree_buf = free_buf - PFE_PKT_HEADER_SZ;\n+\n+\t\t/*Fill free buffer in the descriptor */\n+\t\thif->rx_buf_addr[rtc] = free_buf;\n+\t\thif->rx_buf_vaddr[rtc] = (void *)((size_t)mbuf->buf_addr +\n+\t\t\t\tmbuf->data_off - PFE_PKT_HEADER_SZ);\n+\t\thif->rx_buf_len[rtc] = buf_size - RTE_PKTMBUF_HEADROOM;\n+\n+pkt_drop:\n+\t\twritel(DDR_PHYS_TO_PFE(free_buf), &desc->data);\n+\t\t/*\n+\t\t * Ensure everything else is written to DDR before\n+\t\t * writing bd->ctrl\n+\t\t */\n+\t\trte_wmb();\n+\t\twritel((BD_CTRL_PKT_INT_EN | BD_CTRL_LIFM | BD_CTRL_DIR |\n+\t\t\tBD_CTRL_DESC_EN | BD_BUF_LEN(hif->rx_buf_len[rtc])),\n+\t\t\t&desc->ctrl);\n+\n+\t\trtc = (rtc + 1) & (hif->rx_ring_size - 1);\n+\n+\t\tif (local_desc.ctrl & BD_CTRL_LIFM) {\n+\t\t\tif (!(hif->client_ctrl & HIF_CTRL_RX_CONTINUED))\n+\t\t\t\trx_processed++;\n+\n+\t\t\thif->started = 0;\n+\t\t}\n+\t}\n+\n+\n+\thif->rxtoclean_index = rtc;\n+\trte_spinlock_unlock(&hif->lock);\n+\n+\t/* we made some progress, re-start rx dma in case it stopped */\n+\thif_rx_dma_start();\n+\n+\treturn rx_processed;\n+}\n+\n+/*\n+ * client_ack_txpacket-\n+ * This function ack the Tx packet in the give client Tx queue by resetting\n+ * ownership bit in the descriptor.\n+ */\n+static int\n+client_ack_txpacket(struct pfe_hif *hif, unsigned int client_id,\n+\t\t    unsigned int q_no)\n+{\n+\tstruct hif_tx_queue *queue = &hif->client[client_id].tx_q[q_no];\n+\tstruct tx_queue_desc *desc = queue->base + queue->ack_idx;\n+\n+\tif (readl(&desc->ctrl) & CL_DESC_OWN) {\n+\t\twritel((readl(&desc->ctrl) & ~CL_DESC_OWN), &desc->ctrl);\n+\t\tqueue->ack_idx = (queue->ack_idx + 1) & (queue->size - 1);\n+\n+\t\treturn 0;\n+\n+\t} else {\n+\t\t/*This should not happen */\n+\t\tPFE_PMD_ERR(\"%d %d %d %d %d %p %d\",\n+\t\t       hif->txtosend, hif->txtoclean, hif->txavail,\n+\t\t\tclient_id, q_no, queue, queue->ack_idx);\n+\t\treturn 1;\n+\t}\n+}\n+\n+static void\n+__hif_tx_done_process(struct pfe *pfe, int count)\n+{\n+\tstruct hif_desc *desc;\n+\tstruct hif_desc_sw *desc_sw;\n+\tunsigned int ttc, tx_avl;\n+\tint pkts_done[HIF_CLIENTS_MAX] = {0, 0};\n+\tstruct pfe_hif *hif = &pfe->hif;\n+\n+\tttc = hif->txtoclean;\n+\ttx_avl = hif->txavail;\n+\n+\twhile ((tx_avl < hif->tx_ring_size) && count--) {\n+\t\tdesc = hif->tx_base + ttc;\n+\n+\t\tif (readl(&desc->ctrl) & BD_CTRL_DESC_EN)\n+\t\t\tbreak;\n+\n+\t\tdesc_sw = &hif->tx_sw_queue[ttc];\n+\n+\t\tif (desc_sw->client_id > HIF_CLIENTS_MAX)\n+\t\t\tPFE_PMD_ERR(\"Invalid cl id %d\", desc_sw->client_id);\n+\n+\t\tpkts_done[desc_sw->client_id]++;\n+\n+\t\tclient_ack_txpacket(hif, desc_sw->client_id, desc_sw->q_no);\n+\n+\t\tttc = (ttc + 1) & (hif->tx_ring_size - 1);\n+\t\ttx_avl++;\n+\t}\n+\n+\tif (pkts_done[0])\n+\t\thif_lib_indicate_client(pfe->hif_client[0], EVENT_TXDONE_IND,\n+\t\t\t\t0);\n+\tif (pkts_done[1])\n+\t\thif_lib_indicate_client(pfe->hif_client[1], EVENT_TXDONE_IND,\n+\t\t\t\t0);\n+\thif->txtoclean = ttc;\n+\thif->txavail = tx_avl;\n+}\n+\n+static inline void\n+hif_tx_done_process(struct pfe *pfe, int count)\n+{\n+\tstruct pfe_hif *hif = &pfe->hif;\n+\trte_spinlock_lock(&hif->tx_lock);\n+\t__hif_tx_done_process(pfe, count);\n+\trte_spinlock_unlock(&hif->tx_lock);\n+}\n+\n+void\n+pfe_tx_do_cleanup(struct pfe *pfe)\n+{\n+\thif_tx_done_process(pfe, HIF_TX_DESC_NT);\n+}\n+\n+/*\n+ * __hif_xmit_pkt -\n+ * This function puts one packet in the HIF Tx queue\n+ */\n+void\n+hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int\n+\t     q_no, void *data, u32 len, unsigned int flags)\n+{\n+\tstruct hif_desc\t*desc;\n+\tstruct hif_desc_sw *desc_sw;\n+\n+\tdesc = hif->tx_base + hif->txtosend;\n+\tdesc_sw = &hif->tx_sw_queue[hif->txtosend];\n+\n+\tdesc_sw->len = len;\n+\tdesc_sw->client_id = client_id;\n+\tdesc_sw->q_no = q_no;\n+\tdesc_sw->flags = flags;\n+\n+\twritel((u32)DDR_PHYS_TO_PFE(data), &desc->data);\n+\n+\thif->txtosend = (hif->txtosend + 1) & (hif->tx_ring_size - 1);\n+\thif->txavail--;\n+\n+\tif ((!((flags & HIF_DATA_VALID) && (flags &\n+\t\t\t\tHIF_LAST_BUFFER))))\n+\t\tgoto skip_tx;\n+\n+\t/*\n+\t * Ensure everything else is written to DDR before\n+\t * writing bd->ctrl\n+\t */\n+\trte_wmb();\n+\n+\tdo {\n+\t\tdesc_sw = &hif->tx_sw_queue[hif->txtoflush];\n+\t\tdesc = hif->tx_base + hif->txtoflush;\n+\n+\t\tif (desc_sw->flags & HIF_LAST_BUFFER) {\n+\t\t\twritel((BD_CTRL_LIFM |\n+\t\t\t       BD_CTRL_BRFETCH_DISABLE | BD_CTRL_RTFETCH_DISABLE\n+\t\t\t       | BD_CTRL_PARSE_DISABLE | BD_CTRL_DESC_EN |\n+\t\t\t\t BD_BUF_LEN(desc_sw->len)),\n+\t\t\t\t&desc->ctrl);\n+\t\t} else {\n+\t\t\twritel((BD_CTRL_DESC_EN |\n+\t\t\t\tBD_BUF_LEN(desc_sw->len)), &desc->ctrl);\n+\t\t}\n+\t\thif->txtoflush = (hif->txtoflush + 1) & (hif->tx_ring_size - 1);\n+\t}\n+\twhile (hif->txtoflush != hif->txtosend)\n+\t\t;\n+\n+skip_tx:\n+\treturn;\n+}\n+\n void\n hif_process_client_req(struct pfe_hif *hif, int req,\n-\t\t       int data1, __rte_unused int data2)\n+\t\t\t    int data1, __rte_unused int data2)\n {\n \tunsigned int client_id = data1;\n \n@@ -503,6 +858,9 @@ pfe_hif_exit(struct pfe *pfe)\n \t\thif_rx_disable();\n \t\thif_tx_disable();\n \n+\t\tpfe_hif_release_buffers(hif);\n+\t\tpfe_hif_shm_clean(hif->shm);\n+\n \t\tpfe_hif_free_descr(hif);\n \t\tpfe->hif.setuped = 0;\n \t}\ndiff --git a/drivers/net/ppfe/pfe_hif.h b/drivers/net/ppfe/pfe_hif.h\nindex 80f78551c..5c9cdf0be 100644\n--- a/drivers/net/ppfe/pfe_hif.h\n+++ b/drivers/net/ppfe/pfe_hif.h\n@@ -138,11 +138,19 @@ struct pfe_hif {\n \tstruct rte_device *dev;\n };\n \n+void hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int\n+\t\t\tq_no, void *data, u32 len, unsigned int flags);\n void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int\n \t\t\t\tdata2);\n int pfe_hif_init(struct pfe *pfe);\n void pfe_hif_exit(struct pfe *pfe);\n void pfe_hif_rx_idle(struct pfe_hif *hif);\n+int pfe_hif_rx_process(struct pfe *pfe, int budget);\n int pfe_hif_init_buffers(struct pfe_hif *hif);\n+void pfe_tx_do_cleanup(struct pfe *pfe);\n+\n+#define __memcpy8(dst, src)\t\tmemcpy(dst, src, 8)\n+#define __memcpy12(dst, src)\t\tmemcpy(dst, src, 12)\n+#define __memcpy(dst, src, len)\t\tmemcpy(dst, src, len)\n \n #endif /* _PFE_HIF_H_ */\ndiff --git a/drivers/net/ppfe/pfe_hif_lib.c b/drivers/net/ppfe/pfe_hif_lib.c\nindex f5e290f27..bac9728b9 100644\n--- a/drivers/net/ppfe/pfe_hif_lib.c\n+++ b/drivers/net/ppfe/pfe_hif_lib.c\n@@ -369,6 +369,152 @@ hif_lib_event_handler_start(struct hif_client_s *client, int event,\n \treturn 0;\n }\n \n+#ifdef RTE_LIBRTE_PPFE_SW_PARSE\n+static inline void\n+pfe_sw_parse_pkt(struct rte_mbuf *mbuf)\n+{\n+\tstruct rte_net_hdr_lens hdr_lens;\n+\n+\tmbuf->packet_type = rte_net_get_ptype(mbuf, &hdr_lens,\n+\t\t\tRTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK\n+\t\t\t| RTE_PTYPE_L4_MASK);\n+\tmbuf->l2_len = hdr_lens.l2_len;\n+\tmbuf->l3_len = hdr_lens.l3_len;\n+}\n+#endif\n+\n+/*\n+ * This function gets one packet from the specified client queue\n+ * It also refill the rx buffer\n+ */\n+int\n+hif_lib_receive_pkt(struct hif_client_rx_queue *queue,\n+\t\tstruct rte_mempool *pool, struct rte_mbuf **rx_pkts,\n+\t\tuint16_t nb_pkts)\n+{\n+\tstruct rx_queue_desc *desc;\n+\tstruct pfe_eth_priv_s *priv = queue->priv;\n+\tstruct rte_pktmbuf_pool_private *mb_priv;\n+\tstruct rte_mbuf *mbuf, *p_mbuf = NULL, *first_mbuf = NULL;\n+\tstruct rte_eth_stats *stats = &priv->stats;\n+\tint i, wait_for_last = 0;\n+#ifndef RTE_LIBRTE_PPFE_SW_PARSE\n+\tstruct ppfe_parse *parse_res;\n+#endif\n+\n+\tfor (i = 0; i < nb_pkts;) {\n+\t\tdo {\n+\t\t\tdesc = queue->base + queue->read_idx;\n+\t\t\tif ((desc->ctrl & CL_DESC_OWN)) {\n+\t\t\t\tstats->ipackets += i;\n+\t\t\t\treturn i;\n+\t\t\t}\n+\n+\t\t\tmb_priv = rte_mempool_get_priv(pool);\n+\n+\t\t\tmbuf = desc->data + PFE_PKT_HEADER_SZ\n+\t\t\t\t- sizeof(struct rte_mbuf)\n+\t\t\t\t- RTE_PKTMBUF_HEADROOM\n+\t\t\t\t- mb_priv->mbuf_priv_size;\n+\t\t\tmbuf->next = NULL;\n+\t\t\tif (desc->ctrl & CL_DESC_FIRST) {\n+\t\t\t\t/* TODO size of priv data if present in\n+\t\t\t\t * descriptor\n+\t\t\t\t */\n+\t\t\t\tu16 size = 0;\n+\t\t\t\tmbuf->pkt_len = CL_DESC_BUF_LEN(desc->ctrl)\n+\t\t\t\t\t\t- PFE_PKT_HEADER_SZ - size;\n+\t\t\t\tmbuf->data_len = mbuf->pkt_len;\n+\t\t\t\tmbuf->port = queue->port_id;\n+#ifdef RTE_LIBRTE_PPFE_SW_PARSE\n+\t\t\t\tpfe_sw_parse_pkt(mbuf);\n+#else\n+\t\t\t\tparse_res = (struct ppfe_parse *)(desc->data +\n+\t\t\t\t\t    PFE_HIF_SIZE);\n+\t\t\t\tmbuf->packet_type = parse_res->packet_type;\n+#endif\n+\t\t\t\tmbuf->nb_segs = 1;\n+\t\t\t\tfirst_mbuf = mbuf;\n+\t\t\t\trx_pkts[i++] = first_mbuf;\n+\t\t\t} else {\n+\t\t\t\tmbuf->data_len = CL_DESC_BUF_LEN(desc->ctrl);\n+\t\t\t\tmbuf->data_off = mbuf->data_off -\n+\t\t\t\t\t\t PFE_PKT_HEADER_SZ;\n+\t\t\t\tfirst_mbuf->pkt_len += mbuf->data_len;\n+\t\t\t\tfirst_mbuf->nb_segs++;\n+\t\t\t\tp_mbuf->next = mbuf;\n+\t\t\t}\n+\t\t\tstats->ibytes += mbuf->data_len;\n+\t\t\tp_mbuf = mbuf;\n+\n+\t\t\tif (desc->ctrl & CL_DESC_LAST)\n+\t\t\t\twait_for_last = 0;\n+\t\t\telse\n+\t\t\t\twait_for_last = 1;\n+\t\t\t/*\n+\t\t\t * Needed so we don't free a buffer/page\n+\t\t\t * twice on module_exit\n+\t\t\t */\n+\t\t\tdesc->data = NULL;\n+\n+\t\t\t/*\n+\t\t\t * Ensure everything else is written to DDR before\n+\t\t\t * writing bd->ctrl\n+\t\t\t */\n+\t\t\trte_wmb();\n+\n+\t\t\tdesc->ctrl = CL_DESC_OWN;\n+\t\t\tqueue->read_idx = (queue->read_idx + 1) &\n+\t\t\t\t\t  (queue->size - 1);\n+\t\t} while (wait_for_last);\n+\t}\n+\tstats->ipackets += i;\n+\treturn i;\n+}\n+\n+static inline void\n+hif_hdr_write(struct hif_hdr *pkt_hdr, unsigned int\n+\t      client_id, unsigned int qno,\n+\t      u32 client_ctrl)\n+{\n+\t/* Optimize the write since the destinaton may be non-cacheable */\n+\tif (!((unsigned long)pkt_hdr & 0x3)) {\n+\t\t((u32 *)pkt_hdr)[0] = (client_ctrl << 16) | (qno << 8) |\n+\t\t\t\t\tclient_id;\n+\t} else {\n+\t\t((u16 *)pkt_hdr)[0] = (qno << 8) | (client_id & 0xFF);\n+\t\t((u16 *)pkt_hdr)[1] = (client_ctrl & 0xFFFF);\n+\t}\n+}\n+\n+/*This function puts the given packet in the specific client queue */\n+void\n+hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno,\n+\t\t void *data, void *data1, unsigned int len,\n+\t\t u32 client_ctrl, unsigned int flags, void *client_data)\n+{\n+\tstruct hif_client_tx_queue *queue = &client->tx_q[qno];\n+\tstruct tx_queue_desc *desc = queue->base + queue->write_idx;\n+\n+\t/* First buffer */\n+\tif (flags & HIF_FIRST_BUFFER) {\n+\t\tdata1 -= PFE_HIF_SIZE;\n+\t\tdata -= PFE_HIF_SIZE;\n+\t\tlen += PFE_HIF_SIZE;\n+\n+\t\thif_hdr_write(data1, client->id, qno, client_ctrl);\n+\t}\n+\n+\tdesc->data = client_data;\n+\tdesc->ctrl = CL_DESC_OWN | CL_DESC_FLAGS(flags);\n+\n+\thif_xmit_pkt(&client->pfe->hif, client->id, qno, data, len, flags);\n+\n+\tqueue->write_idx = (queue->write_idx + 1) & (queue->size - 1);\n+\n+\tqueue->tx_pending++;\n+}\n+\n void *\n hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno,\n \t\t\t\t   unsigned int *flags, __rte_unused  int count)\ndiff --git a/drivers/net/ppfe/pfe_hif_lib.h b/drivers/net/ppfe/pfe_hif_lib.h\nindex 03e492559..7c3cdaaa5 100644\n--- a/drivers/net/ppfe/pfe_hif_lib.h\n+++ b/drivers/net/ppfe/pfe_hif_lib.h\n@@ -162,6 +162,9 @@ int pfe_hif_lib_init(struct pfe *pfe);\n void pfe_hif_lib_exit(struct pfe *pfe);\n int hif_lib_client_register(struct hif_client_s *client);\n int hif_lib_client_unregister(struct  hif_client_s *client);\n+void hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno,\n+\t\t\tvoid *data, void *data1, unsigned int len,\n+\t\t\tu32 client_ctrl, unsigned int flags, void *client_data);\n void hif_lib_indicate_client(struct hif_client_s *client, int event, int data);\n int hif_lib_event_handler_start(struct hif_client_s *client, int event, int\n \t\t\t\t\tdata);\n@@ -170,4 +173,9 @@ void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno,\n int pfe_hif_shm_init(struct hif_shm *hif_shm, struct rte_mempool *mb_pool);\n void pfe_hif_shm_clean(struct hif_shm *hif_shm);\n \n+int hif_lib_receive_pkt(struct hif_client_rx_queue *queue,\n+\t\t\t     struct rte_mempool *pool,\n+\t\t\t     struct rte_mbuf **rx_pkts,\n+\t\t\t     uint16_t nb_pkts);\n+\n #endif /* _PFE_HIF_LIB_H_ */\ndiff --git a/drivers/net/ppfe/pfe_mod.h b/drivers/net/ppfe/pfe_mod.h\nindex 24b9ebd1e..475c0566c 100644\n--- a/drivers/net/ppfe/pfe_mod.h\n+++ b/drivers/net/ppfe/pfe_mod.h\n@@ -7,6 +7,8 @@\n \n struct pfe;\n \n+#include <rte_ethdev.h>\n+\n #include \"pfe.h\"\n #include \"pfe_hif.h\"\n #include \"pfe_hif_lib.h\"\ndiff --git a/drivers/net/ppfe/ppfe_ethdev.c b/drivers/net/ppfe/ppfe_ethdev.c\nindex 4619a9d28..8ed40c261 100644\n--- a/drivers/net/ppfe/ppfe_ethdev.c\n+++ b/drivers/net/ppfe/ppfe_ethdev.c\n@@ -2,6 +2,7 @@\n  * Copyright 2019 NXP\n  */\n \n+#include <sys/epoll.h>\n #include <rte_kvargs.h>\n #include <rte_ethdev_vdev.h>\n #include <rte_bus_vdev.h>\n@@ -137,6 +138,119 @@ pfe_eth_event_handler(void *data, int event, __rte_unused int qno)\n \treturn 0;\n }\n \n+static uint16_t\n+pfe_recv_pkts_on_intr(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)\n+{\n+\tstruct hif_client_rx_queue *queue = rxq;\n+\tstruct pfe_eth_priv_s *priv = queue->priv;\n+\tstruct epoll_event epoll_ev;\n+\tuint64_t ticks = 1;  /* 1 msec */\n+\tint ret;\n+\tint have_something, work_done;\n+\n+#define RESET_STATUS (HIF_INT | HIF_RXPKT_INT)\n+\n+\t/*TODO can we remove this cleanup from here?*/\n+\tpfe_tx_do_cleanup(priv->pfe);\n+\thave_something = pfe_hif_rx_process(priv->pfe, nb_pkts);\n+\twork_done = hif_lib_receive_pkt(rxq, priv->pfe->hif.shm->pool,\n+\t\t\trx_pkts, nb_pkts);\n+\n+\tif (!have_something || !work_done) {\n+\t\twritel(RESET_STATUS, HIF_INT_SRC);\n+\t\twritel(readl(HIF_INT_ENABLE) | HIF_RXPKT_INT, HIF_INT_ENABLE);\n+\t\tret = epoll_wait(priv->pfe->hif.epoll_fd, &epoll_ev, 1, ticks);\n+\t\tif (ret < 0 && errno != EINTR)\n+\t\t\tPFE_PMD_ERR(\"epoll_wait fails with %d\\n\", errno);\n+\t}\n+\n+\treturn work_done;\n+}\n+\n+static uint16_t\n+pfe_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)\n+{\n+\tstruct hif_client_rx_queue *queue = rxq;\n+\tstruct pfe_eth_priv_s *priv = queue->priv;\n+\tstruct rte_mempool *pool;\n+\n+\t/*TODO can we remove this cleanup from here?*/\n+\tpfe_tx_do_cleanup(priv->pfe);\n+\tpfe_hif_rx_process(priv->pfe, nb_pkts);\n+\tpool = priv->pfe->hif.shm->pool;\n+\n+\treturn hif_lib_receive_pkt(rxq, pool, rx_pkts, nb_pkts);\n+}\n+\n+static uint16_t\n+pfe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n+{\n+\tstruct hif_client_tx_queue *queue = tx_queue;\n+\tstruct pfe_eth_priv_s *priv = queue->priv;\n+\tstruct rte_eth_stats *stats = &priv->stats;\n+\tint i;\n+\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tif (tx_pkts[i]->nb_segs > 1) {\n+\t\t\tstruct rte_mbuf *mbuf;\n+\t\t\tint j;\n+\n+\t\t\thif_lib_xmit_pkt(&priv->client, queue->queue_id,\n+\t\t\t\t(void *)(size_t)rte_pktmbuf_iova(tx_pkts[i]),\n+\t\t\t\ttx_pkts[i]->buf_addr + tx_pkts[i]->data_off,\n+\t\t\t\ttx_pkts[i]->data_len, 0x0, HIF_FIRST_BUFFER,\n+\t\t\t\ttx_pkts[i]);\n+\n+\t\t\tmbuf = tx_pkts[i]->next;\n+\t\t\tfor (j = 0; j < (tx_pkts[i]->nb_segs - 2); j++) {\n+\t\t\t\thif_lib_xmit_pkt(&priv->client, queue->queue_id,\n+\t\t\t\t\t(void *)(size_t)rte_pktmbuf_iova(mbuf),\n+\t\t\t\t\tmbuf->buf_addr + mbuf->data_off,\n+\t\t\t\t\tmbuf->data_len,\n+\t\t\t\t\t0x0, 0x0, mbuf);\n+\t\t\t\tmbuf = mbuf->next;\n+\t\t\t}\n+\n+\t\t\thif_lib_xmit_pkt(&priv->client, queue->queue_id,\n+\t\t\t\t\t(void *)(size_t)rte_pktmbuf_iova(mbuf),\n+\t\t\t\t\tmbuf->buf_addr + mbuf->data_off,\n+\t\t\t\t\tmbuf->data_len,\n+\t\t\t\t\t0x0, HIF_LAST_BUFFER | HIF_DATA_VALID,\n+\t\t\t\t\tmbuf);\n+\t\t} else {\n+\t\t\thif_lib_xmit_pkt(&priv->client, queue->queue_id,\n+\t\t\t\t(void *)(size_t)rte_pktmbuf_iova(tx_pkts[i]),\n+\t\t\t\ttx_pkts[i]->buf_addr + tx_pkts[i]->data_off,\n+\t\t\t\ttx_pkts[i]->pkt_len, 0 /*ctrl*/,\n+\t\t\t\tHIF_FIRST_BUFFER | HIF_LAST_BUFFER |\n+\t\t\t\tHIF_DATA_VALID,\n+\t\t\t\ttx_pkts[i]);\n+\t\t}\n+\t\tstats->obytes += tx_pkts[i]->pkt_len;\n+\t\thif_tx_dma_start();\n+\t}\n+\tstats->opackets += nb_pkts;\n+\tpfe_tx_do_cleanup(priv->pfe);\n+\n+\treturn nb_pkts;\n+}\n+\n+static uint16_t\n+pfe_dummy_xmit_pkts(__rte_unused void *tx_queue,\n+\t\t__rte_unused struct rte_mbuf **tx_pkts,\n+\t\t__rte_unused uint16_t nb_pkts)\n+{\n+\treturn 0;\n+}\n+\n+static uint16_t\n+pfe_dummy_recv_pkts(__rte_unused void *rxq,\n+\t\t__rte_unused struct rte_mbuf **rx_pkts,\n+\t\t__rte_unused uint16_t nb_pkts)\n+{\n+\treturn 0;\n+}\n+\n static int\n pfe_eth_open(struct rte_eth_dev *dev)\n {\n@@ -174,6 +288,21 @@ pfe_eth_open(struct rte_eth_dev *dev)\n \t\t\t\t\t    \" failed\", client->id);\n \t\t\t\tgoto err0;\n \t\t\t}\n+\t\t} else {\n+\t\t\t/* Freeing the packets if already exists */\n+\t\t\tint ret = 0;\n+\t\t\tstruct rte_mbuf *rx_pkts[32];\n+\t\t\t/* TODO multiqueue support */\n+\t\t\tret = hif_lib_receive_pkt(&client->rx_q[0],\n+\t\t\t\t\t\t  hif_shm->pool, rx_pkts, 32);\n+\t\t\twhile (ret) {\n+\t\t\t\tint i;\n+\t\t\t\tfor (i = 0; i < ret; i++)\n+\t\t\t\t\trte_pktmbuf_free(rx_pkts[i]);\n+\t\t\t\tret = hif_lib_receive_pkt(&client->rx_q[0],\n+\t\t\t\t\t\t\t  hif_shm->pool,\n+\t\t\t\t\t\t\t  rx_pkts, 32);\n+\t\t\t}\n \t\t}\n \t} else {\n \t\t/* Register client driver with HIF */\n@@ -197,6 +326,14 @@ pfe_eth_open(struct rte_eth_dev *dev)\n \t\t}\n \t}\n \trc = pfe_eth_start(priv);\n+\tdev->rx_pkt_burst = &pfe_recv_pkts;\n+\tdev->tx_pkt_burst = &pfe_xmit_pkts;\n+\t/* If no prefetch is configured. */\n+\tif (getenv(\"PPFE_INTR_SUPPORT\")) {\n+\t\tdev->rx_pkt_burst = &pfe_recv_pkts_on_intr;\n+\t\tPFE_PMD_INFO(\"PPFE INTERRUPT Mode enabled\");\n+\t}\n+\n \n err0:\n \treturn rc;\n@@ -243,6 +380,9 @@ pfe_eth_stop(struct rte_eth_dev *dev/*, int wake*/)\n \n \tgemac_disable(priv->EMAC_baseaddr);\n \tgpi_disable(priv->GPI_baseaddr);\n+\n+\tdev->rx_pkt_burst = &pfe_dummy_recv_pkts;\n+\tdev->tx_pkt_burst = &pfe_dummy_xmit_pkts;\n }\n \n static void\n",
    "prefixes": [
        "v3",
        "09/14"
    ]
}