@@ -1415,7 +1415,7 @@ static void esw_destroy_tsar(struct mlx5_eswitch *esw)
1415
1415
}
1416
1416
1417
1417
static 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 )
1419
1419
{
1420
1420
u32 sched_ctx [MLX5_ST_SZ_DW (scheduling_context )] = {0 };
1421
1421
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,
1439
1439
esw -> qos .root_tsar_id );
1440
1440
MLX5_SET (scheduling_context , & sched_ctx , max_average_bw ,
1441
1441
initial_max_rate );
1442
+ MLX5_SET (scheduling_context , & sched_ctx , bw_share , initial_bw_share );
1442
1443
1443
1444
err = mlx5_create_scheduling_element_cmd (dev ,
1444
1445
SCHEDULING_HIERARCHY_E_SWITCH ,
@@ -1473,7 +1474,7 @@ static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
1473
1474
}
1474
1475
1475
1476
static int esw_vport_qos_config (struct mlx5_eswitch * esw , int vport_num ,
1476
- u32 max_rate )
1477
+ u32 max_rate , u32 bw_share )
1477
1478
{
1478
1479
u32 sched_ctx [MLX5_ST_SZ_DW (scheduling_context )] = {0 };
1479
1480
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,
1497
1498
esw -> qos .root_tsar_id );
1498
1499
MLX5_SET (scheduling_context , & sched_ctx , max_average_bw ,
1499
1500
max_rate );
1501
+ MLX5_SET (scheduling_context , & sched_ctx , bw_share , bw_share );
1500
1502
bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW ;
1503
+ bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE ;
1501
1504
1502
1505
err = mlx5_modify_scheduling_element_cmd (dev ,
1503
1506
SCHEDULING_HIERARCHY_E_SWITCH ,
@@ -1563,7 +1566,8 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
1563
1566
esw_apply_vport_conf (esw , vport );
1564
1567
1565
1568
/* 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 ))
1567
1571
esw_warn (esw -> dev , "Failed to attach vport %d to eswitch rate limiter" , vport_num );
1568
1572
1569
1573
/* Sync with current vport context */
@@ -1952,6 +1956,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
1952
1956
ivi -> qos = evport -> info .qos ;
1953
1957
ivi -> spoofchk = evport -> info .spoofchk ;
1954
1958
ivi -> trusted = evport -> info .trusted ;
1959
+ ivi -> min_tx_rate = evport -> info .min_rate ;
1955
1960
ivi -> max_tx_rate = evport -> info .max_rate ;
1956
1961
mutex_unlock (& esw -> state_lock );
1957
1962
@@ -2046,23 +2051,103 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
2046
2051
return 0 ;
2047
2052
}
2048
2053
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 )
2051
2055
{
2056
+ u32 fw_max_bw_share = MLX5_CAP_QOS (esw -> dev , max_tsar_bw_share );
2052
2057
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 ;
2053
2118
int err = 0 ;
2054
2119
2055
2120
if (!ESW_ALLOWED (esw ))
2056
2121
return - EPERM ;
2057
2122
if (!LEGAL_VPORT (esw , vport ))
2058
2123
return - EINVAL ;
2124
+ if ((min_rate && !min_rate_supported ) || (max_rate && !max_rate_supported ))
2125
+ return - EOPNOTSUPP ;
2059
2126
2060
2127
mutex_lock (& esw -> state_lock );
2061
2128
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 );
2063
2147
if (!err )
2064
2148
evport -> info .max_rate = max_rate ;
2065
2149
2150
+ unlock :
2066
2151
mutex_unlock (& esw -> state_lock );
2067
2152
return err ;
2068
2153
}
0 commit comments