@@ -59,6 +59,7 @@ struct mlxbf_tmfifo;
59
59
* @vq: pointer to the virtio virtqueue
60
60
* @desc: current descriptor of the pending packet
61
61
* @desc_head: head descriptor of the pending packet
62
+ * @drop_desc: dummy desc for packet dropping
62
63
* @cur_len: processed length of the current descriptor
63
64
* @rem_len: remaining length of the pending packet
64
65
* @pkt_len: total length of the pending packet
@@ -75,6 +76,7 @@ struct mlxbf_tmfifo_vring {
75
76
struct virtqueue * vq ;
76
77
struct vring_desc * desc ;
77
78
struct vring_desc * desc_head ;
79
+ struct vring_desc drop_desc ;
78
80
int cur_len ;
79
81
int rem_len ;
80
82
u32 pkt_len ;
@@ -86,6 +88,14 @@ struct mlxbf_tmfifo_vring {
86
88
struct mlxbf_tmfifo * fifo ;
87
89
};
88
90
91
+ /* Check whether vring is in drop mode. */
92
+ #define IS_VRING_DROP (_r ) ({ \
93
+ typeof(_r) (r) = (_r); \
94
+ (r->desc_head == &r->drop_desc ? true : false); })
95
+
96
+ /* A stub length to drop maximum length packet. */
97
+ #define VRING_DROP_DESC_MAX_LEN GENMASK(15, 0)
98
+
89
99
/* Interrupt types. */
90
100
enum {
91
101
MLXBF_TM_RX_LWM_IRQ ,
@@ -214,7 +224,7 @@ static u8 mlxbf_tmfifo_net_default_mac[ETH_ALEN] = {
214
224
static efi_char16_t mlxbf_tmfifo_efi_name [] = L"RshimMacAddr" ;
215
225
216
226
/* Maximum L2 header length. */
217
- #define MLXBF_TMFIFO_NET_L2_OVERHEAD 36
227
+ #define MLXBF_TMFIFO_NET_L2_OVERHEAD (ETH_HLEN + VLAN_HLEN)
218
228
219
229
/* Supported virtio-net features. */
220
230
#define MLXBF_TMFIFO_NET_FEATURES \
@@ -262,6 +272,7 @@ static int mlxbf_tmfifo_alloc_vrings(struct mlxbf_tmfifo *fifo,
262
272
vring -> align = SMP_CACHE_BYTES ;
263
273
vring -> index = i ;
264
274
vring -> vdev_id = tm_vdev -> vdev .id .device ;
275
+ vring -> drop_desc .len = VRING_DROP_DESC_MAX_LEN ;
265
276
dev = & tm_vdev -> vdev .dev ;
266
277
267
278
size = vring_size (vring -> num , vring -> align );
@@ -367,7 +378,7 @@ static u32 mlxbf_tmfifo_get_pkt_len(struct mlxbf_tmfifo_vring *vring,
367
378
return len ;
368
379
}
369
380
370
- static void mlxbf_tmfifo_release_pending_pkt (struct mlxbf_tmfifo_vring * vring )
381
+ static void mlxbf_tmfifo_release_pkt (struct mlxbf_tmfifo_vring * vring )
371
382
{
372
383
struct vring_desc * desc_head ;
373
384
u32 len = 0 ;
@@ -596,19 +607,25 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring,
596
607
597
608
if (vring -> cur_len + sizeof (u64 ) <= len ) {
598
609
/* The whole word. */
599
- if (is_rx )
600
- memcpy (addr + vring -> cur_len , & data , sizeof (u64 ));
601
- else
602
- memcpy (& data , addr + vring -> cur_len , sizeof (u64 ));
610
+ if (!IS_VRING_DROP (vring )) {
611
+ if (is_rx )
612
+ memcpy (addr + vring -> cur_len , & data ,
613
+ sizeof (u64 ));
614
+ else
615
+ memcpy (& data , addr + vring -> cur_len ,
616
+ sizeof (u64 ));
617
+ }
603
618
vring -> cur_len += sizeof (u64 );
604
619
} else {
605
620
/* Leftover bytes. */
606
- if (is_rx )
607
- memcpy (addr + vring -> cur_len , & data ,
608
- len - vring -> cur_len );
609
- else
610
- memcpy (& data , addr + vring -> cur_len ,
611
- len - vring -> cur_len );
621
+ if (!IS_VRING_DROP (vring )) {
622
+ if (is_rx )
623
+ memcpy (addr + vring -> cur_len , & data ,
624
+ len - vring -> cur_len );
625
+ else
626
+ memcpy (& data , addr + vring -> cur_len ,
627
+ len - vring -> cur_len );
628
+ }
612
629
vring -> cur_len = len ;
613
630
}
614
631
@@ -625,13 +642,14 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring,
625
642
* flag is set.
626
643
*/
627
644
static void mlxbf_tmfifo_rxtx_header (struct mlxbf_tmfifo_vring * vring ,
628
- struct vring_desc * desc ,
645
+ struct vring_desc * * desc ,
629
646
bool is_rx , bool * vring_change )
630
647
{
631
648
struct mlxbf_tmfifo * fifo = vring -> fifo ;
632
649
struct virtio_net_config * config ;
633
650
struct mlxbf_tmfifo_msg_hdr hdr ;
634
651
int vdev_id , hdr_len ;
652
+ bool drop_rx = false;
635
653
636
654
/* Read/Write packet header. */
637
655
if (is_rx ) {
@@ -651,8 +669,8 @@ static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring,
651
669
if (ntohs (hdr .len ) >
652
670
__virtio16_to_cpu (virtio_legacy_is_little_endian (),
653
671
config -> mtu ) +
654
- MLXBF_TMFIFO_NET_L2_OVERHEAD )
655
- return ;
672
+ MLXBF_TMFIFO_NET_L2_OVERHEAD )
673
+ drop_rx = true ;
656
674
} else {
657
675
vdev_id = VIRTIO_ID_CONSOLE ;
658
676
hdr_len = 0 ;
@@ -667,16 +685,25 @@ static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring,
667
685
668
686
if (!tm_dev2 )
669
687
return ;
670
- vring -> desc = desc ;
688
+ vring -> desc = * desc ;
671
689
vring = & tm_dev2 -> vrings [MLXBF_TMFIFO_VRING_RX ];
672
690
* vring_change = true;
673
691
}
692
+
693
+ if (drop_rx && !IS_VRING_DROP (vring )) {
694
+ if (vring -> desc_head )
695
+ mlxbf_tmfifo_release_pkt (vring );
696
+ * desc = & vring -> drop_desc ;
697
+ vring -> desc_head = * desc ;
698
+ vring -> desc = * desc ;
699
+ }
700
+
674
701
vring -> pkt_len = ntohs (hdr .len ) + hdr_len ;
675
702
} else {
676
703
/* Network virtio has an extra header. */
677
704
hdr_len = (vring -> vdev_id == VIRTIO_ID_NET ) ?
678
705
sizeof (struct virtio_net_hdr ) : 0 ;
679
- vring -> pkt_len = mlxbf_tmfifo_get_pkt_len (vring , desc );
706
+ vring -> pkt_len = mlxbf_tmfifo_get_pkt_len (vring , * desc );
680
707
hdr .type = (vring -> vdev_id == VIRTIO_ID_NET ) ?
681
708
VIRTIO_ID_NET : VIRTIO_ID_CONSOLE ;
682
709
hdr .len = htons (vring -> pkt_len - hdr_len );
@@ -709,15 +736,23 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
709
736
/* Get the descriptor of the next packet. */
710
737
if (!vring -> desc ) {
711
738
desc = mlxbf_tmfifo_get_next_pkt (vring , is_rx );
712
- if (!desc )
713
- return false;
739
+ if (!desc ) {
740
+ /* Drop next Rx packet to avoid stuck. */
741
+ if (is_rx ) {
742
+ desc = & vring -> drop_desc ;
743
+ vring -> desc_head = desc ;
744
+ vring -> desc = desc ;
745
+ } else {
746
+ return false;
747
+ }
748
+ }
714
749
} else {
715
750
desc = vring -> desc ;
716
751
}
717
752
718
753
/* Beginning of a packet. Start to Rx/Tx packet header. */
719
754
if (vring -> pkt_len == 0 ) {
720
- mlxbf_tmfifo_rxtx_header (vring , desc , is_rx , & vring_change );
755
+ mlxbf_tmfifo_rxtx_header (vring , & desc , is_rx , & vring_change );
721
756
(* avail )-- ;
722
757
723
758
/* Return if new packet is for another ring. */
@@ -743,17 +778,24 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
743
778
vring -> rem_len -= len ;
744
779
745
780
/* Get the next desc on the chain. */
746
- if (vring -> rem_len > 0 &&
781
+ if (! IS_VRING_DROP ( vring ) && vring -> rem_len > 0 &&
747
782
(virtio16_to_cpu (vdev , desc -> flags ) & VRING_DESC_F_NEXT )) {
748
783
idx = virtio16_to_cpu (vdev , desc -> next );
749
784
desc = & vr -> desc [idx ];
750
785
goto mlxbf_tmfifo_desc_done ;
751
786
}
752
787
753
- /* Done and release the pending packet. */
754
- mlxbf_tmfifo_release_pending_pkt (vring );
788
+ /* Done and release the packet. */
755
789
desc = NULL ;
756
790
fifo -> vring [is_rx ] = NULL ;
791
+ if (!IS_VRING_DROP (vring )) {
792
+ mlxbf_tmfifo_release_pkt (vring );
793
+ } else {
794
+ vring -> pkt_len = 0 ;
795
+ vring -> desc_head = NULL ;
796
+ vring -> desc = NULL ;
797
+ return false;
798
+ }
757
799
758
800
/*
759
801
* Make sure the load/store are in order before
@@ -933,7 +975,7 @@ static void mlxbf_tmfifo_virtio_del_vqs(struct virtio_device *vdev)
933
975
934
976
/* Release the pending packet. */
935
977
if (vring -> desc )
936
- mlxbf_tmfifo_release_pending_pkt (vring );
978
+ mlxbf_tmfifo_release_pkt (vring );
937
979
vq = vring -> vq ;
938
980
if (vq ) {
939
981
vring -> vq = NULL ;
0 commit comments