|
@@ -1324,6 +1324,38 @@ out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+mlxsw_sp_port_get_hw_xstats(struct net_device *dev,
|
|
|
+ struct mlxsw_sp_port_xstats *xstats)
|
|
|
+{
|
|
|
+ char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
|
|
|
+ int err, i;
|
|
|
+
|
|
|
+ err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_EXT_CNT, 0,
|
|
|
+ ppcnt_pl);
|
|
|
+ if (!err)
|
|
|
+ xstats->ecn = mlxsw_reg_ppcnt_ecn_marked_get(ppcnt_pl);
|
|
|
+
|
|
|
+ for (i = 0; i < TC_MAX_QUEUE; i++) {
|
|
|
+ err = mlxsw_sp_port_get_stats_raw(dev,
|
|
|
+ MLXSW_REG_PPCNT_TC_CONG_TC,
|
|
|
+ i, ppcnt_pl);
|
|
|
+ if (!err)
|
|
|
+ xstats->wred_drop[i] =
|
|
|
+ mlxsw_reg_ppcnt_wred_discard_get(ppcnt_pl);
|
|
|
+
|
|
|
+ err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_TC_CNT,
|
|
|
+ i, ppcnt_pl);
|
|
|
+ if (err)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ xstats->backlog[i] =
|
|
|
+ mlxsw_reg_ppcnt_tc_transmit_queue_get(ppcnt_pl);
|
|
|
+ xstats->tail_drop[i] =
|
|
|
+ mlxsw_reg_ppcnt_tc_no_buffer_discard_uc_get(ppcnt_pl);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void update_stats_cache(struct work_struct *work)
|
|
|
{
|
|
|
struct mlxsw_sp_port *mlxsw_sp_port =
|
|
@@ -1335,6 +1367,8 @@ static void update_stats_cache(struct work_struct *work)
|
|
|
|
|
|
mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev,
|
|
|
&mlxsw_sp_port->periodic_hw_stats.stats);
|
|
|
+ mlxsw_sp_port_get_hw_xstats(mlxsw_sp_port->dev,
|
|
|
+ &mlxsw_sp_port->periodic_hw_stats.xstats);
|
|
|
|
|
|
out:
|
|
|
mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw,
|