Archive-only list for patches
 help / color / mirror / Atom feed
diff for duplicates of <20260923140647.993637736@linuxfoundation.org>

diff --git a/a/1.txt b/N1/1.txt
index d96d9ca..cafe959 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,34 +1,141 @@
-7.2-stable review patch.  If anyone has any objections, please let me know.
+6.18-stable review patch.  If anyone has any objections, please let me know.
 
 ------------------
 
-From: Namjae Jeon <linkinjeon@kernel.org>
+From: Jakub Kicinski <kuba@kernel.org>
 
-[ Upstream commit 1923eeffa63edeff427d76fc302bc5eb835771ce ]
+[ Upstream commit 490599ab23134962a6d18a024e84541d77bdb999 ]
 
-Return the error from __filemap_get_folio() instead of replacing it
-with -ENOMEM.
+fbnic_tx_map() skips the doorbell write, and the completion request,
+for every packet handed to it with xmit_more set, counting on the
+packet which ends the burst to publish them all. When that packet is
+dropped instead - skb_put_padto(), skb_cow_head() or a DMA mapping
+failure - nothing rings. The descriptors of the preceding packets stay
+invisible to the HW until the next transmit on that queue, which for a
+burst-then-idle workload may never come.
 
-Fixes: af0db57d4293 ("ntfs: update inode operations")
-Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
-Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Remember the meta descriptor of the last packet left without a doorbell
+and flush it from the error paths. The completion request has to be set
+on that descriptor rather than simply writing the tail, otherwise the HW
+would transmit the packets but never report a head, and the ring would
+fill up and stall for good.
+
+This is very similar to Joe's recent series of fixes for bnxt.
+Not seen in real life, reproduced under QEMU with failure injection.
+
+Fixes: 9a57bacd574b ("eth: fbnic: Add basic Tx handling")
+Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260915022327.913218-1-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- fs/ntfs/inode.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
-index 560f1dd1fba39..b6e161d51dce2 100644
---- a/fs/ntfs/inode.c
-+++ b/fs/ntfs/inode.c
-@@ -3713,7 +3713,7 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,
- 					FGP_CREAT | FGP_LOCK,
- 					mapping_gfp_mask(mapping));
- 			if (IS_ERR(folio)) {
--				ret = -ENOMEM;
-+				ret = PTR_ERR(folio);
- 				break;
- 			}
- 		} else {
+ drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 42 +++++++++++++++-----
+ drivers/net/ethernet/meta/fbnic/fbnic_txrx.h |  9 ++++-
+ 2 files changed, 40 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
+index dbe0855ecb575..0ea861ff40f56 100644
+--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
++++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
+@@ -311,6 +311,29 @@ fbnic_rx_csum(u64 rcd, struct sk_buff *skb, struct fbnic_ring *rcq,
+ 	}
+ }
+ 
++static void fbnic_tx_doorbell(struct fbnic_ring *ring, __le64 *meta)
++{
++	*meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_COMPLETION);
++	ring->deferred_meta = -1;
++
++	/* Force DMA writes to flush before writing to tail */
++	dma_wmb();
++
++	writel(ring->tail, ring->doorbell);
++}
++
++/* Packets handed to us with xmit_more set are left in the ring without a
++ * doorbell, and without a completion request, in the expectation that the
++ * packet ending the burst will ring for all of them. If that packet gets
++ * dropped instead we have to ring here, otherwise the descriptors sit in
++ * the ring until the next transmit, which may never come.
++ */
++static void fbnic_tx_flush_doorbell(struct fbnic_ring *ring)
++{
++	if (ring->deferred_meta >= 0)
++		fbnic_tx_doorbell(ring, &ring->desc[ring->deferred_meta]);
++}
++
+ static bool
+ fbnic_tx_map(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
+ {
+@@ -378,14 +401,10 @@ fbnic_tx_map(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
+ 	/* Verify there is room for another packet */
+ 	fbnic_maybe_stop_tx(skb->dev, ring, FBNIC_MAX_SKB_DESC);
+ 
+-	if (fbnic_tx_sent_queue(skb, ring)) {
+-		*meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_COMPLETION);
+-
+-		/* Force DMA writes to flush before writing to tail */
+-		dma_wmb();
+-
+-		writel(tail, ring->doorbell);
+-	}
++	if (fbnic_tx_sent_queue(skb, ring))
++		fbnic_tx_doorbell(ring, meta);
++	else
++		ring->deferred_meta = meta - ring->desc;
+ 
+ 	return false;
+ dma_error:
+@@ -425,8 +444,10 @@ fbnic_xmit_frame_ring(struct sk_buff *skb, struct fbnic_ring *ring)
+ 	 * otherwise try next time
+ 	 */
+ 	desc_needed = skb_shinfo(skb)->nr_frags + 10;
+-	if (fbnic_maybe_stop_tx(skb->dev, ring, desc_needed))
++	if (fbnic_maybe_stop_tx(skb->dev, ring, desc_needed)) {
++		fbnic_tx_flush_doorbell(ring);
+ 		return NETDEV_TX_BUSY;
++	}
+ 
+ 	*meta = cpu_to_le64(FBNIC_TWD_FLAG_DEST_MAC);
+ 
+@@ -447,6 +468,8 @@ fbnic_xmit_frame_ring(struct sk_buff *skb, struct fbnic_ring *ring)
+ err_free:
+ 	dev_kfree_skb_any(skb);
+ err_count:
++	fbnic_tx_flush_doorbell(ring);
++
+ 	u64_stats_update_begin(&ring->stats.syncp);
+ 	ring->stats.dropped++;
+ 	u64_stats_update_end(&ring->stats.syncp);
+@@ -2473,6 +2496,7 @@ static void fbnic_enable_twq0(struct fbnic_ring *twq)
+ 	fbnic_ring_wr32(twq, FBNIC_QUEUE_TWQ0_CTL, FBNIC_QUEUE_TWQ_CTL_RESET);
+ 	twq->tail = 0;
+ 	twq->head = 0;
++	twq->deferred_meta = -1;
+ 
+ 	/* Store descriptor ring address and size */
+ 	fbnic_ring_wr32(twq, FBNIC_QUEUE_TWQ0_BAL, lower_32_bits(twq->dma));
+diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
+index f2ee2cbf3486b..643e7d3ddb543 100644
+--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
++++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
+@@ -128,9 +128,14 @@ struct fbnic_ring {
+ 		/* Rx BDQs only */
+ 		struct page_pool *page_pool;
+ 
+-		/* Deferred_head is used to cache the head for TWQ1 if
++		/* TWQ0 only, index of the meta descriptor of the last packet
++		 * placed in the ring without ringing the doorbell, -1 if the
++		 * doorbell is in sync with the tail.
++		 */
++		s32 deferred_meta;
++
++		/* TCQ only, used to cache the head for TWQ1 if
+ 		 * an attempt is made to clean TWQ1 with zero napi_budget.
+-		 * We do not use it for any other ring.
+ 		 */
+ 		s32 deferred_head;
+ 	};
 -- 
 2.53.0
diff --git a/a/content_digest b/N1/content_digest
index bf5d77b..2a5138e 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,48 +1,156 @@
- "ref\020260923140644.756254324@linuxfoundation.org\0"
+ "ref\020260923140643.441954610@linuxfoundation.org\0"
  "From\0Greg Kroah-Hartman <gregkh@linuxfoundation.org>\0"
- "Subject\0[PATCH 7.2 124/438] ntfs: propagate folio errors\0"
- "Date\0Wed, 23 Sep 2026 16:02:25 +0200\0"
+ "Subject\0[PATCH 6.18 176/398] eth: fbnic: ring the doorbell if a burst ends in a drop\0"
+ "Date\0Wed, 23 Sep 2026 16:04:10 +0200\0"
  "To\0stable@vger.kernel.org\0"
  "Cc\0Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
   patches@lists.linux.dev
-  Hyunchul Lee <hyc.lee@gmail.com>
-  Namjae Jeon <linkinjeon@kernel.org>
+  Alexander Duyck <alexanderduyck@fb.com>
+  Simon Horman <horms@kernel.org>
+  Jakub Kicinski <kuba@kernel.org>
  " Sasha Levin <sashal@kernel.org>\0"
  "\00:1\0"
  "b\0"
- "7.2-stable review patch.  If anyone has any objections, please let me know.\n"
+ "6.18-stable review patch.  If anyone has any objections, please let me know.\n"
  "\n"
  "------------------\n"
  "\n"
- "From: Namjae Jeon <linkinjeon@kernel.org>\n"
+ "From: Jakub Kicinski <kuba@kernel.org>\n"
  "\n"
- "[ Upstream commit 1923eeffa63edeff427d76fc302bc5eb835771ce ]\n"
+ "[ Upstream commit 490599ab23134962a6d18a024e84541d77bdb999 ]\n"
  "\n"
- "Return the error from __filemap_get_folio() instead of replacing it\n"
- "with -ENOMEM.\n"
+ "fbnic_tx_map() skips the doorbell write, and the completion request,\n"
+ "for every packet handed to it with xmit_more set, counting on the\n"
+ "packet which ends the burst to publish them all. When that packet is\n"
+ "dropped instead - skb_put_padto(), skb_cow_head() or a DMA mapping\n"
+ "failure - nothing rings. The descriptors of the preceding packets stay\n"
+ "invisible to the HW until the next transmit on that queue, which for a\n"
+ "burst-then-idle workload may never come.\n"
  "\n"
- "Fixes: af0db57d4293 (\"ntfs: update inode operations\")\n"
- "Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>\n"
- "Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>\n"
+ "Remember the meta descriptor of the last packet left without a doorbell\n"
+ "and flush it from the error paths. The completion request has to be set\n"
+ "on that descriptor rather than simply writing the tail, otherwise the HW\n"
+ "would transmit the packets but never report a head, and the ring would\n"
+ "fill up and stall for good.\n"
+ "\n"
+ "This is very similar to Joe's recent series of fixes for bnxt.\n"
+ "Not seen in real life, reproduced under QEMU with failure injection.\n"
+ "\n"
+ "Fixes: 9a57bacd574b (\"eth: fbnic: Add basic Tx handling\")\n"
+ "Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>\n"
+ "Reviewed-by: Simon Horman <horms@kernel.org>\n"
+ "Link: https://patch.msgid.link/20260915022327.913218-1-kuba@kernel.org\n"
+ "Signed-off-by: Jakub Kicinski <kuba@kernel.org>\n"
  "Signed-off-by: Sasha Levin <sashal@kernel.org>\n"
  "---\n"
- " fs/ntfs/inode.c | 2 +-\n"
- " 1 file changed, 1 insertion(+), 1 deletion(-)\n"
- "\n"
- "diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c\n"
- "index 560f1dd1fba39..b6e161d51dce2 100644\n"
- "--- a/fs/ntfs/inode.c\n"
- "+++ b/fs/ntfs/inode.c\n"
- "@@ -3713,7 +3713,7 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,\n"
- " \t\t\t\t\tFGP_CREAT | FGP_LOCK,\n"
- " \t\t\t\t\tmapping_gfp_mask(mapping));\n"
- " \t\t\tif (IS_ERR(folio)) {\n"
- "-\t\t\t\tret = -ENOMEM;\n"
- "+\t\t\t\tret = PTR_ERR(folio);\n"
- " \t\t\t\tbreak;\n"
- " \t\t\t}\n"
- " \t\t} else {\n"
+ " drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 42 +++++++++++++++-----\n"
+ " drivers/net/ethernet/meta/fbnic/fbnic_txrx.h |  9 ++++-\n"
+ " 2 files changed, 40 insertions(+), 11 deletions(-)\n"
+ "\n"
+ "diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c\n"
+ "index dbe0855ecb575..0ea861ff40f56 100644\n"
+ "--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c\n"
+ "+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c\n"
+ "@@ -311,6 +311,29 @@ fbnic_rx_csum(u64 rcd, struct sk_buff *skb, struct fbnic_ring *rcq,\n"
+ " \t}\n"
+ " }\n"
+ " \n"
+ "+static void fbnic_tx_doorbell(struct fbnic_ring *ring, __le64 *meta)\n"
+ "+{\n"
+ "+\t*meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_COMPLETION);\n"
+ "+\tring->deferred_meta = -1;\n"
+ "+\n"
+ "+\t/* Force DMA writes to flush before writing to tail */\n"
+ "+\tdma_wmb();\n"
+ "+\n"
+ "+\twritel(ring->tail, ring->doorbell);\n"
+ "+}\n"
+ "+\n"
+ "+/* Packets handed to us with xmit_more set are left in the ring without a\n"
+ "+ * doorbell, and without a completion request, in the expectation that the\n"
+ "+ * packet ending the burst will ring for all of them. If that packet gets\n"
+ "+ * dropped instead we have to ring here, otherwise the descriptors sit in\n"
+ "+ * the ring until the next transmit, which may never come.\n"
+ "+ */\n"
+ "+static void fbnic_tx_flush_doorbell(struct fbnic_ring *ring)\n"
+ "+{\n"
+ "+\tif (ring->deferred_meta >= 0)\n"
+ "+\t\tfbnic_tx_doorbell(ring, &ring->desc[ring->deferred_meta]);\n"
+ "+}\n"
+ "+\n"
+ " static bool\n"
+ " fbnic_tx_map(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)\n"
+ " {\n"
+ "@@ -378,14 +401,10 @@ fbnic_tx_map(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)\n"
+ " \t/* Verify there is room for another packet */\n"
+ " \tfbnic_maybe_stop_tx(skb->dev, ring, FBNIC_MAX_SKB_DESC);\n"
+ " \n"
+ "-\tif (fbnic_tx_sent_queue(skb, ring)) {\n"
+ "-\t\t*meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_COMPLETION);\n"
+ "-\n"
+ "-\t\t/* Force DMA writes to flush before writing to tail */\n"
+ "-\t\tdma_wmb();\n"
+ "-\n"
+ "-\t\twritel(tail, ring->doorbell);\n"
+ "-\t}\n"
+ "+\tif (fbnic_tx_sent_queue(skb, ring))\n"
+ "+\t\tfbnic_tx_doorbell(ring, meta);\n"
+ "+\telse\n"
+ "+\t\tring->deferred_meta = meta - ring->desc;\n"
+ " \n"
+ " \treturn false;\n"
+ " dma_error:\n"
+ "@@ -425,8 +444,10 @@ fbnic_xmit_frame_ring(struct sk_buff *skb, struct fbnic_ring *ring)\n"
+ " \t * otherwise try next time\n"
+ " \t */\n"
+ " \tdesc_needed = skb_shinfo(skb)->nr_frags + 10;\n"
+ "-\tif (fbnic_maybe_stop_tx(skb->dev, ring, desc_needed))\n"
+ "+\tif (fbnic_maybe_stop_tx(skb->dev, ring, desc_needed)) {\n"
+ "+\t\tfbnic_tx_flush_doorbell(ring);\n"
+ " \t\treturn NETDEV_TX_BUSY;\n"
+ "+\t}\n"
+ " \n"
+ " \t*meta = cpu_to_le64(FBNIC_TWD_FLAG_DEST_MAC);\n"
+ " \n"
+ "@@ -447,6 +468,8 @@ fbnic_xmit_frame_ring(struct sk_buff *skb, struct fbnic_ring *ring)\n"
+ " err_free:\n"
+ " \tdev_kfree_skb_any(skb);\n"
+ " err_count:\n"
+ "+\tfbnic_tx_flush_doorbell(ring);\n"
+ "+\n"
+ " \tu64_stats_update_begin(&ring->stats.syncp);\n"
+ " \tring->stats.dropped++;\n"
+ " \tu64_stats_update_end(&ring->stats.syncp);\n"
+ "@@ -2473,6 +2496,7 @@ static void fbnic_enable_twq0(struct fbnic_ring *twq)\n"
+ " \tfbnic_ring_wr32(twq, FBNIC_QUEUE_TWQ0_CTL, FBNIC_QUEUE_TWQ_CTL_RESET);\n"
+ " \ttwq->tail = 0;\n"
+ " \ttwq->head = 0;\n"
+ "+\ttwq->deferred_meta = -1;\n"
+ " \n"
+ " \t/* Store descriptor ring address and size */\n"
+ " \tfbnic_ring_wr32(twq, FBNIC_QUEUE_TWQ0_BAL, lower_32_bits(twq->dma));\n"
+ "diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h\n"
+ "index f2ee2cbf3486b..643e7d3ddb543 100644\n"
+ "--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h\n"
+ "+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h\n"
+ "@@ -128,9 +128,14 @@ struct fbnic_ring {\n"
+ " \t\t/* Rx BDQs only */\n"
+ " \t\tstruct page_pool *page_pool;\n"
+ " \n"
+ "-\t\t/* Deferred_head is used to cache the head for TWQ1 if\n"
+ "+\t\t/* TWQ0 only, index of the meta descriptor of the last packet\n"
+ "+\t\t * placed in the ring without ringing the doorbell, -1 if the\n"
+ "+\t\t * doorbell is in sync with the tail.\n"
+ "+\t\t */\n"
+ "+\t\ts32 deferred_meta;\n"
+ "+\n"
+ "+\t\t/* TCQ only, used to cache the head for TWQ1 if\n"
+ " \t\t * an attempt is made to clean TWQ1 with zero napi_budget.\n"
+ "-\t\t * We do not use it for any other ring.\n"
+ " \t\t */\n"
+ " \t\ts32 deferred_head;\n"
+ " \t};\n"
  "-- \n"
  2.53.0
 
-9521a702a45c07316a1621d69d0cd49189446e876e008e9132420beb74971994
+eb80bb861fc86d55bb7289532cbf43a1d04c630049df0d77f5293b815a6b8158

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox