* @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
        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;
        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); })
+
+/* A stub length to drop maximum length packet. */
+#define VRING_DROP_DESC_MAX_LEN                GENMASK(15, 0)
+
 /* Interrupt types. */
 enum {
        MLXBF_TM_RX_LWM_IRQ,
                vring->align = SMP_CACHE_BYTES;
                vring->index = i;
                vring->vdev_id = tm_vdev->vdev.id.device;
+               vring->drop_desc.len = VRING_DROP_DESC_MAX_LEN;
                dev = &tm_vdev->vdev.dev;
 
                size = vring_size(vring->num, vring->align);
        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;
 
        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;
        }
 
        /* 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;
        }
                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->pkt_len = 0;
+                       vring->desc_head = NULL;
+                       vring->desc = NULL;
+                       return false;
+               }
 
                /*
                 * Make sure the load/store are in order before
 
                /* 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;