From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 88179A0093;
	Fri, 17 Jun 2022 11:36:40 +0200 (CEST)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id DD73342B95;
	Fri, 17 Jun 2022 11:35:44 +0200 (CEST)
Received: from NAM10-MW2-obe.outbound.protection.outlook.com
 (mail-mw2nam10on2106.outbound.protection.outlook.com [40.107.94.106])
 by mails.dpdk.org (Postfix) with ESMTP id E2B8E40698
 for <dev@dpdk.org>; Fri, 17 Jun 2022 11:35:42 +0200 (CEST)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=YkjDr3hTn6T+lRCHc6ruuvN5lktpoBfzDG0TRjzSVGtgvJU0AcM/ZYM83H5ICfarpmvsdF0q9LZ4NRw+4jvo/D39r4F3yDkpfVaxcqKJ0x05ZQnkMs8qQPBM2PBlN8gUMAequaWoTgrGR0bwhk4dKYOE9GglDrgSnJRuPcovwtHgRkIZW8ciIbmmyDcWYdHR8MWcfTuTv+Tz5R5vd1ck7bAlu24Kx4YYx5brmIooZMe3wRgIV38qge6Rq+jlOdAH8HYLoUhKHMn8RtTsYiJ7MhXJockVBB2MyzhAPcPE8mirv4KR27TnbEveQw5U2P3J/Zs47BYYotVnR4guSSQJfw==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; 
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=9f67gHHj42EtVtwfIFunG6VH+mxbS/D3wnoGOIcuklY=;
 b=ZfV6tPuhYkFW3hbFoN022jKm/vGrOZi++9pzyxv8fTiEE2IyEYV344IeSPkfqhHP56zTSyS3+qH0De5jjmYLwsuyWBpupytGZQTX++JzeyskRy5g98i3uNz37mqqghIF+UEsqfGxbsVvtkV7HOSVcjqbGwnDXR/h/GSzE5Mjt44L/3dwz0kP7Lb1GHwmYBxOdpZQO8rLy1U+8lSBuS13EvyGydhenfXjO68e9LRRckVyrZCE8vl+RBYv7PTOA+vaV11aEoG3tJwYFQekChCrc0wFb7wFkWnsjLbTvjsACY2acZAblJJa/k11UbB0GfLCLPGAY2In7FibbdrYEGwYtA==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
 smtp.mailfrom=corigine.com; dmarc=pass action=none header.from=corigine.com;
 dkim=pass header.d=corigine.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=corigine.onmicrosoft.com; s=selector2-corigine-onmicrosoft-com;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=9f67gHHj42EtVtwfIFunG6VH+mxbS/D3wnoGOIcuklY=;
 b=qJoDLZKMhOt5BbeODTwD3S6RDw/d/IL3ACtkG4xzTWyb+6iZofRI/wHfA37BjzEzlIEThgfQJDoSXj+mf7kfo8/24apnDwAo4Z+ieq7xJAXlsvxYBa4mW8MOcfbUhVdKT1CrzN3IA0VHO7lQrK/sPPmGajlDoiThi+o6KOOgmOM=
Authentication-Results: dkim=none (message not signed)
 header.d=none;dmarc=none action=none header.from=corigine.com;
Received: from DM6PR13MB3004.namprd13.prod.outlook.com (2603:10b6:5:191::21)
 by CO3PR13MB5671.namprd13.prod.outlook.com (2603:10b6:303:17a::16) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5373.9; Fri, 17 Jun
 2022 09:35:41 +0000
Received: from DM6PR13MB3004.namprd13.prod.outlook.com
 ([fe80::ac31:a36a:cc15:cd35]) by DM6PR13MB3004.namprd13.prod.outlook.com
 ([fe80::ac31:a36a:cc15:cd35%7]) with mapi id 15.20.5373.009; Fri, 17 Jun 2022
 09:35:41 +0000
From: Jin Liu <jin.liu@corigine.com>
To: dev@dpdk.org
Cc: niklas.soderlund@corigine.com, Jin Liu <jin.liu@corigine.com>,
 Diana Wang <na.wang@corigine.com>, Peng Zhang <peng.zhang@corigine.com>,
 Chaoyong He <chaoyong.he@corigine.com>
Subject: [PATCH v3 12/13] net/nfp: nfdk packet xmit function
Date: Fri, 17 Jun 2022 11:34:43 +0200
Message-Id: <20220617093444.2004000-13-jin.liu@corigine.com>
X-Mailer: git-send-email 2.27.0
In-Reply-To: <20220617093444.2004000-1-jin.liu@corigine.com>
References: <20220616023939.1798769-1-jin.liu@corigine.com>
 <20220617093444.2004000-1-jin.liu@corigine.com>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-ClientProxiedBy: LO4P123CA0192.GBRP123.PROD.OUTLOOK.COM
 (2603:10a6:600:1a4::17) To DM6PR13MB3004.namprd13.prod.outlook.com
 (2603:10b6:5:191::21)
MIME-Version: 1.0
X-MS-PublicTrafficType: Email
X-MS-Office365-Filtering-Correlation-Id: 13ff7a17-dd7e-4428-3918-08da5044be5e
X-MS-TrafficTypeDiagnostic: CO3PR13MB5671:EE_
X-Microsoft-Antispam-PRVS: <CO3PR13MB567177F8440E89FD2CD79D1594AF9@CO3PR13MB5671.namprd13.prod.outlook.com>
X-MS-Exchange-SenderADCheck: 1
X-MS-Exchange-AntiSpam-Relay: 0
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: +ix/dEwbQHA/oUbagjDAWfceul6KZjUF9+lDD5Cc/cI9w8soqrqU9oM5SimGJFBPC+yzXToe3OwJ3Z6xgyf9wCSVITIpZSVbbqMEx8jWzruF1EaOVuIw3fVRqap0Gc5NJ3Sn1BAh4uLBgPG8ZmKzG600Nki2pwVgvLXVCJs93xWbaZpsGqR/yyFJ1X8eKz/cQCJcgJRjhcn2CB89V2rncKT863eDtxk3ase3P3ILs1MzsImWCS9CoQAV8q1mJbdiDr7m5H20tBdHecoyCJwYQmYd8yJtch0z6ZWedFm+ExVGLiVomxUJ56wXp3BdSfX0s8eIi+gLzaNJWD9zm431GD9VQ+W5EtDAsR77+g1OBHeDo6JPvEGnChkOlUFe136JacX4or8fdgVLvmC5H5EuGQr1Fea2xjYUaVRseGdDcgnrTqzCZ8nB3aVCIuTYwu4hDwwd2JzA8vcEa+s64+N4u2RI6xMaOcKpHflGdN2OpD/Hz2Ph8ERswbMbJQv52uCeplvN7drHIcrkl+59T2KzvuItpCvJB3rz7jZdPB/K7HtMmaicyPCMvYHYgUgCFyGoMnHjFN2ZxqVlKh8wOWqrvrrOLsGPsoBT9ilPlHtCcJpOBNQJ2UJ2sfmy2JVQK8sBVY0YT6Xu8ghJe2kTc3Mh8cYKu3bZUQfgTl/Qab92ArLFxhHwYTvvBKh7MohtZNaok4HnjLdtROzdnakvJaPCYrpQ44ayd49V6Fd334HcsrRJCkTD4UVUR45OBFTOPl0I
X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;
 IPV:NLI; SFV:NSPM; H:DM6PR13MB3004.namprd13.prod.outlook.com; PTR:; CAT:NONE;
 SFS:(13230016)(4636009)(346002)(136003)(366004)(396003)(39840400004)(66476007)(66556008)(26005)(8676002)(66574015)(107886003)(66946007)(6506007)(6916009)(44832011)(30864003)(2906002)(316002)(4326008)(38350700002)(186003)(508600001)(54906003)(5660300002)(6486002)(6512007)(1076003)(8936002)(2616005)(36756003)(52116002)(83380400001)(86362001)(38100700002)(41300700001);
 DIR:OUT; SFP:1102; 
X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1
X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?Q0RhdHBlbEl5c1RvdGduK2VER0xyd0VLUkVtQ2poUUE4NENWSWl5U1k3dFRx?=
 =?utf-8?B?dlpYOGdRQjQ4RUxyNUZJZnRYOUx4NC9vVzdCNTVQa0Y0TjlhUFM0OUNrNzJ0?=
 =?utf-8?B?S1pna3ZEUFJSOXhjNFFEUzZsamp1ZTJUbUx4UzJFcFZmZjN2amZuckhDRk9I?=
 =?utf-8?B?bzF4UTFsQm8ybkNtdEc2UVVFSTNqRTJOYXhTRUVDSkxoNjlCQWh2WG1uQmJU?=
 =?utf-8?B?V2V2SmlwRWFIK3hZMStXLy9sOTB4bHdPdXpUdXJJVjN2Y24xVGhoeVpFUll3?=
 =?utf-8?B?c1h1bmtSTU8xSGc5a1NnaW9JdjFlRkRBNk1VaFJ4VjI3UUk5Y3c5MldyZ2I5?=
 =?utf-8?B?cFByVUhtSVdBVGxBVUNZai8wRUtKQkxINTU0RmRNZ013MXFUcDVKd3VtQ2h4?=
 =?utf-8?B?UG1tZlVzU2lpRFBLOGZISWl4czM5MDVJSTJoMFoyT2M5Y0kwYUxOa3A0dDUz?=
 =?utf-8?B?aVZOeFlzTWZ4WmxyRDE0WjBRMGJrUkJCUHVvdjc0U0hYY2Vzc2kyQkE3ckFL?=
 =?utf-8?B?aWhyUnNyL0diTXd4WUNEeWM5M0JtRHc0OGFnL0hsSi9CUi94cHZWMldqaFd2?=
 =?utf-8?B?azNwcUdVNjZiamkwalZXR29zVFdBd2RlVW1mWm51N3h0akcreSsvR2V0U2N0?=
 =?utf-8?B?RWdCUWtRcmJ5R2Y0ZndmMGo5VHRVcE9xL0NneXZ1VVJ2ZmxBSFI2b1dob1RW?=
 =?utf-8?B?VTBWRzRiTVdJUGk3UGhjekFLWHNIaFR6dlJwOWQvVkRjNVpnb1VLa1UxMmVq?=
 =?utf-8?B?SHJwd3hta2YyY25qNHdQbnBjVGdkbTFzTWpDa3hHbHdRTnhQNjFzQWNZWkNP?=
 =?utf-8?B?R0tlOGZWa0d3bkYzMHcyYVM5UE1JbEsybFBmU3NCakFaMDZXVmdaZzhxemti?=
 =?utf-8?B?YUIyVVRUbUVrTERuTFc2NUF5ZExIc3BTYkwwMDJlUkRTVzExbDhhUlFUYUZ2?=
 =?utf-8?B?SklWOHdmYWx3alNqWUNwcVhkMDF4STVKLzNWZVh2Y3NNSVc5YndPYk1oUGlS?=
 =?utf-8?B?MUowWDRFTlAyMkJwOWRuRndxYTJqSlk2anlBT3N4Zzg3NWl3Z1RnZnlVbGJC?=
 =?utf-8?B?c0pFOHFsU09YbWNVZlBRa2NQN3pnTWpoRXU1ZVRWcU5nbnpxd0hYNWh0KzJL?=
 =?utf-8?B?ZVNDN2M2c0xJSDRrTDBWTlQrWTJUV2tCdHA1UGxOUFdNQVBJMXZJeC9xVW9P?=
 =?utf-8?B?bmhWejJnRXZPN0IxTXNKZXlHNjVIVnNQb3U0dEQxaTBQZWUwRTJjeGxabTdP?=
 =?utf-8?B?bi9zeDBicnNqUkljWXVhTjJjUDZwc0ErNkJmcTcvTWZFNy8ydVNSS29oWlp2?=
 =?utf-8?B?UDFsU0hFTmtPa1pKaktlbk9xblo0ZTZXOG52TDQvWTJsUWJoNVBaUStBVDBn?=
 =?utf-8?B?UlgrVlB2c0FiSjZiT1lFY1RDZlNheVBXQWpSS0tQQUlWcU52ME5JK0QwRGN1?=
 =?utf-8?B?OHZoMVlxaDFQbXhaVW02R2JTOHFsVi85cXY1OVB3V25ZUVdzajlTQWFDRHJ2?=
 =?utf-8?B?VkZqNWpmbjZTS3R4bkh4cE5QV0x6UGhDRDcySFFqNW14bE1sYk16dE5xd2ZY?=
 =?utf-8?B?N01IOHYvaG9Tczd5QUVDWElEdFJkT0xaUVh3RlpKTkNrc0UzckZST3ZjVlVi?=
 =?utf-8?B?N04yUlExTmdycit6SlM0eGx3K0h1L1dENjAxLytuTkxJMXBSK0s1M2VJUFIx?=
 =?utf-8?B?VjB2ZXZNQytTbk5Gd3ZSMWY4dHdWMmlsUG5Bd1ZzSThKZnpPL2dGczN0R1B1?=
 =?utf-8?B?bUZ1SHI5TnhFMzZoQjFNVWpWTW5iL2RsU3k4ZmpwUEF4QWhkNWdNZndjamFk?=
 =?utf-8?B?QVBUMFFpYWFVWFh0Qkl0YWhCQVFFekRUMTBVZlZvRm83dFhYNE1VQ1g2YVRJ?=
 =?utf-8?B?cFZRTDgvd1hCS0ZxTmRuNkhiRy90aWtSNXM3WEM1elIyUk5NZTJBb21GNStk?=
 =?utf-8?B?MzZwTmZ1MGN6c0E0VWlvRTNmemtHc2Z5MkNNMDRySzNZWVFrejRqTkQ0NG0y?=
 =?utf-8?B?ZTlsU0QxNDd3NmFUU1g1RVVtOWFkUFBuSDByaysyWEtWWkNnbXNkdmQ3RUor?=
 =?utf-8?B?MkZZdWZia0o5Uyt6K24wUyttbS92MWdBWHBpclZtUkNJZVdiMnowcENNRjI0?=
 =?utf-8?B?SU9nSUUyREpQd1NQS25lTHRXK3oxQU1sVWVMWlJNcW1mNnROVFdYWStYR3B6?=
 =?utf-8?B?ZmdOQ3FvQTRCWkQ4YTJRVjhGd0NBMHhhbWU4NjVJZG5ZWXpSODdmRmtyMWVD?=
 =?utf-8?B?cUNTM2VBZTRwRmtCUXFlbnpKWHBPUytuOWM0ekNXSUJYb0g1dTQyeGd0RDFq?=
 =?utf-8?B?OHhDU1FzQS9lSkowSjVsWnhQR3l4OGRmWFo0aE91OGNGZnczUGVOdz09?=
X-OriginatorOrg: corigine.com
X-MS-Exchange-CrossTenant-Network-Message-Id: 13ff7a17-dd7e-4428-3918-08da5044be5e
X-MS-Exchange-CrossTenant-AuthSource: DM6PR13MB3004.namprd13.prod.outlook.com
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Jun 2022 09:35:41.1940 (UTC)
X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
X-MS-Exchange-CrossTenant-Id: fe128f2c-073b-4c20-818e-7246a585940c
X-MS-Exchange-CrossTenant-MailboxType: HOSTED
X-MS-Exchange-CrossTenant-UserPrincipalName: ulxaKe7bnKw3zk1ZazC7l+SgRVETZ6o5E29OWhKP7IaOZG1b3tO6e0GrzKeNC8zZG7h/VHtt8gD/ULzmrFo6vA==
X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO3PR13MB5671
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

Implement NFP3800 card packet transmit function for firmware
with NFDk.

Signed-off-by: Jin Liu <jin.liu@corigine.com>
Signed-off-by: Diana Wang <na.wang@corigine.com>
Signed-off-by: Peng Zhang <peng.zhang@corigine.com>
Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Signed-off-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_ethdev.c    |   3 +-
 drivers/net/nfp/nfp_ethdev_vf.c |   3 +-
 drivers/net/nfp/nfp_rxtx.c      | 281 ++++++++++++++++++++++++++++++++
 drivers/net/nfp/nfp_rxtx.h      |   3 +
 4 files changed, 288 insertions(+), 2 deletions(-)

diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c
index e8a8368d0f..b6817c10da 100644
--- a/drivers/net/nfp/nfp_ethdev.c
+++ b/drivers/net/nfp/nfp_ethdev.c
@@ -374,6 +374,7 @@ nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 	switch (NFD_CFG_CLASS_VER_of(hw->ver)) {
 	case NFP_NET_CFG_VERSION_DP_NFD3:
 		eth_dev->dev_ops = &nfp_net_nfd3_eth_dev_ops;
+		eth_dev->tx_pkt_burst = &nfp_net_nfd3_xmit_pkts;
 		break;
 	case NFP_NET_CFG_VERSION_DP_NFDK:
 		if (NFD_CFG_MAJOR_VERSION_of(hw->ver) < 5) {
@@ -382,6 +383,7 @@ nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 			return -EINVAL;
 		}
 		eth_dev->dev_ops = &nfp_net_nfdk_eth_dev_ops;
+		eth_dev->tx_pkt_burst = &nfp_net_nfdk_xmit_pkts;
 		break;
 	default:
 		PMD_DRV_LOG(ERR, "The version of firmware is not correct.");
@@ -390,7 +392,6 @@ nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 
 	eth_dev->rx_queue_count = nfp_net_rx_queue_count;
 	eth_dev->rx_pkt_burst = &nfp_net_recv_pkts;
-	eth_dev->tx_pkt_burst = &nfp_net_nfd3_xmit_pkts;
 
 	return 0;
 }
diff --git a/drivers/net/nfp/nfp_ethdev_vf.c b/drivers/net/nfp/nfp_ethdev_vf.c
index 56428814b7..66a1c0a36b 100644
--- a/drivers/net/nfp/nfp_ethdev_vf.c
+++ b/drivers/net/nfp/nfp_ethdev_vf.c
@@ -279,6 +279,7 @@ nfp_netvf_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 	switch (NFD_CFG_CLASS_VER_of(hw->ver)) {
 	case NFP_NET_CFG_VERSION_DP_NFD3:
 		eth_dev->dev_ops = &nfp_netvf_nfd3_eth_dev_ops;
+		eth_dev->tx_pkt_burst = &nfp_net_nfd3_xmit_pkts;
 		break;
 	case NFP_NET_CFG_VERSION_DP_NFDK:
 		if (NFD_CFG_MAJOR_VERSION_of(hw->ver) < 5) {
@@ -287,6 +288,7 @@ nfp_netvf_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 			return -EINVAL;
 		}
 		eth_dev->dev_ops = &nfp_netvf_nfdk_eth_dev_ops;
+		eth_dev->tx_pkt_burst = &nfp_net_nfdk_xmit_pkts;
 		break;
 	default:
 		PMD_DRV_LOG(ERR, "The version of firmware is not correct.");
@@ -295,7 +297,6 @@ nfp_netvf_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 
 	eth_dev->rx_queue_count = nfp_net_rx_queue_count;
 	eth_dev->rx_pkt_burst = &nfp_net_recv_pkts;
-	eth_dev->tx_pkt_burst = &nfp_net_nfd3_xmit_pkts;
 
 	return 0;
 }
diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c
index 4f422c5090..1b00f96ed3 100644
--- a/drivers/net/nfp/nfp_rxtx.c
+++ b/drivers/net/nfp/nfp_rxtx.c
@@ -20,6 +20,9 @@
 #include "nfp_rxtx.h"
 #include "nfp_logs.h"
 #include "nfp_ctrl.h"
+#include "nfpcore/nfp_mip.h"
+#include "nfpcore/nfp_rtsym.h"
+#include "nfpcore/nfp-common/nfp_platform.h"
 
 static int
 nfp_net_rx_fill_freelist(struct nfp_net_rxq *rxq)
@@ -1104,3 +1107,281 @@ nfp_net_nfdk_tx_queue_setup(struct rte_eth_dev *dev,
 
 	return 0;
 }
+
+static inline uint32_t
+nfp_net_nfdk_free_tx_desc(struct nfp_net_txq *txq)
+{
+	uint32_t free_desc;
+
+	if (txq->wr_p >= txq->rd_p)
+		free_desc = txq->tx_count - (txq->wr_p - txq->rd_p);
+	else
+		free_desc = txq->rd_p - txq->wr_p;
+
+	return (free_desc > NFDK_TX_DESC_STOP_CNT) ?
+		(free_desc - NFDK_TX_DESC_STOP_CNT) : 0;
+}
+
+static inline uint32_t
+nfp_net_nfdk_txq_full(struct nfp_net_txq *txq)
+{
+	return (nfp_net_nfdk_free_tx_desc(txq) < txq->tx_free_thresh);
+}
+
+static inline int
+nfp_net_nfdk_headlen_to_segs(unsigned int headlen)
+{
+	return DIV_ROUND_UP(headlen +
+			NFDK_TX_MAX_DATA_PER_DESC -
+			NFDK_TX_MAX_DATA_PER_HEAD,
+			NFDK_TX_MAX_DATA_PER_DESC);
+}
+
+static int
+nfp_net_nfdk_tx_maybe_close_block(struct nfp_net_txq *txq, struct rte_mbuf *pkt)
+{
+	unsigned int n_descs, wr_p, i, nop_slots;
+	struct rte_mbuf *pkt_temp;
+
+	pkt_temp = pkt;
+	n_descs = nfp_net_nfdk_headlen_to_segs(pkt_temp->data_len);
+	while (pkt_temp->next) {
+		pkt_temp = pkt_temp->next;
+		n_descs += DIV_ROUND_UP(pkt_temp->data_len, NFDK_TX_MAX_DATA_PER_DESC);
+	}
+
+	if (unlikely(n_descs > NFDK_TX_DESC_GATHER_MAX))
+		return -EINVAL;
+
+	n_descs += !!(pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG);
+
+	if (round_down(txq->wr_p, NFDK_TX_DESC_BLOCK_CNT) !=
+			round_down(txq->wr_p + n_descs, NFDK_TX_DESC_BLOCK_CNT))
+		goto close_block;
+
+	if ((uint32_t)txq->data_pending + pkt->pkt_len > NFDK_TX_MAX_DATA_PER_BLOCK)
+		goto close_block;
+
+	return 0;
+
+close_block:
+	wr_p = txq->wr_p;
+	nop_slots = D_BLOCK_CPL(wr_p);
+
+	memset(&txq->ktxds[wr_p], 0, nop_slots * sizeof(struct nfp_net_nfdk_tx_desc));
+	for (i = wr_p; i < nop_slots + wr_p; i++) {
+		if (txq->txbufs[i].mbuf) {
+			rte_pktmbuf_free_seg(txq->txbufs[i].mbuf);
+			txq->txbufs[i].mbuf = NULL;
+		}
+	}
+	txq->data_pending = 0;
+	txq->wr_p = D_IDX(txq, txq->wr_p + nop_slots);
+
+	return nop_slots;
+}
+
+static inline uint64_t
+nfp_net_nfdk_tx_cksum(struct nfp_net_txq *txq, struct rte_mbuf *mb,
+		uint64_t flags)
+{
+	uint64_t ol_flags;
+	struct nfp_net_hw *hw = txq->hw;
+
+	if (!(hw->cap & NFP_NET_CFG_CTRL_TXCSUM))
+		return flags;
+
+	ol_flags = mb->ol_flags;
+
+	/* IPv6 does not need checksum */
+	if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
+		flags |= NFDK_DESC_TX_L3_CSUM;
+
+	if (ol_flags & RTE_MBUF_F_TX_L4_MASK)
+		flags |= NFDK_DESC_TX_L4_CSUM;
+
+	return flags;
+}
+
+static inline uint64_t
+nfp_net_nfdk_tx_tso(struct nfp_net_txq *txq, struct rte_mbuf *mb)
+{
+	uint64_t ol_flags;
+	struct nfp_net_nfdk_tx_desc txd;
+	struct nfp_net_hw *hw = txq->hw;
+
+	if (!(hw->cap & NFP_NET_CFG_CTRL_LSO_ANY))
+		goto clean_txd;
+
+	ol_flags = mb->ol_flags;
+
+	if (!(ol_flags & RTE_MBUF_F_TX_TCP_SEG))
+		goto clean_txd;
+
+	txd.l3_offset = mb->l2_len;
+	txd.l4_offset = mb->l2_len + mb->l3_len;
+	txd.lso_meta_res = 0;
+	txd.mss = rte_cpu_to_le_16(mb->tso_segsz);
+	txd.lso_hdrlen = mb->l2_len + mb->l3_len + mb->l4_len;
+	txd.lso_totsegs = (mb->pkt_len + mb->tso_segsz) / mb->tso_segsz;
+
+clean_txd:
+	txd.l3_offset = 0;
+	txd.l4_offset = 0;
+	txd.lso_hdrlen = 0;
+	txd.mss = 0;
+	txd.lso_totsegs = 0;
+	txd.lso_meta_res = 0;
+
+	return txd.raw;
+}
+
+uint16_t
+nfp_net_nfdk_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	uint32_t buf_idx;
+	uint64_t dma_addr;
+	uint16_t free_descs;
+	uint32_t npkts = 0;
+	uint64_t metadata = 0;
+	uint16_t issued_descs = 0;
+	struct nfp_net_txq *txq;
+	struct nfp_net_hw *hw;
+	struct nfp_net_nfdk_tx_desc *ktxds;
+	struct rte_mbuf *pkt, *temp_pkt;
+	struct rte_mbuf **lmbuf;
+
+	txq = tx_queue;
+	hw = txq->hw;
+
+	PMD_TX_LOG(DEBUG, "working for queue %u at pos %d and %u packets",
+		txq->qidx, txq->wr_p, nb_pkts);
+
+	if ((nfp_net_nfdk_free_tx_desc(txq) < NFDK_TX_DESC_PER_SIMPLE_PKT *
+			nb_pkts) || (nfp_net_nfdk_txq_full(txq)))
+		nfp_net_tx_free_bufs(txq);
+
+	free_descs = (uint16_t)nfp_net_nfdk_free_tx_desc(txq);
+	if (unlikely(free_descs == 0))
+		return 0;
+
+	PMD_TX_LOG(DEBUG, "queue: %u. Sending %u packets", txq->qidx, nb_pkts);
+	/* Sending packets */
+	while ((npkts < nb_pkts) && free_descs) {
+		uint32_t type, dma_len, dlen_type, tmp_dlen;
+		int nop_descs, used_descs;
+
+		pkt = *(tx_pkts + npkts);
+		nop_descs = nfp_net_nfdk_tx_maybe_close_block(txq, pkt);
+		if (nop_descs < 0)
+			goto xmit_end;
+
+		issued_descs += nop_descs;
+		ktxds = &txq->ktxds[txq->wr_p];
+		/* Grabbing the mbuf linked to the current descriptor */
+		buf_idx = txq->wr_p;
+		lmbuf = &txq->txbufs[buf_idx++].mbuf;
+		/* Warming the cache for releasing the mbuf later on */
+		RTE_MBUF_PREFETCH_TO_FREE(*lmbuf);
+
+		temp_pkt = pkt;
+
+		if (unlikely(pkt->nb_segs > 1 &&
+				!(hw->cap & NFP_NET_CFG_CTRL_GATHER))) {
+			PMD_INIT_LOG(INFO, "NFP_NET_CFG_CTRL_GATHER not set");
+			rte_panic("Multisegment packet unsupported\n");
+		}
+
+		/*
+		 * Checksum and VLAN flags just in the first descriptor for a
+		 * multisegment packet, but TSO info needs to be in all of them.
+		 */
+
+		dma_len = pkt->data_len;
+		if ((hw->cap & NFP_NET_CFG_CTRL_LSO_ANY) &&
+				(pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
+			type = NFDK_DESC_TX_TYPE_TSO;
+		} else if (!pkt->next && dma_len < NFDK_TX_MAX_DATA_PER_HEAD) {
+			type = NFDK_DESC_TX_TYPE_SIMPLE;
+		} else {
+			type = NFDK_DESC_TX_TYPE_GATHER;
+		}
+		dma_len -= 1;
+		dlen_type = (NFDK_DESC_TX_DMA_LEN_HEAD & dma_len) |
+			(NFDK_DESC_TX_TYPE_HEAD & (type << 12));
+		ktxds->dma_len_type = rte_cpu_to_le_16(dlen_type);
+		dma_addr = rte_mbuf_data_iova(pkt);
+		PMD_TX_LOG(DEBUG, "Working with mbuf at dma address:"
+				"%" PRIx64 "", dma_addr);
+		ktxds->dma_addr_hi = rte_cpu_to_le_16(dma_addr >> 32);
+		ktxds->dma_addr_lo = rte_cpu_to_le_32(dma_addr & 0xffffffff);
+		ktxds++;
+
+		tmp_dlen = dlen_type & NFDK_DESC_TX_DMA_LEN_HEAD;
+		dma_len -= tmp_dlen;
+		dma_addr += tmp_dlen + 1;
+
+		while (pkt) {
+			if (*lmbuf)
+				rte_pktmbuf_free_seg(*lmbuf);
+			*lmbuf = pkt;
+			while (dma_len > 0) {
+				dma_len -= 1;
+				dlen_type = NFDK_DESC_TX_DMA_LEN & dma_len;
+
+				ktxds->dma_len_type = rte_cpu_to_le_16(dlen_type);
+				ktxds->dma_addr_hi = rte_cpu_to_le_16(dma_addr >> 32);
+				ktxds->dma_addr_lo = rte_cpu_to_le_32(dma_addr & 0xffffffff);
+				ktxds++;
+
+				dma_len -= dlen_type;
+				dma_addr += dlen_type + 1;
+			}
+
+			if (!pkt->next)
+				break;
+
+			pkt = pkt->next;
+			dma_len = pkt->data_len;
+			dma_addr = rte_mbuf_data_iova(pkt);
+			PMD_TX_LOG(DEBUG, "Working with mbuf at dma address:"
+				"%" PRIx64 "", dma_addr);
+
+			lmbuf = &txq->txbufs[buf_idx++].mbuf;
+		}
+
+		(ktxds - 1)->dma_len_type = rte_cpu_to_le_16(dlen_type | NFDK_DESC_TX_EOP);
+
+		ktxds->raw = rte_cpu_to_le_64(nfp_net_nfdk_tx_cksum(txq, temp_pkt, metadata));
+		ktxds++;
+
+		if ((hw->cap & NFP_NET_CFG_CTRL_LSO_ANY) &&
+				(temp_pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
+			ktxds->raw = rte_cpu_to_le_64(nfp_net_nfdk_tx_tso(txq, temp_pkt));
+			ktxds++;
+		}
+
+		used_descs = ktxds - txq->ktxds - txq->wr_p;
+		if (round_down(txq->wr_p, NFDK_TX_DESC_BLOCK_CNT) !=
+			round_down(txq->wr_p + used_descs - 1, NFDK_TX_DESC_BLOCK_CNT)) {
+			rte_panic("Used descs cross block boundary\n");
+		}
+
+		txq->wr_p = D_IDX(txq, txq->wr_p + used_descs);
+		if (txq->wr_p % NFDK_TX_DESC_BLOCK_CNT)
+			txq->data_pending += temp_pkt->pkt_len;
+		else
+			txq->data_pending = 0;
+
+		issued_descs += used_descs;
+		npkts++;
+		free_descs = (uint16_t)nfp_net_nfdk_free_tx_desc(txq);
+	}
+
+xmit_end:
+	/* Increment write pointers. Force memory write before we let HW know */
+	rte_wmb();
+	nfp_qcp_ptr_add(txq->qcp_q, NFP_QCP_WRITE_PTR, issued_descs);
+
+	return npkts;
+}
diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h
index ba8ffbd1ff..5c005d74e7 100644
--- a/drivers/net/nfp/nfp_rxtx.h
+++ b/drivers/net/nfp/nfp_rxtx.h
@@ -352,6 +352,9 @@ int nfp_net_nfdk_tx_queue_setup(struct rte_eth_dev *dev,
 		uint16_t nb_desc,
 		unsigned int socket_id,
 		const struct rte_eth_txconf *tx_conf);
+uint16_t nfp_net_nfdk_xmit_pkts(void *tx_queue,
+		struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts);
 
 #endif /* _NFP_RXTX_H_ */
 /*
-- 
2.27.0