Add receive hardware timestamp metadata support via kfunc to XDP Zero Copy receive packets. Signed-off-by: Song Yoong Siang <yoong.siang.song@xxxxxxxxx> --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7f1c0c36de8c..bcaafeea118b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1611,6 +1611,12 @@ static int stmmac_alloc_rx_buffers_zc(struct stmmac_priv *priv, struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue]; int i; + /* struct stmmac_xdp_buff is using cb field (maximum size of 24 bytes) + * in struct xdp_buff_xsk to stash driver specific information. Thus, + * use this macro to make sure no size violations. + */ + XSK_CHECK_PRIV_TYPE(struct stmmac_xdp_buff); + for (i = 0; i < dma_conf->dma_rx_size; i++) { struct stmmac_rx_buffer *buf; dma_addr_t dma_addr; @@ -4903,7 +4909,7 @@ static struct sk_buff *stmmac_construct_skb_zc(struct stmmac_channel *ch, static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, struct dma_desc *p, struct dma_desc *np, - struct xdp_buff *xdp) + struct xdp_buff *xdp, ktime_t rx_hwts) { struct stmmac_channel *ch = &priv->channel[queue]; struct skb_shared_hwtstamps *shhwtstamp = NULL; @@ -4921,7 +4927,7 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, shhwtstamp = skb_hwtstamps(skb); memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); - stmmac_get_rx_hwtstamp(priv, p, np, &shhwtstamp->hwtstamp); + shhwtstamp->hwtstamp = rx_hwts; stmmac_rx_vlan(priv->dev, skb); skb->protocol = eth_type_trans(skb, priv->dev); @@ -4999,6 +5005,16 @@ static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget) return ret; } +static struct stmmac_xdp_buff *xsk_buff_to_stmmac_ctx(struct xdp_buff *xdp) +{ + /* In XDP zero copy data path, xdp field in struct xdp_buff_xsk is used + * to represent incoming packet, whereas cb field in the same structure + * is used to store driver specific info. Thus, struct stmmac_xdp_buff + * is laid on top of xdp and cb fields of struct xdp_buff_xsk. + */ + return (struct stmmac_xdp_buff *)xdp; +} + static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) { struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; @@ -5028,8 +5044,10 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) } while (count < limit) { struct stmmac_rx_buffer *buf; + struct stmmac_xdp_buff *ctx; unsigned int buf1_len = 0; struct dma_desc *np, *p; + ktime_t rx_hwts = 0; int entry; int res; @@ -5113,6 +5131,10 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) goto read_again; } + stmmac_get_rx_hwtstamp(priv, p, np, &rx_hwts); + ctx = xsk_buff_to_stmmac_ctx(buf->xdp); + ctx->rx_hwts = rx_hwts; + /* XDP ZC Frame only support primary buffers for now */ buf1_len = stmmac_rx_buf1_len(priv, p, status, len); len += buf1_len; @@ -5132,7 +5154,8 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) switch (res) { case STMMAC_XDP_PASS: - stmmac_dispatch_skb_zc(priv, queue, p, np, buf->xdp); + stmmac_dispatch_skb_zc(priv, queue, p, np, buf->xdp, + rx_hwts); xsk_buff_free(buf->xdp); break; case STMMAC_XDP_CONSUMED: -- 2.34.1