Skip to content

Commit

Permalink
Merge branch 'stmmac-EST'
Browse files Browse the repository at this point in the history
Rohan G says:

====================
net: stmmac: EST conformance support

This patchset enables support for queueMaxSDU and transmission overrun
counters which are required for Qbv conformance.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 31, 2024
2 parents 57bf3dd + 5ca63ff commit 2acfd58
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 4 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ struct stmmac_extra_stats {
unsigned long mtl_est_hlbf;
unsigned long mtl_est_btre;
unsigned long mtl_est_btrlm;
unsigned long max_sdu_txq_drop[MTL_MAX_TX_QUEUES];
unsigned long mtl_est_txq_hlbf[MTL_MAX_TX_QUEUES];
/* per queue statistics */
struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES];
struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES];
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_est.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static void est_irq_status(struct stmmac_priv *priv, struct net_device *dev,
u32 status, value, feqn, hbfq, hbfs, btrl, btrl_max;
void __iomem *est_addr = priv->estaddr;
u32 txqcnt_mask = BIT(txqcnt) - 1;
int i;

status = readl(est_addr + EST_STATUS);

Expand Down Expand Up @@ -125,6 +126,11 @@ static void est_irq_status(struct stmmac_priv *priv, struct net_device *dev,

x->mtl_est_hlbf++;

for (i = 0; i < txqcnt; i++) {
if (feqn & BIT(i))
x->mtl_est_txq_hlbf[i]++;
}

/* Clear Interrupt */
writel(feqn, est_addr + EST_FRM_SZ_ERR);

Expand Down
22 changes: 22 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2507,6 +2507,13 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
if (!xsk_tx_peek_desc(pool, &xdp_desc))
break;

if (priv->plat->est && priv->plat->est->enable &&
priv->plat->est->max_sdu[queue] &&
xdp_desc.len > priv->plat->est->max_sdu[queue]) {
priv->xstats.max_sdu_txq_drop[queue]++;
continue;
}

if (likely(priv->extend_desc))
tx_desc = (struct dma_desc *)(tx_q->dma_etx + entry);
else if (tx_q->tbs & STMMAC_TBS_AVAIL)
Expand Down Expand Up @@ -4498,6 +4505,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
return stmmac_tso_xmit(skb, dev);
}

if (priv->plat->est && priv->plat->est->enable &&
priv->plat->est->max_sdu[queue] &&
skb->len > priv->plat->est->max_sdu[queue]){
priv->xstats.max_sdu_txq_drop[queue]++;
goto max_sdu_err;
}

if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, queue))) {
netif_tx_stop_queue(netdev_get_tx_queue(priv->dev,
Expand Down Expand Up @@ -4715,6 +4729,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)

dma_map_err:
netdev_err(priv->dev, "Tx DMA map failed\n");
max_sdu_err:
dev_kfree_skb(skb);
priv->xstats.tx_dropped++;
return NETDEV_TX_OK;
Expand Down Expand Up @@ -4871,6 +4886,13 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
if (stmmac_tx_avail(priv, queue) < STMMAC_TX_THRESH(priv))
return STMMAC_XDP_CONSUMED;

if (priv->plat->est && priv->plat->est->enable &&
priv->plat->est->max_sdu[queue] &&
xdpf->len > priv->plat->est->max_sdu[queue]) {
priv->xstats.max_sdu_txq_drop[queue]++;
return STMMAC_XDP_CONSUMED;
}

if (likely(priv->extend_desc))
tx_desc = (struct dma_desc *)(tx_q->dma_etx + entry);
else if (tx_q->tbs & STMMAC_TBS_AVAIL)
Expand Down
87 changes: 83 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -915,8 +915,30 @@ struct timespec64 stmmac_calc_tas_basetime(ktime_t old_base_time,
return time;
}

static int tc_setup_taprio(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt)
static void tc_taprio_map_maxsdu_txq(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt)
{
struct plat_stmmacenet_data *plat = priv->plat;
u32 num_tc = qopt->mqprio.qopt.num_tc;
u32 offset, count, i, j;

/* QueueMaxSDU received from the driver corresponds to the Linux traffic
* class. Map queueMaxSDU per Linux traffic class to DWMAC Tx queues.
*/
for (i = 0; i < num_tc; i++) {
if (!qopt->max_sdu[i])
continue;

offset = qopt->mqprio.qopt.offset[i];
count = qopt->mqprio.qopt.count[i];

for (j = offset; j < offset + count; j++)
plat->est->max_sdu[j] = qopt->max_sdu[i] + ETH_HLEN - ETH_TLEN;
}
}

static int tc_taprio_configure(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt)
{
u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
struct plat_stmmacenet_data *plat = priv->plat;
Expand Down Expand Up @@ -968,8 +990,6 @@ static int tc_setup_taprio(struct stmmac_priv *priv,

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

if (qopt->num_entries >= dep)
return -EINVAL;
Expand Down Expand Up @@ -1045,6 +1065,8 @@ static int tc_setup_taprio(struct stmmac_priv *priv,

priv->plat->est->ter = qopt->cycle_time_extension;

tc_taprio_map_maxsdu_txq(priv, qopt);

if (fpe && !priv->dma_cap.fpesel) {
mutex_unlock(&priv->plat->est->lock);
return -EOPNOTSUPP;
Expand Down Expand Up @@ -1078,6 +1100,11 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
priv->plat->est->enable = false;
stmmac_est_configure(priv, priv, priv->plat->est,
priv->plat->clk_ptp_rate);
/* Reset taprio status */
for (i = 0; i < priv->plat->tx_queues_to_use; i++) {
priv->xstats.max_sdu_txq_drop[i] = 0;
priv->xstats.mtl_est_txq_hlbf[i] = 0;
}
mutex_unlock(&priv->plat->est->lock);
}

Expand All @@ -1095,6 +1122,57 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
return ret;
}

static void tc_taprio_stats(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt)
{
u64 window_drops = 0;
int i = 0;

for (i = 0; i < priv->plat->tx_queues_to_use; i++)
window_drops += priv->xstats.max_sdu_txq_drop[i] +
priv->xstats.mtl_est_txq_hlbf[i];
qopt->stats.window_drops = window_drops;

/* Transmission overrun doesn't happen for stmmac, hence always 0 */
qopt->stats.tx_overruns = 0;
}

static void tc_taprio_queue_stats(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt)
{
struct tc_taprio_qopt_queue_stats *q_stats = &qopt->queue_stats;
int queue = qopt->queue_stats.queue;

q_stats->stats.window_drops = priv->xstats.max_sdu_txq_drop[queue] +
priv->xstats.mtl_est_txq_hlbf[queue];

/* Transmission overrun doesn't happen for stmmac, hence always 0 */
q_stats->stats.tx_overruns = 0;
}

static int tc_setup_taprio(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt)
{
int err = 0;

switch (qopt->cmd) {
case TAPRIO_CMD_REPLACE:
case TAPRIO_CMD_DESTROY:
err = tc_taprio_configure(priv, qopt);
break;
case TAPRIO_CMD_STATS:
tc_taprio_stats(priv, qopt);
break;
case TAPRIO_CMD_QUEUE_STATS:
tc_taprio_queue_stats(priv, qopt);
break;
default:
err = -EOPNOTSUPP;
}

return err;
}

static int tc_setup_etf(struct stmmac_priv *priv,
struct tc_etf_qopt_offload *qopt)
{
Expand Down Expand Up @@ -1126,6 +1204,7 @@ static int tc_query_caps(struct stmmac_priv *priv,
return -EOPNOTSUPP;

caps->gate_mask_per_txq = true;
caps->supports_queue_max_sdu = true;

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions include/linux/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ struct stmmac_est {
u32 gcl_unaligned[EST_GCL];
u32 gcl[EST_GCL];
u32 gcl_size;
u32 max_sdu[MTL_MAX_TX_QUEUES];
};

struct stmmac_rxq_cfg {
Expand Down

0 comments on commit 2acfd58

Please sign in to comment.