3636#include <linux/errno.h>
3737#include <linux/netdevice.h>
3838#include <net/pkt_cls.h>
39+ #include <net/red.h>
3940
4041#include "spectrum.h"
4142#include "reg.h"
@@ -77,6 +78,27 @@ mlxsw_sp_tclass_congestion_disable(struct mlxsw_sp_port *mlxsw_sp_port,
7778 return mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (cwtpm ), cwtpm_cmd );
7879}
7980
81+ static void
82+ mlxsw_sp_setup_tc_qdisc_clean_stats (struct mlxsw_sp_port * mlxsw_sp_port ,
83+ struct mlxsw_sp_qdisc * mlxsw_sp_qdisc ,
84+ int tclass_num )
85+ {
86+ struct red_stats * xstats_base = & mlxsw_sp_qdisc -> xstats_base ;
87+ struct mlxsw_sp_port_xstats * xstats ;
88+
89+ xstats = & mlxsw_sp_port -> periodic_hw_stats .xstats ;
90+
91+ switch (mlxsw_sp_qdisc -> type ) {
92+ case MLXSW_SP_QDISC_RED :
93+ xstats_base -> prob_mark = xstats -> ecn ;
94+ xstats_base -> prob_drop = xstats -> wred_drop [tclass_num ];
95+ xstats_base -> pdrop = xstats -> tail_drop [tclass_num ];
96+ break ;
97+ default :
98+ break ;
99+ }
100+ }
101+
80102static int
81103mlxsw_sp_qdisc_red_destroy (struct mlxsw_sp_port * mlxsw_sp_port , u32 handle ,
82104 struct mlxsw_sp_qdisc * mlxsw_sp_qdisc ,
@@ -135,6 +157,11 @@ mlxsw_sp_qdisc_red_replace(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
135157 goto err_config ;
136158
137159 mlxsw_sp_qdisc -> type = MLXSW_SP_QDISC_RED ;
160+ if (mlxsw_sp_qdisc -> handle != handle )
161+ mlxsw_sp_setup_tc_qdisc_clean_stats (mlxsw_sp_port ,
162+ mlxsw_sp_qdisc ,
163+ tclass_num );
164+
138165 mlxsw_sp_qdisc -> handle = handle ;
139166 return 0 ;
140167
@@ -146,6 +173,26 @@ mlxsw_sp_qdisc_red_replace(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
146173 return err ;
147174}
148175
176+ static int
177+ mlxsw_sp_qdisc_get_red_xstats (struct mlxsw_sp_port * mlxsw_sp_port , u32 handle ,
178+ struct mlxsw_sp_qdisc * mlxsw_sp_qdisc ,
179+ int tclass_num , struct red_stats * res )
180+ {
181+ struct red_stats * xstats_base = & mlxsw_sp_qdisc -> xstats_base ;
182+ struct mlxsw_sp_port_xstats * xstats ;
183+
184+ if (mlxsw_sp_qdisc -> handle != handle ||
185+ mlxsw_sp_qdisc -> type != MLXSW_SP_QDISC_RED )
186+ return - EOPNOTSUPP ;
187+
188+ xstats = & mlxsw_sp_port -> periodic_hw_stats .xstats ;
189+
190+ res -> prob_drop = xstats -> wred_drop [tclass_num ] - xstats_base -> prob_drop ;
191+ res -> prob_mark = xstats -> ecn - xstats_base -> prob_mark ;
192+ res -> pdrop = xstats -> tail_drop [tclass_num ] - xstats_base -> pdrop ;
193+ return 0 ;
194+ }
195+
149196#define MLXSW_SP_PORT_DEFAULT_TCLASS 0
150197
151198int mlxsw_sp_setup_tc_red (struct mlxsw_sp_port * mlxsw_sp_port ,
@@ -168,6 +215,10 @@ int mlxsw_sp_setup_tc_red(struct mlxsw_sp_port *mlxsw_sp_port,
168215 case TC_RED_DESTROY :
169216 return mlxsw_sp_qdisc_red_destroy (mlxsw_sp_port , p -> handle ,
170217 mlxsw_sp_qdisc , tclass_num );
218+ case TC_RED_XSTATS :
219+ return mlxsw_sp_qdisc_get_red_xstats (mlxsw_sp_port , p -> handle ,
220+ mlxsw_sp_qdisc , tclass_num ,
221+ p -> xstats );
171222 default :
172223 return - EOPNOTSUPP ;
173224 }
0 commit comments