28
28
#define AIROHA_NUM_QOS_QUEUES 8
29
29
#define AIROHA_NUM_TX_RING 32
30
30
#define AIROHA_NUM_RX_RING 32
31
+ #define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \
32
+ AIROHA_NUM_QOS_CHANNELS)
31
33
#define AIROHA_FE_MC_MAX_VLAN_TABLE 64
32
34
#define AIROHA_FE_MC_MAX_VLAN_PORT 16
33
35
#define AIROHA_NUM_TX_IRQ 2
43
45
#define PSE_RSV_PAGES 128
44
46
#define PSE_QUEUE_RSV_PAGES 64
45
47
48
+ #define QDMA_METER_IDX (_n ) ((_n) & 0xff)
49
+ #define QDMA_METER_GROUP (_n ) (((_n) >> 8) & 0x3)
50
+
46
51
/* FE */
47
52
#define PSE_BASE 0x0100
48
53
#define CSR_IFC_BASE 0x0200
583
588
#define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16)
584
589
#define EGRESS_FAST_TICK_MASK GENMASK(15, 0)
585
590
591
+ #define TRTCM_PARAM_RW_MASK BIT(31)
592
+ #define TRTCM_PARAM_RW_DONE_MASK BIT(30)
593
+ #define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28)
594
+ #define TRTCM_METER_GROUP_MASK GENMASK(27, 26)
595
+ #define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17)
596
+ #define TRTCM_PARAM_RATE_TYPE_MASK BIT(16)
597
+
598
+ #define REG_TRTCM_CFG_PARAM (_n ) ((_n) + 0x4)
599
+ #define REG_TRTCM_DATA_LOW (_n ) ((_n) + 0x8)
600
+ #define REG_TRTCM_DATA_HIGH (_n ) ((_n) + 0xc)
601
+
586
602
#define REG_TXWRR_MODE_CFG 0x1020
587
603
#define TWRR_WEIGHT_SCALE_MASK BIT(31)
588
604
#define TWRR_WEIGHT_BASE_MASK BIT(3)
@@ -759,6 +775,29 @@ enum tx_sched_mode {
759
775
TC_SCH_WRR2 ,
760
776
};
761
777
778
+ enum trtcm_param_type {
779
+ TRTCM_MISC_MODE , /* meter_en, pps_mode, tick_sel */
780
+ TRTCM_TOKEN_RATE_MODE ,
781
+ TRTCM_BUCKETSIZE_SHIFT_MODE ,
782
+ TRTCM_BUCKET_COUNTER_MODE ,
783
+ };
784
+
785
+ enum trtcm_mode_type {
786
+ TRTCM_COMMIT_MODE ,
787
+ TRTCM_PEAK_MODE ,
788
+ };
789
+
790
+ enum trtcm_param {
791
+ TRTCM_TICK_SEL = BIT (0 ),
792
+ TRTCM_PKT_MODE = BIT (1 ),
793
+ TRTCM_METER_MODE = BIT (2 ),
794
+ };
795
+
796
+ #define MIN_TOKEN_SIZE 4096
797
+ #define MAX_TOKEN_SIZE_OFFSET 17
798
+ #define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6)
799
+ #define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0)
800
+
762
801
struct airoha_queue_entry {
763
802
union {
764
803
void * buf ;
@@ -850,6 +889,8 @@ struct airoha_gdm_port {
850
889
851
890
struct airoha_hw_stats stats ;
852
891
892
+ DECLARE_BITMAP (qos_sq_bmap , AIROHA_NUM_QOS_CHANNELS );
893
+
853
894
/* qos stats counters */
854
895
u64 cpu_tx_packets ;
855
896
u64 fwd_tx_packets ;
@@ -2817,6 +2858,243 @@ static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port,
2817
2858
}
2818
2859
}
2819
2860
2861
+ static int airoha_qdma_get_trtcm_param (struct airoha_qdma * qdma , int channel ,
2862
+ u32 addr , enum trtcm_param_type param ,
2863
+ enum trtcm_mode_type mode ,
2864
+ u32 * val_low , u32 * val_high )
2865
+ {
2866
+ u32 idx = QDMA_METER_IDX (channel ), group = QDMA_METER_GROUP (channel );
2867
+ u32 val , config = FIELD_PREP (TRTCM_PARAM_TYPE_MASK , param ) |
2868
+ FIELD_PREP (TRTCM_METER_GROUP_MASK , group ) |
2869
+ FIELD_PREP (TRTCM_PARAM_INDEX_MASK , idx ) |
2870
+ FIELD_PREP (TRTCM_PARAM_RATE_TYPE_MASK , mode );
2871
+
2872
+ airoha_qdma_wr (qdma , REG_TRTCM_CFG_PARAM (addr ), config );
2873
+ if (read_poll_timeout (airoha_qdma_rr , val ,
2874
+ val & TRTCM_PARAM_RW_DONE_MASK ,
2875
+ USEC_PER_MSEC , 10 * USEC_PER_MSEC , true,
2876
+ qdma , REG_TRTCM_CFG_PARAM (addr )))
2877
+ return - ETIMEDOUT ;
2878
+
2879
+ * val_low = airoha_qdma_rr (qdma , REG_TRTCM_DATA_LOW (addr ));
2880
+ if (val_high )
2881
+ * val_high = airoha_qdma_rr (qdma , REG_TRTCM_DATA_HIGH (addr ));
2882
+
2883
+ return 0 ;
2884
+ }
2885
+
2886
+ static int airoha_qdma_set_trtcm_param (struct airoha_qdma * qdma , int channel ,
2887
+ u32 addr , enum trtcm_param_type param ,
2888
+ enum trtcm_mode_type mode , u32 val )
2889
+ {
2890
+ u32 idx = QDMA_METER_IDX (channel ), group = QDMA_METER_GROUP (channel );
2891
+ u32 config = TRTCM_PARAM_RW_MASK |
2892
+ FIELD_PREP (TRTCM_PARAM_TYPE_MASK , param ) |
2893
+ FIELD_PREP (TRTCM_METER_GROUP_MASK , group ) |
2894
+ FIELD_PREP (TRTCM_PARAM_INDEX_MASK , idx ) |
2895
+ FIELD_PREP (TRTCM_PARAM_RATE_TYPE_MASK , mode );
2896
+
2897
+ airoha_qdma_wr (qdma , REG_TRTCM_DATA_LOW (addr ), val );
2898
+ airoha_qdma_wr (qdma , REG_TRTCM_CFG_PARAM (addr ), config );
2899
+
2900
+ return read_poll_timeout (airoha_qdma_rr , val ,
2901
+ val & TRTCM_PARAM_RW_DONE_MASK ,
2902
+ USEC_PER_MSEC , 10 * USEC_PER_MSEC , true,
2903
+ qdma , REG_TRTCM_CFG_PARAM (addr ));
2904
+ }
2905
+
2906
+ static int airoha_qdma_set_trtcm_config (struct airoha_qdma * qdma , int channel ,
2907
+ u32 addr , enum trtcm_mode_type mode ,
2908
+ bool enable , u32 enable_mask )
2909
+ {
2910
+ u32 val ;
2911
+
2912
+ if (airoha_qdma_get_trtcm_param (qdma , channel , addr , TRTCM_MISC_MODE ,
2913
+ mode , & val , NULL ))
2914
+ return - EINVAL ;
2915
+
2916
+ val = enable ? val | enable_mask : val & ~enable_mask ;
2917
+
2918
+ return airoha_qdma_set_trtcm_param (qdma , channel , addr , TRTCM_MISC_MODE ,
2919
+ mode , val );
2920
+ }
2921
+
2922
+ static int airoha_qdma_set_trtcm_token_bucket (struct airoha_qdma * qdma ,
2923
+ int channel , u32 addr ,
2924
+ enum trtcm_mode_type mode ,
2925
+ u32 rate_val , u32 bucket_size )
2926
+ {
2927
+ u32 val , config , tick , unit , rate , rate_frac ;
2928
+ int err ;
2929
+
2930
+ if (airoha_qdma_get_trtcm_param (qdma , channel , addr , TRTCM_MISC_MODE ,
2931
+ mode , & config , NULL ))
2932
+ return - EINVAL ;
2933
+
2934
+ val = airoha_qdma_rr (qdma , addr );
2935
+ tick = FIELD_GET (INGRESS_FAST_TICK_MASK , val );
2936
+ if (config & TRTCM_TICK_SEL )
2937
+ tick *= FIELD_GET (INGRESS_SLOW_TICK_RATIO_MASK , val );
2938
+ if (!tick )
2939
+ return - EINVAL ;
2940
+
2941
+ unit = (config & TRTCM_PKT_MODE ) ? 1000000 / tick : 8000 / tick ;
2942
+ if (!unit )
2943
+ return - EINVAL ;
2944
+
2945
+ rate = rate_val / unit ;
2946
+ rate_frac = rate_val % unit ;
2947
+ rate_frac = FIELD_PREP (TRTCM_TOKEN_RATE_MASK , rate_frac ) / unit ;
2948
+ rate = FIELD_PREP (TRTCM_TOKEN_RATE_MASK , rate ) |
2949
+ FIELD_PREP (TRTCM_TOKEN_RATE_FRACTION_MASK , rate_frac );
2950
+
2951
+ err = airoha_qdma_set_trtcm_param (qdma , channel , addr ,
2952
+ TRTCM_TOKEN_RATE_MODE , mode , rate );
2953
+ if (err )
2954
+ return err ;
2955
+
2956
+ val = max_t (u32 , bucket_size , MIN_TOKEN_SIZE );
2957
+ val = min_t (u32 , __fls (val ), MAX_TOKEN_SIZE_OFFSET );
2958
+
2959
+ return airoha_qdma_set_trtcm_param (qdma , channel , addr ,
2960
+ TRTCM_BUCKETSIZE_SHIFT_MODE ,
2961
+ mode , val );
2962
+ }
2963
+
2964
+ static int airoha_qdma_set_tx_rate_limit (struct airoha_gdm_port * port ,
2965
+ int channel , u32 rate ,
2966
+ u32 bucket_size )
2967
+ {
2968
+ int i , err ;
2969
+
2970
+ for (i = 0 ; i <= TRTCM_PEAK_MODE ; i ++ ) {
2971
+ err = airoha_qdma_set_trtcm_config (port -> qdma , channel ,
2972
+ REG_EGRESS_TRTCM_CFG , i ,
2973
+ !!rate , TRTCM_METER_MODE );
2974
+ if (err )
2975
+ return err ;
2976
+
2977
+ err = airoha_qdma_set_trtcm_token_bucket (port -> qdma , channel ,
2978
+ REG_EGRESS_TRTCM_CFG ,
2979
+ i , rate , bucket_size );
2980
+ if (err )
2981
+ return err ;
2982
+ }
2983
+
2984
+ return 0 ;
2985
+ }
2986
+
2987
+ static int airoha_tc_htb_alloc_leaf_queue (struct airoha_gdm_port * port ,
2988
+ struct tc_htb_qopt_offload * opt )
2989
+ {
2990
+ u32 channel = TC_H_MIN (opt -> classid ) % AIROHA_NUM_QOS_CHANNELS ;
2991
+ u32 rate = div_u64 (opt -> rate , 1000 ) << 3 ; /* kbps */
2992
+ struct net_device * dev = port -> dev ;
2993
+ int num_tx_queues = dev -> real_num_tx_queues ;
2994
+ int err ;
2995
+
2996
+ if (opt -> parent_classid != TC_HTB_CLASSID_ROOT ) {
2997
+ NL_SET_ERR_MSG_MOD (opt -> extack , "invalid parent classid" );
2998
+ return - EINVAL ;
2999
+ }
3000
+
3001
+ err = airoha_qdma_set_tx_rate_limit (port , channel , rate , opt -> quantum );
3002
+ if (err ) {
3003
+ NL_SET_ERR_MSG_MOD (opt -> extack ,
3004
+ "failed configuring htb offload" );
3005
+ return err ;
3006
+ }
3007
+
3008
+ if (opt -> command == TC_HTB_NODE_MODIFY )
3009
+ return 0 ;
3010
+
3011
+ err = netif_set_real_num_tx_queues (dev , num_tx_queues + 1 );
3012
+ if (err ) {
3013
+ airoha_qdma_set_tx_rate_limit (port , channel , 0 , opt -> quantum );
3014
+ NL_SET_ERR_MSG_MOD (opt -> extack ,
3015
+ "failed setting real_num_tx_queues" );
3016
+ return err ;
3017
+ }
3018
+
3019
+ set_bit (channel , port -> qos_sq_bmap );
3020
+ opt -> qid = AIROHA_NUM_TX_RING + channel ;
3021
+
3022
+ return 0 ;
3023
+ }
3024
+
3025
+ static void airoha_tc_remove_htb_queue (struct airoha_gdm_port * port , int queue )
3026
+ {
3027
+ struct net_device * dev = port -> dev ;
3028
+
3029
+ netif_set_real_num_tx_queues (dev , dev -> real_num_tx_queues - 1 );
3030
+ airoha_qdma_set_tx_rate_limit (port , queue + 1 , 0 , 0 );
3031
+ clear_bit (queue , port -> qos_sq_bmap );
3032
+ }
3033
+
3034
+ static int airoha_tc_htb_delete_leaf_queue (struct airoha_gdm_port * port ,
3035
+ struct tc_htb_qopt_offload * opt )
3036
+ {
3037
+ u32 channel = TC_H_MIN (opt -> classid ) % AIROHA_NUM_QOS_CHANNELS ;
3038
+
3039
+ if (!test_bit (channel , port -> qos_sq_bmap )) {
3040
+ NL_SET_ERR_MSG_MOD (opt -> extack , "invalid queue id" );
3041
+ return - EINVAL ;
3042
+ }
3043
+
3044
+ airoha_tc_remove_htb_queue (port , channel );
3045
+
3046
+ return 0 ;
3047
+ }
3048
+
3049
+ static int airoha_tc_htb_destroy (struct airoha_gdm_port * port )
3050
+ {
3051
+ int q ;
3052
+
3053
+ for_each_set_bit (q , port -> qos_sq_bmap , AIROHA_NUM_QOS_CHANNELS )
3054
+ airoha_tc_remove_htb_queue (port , q );
3055
+
3056
+ return 0 ;
3057
+ }
3058
+
3059
+ static int airoha_tc_get_htb_get_leaf_queue (struct airoha_gdm_port * port ,
3060
+ struct tc_htb_qopt_offload * opt )
3061
+ {
3062
+ u32 channel = TC_H_MIN (opt -> classid ) % AIROHA_NUM_QOS_CHANNELS ;
3063
+
3064
+ if (!test_bit (channel , port -> qos_sq_bmap )) {
3065
+ NL_SET_ERR_MSG_MOD (opt -> extack , "invalid queue id" );
3066
+ return - EINVAL ;
3067
+ }
3068
+
3069
+ opt -> qid = channel ;
3070
+
3071
+ return 0 ;
3072
+ }
3073
+
3074
+ static int airoha_tc_setup_qdisc_htb (struct airoha_gdm_port * port ,
3075
+ struct tc_htb_qopt_offload * opt )
3076
+ {
3077
+ switch (opt -> command ) {
3078
+ case TC_HTB_CREATE :
3079
+ break ;
3080
+ case TC_HTB_DESTROY :
3081
+ return airoha_tc_htb_destroy (port );
3082
+ case TC_HTB_NODE_MODIFY :
3083
+ case TC_HTB_LEAF_ALLOC_QUEUE :
3084
+ return airoha_tc_htb_alloc_leaf_queue (port , opt );
3085
+ case TC_HTB_LEAF_DEL :
3086
+ case TC_HTB_LEAF_DEL_LAST :
3087
+ case TC_HTB_LEAF_DEL_LAST_FORCE :
3088
+ return airoha_tc_htb_delete_leaf_queue (port , opt );
3089
+ case TC_HTB_LEAF_QUERY_QUEUE :
3090
+ return airoha_tc_get_htb_get_leaf_queue (port , opt );
3091
+ default :
3092
+ return - EOPNOTSUPP ;
3093
+ }
3094
+
3095
+ return 0 ;
3096
+ }
3097
+
2820
3098
static int airoha_dev_tc_setup (struct net_device * dev , enum tc_setup_type type ,
2821
3099
void * type_data )
2822
3100
{
@@ -2825,6 +3103,8 @@ static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
2825
3103
switch (type ) {
2826
3104
case TC_SETUP_QDISC_ETS :
2827
3105
return airoha_tc_setup_qdisc_ets (port , type_data );
3106
+ case TC_SETUP_QDISC_HTB :
3107
+ return airoha_tc_setup_qdisc_htb (port , type_data );
2828
3108
default :
2829
3109
return - EOPNOTSUPP ;
2830
3110
}
@@ -2875,7 +3155,8 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np)
2875
3155
}
2876
3156
2877
3157
dev = devm_alloc_etherdev_mqs (eth -> dev , sizeof (* port ),
2878
- AIROHA_NUM_TX_RING , AIROHA_NUM_RX_RING );
3158
+ AIROHA_NUM_NETDEV_TX_RINGS ,
3159
+ AIROHA_NUM_RX_RING );
2879
3160
if (!dev ) {
2880
3161
dev_err (eth -> dev , "alloc_etherdev failed\n" );
2881
3162
return - ENOMEM ;
@@ -2895,6 +3176,11 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np)
2895
3176
dev -> irq = qdma -> irq ;
2896
3177
SET_NETDEV_DEV (dev , eth -> dev );
2897
3178
3179
+ /* reserve hw queues for HTB offloading */
3180
+ err = netif_set_real_num_tx_queues (dev , AIROHA_NUM_TX_RING );
3181
+ if (err )
3182
+ return err ;
3183
+
2898
3184
err = of_get_ethdev_address (np , dev );
2899
3185
if (err ) {
2900
3186
if (err == - EPROBE_DEFER )
0 commit comments