diff mbox series

[1/2,SRU,J:linux-bluefield,v1,1/2] UBUNTU: SAUCE: mlxbf-tmfifo: Drop the Rx packet if no more descriptors

Message ID 0c5d1413dec7019a2ad8520920e8fcbef8ed72f2.1685455239.git.limings@nvidia.com
State New
Headers show
Series UBUNTU: SAUCE: mlxbf-tmfifo: robust fix to drop over-sized packet or no Rx descriptors | expand

Commit Message

Liming Sun May 30, 2023, 2:30 p.m. UTC
BugLink: https://bugs.launchpad.net/bugs/2021749

This commit fixes tmfifo console stuck issue when the virtual
networking interface is in down state. In such case, the network
Rx descriptors runs out which causes the network packet stays
in the tmfifo and couldn't be popped out thus blocking the console
packets. The fix is to drop the receiving packet when no more Rx
descriptors.

Signed-off-by: Liming Sun <limings@nvidia.com>

Change-Id: I98c2b9aa2e21277675022775538f053df393da4e
---
 drivers/platform/mellanox/mlxbf-tmfifo.c | 64 +++++++++++++++++-------
 1 file changed, 45 insertions(+), 19 deletions(-)

Comments

Liming Sun June 4, 2023, 2:23 p.m. UTC | #1
BugLink: https://bugs.launchpad.net/bugs/2021749

SRU Justification:

[Impact]
This change is needed to avoid potential tmfifo console stuck when
network interface is down or receiving oversized packets.

[Fix]
Drop the Rx packets in the above cases. Since tmfifo is shared
resource for both console and networking. Dropping such network
packets can continue to process the fifo and avoid console stuck.

[Test Case]
Same functionality and testing as on BlueField-1/2/3. No functionality
change. Add negative tests:
- 'ifconfig tmfifo_net0 down' on ARM side during traffic, then verify
  rshim console doesn't stuck.
- Config MTU to 4000 on rshim host and send oversized packet with command
  'ping 192.168.100.2 -s 2000". It shouldn't cause any stuck.

[Regression Potential]
Same behavior from user perspective.

Liming Sun (2):
  mlxbf-tmfifo: Drop the Rx packet if no more descriptors
  mlxbf-tmfifo: Drop jumbo frames

 drivers/platform/mellanox/mlxbf-tmfifo.c | 89 +++++++++++++++++-------
 1 file changed, 63 insertions(+), 26 deletions(-)
diff mbox series

Patch

diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
index 19d539fc99ae..b986496b1da0 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -59,6 +59,7 @@  struct mlxbf_tmfifo;
  * @vq: pointer to the virtio virtqueue
  * @desc: current descriptor of the pending packet
  * @desc_head: head descriptor of the pending packet
+ * @drop_desc: dummy desc for packet dropping
  * @cur_len: processed length of the current descriptor
  * @rem_len: remaining length of the pending packet
  * @pkt_len: total length of the pending packet
@@ -75,6 +76,7 @@  struct mlxbf_tmfifo_vring {
 	struct virtqueue *vq;
 	struct vring_desc *desc;
 	struct vring_desc *desc_head;
+	struct vring_desc drop_desc;
 	int cur_len;
 	int rem_len;
 	u32 pkt_len;
@@ -86,6 +88,11 @@  struct mlxbf_tmfifo_vring {
 	struct mlxbf_tmfifo *fifo;
 };
 
+/* Check whether vring is in drop mode. */
+#define IS_VRING_DROP(_r) ({ \
+	typeof(_r) (r) = (_r); \
+	(r->desc_head == &r->drop_desc ? true : false); })
+
 /* Interrupt types. */
 enum {
 	MLXBF_TM_RX_LWM_IRQ,
@@ -275,6 +282,7 @@  static int mlxbf_tmfifo_alloc_vrings(struct mlxbf_tmfifo *fifo,
 		vring->align = SMP_CACHE_BYTES;
 		vring->index = i;
 		vring->vdev_id = tm_vdev->vdev.id.device;
+		vring->drop_desc.len = 0xffff;
 		dev = &tm_vdev->vdev.dev;
 
 		size = vring_size(vring->num, vring->align);
@@ -380,7 +388,7 @@  static u32 mlxbf_tmfifo_get_pkt_len(struct mlxbf_tmfifo_vring *vring,
 	return len;
 }
 
-static void mlxbf_tmfifo_release_pending_pkt(struct mlxbf_tmfifo_vring *vring)
+static void mlxbf_tmfifo_release_pkt(struct mlxbf_tmfifo_vring *vring)
 {
 	struct vring_desc *desc_head;
 	u32 len = 0;
@@ -508,8 +516,6 @@  static int mlxbf_tmfifo_get_rx_avail(struct mlxbf_tmfifo *fifo)
 	return FIELD_GET(MLXBF_TMFIFO_RX_STS__COUNT_MASK, sts);
 }
 
-
-
 /* Get the number of available words in the TmFifo for sending. */
 static int mlxbf_tmfifo_get_tx_avail(struct mlxbf_tmfifo *fifo, int vdev_id)
 {
@@ -732,19 +738,25 @@  static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring,
 
 	if (vring->cur_len + sizeof(u64) <= len) {
 		/* The whole word. */
-		if (is_rx)
-			memcpy(addr + vring->cur_len, &data, sizeof(u64));
-		else
-			memcpy(&data, addr + vring->cur_len, sizeof(u64));
+		if (!IS_VRING_DROP(vring)) {
+			if (is_rx)
+				memcpy(addr + vring->cur_len, &data,
+				       sizeof(u64));
+			else
+				memcpy(&data, addr + vring->cur_len,
+				       sizeof(u64));
+		}
 		vring->cur_len += sizeof(u64);
 	} else {
 		/* Leftover bytes. */
-		if (is_rx)
-			memcpy(addr + vring->cur_len, &data,
-			       len - vring->cur_len);
-		else
-			memcpy(&data, addr + vring->cur_len,
-			       len - vring->cur_len);
+		if (!IS_VRING_DROP(vring)) {
+			if (is_rx)
+				memcpy(addr + vring->cur_len, &data,
+				       len - vring->cur_len);
+			else
+				memcpy(&data, addr + vring->cur_len,
+				       len - vring->cur_len);
+		}
 		vring->cur_len = len;
 	}
 
@@ -847,8 +859,16 @@  static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
 	/* Get the descriptor of the next packet. */
 	if (!vring->desc) {
 		desc = mlxbf_tmfifo_get_next_pkt(vring, is_rx);
-		if (!desc)
-			return false;
+		if (!desc) {
+			/* Drop next Rx packet to avoid stuck. */
+			if (is_rx) {
+				desc = &vring->drop_desc;
+				vring->desc_head = desc;
+				vring->desc = desc;
+			} else {
+				return false;
+			}
+		}
 	} else {
 		desc = vring->desc;
 	}
@@ -881,17 +901,23 @@  static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
 		vring->rem_len -= len;
 
 		/* Get the next desc on the chain. */
-		if (vring->rem_len > 0 &&
+		if (!IS_VRING_DROP(vring) && vring->rem_len > 0 &&
 		    (virtio16_to_cpu(vdev, desc->flags) & VRING_DESC_F_NEXT)) {
 			idx = virtio16_to_cpu(vdev, desc->next);
 			desc = &vr->desc[idx];
 			goto mlxbf_tmfifo_desc_done;
 		}
 
-		/* Done and release the pending packet. */
-		mlxbf_tmfifo_release_pending_pkt(vring);
+		/* Done and release the packet. */
 		desc = NULL;
 		fifo->vring[is_rx] = NULL;
+		if (!IS_VRING_DROP(vring)) {
+			mlxbf_tmfifo_release_pkt(vring);
+		} else {
+			vring->desc_head = NULL;
+			vring->desc = NULL;
+			return false;
+		}
 
 		/*
 		 * Make sure the load/store are in order before
@@ -1073,7 +1099,7 @@  static void mlxbf_tmfifo_virtio_del_vqs(struct virtio_device *vdev)
 
 		/* Release the pending packet. */
 		if (vring->desc)
-			mlxbf_tmfifo_release_pending_pkt(vring);
+			mlxbf_tmfifo_release_pkt(vring);
 		vq = vring->vq;
 		if (vq) {
 			vring->vq = NULL;