From patchwork Fri Aug 16 09:24:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kurt Kanzenbach X-Patchwork-Id: 13765808 X-Patchwork-Delegate: kuba@kernel.org Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2BA9D13CA9C; Fri, 16 Aug 2024 09:24:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800253; cv=none; b=XO6qT2VKEWD6CzGTsskeaOOQQMLzG9zFQLEU9JIkp4tmxlkb7L5OKJ2pFidJcJalEVQrK4eYDgjbSdStoNC1N29e4qaIqjX0aSZzcGNN+2RHH5TqrKwaW3jWR0DZR9PdRWyYZFTVarNP95aBAKcHGZt3XRI9/EZDuU8LKGlklhY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800253; c=relaxed/simple; bh=tW171kOYcZmd4mFk0mRF/gs59thtIlcEIw5cqoowYlM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=r1EcPU4Uw+GXsEgYXAWcwCeNozI/04u5By3tUqEb64tfK+ZuSI0tNgFcQKjCzyPkB1GtWh8Llf2fD9AD2ro3OaYDkcuDf3LX0zrnfalJlLVGB5+f/pxpRvR0KavsZfbR9pYFoySHoYsjnM58ml2rPKt8hW9I2IoF9PMaEnPMtPk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=4nWx4hb/; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=H9SkJjuF; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="4nWx4hb/"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="H9SkJjuF" From: Kurt Kanzenbach DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1723800245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Bak+m2qQoBEQzYHvJmjORRQi4Tj5On9ZejuXC/d+69E=; b=4nWx4hb/K/UsXkzYYqApOvbdCjONyzCjhDLV0UTfrWiF5aqc7Mg8iOH4KIqntZqEtfQ8fQ 9EnwAN8zGcZ7YY3ibyp1mgXqJtR/ltF7NmZ3IFG4EuUmMRUfPKtAAtQpZPnPFqKsd99RMZ R3IU65l/Bz5uUls5OeWrWbV8nGI2Hj6kJM2eL4PY8heZZEPcQ2iqhXGLRInIphwI//sQF/ u+i8aJWoXmNWqPHixCWgU8tAy+HbHGHnjIHvsbFCXi15xylMuhdQch9/YWJ62BKgQ/2T5w 7qTzpQRpWj7Kv0i9+ZoMpK78qLrFamWpNMz9pmDm9YGLhIMCk4sZT6E7yqqAhg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1723800245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Bak+m2qQoBEQzYHvJmjORRQi4Tj5On9ZejuXC/d+69E=; b=H9SkJjuFqaoe6ZVoNMhmPqjEyxboXhrC+eu+p7fL5h/qocsdVStcgpJPEpXBUJmJ5coJnv Qz6WcDCXQkindEDg== Date: Fri, 16 Aug 2024 11:24:00 +0200 Subject: [PATCH iwl-next v6 1/6] igb: Always call igb_xdp_ring_update_tail() under Tx lock Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240711-b4-igb_zero_copy-v6-1-4bfb68773b18@linutronix.de> References: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> In-Reply-To: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> To: Tony Nguyen , Przemek Kitszel Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Richard Cochran , Sriram Yagnaraman , Benjamin Steinke , Sebastian Andrzej Siewior , Maciej Fijalkowski , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Sriram Yagnaraman , Kurt Kanzenbach X-Developer-Signature: v=1; a=openpgp-sha256; l=2300; i=kurt@linutronix.de; h=from:subject:message-id; bh=U6trs47/PyNyJV/m4Ea4yvgs+072UkD6YSCfX6FH6WE=; b=owEBbQKS/ZANAwAKAcGT0fKqRnOCAcsmYgBmvxqyKDiKZjJAp9CblBxFnNhNqSEQqAXGeAt1G 8Dm1VoIpIGJAjMEAAEKAB0WIQS8ub+yyMN909/bWZLBk9HyqkZzggUCZr8asgAKCRDBk9HyqkZz gsL0D/40xSksBfB+rDd3hF91cgxuSCBmJMP2Yyptt0AJ9OVJbG3GfZG9+2/GnXPEgRlt2Sr90aT qcpfeQTrMD9FWWCcFx1jIBfWEPKDPWhvb4C9olgaGviYUlDyufdQWc6kHVHr9l+e6m7ekTOEBf/ XIL5cn1BYbNNJ9/pPftfrdBsxv00Ii+TLBVvP2gvM/6RmSexGUUpFHS+XUb4Cr9d15eWqph0CI9 ua+5S/FT/zOXMhhwdLH3bKbVJEZzDmPYIZVF29624DEeonFIe7BcUrXUKNxwMO4mS4vUPXSirty Nr4idfrE3mhDtA1dbkpnhAdy+IKuJ/wniZym3i/jkY8TxD3Nw43itDId5+nPm8yMjCkADLWwa6G TF+unyg3oXk96+OpunovOGeQ/enwg33OCWvPFI0xJHQheDl7zGGzkx2QEF9vQitmF5Q3OGAgJxG JZ+E3WUu0yGGti6E1VJBLulclFHsnrXgK1hGAfx7O2xvlmNtf/4mB2TYNB6odsNHzWqBZADKlak npMn1vCKsuxIDa7gt1CEqcHSeU5Pvwr8yoibfDTpSEvQmv+yy86fmopSmo45OahZlVDTBd9ou5T C0rt8nuTz6Tgs27Mhz/djNNWuciwsEZ/dudCU/FVE9QaLGj8hwuk7Y4SpEXpY6Cq+40gCIj9qeV w9CD/EYljYdt4gg== X-Developer-Key: i=kurt@linutronix.de; a=openpgp; fpr=BCB9BFB2C8C37DD3DFDB5992C193D1F2AA467382 X-Patchwork-Delegate: kuba@kernel.org From: Sriram Yagnaraman Always call igb_xdp_ring_update_tail() under __netif_tx_lock(), add a comment to indicate that. This is needed to share the same TX ring between XDP, XSK and slow paths. Signed-off-by: Sriram Yagnaraman [Kurt: Split patches] Signed-off-by: Kurt Kanzenbach --- drivers/net/ethernet/intel/igb/igb_main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 11be39f435f3..4d5e5691c9bd 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2914,6 +2914,7 @@ static int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp) } } +/* This function assumes __netif_tx_lock is held by the caller. */ static void igb_xdp_ring_update_tail(struct igb_ring *ring) { /* Force memory writes to complete before letting h/w know there @@ -3000,11 +3001,11 @@ static int igb_xdp_xmit(struct net_device *dev, int n, nxmit++; } - __netif_tx_unlock(nq); - if (unlikely(flags & XDP_XMIT_FLUSH)) igb_xdp_ring_update_tail(tx_ring); + __netif_tx_unlock(nq); + return nxmit; } @@ -8853,12 +8854,14 @@ static void igb_put_rx_buffer(struct igb_ring *rx_ring, static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) { + unsigned int total_bytes = 0, total_packets = 0; struct igb_adapter *adapter = q_vector->adapter; struct igb_ring *rx_ring = q_vector->rx.ring; - struct sk_buff *skb = rx_ring->skb; - unsigned int total_bytes = 0, total_packets = 0; u16 cleaned_count = igb_desc_unused(rx_ring); + struct sk_buff *skb = rx_ring->skb; + int cpu = smp_processor_id(); unsigned int xdp_xmit = 0; + struct netdev_queue *nq; struct xdp_buff xdp; u32 frame_sz = 0; int rx_buf_pgcnt; @@ -8986,7 +8989,10 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) if (xdp_xmit & IGB_XDP_TX) { struct igb_ring *tx_ring = igb_xdp_tx_queue_mapping(adapter); + nq = txring_txq(tx_ring); + __netif_tx_lock(nq, cpu); igb_xdp_ring_update_tail(tx_ring); + __netif_tx_unlock(nq); } u64_stats_update_begin(&rx_ring->rx_syncp); From patchwork Fri Aug 16 09:24:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kurt Kanzenbach X-Patchwork-Id: 13765810 X-Patchwork-Delegate: kuba@kernel.org Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A7E8613D52E; Fri, 16 Aug 2024 09:24:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800255; cv=none; b=Txi1SZ31qhGP1YRNv5bDwgnVv+Yw7ID246izkv9jp3JrnzFWCLKJfCjchGvq62ZA1Rl6dJ2SFNtwCzPZr75dXVIbE2HtdyMTqmee2Y10oEdJxAXkcSDJGqV7CghTHZ9GkQ20Mb9eqLfNZEkg3J0QEqpVIFVC8iHXjQkzOzSLQdc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800255; c=relaxed/simple; bh=cNAWzT2PzGI4DFtjGQKZX+80uudD0zUufetAgGvKfhs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XXam30OApM0anlclglLUKELifaH/5AIUgPyPXUmVvDdzrTZq/vVV2K8aK2goIg0Hb/RiYQymqo9kS+wqB8mner3W+RHE43O+J3vdI9aqferxZRguGyiY5T+vClhAwH9WDmAv8vin4R7/75rsmzfAgBROpkj6Gy+IF2Ca7Ugyynk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=wKbtkrDK; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=QmYs8Qjl; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="wKbtkrDK"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="QmYs8Qjl" From: Kurt Kanzenbach DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1723800246; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ka5fmZDFfq4l5gmlJyy4aVxbHR/oXLEe5oKx0MPza+I=; b=wKbtkrDK6jC5WiK4sQJLB2uj6byjFah+3oEGELxUfDzvpz6IHRVWOb4I+mQwG3PmVxH3LK /zRVBF3sGSeNnZUWTj5qE31Pn31mZt2X09BXjdiarDMlc/+BhU2OKc50IrrNXRwp06OcXz c3X0PVFuucmAF33KNZRGCvX4Jiv9UtDLchkTJgW9ppeabCH88NrOk573PLDMMAUkZRLIOs ljfA4y2IFkptNEVAP31kL2oPorSaT4oB1071Msvrrin4xMBe+KkB64QoxXodljtGcd3iPw AHIhoU+p3n17liIOTCIFxOLy3oKIqGr22krOXbLQzbGPNx84dY7SBN2d3rhdcA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1723800246; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ka5fmZDFfq4l5gmlJyy4aVxbHR/oXLEe5oKx0MPza+I=; b=QmYs8QjlNf3MKVw9Ayp4UGpO/HUFpnPDEY1l+WPWVXRGEspmXnZdCHtXnW1/QfCmbEH6uh HJaxuY1qd3MRakCQ== Date: Fri, 16 Aug 2024 11:24:01 +0200 Subject: [PATCH iwl-next v6 2/6] igb: Remove static qualifiers Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240711-b4-igb_zero_copy-v6-2-4bfb68773b18@linutronix.de> References: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> In-Reply-To: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> To: Tony Nguyen , Przemek Kitszel Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Richard Cochran , Sriram Yagnaraman , Benjamin Steinke , Sebastian Andrzej Siewior , Maciej Fijalkowski , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Sriram Yagnaraman , Kurt Kanzenbach X-Developer-Signature: v=1; a=openpgp-sha256; l=5439; i=kurt@linutronix.de; h=from:subject:message-id; bh=apin6g4hsdf4NqLiu8QsdTbpSf/PzeVDGqokkaQsDfk=; b=owEBbQKS/ZANAwAKAcGT0fKqRnOCAcsmYgBmvxqyDef2JoZaUIIkiPsDCwsP3/qzW9/nJjXSe 9XkowaUVTKJAjMEAAEKAB0WIQS8ub+yyMN909/bWZLBk9HyqkZzggUCZr8asgAKCRDBk9HyqkZz gnL1EACiP2p+EMcDIw9ansl1NH8w6Us9t3PCJaB1TDZ/EptzqLB0nkwm4vLT1nKg02IW4edwmbU oaL00dRSdmFJ02DBujEmWDSKn2BxLJfsqyBqgLr27QqM8Kll8Yp3awGq9M0qcMQQpXl+B80M6Po KgA2yeejlmZASTNjfDq3f1IZzyJAOLBfsTypx4T0tYPFvACxQxktgcy+jGPQJlhqD1c8woZO2eb R9ksKDwk3uPmjXbUbdiwqTiFEIVRbYCUQLOyiLCCOTscwDe5DKSQ+Qg7Q7iufOE2OBm1CU0kqZQ hQwYC9yx5dwaZK0PgmbeQw6AunhGpn/9Vc4S787C1P96EeFMh1ONZ4KAfIDjKgXQb9c49g10Jcn dnIOEEKlY8XMl+tJf6yk+XxDW/kwv7eN+lNLEj072Yd576f82ozswwXiqlmwwc9g1YSEVXij0qz ThtOQO5SBdrLd3TJSlf42K6T1MMz0BKcLkEu9iyOUanNl+Y2G01RDAFX2c3YKMRUfjvvZXtSH24 5F3kK/1RIipDwXIfXv/w4rd5j3ickFKWSXQgn1nN47Al/odyY6DOAB5NiZpai9XCza6nQiZ44VD E/qRCbmCAu1Qa0NBp6aFqzKq0mvTlor/wtkpU323U5Vw73nsnohxBn1L7rHX7ycvWFiPuiaYU9c Pj2Ld+5aPspNAaA== X-Developer-Key: i=kurt@linutronix.de; a=openpgp; fpr=BCB9BFB2C8C37DD3DFDB5992C193D1F2AA467382 X-Patchwork-Delegate: kuba@kernel.org From: Sriram Yagnaraman Remove static qualifiers on the following functions to be able to call from XSK specific file that is added in the later patches: - igb_xdp_tx_queue_mapping() - igb_xdp_ring_update_tail() - igb_clean_tx_ring() - igb_clean_rx_ring() - igb_xdp_xmit_back() - igb_process_skb_fields() Signed-off-by: Sriram Yagnaraman [Kurt: Split patches] Signed-off-by: Kurt Kanzenbach --- drivers/net/ethernet/intel/igb/igb.h | 8 ++++++++ drivers/net/ethernet/intel/igb/igb_main.c | 18 ++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 3c2dc7bdebb5..c718e3d14401 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -718,6 +718,8 @@ extern char igb_driver_name[]; int igb_xmit_xdp_ring(struct igb_adapter *adapter, struct igb_ring *ring, struct xdp_frame *xdpf); +struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter); +void igb_xdp_ring_update_tail(struct igb_ring *ring); int igb_open(struct net_device *netdev); int igb_close(struct net_device *netdev); int igb_up(struct igb_adapter *); @@ -731,12 +733,18 @@ int igb_setup_tx_resources(struct igb_ring *); int igb_setup_rx_resources(struct igb_ring *); void igb_free_tx_resources(struct igb_ring *); void igb_free_rx_resources(struct igb_ring *); +void igb_clean_tx_ring(struct igb_ring *tx_ring); +void igb_clean_rx_ring(struct igb_ring *rx_ring); void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *); void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *); void igb_setup_tctl(struct igb_adapter *); void igb_setup_rctl(struct igb_adapter *); void igb_setup_srrctl(struct igb_adapter *, struct igb_ring *); netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *); +int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp); +void igb_process_skb_fields(struct igb_ring *rx_ring, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb); void igb_alloc_rx_buffers(struct igb_ring *, u16); void igb_update_stats(struct igb_adapter *); bool igb_has_link(struct igb_adapter *adapter); diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 4d5e5691c9bd..0b81665b2478 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -115,8 +115,6 @@ static void igb_configure_tx(struct igb_adapter *); static void igb_configure_rx(struct igb_adapter *); static void igb_clean_all_tx_rings(struct igb_adapter *); static void igb_clean_all_rx_rings(struct igb_adapter *); -static void igb_clean_tx_ring(struct igb_ring *); -static void igb_clean_rx_ring(struct igb_ring *); static void igb_set_rx_mode(struct net_device *); static void igb_update_phy_info(struct timer_list *); static void igb_watchdog(struct timer_list *); @@ -2915,7 +2913,7 @@ static int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp) } /* This function assumes __netif_tx_lock is held by the caller. */ -static void igb_xdp_ring_update_tail(struct igb_ring *ring) +void igb_xdp_ring_update_tail(struct igb_ring *ring) { /* Force memory writes to complete before letting h/w know there * are new descriptors to fetch. @@ -2924,7 +2922,7 @@ static void igb_xdp_ring_update_tail(struct igb_ring *ring) writel(ring->next_to_use, ring->tail); } -static struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter) +struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter) { unsigned int r_idx = smp_processor_id(); @@ -2934,7 +2932,7 @@ static struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter) return adapter->tx_ring[r_idx]; } -static int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp) +int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp) { struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); int cpu = smp_processor_id(); @@ -4880,7 +4878,7 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter) * igb_clean_tx_ring - Free Tx Buffers * @tx_ring: ring to be cleaned **/ -static void igb_clean_tx_ring(struct igb_ring *tx_ring) +void igb_clean_tx_ring(struct igb_ring *tx_ring) { u16 i = tx_ring->next_to_clean; struct igb_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; @@ -4999,7 +4997,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter) * igb_clean_rx_ring - Free Rx Buffers per Queue * @rx_ring: ring to free buffers from **/ -static void igb_clean_rx_ring(struct igb_ring *rx_ring) +void igb_clean_rx_ring(struct igb_ring *rx_ring) { u16 i = rx_ring->next_to_clean; @@ -8768,9 +8766,9 @@ static bool igb_cleanup_headers(struct igb_ring *rx_ring, * order to populate the hash, checksum, VLAN, timestamp, protocol, and * other fields within the skb. **/ -static void igb_process_skb_fields(struct igb_ring *rx_ring, - union e1000_adv_rx_desc *rx_desc, - struct sk_buff *skb) +void igb_process_skb_fields(struct igb_ring *rx_ring, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) { struct net_device *dev = rx_ring->netdev; From patchwork Fri Aug 16 09:24:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kurt Kanzenbach X-Patchwork-Id: 13765811 X-Patchwork-Delegate: kuba@kernel.org Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5181A13F428; Fri, 16 Aug 2024 09:24:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800256; cv=none; b=UIMEAYhTkdNhtpHgwUG69jYyIy/OE1/J5Fn70ne6GauFqfikJlIsSF8iHijjAU6ZxyFcI180Xj91lPFhM+6ZzOsueJFncG2XNISTWIo77RDLeARgl6MNdhuDc1EWKy8TkwhYW+86DZeXZLoBnTf8elXAfbNjG3ulIhNc3p3FlbQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800256; c=relaxed/simple; bh=cgdjYkD6a4jg5Bm1eLGelKxrpHdkfMFAk04EW5Zt90E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iyf4Yr0e5+qn5LwCMzXcFmaPGwtrCAX9fGNFE6ieufNd80uiOZrjm+CXrB9lK6hSQQzZBY19ifX0hapn79UDihjZodJJ9OG0XG0uyu3aLH5mWWuALOs/x39+2OuLTXNkdErKlf8AzoSMtZ7+++01273vVUhWEQBoM12rwBgk2hk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=POsw0eHq; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=4Om9ccw7; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="POsw0eHq"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="4Om9ccw7" From: Kurt Kanzenbach DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1723800246; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c+fPaZ+j1KtvWllGwHu58X7smPAoZP18kh5OqiYAz+I=; b=POsw0eHq5BHj6AfCKZPeS1oRq9IAT+LmaHOofJHg1bIOO0k1EJYVHG312hbSRv4nH+y4F0 z+NzFS1WCdpji0Najvab2NTxrKNOsPR4/9LfImwZLFP9bwmw0gPqRlwTDPiA509LZdZy5h jKY4IIt7WGAJDoqdenCsRgqEA+KdmH1dZSEllWQ/3dFzIFLVwC8nVYT29zUJXX+tSHQ0cM n+R+5URQjum5dMAFE05nIPGTumDOMt7OC29x+4gud1URPyTOlbWbee1UI35fPvMjtcbzFd gqd1sfIJEVosul0Gqx07t9+UHM4Q7fwGiS2pianJZL+7y6GanNdMJICfNA8rhQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1723800246; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c+fPaZ+j1KtvWllGwHu58X7smPAoZP18kh5OqiYAz+I=; b=4Om9ccw7A03ClFUtdIkCKEbmRJ39+oj3Pl01XhyQVkA33BanIi2BCeZh8la8yqB2kd66on Jty1PokyvTf1xQCw== Date: Fri, 16 Aug 2024 11:24:02 +0200 Subject: [PATCH iwl-next v6 3/6] igb: Introduce igb_xdp_is_enabled() Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240711-b4-igb_zero_copy-v6-3-4bfb68773b18@linutronix.de> References: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> In-Reply-To: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> To: Tony Nguyen , Przemek Kitszel Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Richard Cochran , Sriram Yagnaraman , Benjamin Steinke , Sebastian Andrzej Siewior , Maciej Fijalkowski , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Sriram Yagnaraman , Kurt Kanzenbach X-Developer-Signature: v=1; a=openpgp-sha256; l=2635; i=kurt@linutronix.de; h=from:subject:message-id; bh=diD1pMkZnZRJQC5ME9B282Jyhc0fUmv3nNbZJfwcJuk=; b=owEBbQKS/ZANAwAKAcGT0fKqRnOCAcsmYgBmvxqySlt8QUGbkalaDsiIfloKTu54OvXAvkQ67 GTTfmmJ7hSJAjMEAAEKAB0WIQS8ub+yyMN909/bWZLBk9HyqkZzggUCZr8asgAKCRDBk9HyqkZz ghLDD/9RpfDyD+574KnaAjvfzZfpdrRNgysAj7c/E8OKLS1Q1r/yTvNR8F+Wu+YhDU2pzrV9kIw xVAcke9A01wViooZYToFx4igoegyIwyUdiGvDAL5tORl9NkkqKkWL4hph/MQ/lMTlBRyon1RUrm q3NfBl5LUc1HvXuQTEMeRTecxLxxX751x5WbLQWKfg+OC1WgyzPlC+vqPmhox3vWU5qAQlHjnjX EXbn8jIjtxw3DOIqvvGnQxEQxQVWhKqICueHiShQ+S4JpTrfy1P7JTO73aLngbmoSYlItq3lU0I p6N21xTUR59jJxWBlcjyYSuNOOfE4V0QXKuow7dT/8XJxhV554YBRdCqa/4dubVDYoOKQAPzBYr B2nZQD2sj3PYt5Q3kIXNxXGixEDd68re482QAmdz09+MdZanj0EvlQkZIpStoes7aueL+wpnQ+i 2el5F2DpZyx4pJEL5ayQRzNc3lklvjmClU3ksZDWExiU/k1hHaoO7/F9REuJtTyYsXsWIMeTUuh KSCsiJKA/v9xh/WWFozUWda5ff/dXoJuj75R8dpcMD+dONrvN6NRFpnBm09stasWHh7pBCsujJf UloxP020z0Z5BvlCELsn+hqK7FiDTwnzD697zvrxGFhSrchd7LOR0tF/TTRMVdPmglO1YyjYKu+ ZYetxNiiVLAo9Hg== X-Developer-Key: i=kurt@linutronix.de; a=openpgp; fpr=BCB9BFB2C8C37DD3DFDB5992C193D1F2AA467382 X-Patchwork-Delegate: kuba@kernel.org From: Sriram Yagnaraman Introduce igb_xdp_is_enabled() to check if an XDP program is assigned to the device. Use that wherever xdp_prog is read and evaluated. Signed-off-by: Sriram Yagnaraman [Kurt: Split patches and use READ_ONCE()] Signed-off-by: Kurt Kanzenbach Acked-by: Maciej Fijalkowski --- drivers/net/ethernet/intel/igb/igb.h | 5 +++++ drivers/net/ethernet/intel/igb/igb_main.c | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index c718e3d14401..dbba193241b9 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -805,6 +805,11 @@ static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring) return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index); } +static inline bool igb_xdp_is_enabled(struct igb_adapter *adapter) +{ + return !!READ_ONCE(adapter->xdp_prog); +} + int igb_add_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input); int igb_erase_filter(struct igb_adapter *adapter, diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 0b81665b2478..db1598876424 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2946,7 +2946,8 @@ int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp) /* During program transitions its possible adapter->xdp_prog is assigned * but ring has not been configured yet. In this case simply abort xmit. */ - tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL; + tx_ring = igb_xdp_is_enabled(adapter) ? + igb_xdp_tx_queue_mapping(adapter) : NULL; if (unlikely(!tx_ring)) return IGB_XDP_CONSUMED; @@ -2979,7 +2980,8 @@ static int igb_xdp_xmit(struct net_device *dev, int n, /* During program transitions its possible adapter->xdp_prog is assigned * but ring has not been configured yet. In this case simply abort xmit. */ - tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL; + tx_ring = igb_xdp_is_enabled(adapter) ? + igb_xdp_tx_queue_mapping(adapter) : NULL; if (unlikely(!tx_ring)) return -ENXIO; @@ -6612,7 +6614,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) struct igb_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + IGB_ETH_PKT_HDR_PAD; - if (adapter->xdp_prog) { + if (igb_xdp_is_enabled(adapter)) { int i; for (i = 0; i < adapter->num_rx_queues; i++) { From patchwork Fri Aug 16 09:24:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kurt Kanzenbach X-Patchwork-Id: 13765812 X-Patchwork-Delegate: kuba@kernel.org Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 517D613F426; Fri, 16 Aug 2024 09:24:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800256; cv=none; b=ULeSbUsSfxX/E0CPFKILqZdv1dWvcMkve3y/AHcC60n1mqMPAoYYDmkAgIS4+f69JxyHKo6X6wIdhAY32ihhpL44irBMNQ34NKBihGm6SiS/1PH4k/LYUxovkCTFydDA3dgKBbtvK2oNI1Go3PKGt7lfbdiszQDNI37pVE/1ZnA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800256; c=relaxed/simple; bh=zwqVV72Zbny6oJwgOYdzdOqVoBp8a4C1br611q5SXXA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j/rs70uNDXdZy6dHTMl2pXiY+fJncdSFIWXdFoWsHxQpUBkUKbj0enCKY1m3JVOS2XPe4rd95LRZD3Ki88Q8Uqn5nP9KW3P53AzFLxABg5MvSZqd9YLpsQa+1ccvPZoXyADaq7wev41UWnN7EII+3Jl0In0qQPAwhFEWOUPHzUE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ldmwSP7l; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=NqyEh+An; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ldmwSP7l"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="NqyEh+An" From: Kurt Kanzenbach DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1723800247; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4RaBDnckgLsEADXQ5SmWoAlA9svRPFOwL49saaqXgkw=; b=ldmwSP7laHsNK8fZ8Eb9KmgHBaF0JKP40CNNJ4lphatYBIDbfRSOhR+DMKM6QuC3p0/Okp USxSM1aqDNd2NkLQV2cJf1FAyVTxgOkiEQ3TRzMYbY8xjbcZoYDRLGT0EfdG0z/aimQLh4 pjfz3DfliSTLejWslvvUlsfPzee2pmnEvxdXmClP8ANHLwcymAFqNL8NrK4pCHFzvmO14B eaGT+eLuUWLBR6MmbdGEwMXjmFtzwXKIbOfWSc0+4/o93f095sg8OWWiyTFVyZbwUEhPyo /giIBL293Pd4eb4Nq8Q3Rb+bdAptPrB7SOgplDx8HNtKBetYnVc0u+qrG16GoA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1723800247; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4RaBDnckgLsEADXQ5SmWoAlA9svRPFOwL49saaqXgkw=; b=NqyEh+AnRixwFos1pA6pmbaSxp466dPyPahBqt9mbt4QUBuV0/Las2pFm5hfI8XJ7xTGmn UwWI6EtnmXc3T2CA== Date: Fri, 16 Aug 2024 11:24:03 +0200 Subject: [PATCH iwl-next v6 4/6] igb: Introduce XSK data structures and helpers Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240711-b4-igb_zero_copy-v6-4-4bfb68773b18@linutronix.de> References: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> In-Reply-To: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> To: Tony Nguyen , Przemek Kitszel Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Richard Cochran , Sriram Yagnaraman , Benjamin Steinke , Sebastian Andrzej Siewior , Maciej Fijalkowski , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Sriram Yagnaraman , Kurt Kanzenbach X-Developer-Signature: v=1; a=openpgp-sha256; l=10214; i=kurt@linutronix.de; h=from:subject:message-id; bh=RKBGCq7JD2rG3Y9Ymi6uliDDlkk8sghR1sc8hDYXu1w=; b=owEBbQKS/ZANAwAKAcGT0fKqRnOCAcsmYgBmvxqy0i3lA7k2UlCI2iIs3y43SStz0NiVlN9/R F1H1tyOL/yJAjMEAAEKAB0WIQS8ub+yyMN909/bWZLBk9HyqkZzggUCZr8asgAKCRDBk9HyqkZz gpZmD/9x1W+FaTDDaCkxXg+q2smJuZVPJQKb4xVdzudULPB1uUeiDWD0EByoY3r4eAuGX1dy7py zMkH1NwSnNiCFuLzeK+VizI7lLk4PFfhFDV6WSGo4T3vVTn9oA3UWZrJuUciEXbflNkht77qjX2 n5OT1FMOnNXliSXa3vvpfGOTwzH5YxVdYbO87zccH/dw5I9OeqLTNJmj3QBjSfmVFM7aw4TBJkB eOH1Fp8SzFaISTIUIDSIfq9f6cESfCgTCO/Xa9PwMTMo+xgw4cSZHaKfaBW9oNqNJj1og6NJdAq IJUl8QuEjf3dG54Xxb6EeGxq2AC8RZwR/Ejfuo1HPHn9w8qHOVFRneb8cFP0clTwmFYY2KJySMD YlmP2yI43/jEakG8oK0zh/+buf0ECh5wEbD41UTFjQ+9Egu9dZtiASvQhMSl7cVvPxM2zfnz7MP CO+d+vr75yu4eBHophJC8/wh3LlPTh+lOKdtrd3/kK8igC0FB/0U/AmjDSNVSc6EOSnASyDE1TY ZAUxsEA954Ar35n6tA21mEEykH6SQjHJrRkBzS+Q0YtJfJEjfGaz8wemXYSm30TeA0QRvumUPyo vcGrEl0wmcncSzBDhPVxfa86uKPT/5yBp4QAauXcJLdCB6xJF09dNU6/92gH1U5fUnh8wJrVABm 6/PQ9eXfTCxFmng== X-Developer-Key: i=kurt@linutronix.de; a=openpgp; fpr=BCB9BFB2C8C37DD3DFDB5992C193D1F2AA467382 X-Patchwork-Delegate: kuba@kernel.org From: Sriram Yagnaraman Add the following ring flag: - IGB_RING_FLAG_TX_DISABLED (when xsk pool is being setup) Add a xdp_buff array for use with XSK receive batch API, and a pointer to xsk_pool in igb_adapter. Add enable/disable functions for TX and RX rings. Add enable/disable functions for XSK pool. Add xsk wakeup function. None of the above functionality will be active until NETDEV_XDP_ACT_XSK_ZEROCOPY is advertised in netdev->xdp_features. Signed-off-by: Sriram Yagnaraman [Kurt: Add READ/WRITE_ONCE(), synchronize_net(), remove IGB_RING_FLAG_AF_XDP_ZC] Signed-off-by: Kurt Kanzenbach Reviewed-by: Maciej Fijalkowski --- drivers/net/ethernet/intel/igb/Makefile | 2 +- drivers/net/ethernet/intel/igb/igb.h | 13 +- drivers/net/ethernet/intel/igb/igb_main.c | 9 ++ drivers/net/ethernet/intel/igb/igb_xsk.c | 207 ++++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile index 463c0d26b9d4..6c1b702fd992 100644 --- a/drivers/net/ethernet/intel/igb/Makefile +++ b/drivers/net/ethernet/intel/igb/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_IGB) += igb.o igb-y := igb_main.o igb_ethtool.o e1000_82575.o \ e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \ - e1000_i210.o igb_ptp.o igb_hwmon.o + e1000_i210.o igb_ptp.o igb_hwmon.o igb_xsk.o diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index dbba193241b9..8db5b44b4576 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -20,6 +20,7 @@ #include #include +#include struct igb_adapter; @@ -320,6 +321,7 @@ struct igb_ring { union { /* array of buffer info structs */ struct igb_tx_buffer *tx_buffer_info; struct igb_rx_buffer *rx_buffer_info; + struct xdp_buff **rx_buffer_info_zc; }; void *desc; /* descriptor ring memory */ unsigned long flags; /* ring specific flags */ @@ -357,6 +359,7 @@ struct igb_ring { }; }; struct xdp_rxq_info xdp_rxq; + struct xsk_buff_pool *xsk_pool; } ____cacheline_internodealigned_in_smp; struct igb_q_vector { @@ -384,7 +387,8 @@ enum e1000_ring_flags_t { IGB_RING_FLAG_RX_SCTP_CSUM, IGB_RING_FLAG_RX_LB_VLAN_BSWAP, IGB_RING_FLAG_TX_CTX_IDX, - IGB_RING_FLAG_TX_DETECT_HANG + IGB_RING_FLAG_TX_DETECT_HANG, + IGB_RING_FLAG_TX_DISABLED }; #define ring_uses_large_buffer(ring) \ @@ -820,4 +824,11 @@ int igb_add_mac_steering_filter(struct igb_adapter *adapter, int igb_del_mac_steering_filter(struct igb_adapter *adapter, const u8 *addr, u8 queue, u8 flags); +struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter, + struct igb_ring *ring); +int igb_xsk_pool_setup(struct igb_adapter *adapter, + struct xsk_buff_pool *pool, + u16 qid); +int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags); + #endif /* _IGB_H_ */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index db1598876424..9234c768a600 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2904,9 +2904,14 @@ static int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf) static int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp) { + struct igb_adapter *adapter = netdev_priv(dev); + switch (xdp->command) { case XDP_SETUP_PROG: return igb_xdp_setup(dev, xdp); + case XDP_SETUP_XSK_POOL: + return igb_xsk_pool_setup(adapter, xdp->xsk.pool, + xdp->xsk.queue_id); default: return -EINVAL; } @@ -3035,6 +3040,7 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_setup_tc = igb_setup_tc, .ndo_bpf = igb_xdp, .ndo_xdp_xmit = igb_xdp_xmit, + .ndo_xsk_wakeup = igb_xsk_wakeup, }; /** @@ -4357,6 +4363,8 @@ void igb_configure_tx_ring(struct igb_adapter *adapter, u64 tdba = ring->dma; int reg_idx = ring->reg_idx; + WRITE_ONCE(ring->xsk_pool, igb_xsk_pool(adapter, ring)); + wr32(E1000_TDLEN(reg_idx), ring->count * sizeof(union e1000_adv_tx_desc)); wr32(E1000_TDBAL(reg_idx), @@ -4752,6 +4760,7 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, MEM_TYPE_PAGE_SHARED, NULL)); + WRITE_ONCE(ring->xsk_pool, igb_xsk_pool(adapter, ring)); /* disable the queue */ wr32(E1000_RXDCTL(reg_idx), 0); diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c new file mode 100644 index 000000000000..7b632be3e7e3 --- /dev/null +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2018 Intel Corporation. */ + +#include +#include +#include + +#include "e1000_hw.h" +#include "igb.h" + +static int igb_realloc_rx_buffer_info(struct igb_ring *ring, bool pool_present) +{ + int size = pool_present ? + sizeof(*ring->rx_buffer_info_zc) * ring->count : + sizeof(*ring->rx_buffer_info) * ring->count; + void *buff_info = vmalloc(size); + + if (!buff_info) + return -ENOMEM; + + if (pool_present) { + vfree(ring->rx_buffer_info); + ring->rx_buffer_info = NULL; + ring->rx_buffer_info_zc = buff_info; + } else { + vfree(ring->rx_buffer_info_zc); + ring->rx_buffer_info_zc = NULL; + ring->rx_buffer_info = buff_info; + } + + return 0; +} + +static void igb_txrx_ring_disable(struct igb_adapter *adapter, u16 qid) +{ + struct igb_ring *tx_ring = adapter->tx_ring[qid]; + struct igb_ring *rx_ring = adapter->rx_ring[qid]; + struct e1000_hw *hw = &adapter->hw; + + set_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags); + + wr32(E1000_TXDCTL(tx_ring->reg_idx), 0); + wr32(E1000_RXDCTL(rx_ring->reg_idx), 0); + + synchronize_net(); + + /* Rx/Tx share the same napi context. */ + napi_disable(&rx_ring->q_vector->napi); + + igb_clean_tx_ring(tx_ring); + igb_clean_rx_ring(rx_ring); + + memset(&rx_ring->rx_stats, 0, sizeof(rx_ring->rx_stats)); + memset(&tx_ring->tx_stats, 0, sizeof(tx_ring->tx_stats)); +} + +static void igb_txrx_ring_enable(struct igb_adapter *adapter, u16 qid) +{ + struct igb_ring *tx_ring = adapter->tx_ring[qid]; + struct igb_ring *rx_ring = adapter->rx_ring[qid]; + + igb_configure_tx_ring(adapter, tx_ring); + igb_configure_rx_ring(adapter, rx_ring); + + synchronize_net(); + + clear_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags); + + /* call igb_desc_unused which always leaves + * at least 1 descriptor unused to make sure + * next_to_use != next_to_clean + */ + igb_alloc_rx_buffers(rx_ring, igb_desc_unused(rx_ring)); + + /* Rx/Tx share the same napi context. */ + napi_enable(&rx_ring->q_vector->napi); +} + +struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter, + struct igb_ring *ring) +{ + int qid = ring->queue_index; + struct xsk_buff_pool *pool; + + pool = xsk_get_pool_from_qid(adapter->netdev, qid); + + if (!igb_xdp_is_enabled(adapter)) + return NULL; + + return (pool && pool->dev) ? pool : NULL; +} + +static int igb_xsk_pool_enable(struct igb_adapter *adapter, + struct xsk_buff_pool *pool, + u16 qid) +{ + struct net_device *netdev = adapter->netdev; + struct igb_ring *rx_ring; + bool if_running; + int err; + + if (qid >= adapter->num_rx_queues) + return -EINVAL; + + if (qid >= netdev->real_num_rx_queues || + qid >= netdev->real_num_tx_queues) + return -EINVAL; + + err = xsk_pool_dma_map(pool, &adapter->pdev->dev, IGB_RX_DMA_ATTR); + if (err) + return err; + + rx_ring = adapter->rx_ring[qid]; + if_running = netif_running(adapter->netdev) && igb_xdp_is_enabled(adapter); + if (if_running) + igb_txrx_ring_disable(adapter, qid); + + if (if_running) { + err = igb_realloc_rx_buffer_info(rx_ring, true); + if (!err) { + igb_txrx_ring_enable(adapter, qid); + /* Kick start the NAPI context so that receiving will start */ + err = igb_xsk_wakeup(adapter->netdev, qid, XDP_WAKEUP_RX); + } + + if (err) { + xsk_pool_dma_unmap(pool, IGB_RX_DMA_ATTR); + return err; + } + } + + return 0; +} + +static int igb_xsk_pool_disable(struct igb_adapter *adapter, u16 qid) +{ + struct xsk_buff_pool *pool; + struct igb_ring *rx_ring; + bool if_running; + int err; + + pool = xsk_get_pool_from_qid(adapter->netdev, qid); + if (!pool) + return -EINVAL; + + rx_ring = adapter->rx_ring[qid]; + if_running = netif_running(adapter->netdev) && igb_xdp_is_enabled(adapter); + if (if_running) + igb_txrx_ring_disable(adapter, qid); + + xsk_pool_dma_unmap(pool, IGB_RX_DMA_ATTR); + + if (if_running) { + err = igb_realloc_rx_buffer_info(rx_ring, false); + if (err) + return err; + + igb_txrx_ring_enable(adapter, qid); + } + + return 0; +} + +int igb_xsk_pool_setup(struct igb_adapter *adapter, + struct xsk_buff_pool *pool, + u16 qid) +{ + return pool ? igb_xsk_pool_enable(adapter, pool, qid) : + igb_xsk_pool_disable(adapter, qid); +} + +int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags) +{ + struct igb_adapter *adapter = netdev_priv(dev); + struct e1000_hw *hw = &adapter->hw; + struct igb_ring *ring; + u32 eics = 0; + + if (test_bit(__IGB_DOWN, &adapter->state)) + return -ENETDOWN; + + if (!igb_xdp_is_enabled(adapter)) + return -EINVAL; + + if (qid >= adapter->num_tx_queues) + return -EINVAL; + + ring = adapter->tx_ring[qid]; + + if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags)) + return -ENETDOWN; + + if (!READ_ONCE(ring->xsk_pool)) + return -EINVAL; + + if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) { + /* Cause software interrupt */ + if (adapter->flags & IGB_FLAG_HAS_MSIX) { + eics |= ring->q_vector->eims_value; + wr32(E1000_EICS, eics); + } else { + wr32(E1000_ICS, E1000_ICS_RXDMT0); + } + } + + return 0; +} From patchwork Fri Aug 16 09:24:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kurt Kanzenbach X-Patchwork-Id: 13765814 X-Patchwork-Delegate: kuba@kernel.org Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A5F0143873; Fri, 16 Aug 2024 09:24:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800257; cv=none; b=cN0OQiFBSDjBtyJz3nAYTbqJPTdCPHiLtpTCQoknnHv3156evGMFGf8JGn/ZzvaXgNOFIb6bZ3M+5liGPLiWJ442LtRkCSxMu+KcJWecNf5U5HGtn2p9f5JNy6gYfSxLnVn0XrScmHnupfnUWZEMJJ1zgjXH9TABGEFAOdQkvnY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800257; c=relaxed/simple; bh=OcrbpsyFFFmuq+lX6/r7H0uY+hgS06WCPMhJ1IaGCvk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=texeg3thszyCqEgh5jOB8nK9Iac4KcQ9SuWZnLALJtBpvPCh9jlG9FCcbULysBi60hw6d6klSp2IvhxcO1QKagIopU/pD4Pcjf89Q0Wcs0W6lLpeHjmISoQLzKwgt4P72+qHDCwyUdjO+tDhzfFxMAl4Ip7w3SKHdlqZBud2+4s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=MkgQU6nJ; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=eZObyBYc; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="MkgQU6nJ"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="eZObyBYc" From: Kurt Kanzenbach DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1723800248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZaR8iEzX7KBsYHzVBJx2Y4+FMFVonSVh7MepxUI1Uo4=; b=MkgQU6nJO/UmNWYpuy7ipYwVolmNY2F/g/WO2QaRvKkK6bwBI3AO1wqKkA//jvXLck8aGT owPYoM+IwfuULYkL7MuGe8dCL99dZ0uG1zVJX8QTsxMyesohI7ETRh8jEt59lcUR8Eqi+E MNaca1zDPrrz1jg+HNsKZDNM0NdGgGeoLnjnGNeQRTR+FwFRf3dmP1fTH9HWKjf8jqOfgz JoM3Tu9lPQBsl7FGtG7bff+1+ObEO9z9dNsUNqK+Oz6a9JuZfFQFl4hn3TUAhlf/Wb4F/+ TElNvgw7pwbzvLYiYjhj3pHDF1fnmSwVFb3PElTdxj3N6X7A4BmLCUUw+LdKlg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1723800248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZaR8iEzX7KBsYHzVBJx2Y4+FMFVonSVh7MepxUI1Uo4=; b=eZObyBYcV4umnHOEWZlnW8ficzoDiglcy3hyQAkBnIf4ACZ/6JHgyqjcY+5JnnhbB73hKf Um7DcqtsVLAKv3Bw== Date: Fri, 16 Aug 2024 11:24:04 +0200 Subject: [PATCH iwl-next v6 5/6] igb: Add AF_XDP zero-copy Rx support Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240711-b4-igb_zero_copy-v6-5-4bfb68773b18@linutronix.de> References: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> In-Reply-To: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> To: Tony Nguyen , Przemek Kitszel Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Richard Cochran , Sriram Yagnaraman , Benjamin Steinke , Sebastian Andrzej Siewior , Maciej Fijalkowski , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Sriram Yagnaraman , Kurt Kanzenbach X-Developer-Signature: v=1; a=openpgp-sha256; l=19393; i=kurt@linutronix.de; h=from:subject:message-id; bh=5r7fS6lGQuqUz3aHw5lemeFtOV/4tvxLVskoSIdYHa0=; b=owEBbQKS/ZANAwAKAcGT0fKqRnOCAcsmYgBmvxqz8NDUVHsYSs0i2+MCnLVG5r7xnbhHo20B2 rKJ9Mv0MHSJAjMEAAEKAB0WIQS8ub+yyMN909/bWZLBk9HyqkZzggUCZr8aswAKCRDBk9HyqkZz guK0D/9YawkZ7tnQN/npgs6ZWQ6X/0Qz3dqS+iCXuLoYyluO+cB+JHpltGOw3sCY2eJci5/yA2y fvPGW/VYr8Nu5/dJP4Z2Qe7uPrd6FZVsx855hVt5ki9nfZoNLSDsXcJiK81xnYXTWR66HyDhPtF kQCQ86cXhh6faYbW6poF+9bzpHWrLcngkSwZgECrJe2PYsSaYSfVTPF/lIHIrJv/ZrWJ6yzcJC6 A9xsGl+DYOkMoHcv2F8uO6MhJ0FncrEdNt8VPDqQ/SHShJbW+wzyHdHeIV4cWQhZN/in/dgBbi3 hYNEeCSjTXuEQ/R4QJqTHw4WrI/RncyJv3LJqPLd6xkjYjxIlINa8me+7gZ0ETZtxLUZk/mXWBa e36VnxjNuLl8jIb8PgA7UHafnqv92bWVIB1MTyhh9WjspsocEKSKIdJAp4NmTMO7GuFeNjfOx8P 8VHuSamZ2xMcdpOnPJkX63dIeFhUYY1FQHF7o2AQl3Fxs7WgFBUAh+R6G5cfFNHvZ+eQxmjhpbE tL2qOns/o5gJZJbJdvK6f5jlCEzat5uNCTB2tfGrGdE39mbYlYVYuV5V4vZ6oWR45cJtKbSrKSq C0/i8N59z7Cumj4CTZOFqTRe+puM8FL+boe6nsaX78s3SEEUyn6B2q0gvaeqcD4avA5uvzIrbbs nCLf1FnolYJCLMg== X-Developer-Key: i=kurt@linutronix.de; a=openpgp; fpr=BCB9BFB2C8C37DD3DFDB5992C193D1F2AA467382 X-Patchwork-Delegate: kuba@kernel.org From: Sriram Yagnaraman Add support for AF_XDP zero-copy receive path. When AF_XDP zero-copy is enabled, the rx buffers are allocated from the xsk buff pool using igb_alloc_rx_buffers_zc(). Use xsk_pool_get_rx_frame_size() to set SRRCTL rx buf size when zero-copy is enabled. Signed-off-by: Sriram Yagnaraman [Kurt: Port to v6.10 and provide napi_id for xdp_rxq_info_reg(), RCT, remove NETDEV_XDP_ACT_XSK_ZEROCOPY, update NTC handling, move stats update and xdp finalize to common functions, READ_ONCE() xsk_pool, likelyfy for XDP_REDIRECT case] Signed-off-by: Kurt Kanzenbach --- drivers/net/ethernet/intel/igb/igb.h | 8 + drivers/net/ethernet/intel/igb/igb_main.c | 132 +++++++++---- drivers/net/ethernet/intel/igb/igb_xsk.c | 297 +++++++++++++++++++++++++++++- 3 files changed, 399 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 8db5b44b4576..348f32f4c11c 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -87,6 +87,7 @@ struct igb_adapter; #define IGB_XDP_CONSUMED BIT(0) #define IGB_XDP_TX BIT(1) #define IGB_XDP_REDIR BIT(2) +#define IGB_XDP_EXIT BIT(3) struct vf_data_storage { unsigned char vf_mac_addresses[ETH_ALEN]; @@ -741,6 +742,9 @@ void igb_clean_tx_ring(struct igb_ring *tx_ring); void igb_clean_rx_ring(struct igb_ring *rx_ring); void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *); void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *); +void igb_finalize_xdp(struct igb_adapter *adapter, unsigned int status); +void igb_update_rx_stats(struct igb_q_vector *q_vector, unsigned int packets, + unsigned int bytes); void igb_setup_tctl(struct igb_adapter *); void igb_setup_rctl(struct igb_adapter *); void igb_setup_srrctl(struct igb_adapter *, struct igb_ring *); @@ -829,6 +833,10 @@ struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter, int igb_xsk_pool_setup(struct igb_adapter *adapter, struct xsk_buff_pool *pool, u16 qid); +bool igb_alloc_rx_buffers_zc(struct igb_ring *rx_ring, u16 count); +void igb_clean_rx_ring_zc(struct igb_ring *rx_ring); +int igb_clean_rx_irq_zc(struct igb_q_vector *q_vector, + struct xsk_buff_pool *xsk_pool, const int budget); int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags); #endif /* _IGB_H_ */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 9234c768a600..063ba0144dfd 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -472,12 +472,17 @@ static void igb_dump(struct igb_adapter *adapter) for (i = 0; i < rx_ring->count; i++) { const char *next_desc; - struct igb_rx_buffer *buffer_info; - buffer_info = &rx_ring->rx_buffer_info[i]; + dma_addr_t dma = (dma_addr_t)0; + struct igb_rx_buffer *buffer_info = NULL; rx_desc = IGB_RX_DESC(rx_ring, i); u0 = (struct my_u0 *)rx_desc; staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + if (!rx_ring->xsk_pool) { + buffer_info = &rx_ring->rx_buffer_info[i]; + dma = buffer_info->dma; + } + if (i == rx_ring->next_to_use) next_desc = " NTU"; else if (i == rx_ring->next_to_clean) @@ -497,11 +502,11 @@ static void igb_dump(struct igb_adapter *adapter) "R ", i, le64_to_cpu(u0->a), le64_to_cpu(u0->b), - (u64)buffer_info->dma, + (u64)dma, next_desc); if (netif_msg_pktdata(adapter) && - buffer_info->dma && buffer_info->page) { + buffer_info && dma && buffer_info->page) { print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, @@ -1983,7 +1988,10 @@ static void igb_configure(struct igb_adapter *adapter) */ for (i = 0; i < adapter->num_rx_queues; i++) { struct igb_ring *ring = adapter->rx_ring[i]; - igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); + if (ring->xsk_pool) + igb_alloc_rx_buffers_zc(ring, igb_desc_unused(ring)); + else + igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); } } @@ -4425,7 +4433,8 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring) if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq)) xdp_rxq_info_unreg(&rx_ring->xdp_rxq); res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, - rx_ring->queue_index, 0); + rx_ring->queue_index, + rx_ring->q_vector->napi.napi_id); if (res < 0) { dev_err(dev, "Failed to register xdp_rxq index %u\n", rx_ring->queue_index); @@ -4721,12 +4730,17 @@ void igb_setup_srrctl(struct igb_adapter *adapter, struct igb_ring *ring) struct e1000_hw *hw = &adapter->hw; int reg_idx = ring->reg_idx; u32 srrctl = 0; + u32 buf_size; - srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; - if (ring_uses_large_buffer(ring)) - srrctl |= IGB_RXBUFFER_3072 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + if (ring->xsk_pool) + buf_size = xsk_pool_get_rx_frame_size(ring->xsk_pool); + else if (ring_uses_large_buffer(ring)) + buf_size = IGB_RXBUFFER_3072; else - srrctl |= IGB_RXBUFFER_2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + buf_size = IGB_RXBUFFER_2048; + + srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; + srrctl |= buf_size >> E1000_SRRCTL_BSIZEPKT_SHIFT; srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; if (hw->mac.type >= e1000_82580) srrctl |= E1000_SRRCTL_TIMESTAMP; @@ -4758,9 +4772,17 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, u32 rxdctl = 0; xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); - WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, - MEM_TYPE_PAGE_SHARED, NULL)); WRITE_ONCE(ring->xsk_pool, igb_xsk_pool(adapter, ring)); + if (ring->xsk_pool) { + WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, + MEM_TYPE_XSK_BUFF_POOL, + NULL)); + xsk_pool_set_rxq_info(ring->xsk_pool, &ring->xdp_rxq); + } else { + WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, + MEM_TYPE_PAGE_SHARED, + NULL)); + } /* disable the queue */ wr32(E1000_RXDCTL(reg_idx), 0); @@ -4787,9 +4809,12 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, rxdctl |= IGB_RX_HTHRESH << 8; rxdctl |= IGB_RX_WTHRESH << 16; - /* initialize rx_buffer_info */ - memset(ring->rx_buffer_info, 0, - sizeof(struct igb_rx_buffer) * ring->count); + if (ring->xsk_pool) + memset(ring->rx_buffer_info_zc, 0, + sizeof(*ring->rx_buffer_info_zc) * ring->count); + else + memset(ring->rx_buffer_info, 0, + sizeof(*ring->rx_buffer_info) * ring->count); /* initialize Rx descriptor 0 */ rx_desc = IGB_RX_DESC(ring, 0); @@ -4976,8 +5001,13 @@ void igb_free_rx_resources(struct igb_ring *rx_ring) rx_ring->xdp_prog = NULL; xdp_rxq_info_unreg(&rx_ring->xdp_rxq); - vfree(rx_ring->rx_buffer_info); - rx_ring->rx_buffer_info = NULL; + if (rx_ring->xsk_pool) { + vfree(rx_ring->rx_buffer_info_zc); + rx_ring->rx_buffer_info_zc = NULL; + } else { + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; + } /* if not set, then don't free */ if (!rx_ring->desc) @@ -5015,6 +5045,11 @@ void igb_clean_rx_ring(struct igb_ring *rx_ring) dev_kfree_skb(rx_ring->skb); rx_ring->skb = NULL; + if (rx_ring->xsk_pool) { + igb_clean_rx_ring_zc(rx_ring); + goto skip_for_xsk; + } + /* Free all the Rx ring sk_buffs */ while (i != rx_ring->next_to_alloc) { struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; @@ -5042,6 +5077,7 @@ void igb_clean_rx_ring(struct igb_ring *rx_ring) i = 0; } +skip_for_xsk: rx_ring->next_to_alloc = 0; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; @@ -8186,6 +8222,7 @@ static int igb_poll(struct napi_struct *napi, int budget) struct igb_q_vector *q_vector = container_of(napi, struct igb_q_vector, napi); + struct xsk_buff_pool *xsk_pool; bool clean_complete = true; int work_done = 0; @@ -8197,7 +8234,12 @@ static int igb_poll(struct napi_struct *napi, int budget) clean_complete = igb_clean_tx_irq(q_vector, budget); if (q_vector->rx.ring) { - int cleaned = igb_clean_rx_irq(q_vector, budget); + int cleaned; + + xsk_pool = READ_ONCE(q_vector->rx.ring->xsk_pool); + cleaned = xsk_pool ? + igb_clean_rx_irq_zc(q_vector, xsk_pool, budget) : + igb_clean_rx_irq(q_vector, budget); work_done += cleaned; if (cleaned >= budget) @@ -8861,6 +8903,38 @@ static void igb_put_rx_buffer(struct igb_ring *rx_ring, rx_buffer->page = NULL; } +void igb_finalize_xdp(struct igb_adapter *adapter, unsigned int status) +{ + int cpu = smp_processor_id(); + struct netdev_queue *nq; + + if (status & IGB_XDP_REDIR) + xdp_do_flush(); + + if (status & IGB_XDP_TX) { + struct igb_ring *tx_ring = igb_xdp_tx_queue_mapping(adapter); + + nq = txring_txq(tx_ring); + __netif_tx_lock(nq, cpu); + igb_xdp_ring_update_tail(tx_ring); + __netif_tx_unlock(nq); + } +} + +void igb_update_rx_stats(struct igb_q_vector *q_vector, unsigned int packets, + unsigned int bytes) +{ + struct igb_ring *ring = q_vector->rx.ring; + + u64_stats_update_begin(&ring->rx_syncp); + ring->rx_stats.packets += packets; + ring->rx_stats.bytes += bytes; + u64_stats_update_end(&ring->rx_syncp); + + q_vector->rx.total_packets += packets; + q_vector->rx.total_bytes += bytes; +} + static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) { unsigned int total_bytes = 0, total_packets = 0; @@ -8868,9 +8942,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) struct igb_ring *rx_ring = q_vector->rx.ring; u16 cleaned_count = igb_desc_unused(rx_ring); struct sk_buff *skb = rx_ring->skb; - int cpu = smp_processor_id(); unsigned int xdp_xmit = 0; - struct netdev_queue *nq; struct xdp_buff xdp; u32 frame_sz = 0; int rx_buf_pgcnt; @@ -8992,24 +9064,10 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) /* place incomplete frames back on ring for completion */ rx_ring->skb = skb; - if (xdp_xmit & IGB_XDP_REDIR) - xdp_do_flush(); - - if (xdp_xmit & IGB_XDP_TX) { - struct igb_ring *tx_ring = igb_xdp_tx_queue_mapping(adapter); - - nq = txring_txq(tx_ring); - __netif_tx_lock(nq, cpu); - igb_xdp_ring_update_tail(tx_ring); - __netif_tx_unlock(nq); - } + if (xdp_xmit) + igb_finalize_xdp(adapter, xdp_xmit); - u64_stats_update_begin(&rx_ring->rx_syncp); - rx_ring->rx_stats.packets += total_packets; - rx_ring->rx_stats.bytes += total_bytes; - u64_stats_update_end(&rx_ring->rx_syncp); - q_vector->rx.total_packets += total_packets; - q_vector->rx.total_bytes += total_bytes; + igb_update_rx_stats(q_vector, total_packets, total_bytes); if (cleaned_count) igb_alloc_rx_buffers(rx_ring, cleaned_count); diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c index 7b632be3e7e3..2ae16ae99193 100644 --- a/drivers/net/ethernet/intel/igb/igb_xsk.c +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c @@ -70,7 +70,10 @@ static void igb_txrx_ring_enable(struct igb_adapter *adapter, u16 qid) * at least 1 descriptor unused to make sure * next_to_use != next_to_clean */ - igb_alloc_rx_buffers(rx_ring, igb_desc_unused(rx_ring)); + if (rx_ring->xsk_pool) + igb_alloc_rx_buffers_zc(rx_ring, igb_desc_unused(rx_ring)); + else + igb_alloc_rx_buffers(rx_ring, igb_desc_unused(rx_ring)); /* Rx/Tx share the same napi context. */ napi_enable(&rx_ring->q_vector->napi); @@ -169,6 +172,298 @@ int igb_xsk_pool_setup(struct igb_adapter *adapter, igb_xsk_pool_disable(adapter, qid); } +static u16 igb_fill_rx_descs(struct xsk_buff_pool *pool, struct xdp_buff **xdp, + union e1000_adv_rx_desc *rx_desc, u16 count) +{ + dma_addr_t dma; + u16 buffs; + int i; + + /* nothing to do */ + if (!count) + return 0; + + buffs = xsk_buff_alloc_batch(pool, xdp, count); + for (i = 0; i < buffs; i++) { + dma = xsk_buff_xdp_get_dma(*xdp); + rx_desc->read.pkt_addr = cpu_to_le64(dma); + rx_desc->wb.upper.length = 0; + + rx_desc++; + xdp++; + } + + return buffs; +} + +bool igb_alloc_rx_buffers_zc(struct igb_ring *rx_ring, u16 count) +{ + u32 nb_buffs_extra = 0, nb_buffs = 0; + union e1000_adv_rx_desc *rx_desc; + u16 ntu = rx_ring->next_to_use; + u16 total_count = count; + struct xdp_buff **xdp; + + rx_desc = IGB_RX_DESC(rx_ring, ntu); + xdp = &rx_ring->rx_buffer_info_zc[ntu]; + + if (ntu + count >= rx_ring->count) { + nb_buffs_extra = igb_fill_rx_descs(rx_ring->xsk_pool, xdp, + rx_desc, + rx_ring->count - ntu); + if (nb_buffs_extra != rx_ring->count - ntu) { + ntu += nb_buffs_extra; + goto exit; + } + rx_desc = IGB_RX_DESC(rx_ring, 0); + xdp = rx_ring->rx_buffer_info_zc; + ntu = 0; + count -= nb_buffs_extra; + } + + nb_buffs = igb_fill_rx_descs(rx_ring->xsk_pool, xdp, rx_desc, count); + ntu += nb_buffs; + if (ntu == rx_ring->count) + ntu = 0; + + /* clear the length for the next_to_use descriptor */ + rx_desc = IGB_RX_DESC(rx_ring, ntu); + rx_desc->wb.upper.length = 0; + +exit: + if (rx_ring->next_to_use != ntu) { + rx_ring->next_to_use = ntu; + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + writel(ntu, rx_ring->tail); + } + + return total_count == (nb_buffs + nb_buffs_extra); +} + +void igb_clean_rx_ring_zc(struct igb_ring *rx_ring) +{ + u16 ntc = rx_ring->next_to_clean; + u16 ntu = rx_ring->next_to_use; + + while (ntc != ntu) { + struct xdp_buff *xdp = rx_ring->rx_buffer_info_zc[ntc]; + + xsk_buff_free(xdp); + ntc++; + if (ntc >= rx_ring->count) + ntc = 0; + } +} + +static struct sk_buff *igb_construct_skb_zc(struct igb_ring *rx_ring, + struct xdp_buff *xdp, + ktime_t timestamp) +{ + unsigned int totalsize = xdp->data_end - xdp->data_meta; + unsigned int metasize = xdp->data - xdp->data_meta; + struct sk_buff *skb; + + net_prefetch(xdp->data_meta); + + /* allocate a skb to store the frags */ + skb = napi_alloc_skb(&rx_ring->q_vector->napi, totalsize); + if (unlikely(!skb)) + return NULL; + + if (timestamp) + skb_hwtstamps(skb)->hwtstamp = timestamp; + + memcpy(__skb_put(skb, totalsize), xdp->data_meta, + ALIGN(totalsize, sizeof(long))); + + if (metasize) { + skb_metadata_set(skb, metasize); + __skb_pull(skb, metasize); + } + + return skb; +} + +static struct sk_buff *igb_run_xdp_zc(struct igb_adapter *adapter, + struct igb_ring *rx_ring, + struct xdp_buff *xdp, + struct xsk_buff_pool *xsk_pool) +{ + int err, result = IGB_XDP_PASS; + struct bpf_prog *xdp_prog; + u32 act; + + xdp_prog = READ_ONCE(rx_ring->xdp_prog); + + if (!xdp_prog) + goto xdp_out; + + prefetchw(xdp->data_hard_start); /* xdp_frame write */ + + act = bpf_prog_run_xdp(xdp_prog, xdp); + + if (likely(act == XDP_REDIRECT)) { + err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); + if (!err) { + result = IGB_XDP_REDIR; + goto xdp_out; + } + + if (xsk_uses_need_wakeup(xsk_pool) && + err == -ENOBUFS) + result = IGB_XDP_EXIT; + else + result = IGB_XDP_CONSUMED; + goto out_failure; + } + + switch (act) { + case XDP_PASS: + break; + case XDP_TX: + result = igb_xdp_xmit_back(adapter, xdp); + if (result == IGB_XDP_CONSUMED) + goto out_failure; + break; + default: + bpf_warn_invalid_xdp_action(adapter->netdev, xdp_prog, act); + fallthrough; + case XDP_ABORTED: +out_failure: + trace_xdp_exception(rx_ring->netdev, xdp_prog, act); + fallthrough; + case XDP_DROP: + result = IGB_XDP_CONSUMED; + break; + } +xdp_out: + return ERR_PTR(-result); +} + +int igb_clean_rx_irq_zc(struct igb_q_vector *q_vector, + struct xsk_buff_pool *xsk_pool, const int budget) +{ + struct igb_adapter *adapter = q_vector->adapter; + unsigned int total_bytes = 0, total_packets = 0; + struct igb_ring *rx_ring = q_vector->rx.ring; + u16 ntc = rx_ring->next_to_clean; + unsigned int xdp_xmit = 0; + bool failure = false; + u16 entries_to_alloc; + struct sk_buff *skb; + + while (likely(total_packets < budget)) { + union e1000_adv_rx_desc *rx_desc; + ktime_t timestamp = 0; + struct xdp_buff *xdp; + unsigned int size; + + rx_desc = IGB_RX_DESC(rx_ring, ntc); + size = le16_to_cpu(rx_desc->wb.upper.length); + if (!size) + break; + + /* This memory barrier is needed to keep us from reading + * any other fields out of the rx_desc until we know the + * descriptor has been written back + */ + dma_rmb(); + + xdp = rx_ring->rx_buffer_info_zc[ntc]; + xsk_buff_set_size(xdp, size); + xsk_buff_dma_sync_for_cpu(xdp); + + /* pull rx packet timestamp if available and valid */ + if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { + int ts_hdr_len; + + ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector, + xdp->data, + ×tamp); + + xdp->data += ts_hdr_len; + xdp->data_meta += ts_hdr_len; + size -= ts_hdr_len; + } + + skb = igb_run_xdp_zc(adapter, rx_ring, xdp, xsk_pool); + + if (IS_ERR(skb)) { + unsigned int xdp_res = -PTR_ERR(skb); + + if (likely(xdp_res & (IGB_XDP_TX | IGB_XDP_REDIR))) { + xdp_xmit |= xdp_res; + } else if (xdp_res == IGB_XDP_EXIT) { + failure = true; + break; + } else if (xdp_res == IGB_XDP_CONSUMED) { + xsk_buff_free(xdp); + } + + total_packets++; + total_bytes += size; + ntc++; + if (ntc == rx_ring->count) + ntc = 0; + continue; + } + + skb = igb_construct_skb_zc(rx_ring, xdp, timestamp); + + /* exit if we failed to retrieve a buffer */ + if (!skb) { + rx_ring->rx_stats.alloc_failed++; + break; + } + + xsk_buff_free(xdp); + ntc++; + if (ntc == rx_ring->count) + ntc = 0; + + if (eth_skb_pad(skb)) + continue; + + /* probably a little skewed due to removing CRC */ + total_bytes += skb->len; + + /* populate checksum, timestamp, VLAN, and protocol */ + igb_process_skb_fields(rx_ring, rx_desc, skb); + + napi_gro_receive(&q_vector->napi, skb); + + /* update budget accounting */ + total_packets++; + } + + rx_ring->next_to_clean = ntc; + + if (xdp_xmit) + igb_finalize_xdp(adapter, xdp_xmit); + + igb_update_rx_stats(q_vector, total_packets, total_bytes); + + entries_to_alloc = igb_desc_unused(rx_ring); + if (entries_to_alloc >= IGB_RX_BUFFER_WRITE) + failure |= !igb_alloc_rx_buffers_zc(rx_ring, entries_to_alloc); + + if (xsk_uses_need_wakeup(xsk_pool)) { + if (failure || rx_ring->next_to_clean == rx_ring->next_to_use) + xsk_set_rx_need_wakeup(xsk_pool); + else + xsk_clear_rx_need_wakeup(xsk_pool); + + return (int)total_packets; + } + return failure ? budget : (int)total_packets; +} + int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags) { struct igb_adapter *adapter = netdev_priv(dev); From patchwork Fri Aug 16 09:24:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kurt Kanzenbach X-Patchwork-Id: 13765813 X-Patchwork-Delegate: kuba@kernel.org Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A5A9143864; Fri, 16 Aug 2024 09:24:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800257; cv=none; b=HYUPjnW8rNYlMuT/M2n7gDygs6CsCR8GhK/DRirEpbGZd4zOl3dmrfnBOVm4SIdamcZA1gpI1GCIPnFDLMZkcUZ/coqPQRkxMawLe89PIFi0gAN/nwJkmqquDrH1qZfwKx5SpWWLUNGzDAcmJxk0SyhJHDJleM2L0F1sPDqObww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723800257; c=relaxed/simple; bh=WJa68WzNB9mZfT2/vBSrtYWAR78qxOXvCRDnA3Fpcb0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DoQxaFHqg9vz5VG0EpmxBIQyesVuI46sjwap5EnHU+upS03yKYn8mGWjNiGHJ6TQu0fAcGXe0+daf8hNrPIMr08kFEnNXYbpuIbG8m5qy5kAVw5g7rrTfewOjm/H1WSPaGKcHWqmfZ7DY5/LT2Lj4x2TVxeNQ1wd/MKC/e/GE2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=HVWzGKcc; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=US96cqC4; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="HVWzGKcc"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="US96cqC4" From: Kurt Kanzenbach DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1723800249; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7yG1ACRnHrh+YmajwvU3e4DURwq84JBWecStQNpiZO0=; b=HVWzGKccULbwPqp6Cs7IGtziZFaPA243AJgPE1u4aZ0r20cXJ/zB20TcauMqwxoMsp6ZVm cxRMKnOqie9JU+RW1kVWMV/zKEFtVBGYzxBiH8q/HtayPWQXkLBhzumH0UB+9IVQULgqKP lPCQoZfMCcfgo22Fp/rSoAgi8/5soAg+KkfLPCCgBeW1NW1hmWa8w9gVGLa0EUmtlouegP JkUrvorZVjilsI+4vMZ0e39nxPjXJXEnD54KqSNERFZhXRE7MaOQ0LgUA7e5ydnUuMplMD 4f5SfBl599GX0dYIwS5CIFjUrEtkk7ic5iSIzFw3mWpiWvvexd5uDc9/WShjiA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1723800249; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7yG1ACRnHrh+YmajwvU3e4DURwq84JBWecStQNpiZO0=; b=US96cqC4CIODqTZ2mnakBwdJZiKIk4t+HQYnPjo7N/xkRmg59FKm+2gvfnIm6wJKu0/7Fm Y7Dr87HFAhHdfkCw== Date: Fri, 16 Aug 2024 11:24:05 +0200 Subject: [PATCH iwl-next v6 6/6] igb: Add AF_XDP zero-copy Tx support Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240711-b4-igb_zero_copy-v6-6-4bfb68773b18@linutronix.de> References: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> In-Reply-To: <20240711-b4-igb_zero_copy-v6-0-4bfb68773b18@linutronix.de> To: Tony Nguyen , Przemek Kitszel Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Richard Cochran , Sriram Yagnaraman , Benjamin Steinke , Sebastian Andrzej Siewior , Maciej Fijalkowski , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Sriram Yagnaraman , Kurt Kanzenbach X-Developer-Signature: v=1; a=openpgp-sha256; l=9478; i=kurt@linutronix.de; h=from:subject:message-id; bh=PefxL3kNeXOYDdUS68qN4pno+ulpwpgKURF3sXGr9k8=; b=owEBbQKS/ZANAwAKAcGT0fKqRnOCAcsmYgBmvxqzU7muPTaFHW2Pgk7wZGebNbY9HBNHH+Quv K9mDzC43SyJAjMEAAEKAB0WIQS8ub+yyMN909/bWZLBk9HyqkZzggUCZr8aswAKCRDBk9HyqkZz gjHpD/9+09Nuvt2YDrqFYYj7W5xYTx+eHuDfQPxI6K8sx+6gXsAF9a50SkEP0jOxwj8bN1r9lzz Hb4XghlhK5sp5V3iRpAgrr+dXG166263lBWhSNpaC1JEilZeT9ctxkSfyHD/FPEBH9CzD3H4FW5 WUmxE+fBZx4rW7nkWoBry2tAVgTE2PnEDDA2XucX32HsNrR4qso9AL+DLeTjyx8rCX8ZezCYl28 CyJe1OGHbIEo9R2CSMTRWk8NhvSyvAU/UX4kfTEl8ByXgqh2CrIwHL3aXblaT5rZTnGF2550RiG 43cWOP5+R3npgl2BlFDZotDqMk1yNhfQECUy1m7unS3dD+IK73QARB9A5Xshmkrnt1juBpdhIof sdL5E7fUCcSlzlTZ0jXdFmhA3Umr/9qcKz/vKPZGbKZRYQMoz21BelcrgYgcsYpq3FaQePBiVMg yGjjQgClcobR2oV8PTqwo1W3A+ydaKevMtQrt5j5EUjx/qucjA036To7ZBzbHMYwLJcoBJiUUhO eAOnb1oeZuzJbaHPTFuipHa9NYIchKh0fYi66tJD6jRR0WhlGtEzt3YmHanIPAdPVxd9CHMMEn9 p00LLzcp3+6q5H6qENr5EVP/yKkvh4n4uLt2CI5A5N6zMgh329p48ab261dfF3FJU3EpLFPLcAN ViIFr/jdfNS2rrg== X-Developer-Key: i=kurt@linutronix.de; a=openpgp; fpr=BCB9BFB2C8C37DD3DFDB5992C193D1F2AA467382 X-Patchwork-Delegate: kuba@kernel.org From: Sriram Yagnaraman Add support for AF_XDP zero-copy transmit path. A new TX buffer type IGB_TYPE_XSK is introduced to indicate that the Tx frame was allocated from the xsk buff pool, so igb_clean_tx_ring() and igb_clean_tx_irq() can clean the buffers correctly based on type. igb_xmit_zc() performs the actual packet transmit when AF_XDP zero-copy is enabled. We share the TX ring between slow path, XDP and AF_XDP zero-copy, so we use the netdev queue lock to ensure mutual exclusion. Signed-off-by: Sriram Yagnaraman [Kurt: Set olinfo_status in igb_xmit_zc() so that frames are transmitted, Use READ_ONCE() for xsk_pool and check Tx disabled and carrier in igb_xmit_zc()] Signed-off-by: Kurt Kanzenbach Reviewed-by: Maciej Fijalkowski --- drivers/net/ethernet/intel/igb/igb.h | 2 + drivers/net/ethernet/intel/igb/igb_main.c | 61 ++++++++++++++++++++++++++----- drivers/net/ethernet/intel/igb/igb_xsk.c | 59 ++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 348f32f4c11c..cd8b68eb2eea 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -257,6 +257,7 @@ enum igb_tx_flags { enum igb_tx_buf_type { IGB_TYPE_SKB = 0, IGB_TYPE_XDP, + IGB_TYPE_XSK }; /* wrapper around a pointer to a socket buffer, @@ -837,6 +838,7 @@ bool igb_alloc_rx_buffers_zc(struct igb_ring *rx_ring, u16 count); void igb_clean_rx_ring_zc(struct igb_ring *rx_ring); int igb_clean_rx_irq_zc(struct igb_q_vector *q_vector, struct xsk_buff_pool *xsk_pool, const int budget); +bool igb_xmit_zc(struct igb_ring *tx_ring); int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags); #endif /* _IGB_H_ */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 063ba0144dfd..c6d54b5a9688 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2998,6 +2998,9 @@ static int igb_xdp_xmit(struct net_device *dev, int n, if (unlikely(!tx_ring)) return -ENXIO; + if (unlikely(test_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags))) + return -ENXIO; + nq = txring_txq(tx_ring); __netif_tx_lock(nq, cpu); @@ -3345,7 +3348,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->priv_flags |= IFF_SUPP_NOFCS; netdev->priv_flags |= IFF_UNICAST_FLT; - netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT; + netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | + NETDEV_XDP_ACT_XSK_ZEROCOPY; /* MTU range: 68 - 9216 */ netdev->min_mtu = ETH_MIN_MTU; @@ -4918,15 +4922,20 @@ void igb_clean_tx_ring(struct igb_ring *tx_ring) { u16 i = tx_ring->next_to_clean; struct igb_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; + u32 xsk_frames = 0; while (i != tx_ring->next_to_use) { union e1000_adv_tx_desc *eop_desc, *tx_desc; /* Free all the Tx ring sk_buffs or xdp frames */ - if (tx_buffer->type == IGB_TYPE_SKB) + if (tx_buffer->type == IGB_TYPE_SKB) { dev_kfree_skb_any(tx_buffer->skb); - else + } else if (tx_buffer->type == IGB_TYPE_XDP) { xdp_return_frame(tx_buffer->xdpf); + } else if (tx_buffer->type == IGB_TYPE_XSK) { + xsk_frames++; + goto skip_for_xsk; + } /* unmap skb header data */ dma_unmap_single(tx_ring->dev, @@ -4957,6 +4966,7 @@ void igb_clean_tx_ring(struct igb_ring *tx_ring) DMA_TO_DEVICE); } +skip_for_xsk: tx_buffer->next_to_watch = NULL; /* move us one more past the eop_desc for start of next pkt */ @@ -4971,6 +4981,9 @@ void igb_clean_tx_ring(struct igb_ring *tx_ring) /* reset BQL for queue */ netdev_tx_reset_queue(txring_txq(tx_ring)); + if (tx_ring->xsk_pool && xsk_frames) + xsk_tx_completed(tx_ring->xsk_pool, xsk_frames); + /* reset next_to_use and next_to_clean */ tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; @@ -6504,6 +6517,9 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, return NETDEV_TX_BUSY; } + if (unlikely(test_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags))) + return NETDEV_TX_BUSY; + /* record the location of the first descriptor for this packet */ first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; first->type = IGB_TYPE_SKB; @@ -8268,13 +8284,18 @@ static int igb_poll(struct napi_struct *napi, int budget) **/ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) { - struct igb_adapter *adapter = q_vector->adapter; - struct igb_ring *tx_ring = q_vector->tx.ring; - struct igb_tx_buffer *tx_buffer; - union e1000_adv_tx_desc *tx_desc; unsigned int total_bytes = 0, total_packets = 0; + struct igb_adapter *adapter = q_vector->adapter; unsigned int budget = q_vector->tx.work_limit; + struct igb_ring *tx_ring = q_vector->tx.ring; unsigned int i = tx_ring->next_to_clean; + union e1000_adv_tx_desc *tx_desc; + struct igb_tx_buffer *tx_buffer; + struct xsk_buff_pool *xsk_pool; + int cpu = smp_processor_id(); + bool xsk_xmit_done = true; + struct netdev_queue *nq; + u32 xsk_frames = 0; if (test_bit(__IGB_DOWN, &adapter->state)) return true; @@ -8305,10 +8326,14 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) total_packets += tx_buffer->gso_segs; /* free the skb */ - if (tx_buffer->type == IGB_TYPE_SKB) + if (tx_buffer->type == IGB_TYPE_SKB) { napi_consume_skb(tx_buffer->skb, napi_budget); - else + } else if (tx_buffer->type == IGB_TYPE_XDP) { xdp_return_frame(tx_buffer->xdpf); + } else if (tx_buffer->type == IGB_TYPE_XSK) { + xsk_frames++; + goto skip_for_xsk; + } /* unmap skb header data */ dma_unmap_single(tx_ring->dev, @@ -8340,6 +8365,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) } } +skip_for_xsk: /* move us one more past the eop_desc for start of next pkt */ tx_buffer++; tx_desc++; @@ -8368,6 +8394,21 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) q_vector->tx.total_bytes += total_bytes; q_vector->tx.total_packets += total_packets; + xsk_pool = READ_ONCE(tx_ring->xsk_pool); + if (xsk_pool) { + if (xsk_frames) + xsk_tx_completed(xsk_pool, xsk_frames); + if (xsk_uses_need_wakeup(xsk_pool)) + xsk_set_tx_need_wakeup(xsk_pool); + + nq = txring_txq(tx_ring); + __netif_tx_lock(nq, cpu); + /* Avoid transmit queue timeout since we share it with the slow path */ + txq_trans_cond_update(nq); + xsk_xmit_done = igb_xmit_zc(tx_ring); + __netif_tx_unlock(nq); + } + if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { struct e1000_hw *hw = &adapter->hw; @@ -8430,7 +8471,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) } } - return !!budget; + return !!budget && xsk_xmit_done; } /** diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c index 2ae16ae99193..52602ef25321 100644 --- a/drivers/net/ethernet/intel/igb/igb_xsk.c +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c @@ -464,6 +464,65 @@ int igb_clean_rx_irq_zc(struct igb_q_vector *q_vector, return failure ? budget : (int)total_packets; } +bool igb_xmit_zc(struct igb_ring *tx_ring) +{ + unsigned int budget = igb_desc_unused(tx_ring); + struct xsk_buff_pool *pool = tx_ring->xsk_pool; + u32 cmd_type, olinfo_status, nb_pkts, i = 0; + struct xdp_desc *descs = pool->tx_descs; + union e1000_adv_tx_desc *tx_desc = NULL; + struct igb_tx_buffer *tx_buffer_info; + unsigned int total_bytes = 0; + dma_addr_t dma; + + if (!netif_carrier_ok(tx_ring->netdev)) + return true; + + if (test_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags)) + return true; + + nb_pkts = xsk_tx_peek_release_desc_batch(pool, budget); + if (!nb_pkts) + return true; + + while (nb_pkts-- > 0) { + dma = xsk_buff_raw_get_dma(pool, descs[i].addr); + xsk_buff_raw_dma_sync_for_device(pool, dma, descs[i].len); + + tx_buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; + tx_buffer_info->bytecount = descs[i].len; + tx_buffer_info->type = IGB_TYPE_XSK; + tx_buffer_info->xdpf = NULL; + tx_buffer_info->gso_segs = 1; + tx_buffer_info->time_stamp = jiffies; + + tx_desc = IGB_TX_DESC(tx_ring, tx_ring->next_to_use); + tx_desc->read.buffer_addr = cpu_to_le64(dma); + + /* put descriptor type bits */ + cmd_type = E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_DEXT | + E1000_ADVTXD_DCMD_IFCS; + olinfo_status = descs[i].len << E1000_ADVTXD_PAYLEN_SHIFT; + + cmd_type |= descs[i].len | IGB_TXD_DCMD; + tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); + + total_bytes += descs[i].len; + + i++; + tx_ring->next_to_use++; + tx_buffer_info->next_to_watch = tx_desc; + if (tx_ring->next_to_use == tx_ring->count) + tx_ring->next_to_use = 0; + } + + netdev_tx_sent_queue(txring_txq(tx_ring), total_bytes); + igb_xdp_ring_update_tail(tx_ring); + + return nb_pkts < budget; +} + int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags) { struct igb_adapter *adapter = netdev_priv(dev);