@@ -812,6 +812,112 @@ static int hns_desc_unused(struct hnae_ring *ring)
812
812
return ((ntc >= ntu ) ? 0 : ring -> desc_num ) + ntc - ntu ;
813
813
}
814
814
815
+ #define HNS_LOWEST_LATENCY_RATE 27 /* 27 MB/s */
816
+ #define HNS_LOW_LATENCY_RATE 80 /* 80 MB/s */
817
+
818
+ #define HNS_COAL_BDNUM 3
819
+
820
+ static u32 hns_coal_rx_bdnum (struct hnae_ring * ring )
821
+ {
822
+ bool coal_enable = ring -> q -> handle -> coal_adapt_en ;
823
+
824
+ if (coal_enable &&
825
+ ring -> coal_last_rx_bytes > HNS_LOWEST_LATENCY_RATE )
826
+ return HNS_COAL_BDNUM ;
827
+ else
828
+ return 0 ;
829
+ }
830
+
831
+ static void hns_update_rx_rate (struct hnae_ring * ring )
832
+ {
833
+ bool coal_enable = ring -> q -> handle -> coal_adapt_en ;
834
+ u32 time_passed_ms ;
835
+ u64 total_bytes ;
836
+
837
+ if (!coal_enable ||
838
+ time_before (jiffies , ring -> coal_last_jiffies + (HZ >> 4 )))
839
+ return ;
840
+
841
+ /* ring->stats.rx_bytes overflowed */
842
+ if (ring -> coal_last_rx_bytes > ring -> stats .rx_bytes ) {
843
+ ring -> coal_last_rx_bytes = ring -> stats .rx_bytes ;
844
+ ring -> coal_last_jiffies = jiffies ;
845
+ return ;
846
+ }
847
+
848
+ total_bytes = ring -> stats .rx_bytes - ring -> coal_last_rx_bytes ;
849
+ time_passed_ms = jiffies_to_msecs (jiffies - ring -> coal_last_jiffies );
850
+ ring -> coal_rx_rate = (total_bytes / time_passed_ms ) >> 10 ;
851
+
852
+ ring -> coal_last_rx_bytes = ring -> stats .rx_bytes ;
853
+ ring -> coal_last_jiffies = jiffies ;
854
+ }
855
+
856
+ /**
857
+ * smooth_alg - smoothing algrithm for adjusting coalesce parameter
858
+ **/
859
+ static u32 smooth_alg (u32 new_param , u32 old_param )
860
+ {
861
+ u32 gap = (new_param > old_param ) ? new_param - old_param
862
+ : old_param - new_param ;
863
+
864
+ if (gap > 8 )
865
+ gap >>= 3 ;
866
+
867
+ if (new_param > old_param )
868
+ return old_param + gap ;
869
+ else
870
+ return old_param - gap ;
871
+ }
872
+
873
+ /**
874
+ * hns_nic_adp_coalesce - self adapte coalesce according to rx rate
875
+ * @ring_data: pointer to hns_nic_ring_data
876
+ **/
877
+ static void hns_nic_adpt_coalesce (struct hns_nic_ring_data * ring_data )
878
+ {
879
+ struct hnae_ring * ring = ring_data -> ring ;
880
+ struct hnae_handle * handle = ring -> q -> handle ;
881
+ u32 new_coal_param , old_coal_param = ring -> coal_param ;
882
+
883
+ if (ring -> coal_rx_rate < HNS_LOWEST_LATENCY_RATE )
884
+ new_coal_param = HNAE_LOWEST_LATENCY_COAL_PARAM ;
885
+ else if (ring -> coal_rx_rate < HNS_LOW_LATENCY_RATE )
886
+ new_coal_param = HNAE_LOW_LATENCY_COAL_PARAM ;
887
+ else
888
+ new_coal_param = HNAE_BULK_LATENCY_COAL_PARAM ;
889
+
890
+ if (new_coal_param == old_coal_param &&
891
+ new_coal_param == handle -> coal_param )
892
+ return ;
893
+
894
+ new_coal_param = smooth_alg (new_coal_param , old_coal_param );
895
+ ring -> coal_param = new_coal_param ;
896
+
897
+ /**
898
+ * Because all ring in one port has one coalesce param, when one ring
899
+ * calculate its own coalesce param, it cannot write to hardware at
900
+ * once. There are three conditions as follows:
901
+ * 1. current ring's coalesce param is larger than the hardware.
902
+ * 2. or ring which adapt last time can change again.
903
+ * 3. timeout.
904
+ */
905
+ if (new_coal_param == handle -> coal_param ) {
906
+ handle -> coal_last_jiffies = jiffies ;
907
+ handle -> coal_ring_idx = ring_data -> queue_index ;
908
+ } else if (new_coal_param > handle -> coal_param ||
909
+ handle -> coal_ring_idx == ring_data -> queue_index ||
910
+ time_after (jiffies , handle -> coal_last_jiffies + (HZ >> 4 ))) {
911
+ handle -> dev -> ops -> set_coalesce_usecs (handle ,
912
+ new_coal_param );
913
+ handle -> dev -> ops -> set_coalesce_frames (handle ,
914
+ 1 , new_coal_param );
915
+ handle -> coal_param = new_coal_param ;
916
+ handle -> coal_ring_idx = ring_data -> queue_index ;
917
+ handle -> coal_last_jiffies = jiffies ;
918
+ }
919
+ }
920
+
815
921
static int hns_nic_rx_poll_one (struct hns_nic_ring_data * ring_data ,
816
922
int budget , void * v )
817
923
{
@@ -868,33 +974,45 @@ static bool hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data)
868
974
{
869
975
struct hnae_ring * ring = ring_data -> ring ;
870
976
int num = 0 ;
977
+ bool rx_stopped ;
871
978
872
- ring_data -> ring -> q -> handle -> dev -> ops -> toggle_ring_irq (ring , 0 );
979
+ hns_update_rx_rate (ring );
873
980
874
981
/* for hardware bug fixed */
982
+ ring_data -> ring -> q -> handle -> dev -> ops -> toggle_ring_irq (ring , 0 );
875
983
num = readl_relaxed (ring -> io_base + RCB_REG_FBDNUM );
876
984
877
- if (num > 0 ) {
985
+ if (num <= hns_coal_rx_bdnum (ring )) {
986
+ if (ring -> q -> handle -> coal_adapt_en )
987
+ hns_nic_adpt_coalesce (ring_data );
988
+
989
+ rx_stopped = true;
990
+ } else {
878
991
ring_data -> ring -> q -> handle -> dev -> ops -> toggle_ring_irq (
879
992
ring_data -> ring , 1 );
880
993
881
- return false;
882
- } else {
883
- return true;
994
+ rx_stopped = false;
884
995
}
996
+
997
+ return rx_stopped ;
885
998
}
886
999
887
1000
static bool hns_nic_rx_fini_pro_v2 (struct hns_nic_ring_data * ring_data )
888
1001
{
889
1002
struct hnae_ring * ring = ring_data -> ring ;
890
1003
int num ;
891
1004
1005
+ hns_update_rx_rate (ring );
892
1006
num = readl_relaxed (ring -> io_base + RCB_REG_FBDNUM );
893
1007
894
- if (!num )
1008
+ if (num <= hns_coal_rx_bdnum (ring )) {
1009
+ if (ring -> q -> handle -> coal_adapt_en )
1010
+ hns_nic_adpt_coalesce (ring_data );
1011
+
895
1012
return true;
896
- else
897
- return false;
1013
+ }
1014
+
1015
+ return false;
898
1016
}
899
1017
900
1018
static inline void hns_nic_reclaim_one_desc (struct hnae_ring * ring ,
0 commit comments