Skip to content

Commit

Permalink
Merge branch 'xstats-for-tc-taprio'
Browse files Browse the repository at this point in the history
Vladimir Oltean says:

====================
xstats for tc-taprio

As a result of this discussion:
https://lore.kernel.org/intel-wired-lan/20230411055543.24177-1-muhammad.husaini.zulkifli@intel.com/

it became apparent that tc-taprio should make an effort to standardize
statistics counters related to the 802.1Qbv scheduling as implemented
by the NIC. I'm presenting here one counter suggested by the standard,
and one counter defined by the NXP ENETC controller from LS1028A. Both
counters are reported globally and per traffic class - drivers get
different callbacks for reporting both of these, and get to choose what
to report in both cases.

The iproute2 counterpart is available here for testing:
https://github.com/vladimiroltean/iproute2/commits/taprio-xstats
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 31, 2023
2 parents 5dedf5c + 4802fca commit 60cbd38
Show file tree
Hide file tree
Showing 15 changed files with 286 additions and 66 deletions.
14 changes: 9 additions & 5 deletions drivers/net/dsa/hirschmann/hellcreek.c
Original file line number Diff line number Diff line change
Expand Up @@ -1885,13 +1885,17 @@ static int hellcreek_port_setup_tc(struct dsa_switch *ds, int port,
case TC_SETUP_QDISC_TAPRIO: {
struct tc_taprio_qopt_offload *taprio = type_data;

if (!hellcreek_validate_schedule(hellcreek, taprio))
return -EOPNOTSUPP;
switch (taprio->cmd) {
case TAPRIO_CMD_REPLACE:
if (!hellcreek_validate_schedule(hellcreek, taprio))
return -EOPNOTSUPP;

if (taprio->enable)
return hellcreek_port_set_schedule(ds, port, taprio);

return hellcreek_port_del_schedule(ds, port);
case TAPRIO_CMD_DESTROY:
return hellcreek_port_del_schedule(ds, port);
default:
return -EOPNOTSUPP;
}
}
default:
return -EOPNOTSUPP;
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/dsa/ocelot/felix_vsc9959.c
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,

mutex_lock(&ocelot->tas_lock);

if (!taprio->enable) {
if (taprio->cmd == TAPRIO_CMD_DESTROY) {
ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE,
QSYS_TAG_CONFIG, port);
Expand All @@ -1423,6 +1423,8 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,

mutex_unlock(&ocelot->tas_lock);
return 0;
} else if (taprio->cmd != TAPRIO_CMD_REPLACE) {
return -EOPNOTSUPP;
}

ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
Expand Down
7 changes: 5 additions & 2 deletions drivers/net/dsa/sja1105/sja1105_tas.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,10 +516,11 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
/* Can't change an already configured port (must delete qdisc first).
* Can't delete the qdisc from an unconfigured port.
*/
if (!!tas_data->offload[port] == admin->enable)
if ((!!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_REPLACE) ||
(!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_DESTROY))
return -EINVAL;

if (!admin->enable) {
if (admin->cmd == TAPRIO_CMD_DESTROY) {
taprio_offload_free(tas_data->offload[port]);
tas_data->offload[port] = NULL;

Expand All @@ -528,6 +529,8 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
return rc;

return sja1105_static_config_reload(priv, SJA1105_SCHEDULING);
} else if (admin->cmd != TAPRIO_CMD_REPLACE) {
return -EOPNOTSUPP;
}

/* The cycle time extension is the amount of time the last cycle from
Expand Down
12 changes: 6 additions & 6 deletions drivers/net/ethernet/engleder/tsnep_selftests.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ static bool disable_taprio(struct tsnep_adapter *adapter)
int retval;

memset(&qopt, 0, sizeof(qopt));
qopt.enable = 0;
qopt.cmd = TAPRIO_CMD_DESTROY;
retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt);
if (retval)
return false;
Expand Down Expand Up @@ -360,7 +360,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;

qopt->enable = 1;
qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 1500000;
qopt->cycle_time_extension = 0;
Expand All @@ -382,7 +382,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
if (!run_taprio(adapter, qopt, 100))
goto failed;

qopt->enable = 1;
qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 411854;
qopt->cycle_time_extension = 0;
Expand All @@ -406,7 +406,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
if (!run_taprio(adapter, qopt, 100))
goto failed;

qopt->enable = 1;
qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
delay_base_time(adapter, qopt, 12);
qopt->cycle_time = 125000;
Expand Down Expand Up @@ -457,7 +457,7 @@ static bool tsnep_test_taprio_change(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;

qopt->enable = 1;
qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 100000;
qopt->cycle_time_extension = 0;
Expand Down Expand Up @@ -610,7 +610,7 @@ static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;

qopt->enable = 1;
qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 100000;
qopt->cycle_time_extension = 50000;
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ethernet/engleder/tsnep_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ static int tsnep_taprio(struct tsnep_adapter *adapter,
if (!adapter->gate_control)
return -EOPNOTSUPP;

if (!qopt->enable) {
if (qopt->cmd == TAPRIO_CMD_DESTROY) {
/* disable gate control if active */
mutex_lock(&adapter->gate_control_lock);

Expand All @@ -337,6 +337,8 @@ static int tsnep_taprio(struct tsnep_adapter *adapter,
mutex_unlock(&adapter->gate_control_lock);

return 0;
} else if (qopt->cmd != TAPRIO_CMD_REPLACE) {
return -EOPNOTSUPP;
}

retval = tsnep_validate_gcl(qopt);
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/freescale/enetc/enetc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2624,7 +2624,7 @@ static void enetc_debug_tx_ring_prios(struct enetc_ndev_priv *priv)
priv->tx_ring[i]->prio);
}

static void enetc_reset_tc_mqprio(struct net_device *ndev)
void enetc_reset_tc_mqprio(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
Expand All @@ -2649,6 +2649,7 @@ static void enetc_reset_tc_mqprio(struct net_device *ndev)

enetc_change_preemptible_tcs(priv, 0);
}
EXPORT_SYMBOL_GPL(enetc_reset_tc_mqprio);

int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
{
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/freescale/enetc/enetc.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev);
void enetc_set_features(struct net_device *ndev, netdev_features_t features);
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data);
void enetc_reset_tc_mqprio(struct net_device *ndev);
int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf);
int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
struct xdp_frame **frames, u32 flags);
Expand Down
110 changes: 86 additions & 24 deletions drivers/net/ethernet/freescale/enetc/enetc_qos.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed)
enetc_port_wr(hw, ENETC_PMR, (tmp & ~ENETC_PMR_PSPEED_MASK) | pspeed);
}

static int enetc_setup_taprio(struct net_device *ndev,
static int enetc_setup_taprio(struct enetc_ndev_priv *priv,
struct tc_taprio_qopt_offload *admin_conf)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
struct enetc_cbd cbd = {.cmd = 0};
struct tgs_gcl_conf *gcl_config;
Expand All @@ -60,19 +59,13 @@ static int enetc_setup_taprio(struct net_device *ndev,
int err;
int i;

/* TSD and Qbv are mutually exclusive in hardware */
for (i = 0; i < priv->num_tx_rings; i++)
if (priv->tx_ring[i]->tsd_enable)
return -EBUSY;

if (admin_conf->num_entries > enetc_get_max_gcl_len(hw))
return -EINVAL;
gcl_len = admin_conf->num_entries;

tge = enetc_rd(hw, ENETC_PTGCR);
if (!admin_conf->enable) {
enetc_wr(hw, ENETC_PTGCR, tge & ~ENETC_PTGCR_TGE);
enetc_reset_ptcmsdur(hw);

priv->active_offloads &= ~ENETC_F_QBV;

return 0;
}

if (admin_conf->cycle_time > U32_MAX ||
admin_conf->cycle_time_extension > U32_MAX)
Expand All @@ -82,6 +75,7 @@ static int enetc_setup_taprio(struct net_device *ndev,
* control BD descriptor.
*/
gcl_config = &cbd.gcl_conf;
gcl_len = admin_conf->num_entries;

data_size = struct_size(gcl_data, entry, gcl_len);
tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size,
Expand Down Expand Up @@ -115,6 +109,7 @@ static int enetc_setup_taprio(struct net_device *ndev,
cbd.cls = BDCR_CMD_PORT_GCL;
cbd.status_flags = 0;

tge = enetc_rd(hw, ENETC_PTGCR);
enetc_wr(hw, ENETC_PTGCR, tge | ENETC_PTGCR_TGE);

err = enetc_send_cmd(priv->si, &cbd);
Expand All @@ -132,25 +127,92 @@ static int enetc_setup_taprio(struct net_device *ndev,
return 0;
}

int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
static void enetc_reset_taprio(struct enetc_ndev_priv *priv)
{
struct enetc_hw *hw = &priv->si->hw;
u32 val;

val = enetc_rd(hw, ENETC_PTGCR);
enetc_wr(hw, ENETC_PTGCR, val & ~ENETC_PTGCR_TGE);
enetc_reset_ptcmsdur(hw);

priv->active_offloads &= ~ENETC_F_QBV;
}

static void enetc_taprio_destroy(struct net_device *ndev)
{
struct tc_taprio_qopt_offload *taprio = type_data;
struct enetc_ndev_priv *priv = netdev_priv(ndev);
int err, i;

/* TSD and Qbv are mutually exclusive in hardware */
enetc_reset_taprio(priv);
enetc_reset_tc_mqprio(ndev);
}

static void enetc_taprio_stats(struct net_device *ndev,
struct tc_taprio_qopt_stats *stats)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
u64 window_drops = 0;
int i;

for (i = 0; i < priv->num_tx_rings; i++)
if (priv->tx_ring[i]->tsd_enable)
return -EBUSY;
window_drops += priv->tx_ring[i]->stats.win_drop;

stats->window_drops = window_drops;
}

static void enetc_taprio_tc_stats(struct net_device *ndev,
struct tc_taprio_qopt_tc_stats *tc_stats)
{
struct tc_taprio_qopt_stats *stats = &tc_stats->stats;
struct enetc_ndev_priv *priv = netdev_priv(ndev);
int tc = tc_stats->tc;
u64 window_drops = 0;
int i;

for (i = 0; i < priv->num_tx_rings; i++)
if (priv->tx_ring[i]->prio == tc)
window_drops += priv->tx_ring[i]->stats.win_drop;

stats->window_drops = window_drops;
}

static int enetc_taprio_replace(struct net_device *ndev,
struct tc_taprio_qopt_offload *offload)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
int err;

err = enetc_setup_tc_mqprio(ndev, &taprio->mqprio);
err = enetc_setup_tc_mqprio(ndev, &offload->mqprio);
if (err)
return err;

err = enetc_setup_taprio(ndev, taprio);
if (err) {
taprio->mqprio.qopt.num_tc = 0;
enetc_setup_tc_mqprio(ndev, &taprio->mqprio);
err = enetc_setup_taprio(priv, offload);
if (err)
enetc_reset_tc_mqprio(ndev);

return err;
}

int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
{
struct tc_taprio_qopt_offload *offload = type_data;
int err = 0;

switch (offload->cmd) {
case TAPRIO_CMD_REPLACE:
err = enetc_taprio_replace(ndev, offload);
break;
case TAPRIO_CMD_DESTROY:
enetc_taprio_destroy(ndev);
break;
case TAPRIO_CMD_STATS:
enetc_taprio_stats(ndev, &offload->stats);
break;
case TAPRIO_CMD_TC_STATS:
enetc_taprio_tc_stats(ndev, &offload->tc_stats);
break;
default:
err = -EOPNOTSUPP;
}

return err;
Expand Down
13 changes: 11 additions & 2 deletions drivers/net/ethernet/intel/igc/igc_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6113,9 +6113,18 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
size_t n;
int i;

adapter->qbv_enable = qopt->enable;
switch (qopt->cmd) {
case TAPRIO_CMD_REPLACE:
adapter->qbv_enable = true;
break;
case TAPRIO_CMD_DESTROY:
adapter->qbv_enable = false;
break;
default:
return -EOPNOTSUPP;
}

if (!qopt->enable)
if (!adapter->qbv_enable)
return igc_tsn_clear_schedule(adapter);

if (qopt->base_time < 0)
Expand Down
10 changes: 8 additions & 2 deletions drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port,
static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port,
struct tc_taprio_qopt_offload *taprio)
{
return taprio->enable ? lan966x_taprio_add(port, taprio) :
lan966x_taprio_del(port);
switch (taprio->cmd) {
case TAPRIO_CMD_REPLACE:
return lan966x_taprio_add(port, taprio);
case TAPRIO_CMD_DESTROY:
return lan966x_taprio_del(port);
default:
return -EOPNOTSUPP;
}
}

static int lan966x_tc_setup_qdisc_tbf(struct lan966x_port *port,
Expand Down
7 changes: 5 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,8 +966,11 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
return -EOPNOTSUPP;
}

if (!qopt->enable)
if (qopt->cmd == TAPRIO_CMD_DESTROY)
goto disable;
else if (qopt->cmd != TAPRIO_CMD_REPLACE)
return -EOPNOTSUPP;

if (qopt->num_entries >= dep)
return -EINVAL;
if (!qopt->cycle_time)
Expand All @@ -988,7 +991,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv,

mutex_lock(&priv->plat->est->lock);
priv->plat->est->gcl_size = size;
priv->plat->est->enable = qopt->enable;
priv->plat->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE;
mutex_unlock(&priv->plat->est->lock);

for (i = 0; i < size; i++) {
Expand Down
Loading

0 comments on commit 60cbd38

Please sign in to comment.