@@ -1415,7 +1415,7 @@ static void esw_destroy_tsar(struct mlx5_eswitch *esw)
14151415}
14161416
14171417static int esw_vport_enable_qos (struct mlx5_eswitch * esw , int vport_num ,
1418- u32 initial_max_rate )
1418+ u32 initial_max_rate , u32 initial_bw_share )
14191419{
14201420 u32 sched_ctx [MLX5_ST_SZ_DW (scheduling_context )] = {0 };
14211421 struct mlx5_vport * vport = & esw -> vports [vport_num ];
@@ -1439,6 +1439,7 @@ static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
14391439 esw -> qos .root_tsar_id );
14401440 MLX5_SET (scheduling_context , & sched_ctx , max_average_bw ,
14411441 initial_max_rate );
1442+ MLX5_SET (scheduling_context , & sched_ctx , bw_share , initial_bw_share );
14421443
14431444 err = mlx5_create_scheduling_element_cmd (dev ,
14441445 SCHEDULING_HIERARCHY_E_SWITCH ,
@@ -1473,7 +1474,7 @@ static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
14731474}
14741475
14751476static int esw_vport_qos_config (struct mlx5_eswitch * esw , int vport_num ,
1476- u32 max_rate )
1477+ u32 max_rate , u32 bw_share )
14771478{
14781479 u32 sched_ctx [MLX5_ST_SZ_DW (scheduling_context )] = {0 };
14791480 struct mlx5_vport * vport = & esw -> vports [vport_num ];
@@ -1497,7 +1498,9 @@ static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num,
14971498 esw -> qos .root_tsar_id );
14981499 MLX5_SET (scheduling_context , & sched_ctx , max_average_bw ,
14991500 max_rate );
1501+ MLX5_SET (scheduling_context , & sched_ctx , bw_share , bw_share );
15001502 bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW ;
1503+ bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE ;
15011504
15021505 err = mlx5_modify_scheduling_element_cmd (dev ,
15031506 SCHEDULING_HIERARCHY_E_SWITCH ,
@@ -1563,7 +1566,8 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
15631566 esw_apply_vport_conf (esw , vport );
15641567
15651568 /* Attach vport to the eswitch rate limiter */
1566- if (esw_vport_enable_qos (esw , vport_num , vport -> info .max_rate ))
1569+ if (esw_vport_enable_qos (esw , vport_num , vport -> info .max_rate ,
1570+ vport -> qos .bw_share ))
15671571 esw_warn (esw -> dev , "Failed to attach vport %d to eswitch rate limiter" , vport_num );
15681572
15691573 /* Sync with current vport context */
@@ -1952,6 +1956,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
19521956 ivi -> qos = evport -> info .qos ;
19531957 ivi -> spoofchk = evport -> info .spoofchk ;
19541958 ivi -> trusted = evport -> info .trusted ;
1959+ ivi -> min_tx_rate = evport -> info .min_rate ;
19551960 ivi -> max_tx_rate = evport -> info .max_rate ;
19561961 mutex_unlock (& esw -> state_lock );
19571962
@@ -2046,23 +2051,103 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
20462051 return 0 ;
20472052}
20482053
2049- int mlx5_eswitch_set_vport_rate (struct mlx5_eswitch * esw ,
2050- int vport , u32 max_rate )
2054+ static u32 calculate_vports_min_rate_divider (struct mlx5_eswitch * esw )
20512055{
2056+ u32 fw_max_bw_share = MLX5_CAP_QOS (esw -> dev , max_tsar_bw_share );
20522057 struct mlx5_vport * evport ;
2058+ u32 max_guarantee = 0 ;
2059+ int i ;
2060+
2061+ for (i = 0 ; i <= esw -> total_vports ; i ++ ) {
2062+ evport = & esw -> vports [i ];
2063+ if (!evport -> enabled || evport -> info .min_rate < max_guarantee )
2064+ continue ;
2065+ max_guarantee = evport -> info .min_rate ;
2066+ }
2067+
2068+ return max_t (u32 , max_guarantee / fw_max_bw_share , 1 );
2069+ }
2070+
2071+ static int normalize_vports_min_rate (struct mlx5_eswitch * esw , u32 divider )
2072+ {
2073+ u32 fw_max_bw_share = MLX5_CAP_QOS (esw -> dev , max_tsar_bw_share );
2074+ struct mlx5_vport * evport ;
2075+ u32 vport_max_rate ;
2076+ u32 vport_min_rate ;
2077+ u32 bw_share ;
2078+ int err ;
2079+ int i ;
2080+
2081+ for (i = 0 ; i <= esw -> total_vports ; i ++ ) {
2082+ evport = & esw -> vports [i ];
2083+ if (!evport -> enabled )
2084+ continue ;
2085+ vport_min_rate = evport -> info .min_rate ;
2086+ vport_max_rate = evport -> info .max_rate ;
2087+ bw_share = MLX5_MIN_BW_SHARE ;
2088+
2089+ if (vport_min_rate )
2090+ bw_share = MLX5_RATE_TO_BW_SHARE (vport_min_rate ,
2091+ divider ,
2092+ fw_max_bw_share );
2093+
2094+ if (bw_share == evport -> qos .bw_share )
2095+ continue ;
2096+
2097+ err = esw_vport_qos_config (esw , i , vport_max_rate ,
2098+ bw_share );
2099+ if (!err )
2100+ evport -> qos .bw_share = bw_share ;
2101+ else
2102+ return err ;
2103+ }
2104+
2105+ return 0 ;
2106+ }
2107+
2108+ int mlx5_eswitch_set_vport_rate (struct mlx5_eswitch * esw , int vport ,
2109+ u32 max_rate , u32 min_rate )
2110+ {
2111+ u32 fw_max_bw_share = MLX5_CAP_QOS (esw -> dev , max_tsar_bw_share );
2112+ bool min_rate_supported = MLX5_CAP_QOS (esw -> dev , esw_bw_share ) &&
2113+ fw_max_bw_share >= MLX5_MIN_BW_SHARE ;
2114+ bool max_rate_supported = MLX5_CAP_QOS (esw -> dev , esw_rate_limit );
2115+ struct mlx5_vport * evport ;
2116+ u32 previous_min_rate ;
2117+ u32 divider ;
20532118 int err = 0 ;
20542119
20552120 if (!ESW_ALLOWED (esw ))
20562121 return - EPERM ;
20572122 if (!LEGAL_VPORT (esw , vport ))
20582123 return - EINVAL ;
2124+ if ((min_rate && !min_rate_supported ) || (max_rate && !max_rate_supported ))
2125+ return - EOPNOTSUPP ;
20592126
20602127 mutex_lock (& esw -> state_lock );
20612128 evport = & esw -> vports [vport ];
2062- err = esw_vport_qos_config (esw , vport , max_rate );
2129+
2130+ if (min_rate == evport -> info .min_rate )
2131+ goto set_max_rate ;
2132+
2133+ previous_min_rate = evport -> info .min_rate ;
2134+ evport -> info .min_rate = min_rate ;
2135+ divider = calculate_vports_min_rate_divider (esw );
2136+ err = normalize_vports_min_rate (esw , divider );
2137+ if (err ) {
2138+ evport -> info .min_rate = previous_min_rate ;
2139+ goto unlock ;
2140+ }
2141+
2142+ set_max_rate :
2143+ if (max_rate == evport -> info .max_rate )
2144+ goto unlock ;
2145+
2146+ err = esw_vport_qos_config (esw , vport , max_rate , evport -> qos .bw_share );
20632147 if (!err )
20642148 evport -> info .max_rate = max_rate ;
20652149
2150+ unlock :
20662151 mutex_unlock (& esw -> state_lock );
20672152 return err ;
20682153}
0 commit comments