From nobody Fri Oct 3 13:34:14 2025 Received: from fllvem-ot04.ext.ti.com (fllvem-ot04.ext.ti.com [198.47.19.246]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5480430F538; Mon, 1 Sep 2025 10:03:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.246 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756721010; cv=none; b=c9APj8ccZTftLxo/hRv25Jys1br49GsJ79KPtyHL23VirxIvtii6y5cmHDR+LTILietqQL4Wr2eFFczkbR/z/r6pk4thFPppyULH7OtjklKzyqZTEM7w64SuSXaw9siLNiCvpKPmKjcyUTI8eJYlFkLtZBRmt3A1YBoHD3DcW9k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756721010; c=relaxed/simple; bh=V7wi1t1Mxv24OLC5oN7A2CJcp+Ossv0qRRVdc9+fqdM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Dbuaw0/pdhc9FCyeEwx2xezMCYaIHm26yawQbNDBQGZEd2Vw+j8EJho4hanuOceW9txhpRCbpGprHqYnStf8A930zTxvC+UEqQ1qLfuJEcu+jIUWewQbReU51QC5y4VSkWbYbBVgDVzAuKI08Qhp6bVs9rvIE6Q/1XbQHnl8DpM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=TJDTQQw6; arc=none smtp.client-ip=198.47.19.246 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="TJDTQQw6" Received: from lelvem-sh01.itg.ti.com ([10.180.77.71]) by fllvem-ot04.ext.ti.com (8.15.2/8.15.2) with ESMTP id 581A2hKC2750352; Mon, 1 Sep 2025 05:02:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1756720963; bh=mezemkz3qEN85uCSR/gFF2SBsPuVzs2DVq2YLAEIpTk=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=TJDTQQw6EQGYrtTw5xVVhY0sBsTwrVU2ldCTMh5mmRn4/tBrdJCxy/EBjyQin6geV sFPxwdbetib+LL9aMOYp4X09BeYcmA3digVKWNClazhDtAyCtAiinWl8i3Q6GWmu4k y82chDfBMW3U4V2fb3jaQYlgIbN77hqO9J0gd11w= Received: from DLEE106.ent.ti.com (dlee106.ent.ti.com [157.170.170.36]) by lelvem-sh01.itg.ti.com (8.18.1/8.18.1) with ESMTPS id 581A2hEb1467222 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA256 bits=128 verify=FAIL); Mon, 1 Sep 2025 05:02:43 -0500 Received: from DLEE111.ent.ti.com (157.170.170.22) by DLEE106.ent.ti.com (157.170.170.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55; Mon, 1 Sep 2025 05:02:42 -0500 Received: from fllvem-mr07.itg.ti.com (10.64.41.89) by DLEE111.ent.ti.com (157.170.170.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55 via Frontend Transport; Mon, 1 Sep 2025 05:02:42 -0500 Received: from fllv0122.itg.ti.com (fllv0122.itg.ti.com [10.247.120.72]) by fllvem-mr07.itg.ti.com (8.18.1/8.18.1) with ESMTP id 581A2gpJ159821; Mon, 1 Sep 2025 05:02:42 -0500 Received: from localhost (meghana-pc.dhcp.ti.com [10.24.69.13] (may be forged)) by fllv0122.itg.ti.com (8.14.7/8.14.7) with ESMTP id 581A2fTE011172; Mon, 1 Sep 2025 05:02:41 -0500 From: Meghana Malladi To: , , , , , , , , , , , , , , CC: , , , , , , , , Vignesh Raghavendra , Roger Quadros , Subject: [PATCH net-next v2 3/6] net: ti: icssg-prueth: Add AF_XDP zero copy for TX Date: Mon, 1 Sep 2025 15:32:24 +0530 Message-ID: <20250901100227.1150567-4-m-malladi@ti.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250901100227.1150567-1-m-malladi@ti.com> References: <20250901100227.1150567-1-m-malladi@ti.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-C2ProcessedOrg: 333ef613-75bf-4e12-a4b1-8e3623f5dcea Content-Type: text/plain; charset="utf-8" Use xsk_qid to check if a given port+qid has been registered for xsk zero copy and populate it inside tx channel xsk_pool. If xsk_pool is set, get frames from the pool in NAPI context and submit them to the Tx channel. Tx completion is also handled in the NAPI context. Signed-off-by: Meghana Malladi --- drivers/net/ethernet/ti/icssg/icssg_common.c | 122 ++++++++++++++++++- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 16 +++ drivers/net/ethernet/ti/icssg/icssg_prueth.h | 5 + 3 files changed, 141 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/eth= ernet/ti/icssg/icssg_common.c index 8a0ebe011960..8ff1707a2328 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_common.c +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c @@ -93,15 +93,91 @@ void prueth_ndev_del_tx_napi(struct prueth_emac *emac, = int num) } EXPORT_SYMBOL_GPL(prueth_ndev_del_tx_napi); =20 +static int emac_xsk_xmit_zc(struct prueth_emac *emac, + unsigned int q_idx) +{ + struct prueth_tx_chn *tx_chn =3D &emac->tx_chns[q_idx]; + struct xsk_buff_pool *pool =3D tx_chn->xsk_pool; + struct net_device *ndev =3D emac->ndev; + struct cppi5_host_desc_t *host_desc; + dma_addr_t dma_desc, dma_buf; + struct prueth_swdata *swdata; + struct xdp_desc xdp_desc; + int num_tx =3D 0, pkt_len; + int descs_avail, ret; + u32 *epib; + int i; + + descs_avail =3D k3_cppi_desc_pool_avail(tx_chn->desc_pool); + /* ensure that TX ring is not filled up by XDP, always MAX_SKB_FRAGS + * will be available for normal TX path and queue is stopped there if + * necessary + */ + if (descs_avail <=3D MAX_SKB_FRAGS) + return 0; + + descs_avail -=3D MAX_SKB_FRAGS; + + for (i =3D 0; i < descs_avail; i++) { + if (!xsk_tx_peek_desc(pool, &xdp_desc)) + break; + + dma_buf =3D xsk_buff_raw_get_dma(pool, xdp_desc.addr); + pkt_len =3D xdp_desc.len; + xsk_buff_raw_dma_sync_for_device(pool, dma_buf, pkt_len); + + host_desc =3D k3_cppi_desc_pool_alloc(tx_chn->desc_pool); + if (unlikely(!host_desc)) + break; + + cppi5_hdesc_init(host_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT, + PRUETH_NAV_PS_DATA_SIZE); + cppi5_hdesc_set_pkttype(host_desc, 0); + epib =3D host_desc->epib; + epib[0] =3D 0; + epib[1] =3D 0; + cppi5_hdesc_set_pktlen(host_desc, pkt_len); + cppi5_desc_set_tags_ids(&host_desc->hdr, 0, + (emac->port_id | (q_idx << 8))); + + k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &dma_buf); + cppi5_hdesc_attach_buf(host_desc, dma_buf, pkt_len, dma_buf, + pkt_len); + + swdata =3D cppi5_hdesc_get_swdata(host_desc); + swdata->type =3D PRUETH_SWDATA_XSK; + + dma_desc =3D k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, + host_desc); + ret =3D k3_udma_glue_push_tx_chn(tx_chn->tx_chn, + host_desc, dma_desc); + + if (ret) { + ndev->stats.tx_errors++; + k3_cppi_desc_pool_free(tx_chn->desc_pool, host_desc); + break; + } + + num_tx++; + } + + xsk_tx_release(tx_chn->xsk_pool); + return num_tx; +} + void prueth_xmit_free(struct prueth_tx_chn *tx_chn, struct cppi5_host_desc_t *desc) { struct cppi5_host_desc_t *first_desc, *next_desc; dma_addr_t buf_dma, next_desc_dma; u32 buf_dma_len; + struct prueth_swdata *swdata; =20 first_desc =3D desc; next_desc =3D first_desc; + swdata =3D cppi5_hdesc_get_swdata(first_desc); + if (swdata->type =3D=3D PRUETH_SWDATA_XSK) + goto free_pool; =20 cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len); k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); @@ -126,6 +202,7 @@ void prueth_xmit_free(struct prueth_tx_chn *tx_chn, k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); } =20 +free_pool: k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc); } EXPORT_SYMBOL_GPL(prueth_xmit_free); @@ -139,7 +216,9 @@ int emac_tx_complete_packets(struct prueth_emac *emac, = int chn, struct prueth_swdata *swdata; struct prueth_tx_chn *tx_chn; unsigned int total_bytes =3D 0; + int xsk_frames_done =3D 0; struct xdp_frame *xdpf; + unsigned int pkt_len; struct sk_buff *skb; dma_addr_t desc_dma; int res, num_tx =3D 0; @@ -176,6 +255,11 @@ int emac_tx_complete_packets(struct prueth_emac *emac,= int chn, total_bytes +=3D xdpf->len; xdp_return_frame(xdpf); break; + case PRUETH_SWDATA_XSK: + pkt_len =3D cppi5_hdesc_get_pktlen(desc_tx); + dev_sw_netstats_tx_add(ndev, 1, pkt_len); + xsk_frames_done++; + break; default: prueth_xmit_free(tx_chn, desc_tx); ndev->stats.tx_dropped++; @@ -204,6 +288,18 @@ int emac_tx_complete_packets(struct prueth_emac *emac,= int chn, __netif_tx_unlock(netif_txq); } =20 + if (tx_chn->xsk_pool) { + if (xsk_frames_done) + xsk_tx_completed(tx_chn->xsk_pool, xsk_frames_done); + + if (xsk_uses_need_wakeup(tx_chn->xsk_pool)) + xsk_set_tx_need_wakeup(tx_chn->xsk_pool); + + netif_txq =3D netdev_get_tx_queue(ndev, chn); + txq_trans_cond_update(netif_txq); + emac_xsk_xmit_zc(emac, chn); + } + return num_tx; } =20 @@ -212,7 +308,10 @@ static enum hrtimer_restart emac_tx_timer_callback(str= uct hrtimer *timer) struct prueth_tx_chn *tx_chns =3D container_of(timer, struct prueth_tx_chn, tx_hrtimer); =20 - enable_irq(tx_chns->irq); + if (tx_chns->irq_disabled) { + tx_chns->irq_disabled =3D false; + enable_irq(tx_chns->irq); + } return HRTIMER_NORESTART; } =20 @@ -235,7 +334,10 @@ static int emac_napi_tx_poll(struct napi_struct *napi_= tx, int budget) ns_to_ktime(tx_chn->tx_pace_timeout_ns), HRTIMER_MODE_REL_PINNED); } else { - enable_irq(tx_chn->irq); + if (tx_chn->irq_disabled) { + tx_chn->irq_disabled =3D false; + enable_irq(tx_chn->irq); + } } } =20 @@ -246,6 +348,7 @@ static irqreturn_t prueth_tx_irq(int irq, void *dev_id) { struct prueth_tx_chn *tx_chn =3D dev_id; =20 + tx_chn->irq_disabled =3D true; disable_irq_nosync(irq); napi_schedule(&tx_chn->napi_tx); =20 @@ -1030,6 +1133,7 @@ void prueth_tx_cleanup(void *data, dma_addr_t desc_dm= a) { struct prueth_tx_chn *tx_chn =3D data; struct cppi5_host_desc_t *desc_tx; + struct xsk_buff_pool *xsk_pool; struct prueth_swdata *swdata; struct xdp_frame *xdpf; struct sk_buff *skb; @@ -1046,6 +1150,10 @@ void prueth_tx_cleanup(void *data, dma_addr_t desc_d= ma) xdpf =3D swdata->data.xdpf; xdp_return_frame(xdpf); break; + case PRUETH_SWDATA_XSK: + xsk_pool =3D tx_chn->xsk_pool; + xsk_tx_completed(xsk_pool, 1); + break; default: break; } @@ -1123,6 +1231,16 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, = int budget) } EXPORT_SYMBOL_GPL(icssg_napi_rx_poll); =20 +struct xsk_buff_pool *prueth_get_xsk_pool(struct prueth_emac *emac, u32 qi= d) +{ + if (!prueth_xdp_is_enabled(emac) || + emac->xsk_qid !=3D qid) + return NULL; + + return xsk_get_pool_from_qid(emac->ndev, qid); +} +EXPORT_SYMBOL_GPL(prueth_get_xsk_pool); + static struct page_pool *prueth_create_page_pool(struct prueth_emac *emac, struct device *dma_dev, int size) diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/eth= ernet/ti/icssg/icssg_prueth.c index 942f78a9016b..5d2896f74987 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -754,6 +754,7 @@ static void prueth_destroy_txq(struct prueth_emac *emac) k3_udma_glue_disable_tx_chn(emac->tx_chns[i].tx_chn); napi_disable(&emac->tx_chns[i].napi_tx); hrtimer_cancel(&emac->tx_chns[i].tx_hrtimer); + emac->tx_chns[i].xsk_pool =3D NULL; } } =20 @@ -790,6 +791,7 @@ static int prueth_create_txq(struct prueth_emac *emac) if (ret) goto reset_tx_chan; napi_enable(&emac->tx_chns[i].napi_tx); + emac->tx_chns[i].xsk_pool =3D prueth_get_xsk_pool(emac, i); } return 0; =20 @@ -859,6 +861,7 @@ static int emac_ndo_open(struct net_device *ndev) return ret; } =20 + emac->xsk_qid =3D -EINVAL; init_completion(&emac->cmd_complete); ret =3D prueth_init_tx_chns(emac); if (ret) { @@ -1340,6 +1343,7 @@ static int emac_ndo_bpf(struct net_device *ndev, stru= ct netdev_bpf *bpf) static int prueth_xsk_wakeup(struct net_device *ndev, u32 qid, u32 flags) { struct prueth_emac *emac =3D netdev_priv(ndev); + struct prueth_tx_chn *tx_chn =3D &emac->tx_chns[qid]; =20 if (!netif_running(ndev) || !netif_carrier_ok(ndev)) return -ENETDOWN; @@ -1354,6 +1358,18 @@ static int prueth_xsk_wakeup(struct net_device *ndev= , u32 qid, u32 flags) return -EINVAL; } =20 + if (!tx_chn->xsk_pool) { + netdev_err(ndev, "XSK pool not registered for queue %d\n", qid); + return -EINVAL; + } + + if (flags & XDP_WAKEUP_TX) { + if (!napi_if_scheduled_mark_missed(&tx_chn->napi_tx)) { + if (likely(napi_schedule_prep(&tx_chn->napi_tx))) + __napi_schedule(&tx_chn->napi_tx); + } + } + return 0; } =20 diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/eth= ernet/ti/icssg/icssg_prueth.h index 2f64ec97b454..d8b068194fb6 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -128,6 +128,8 @@ struct prueth_tx_chn { char name[32]; struct hrtimer tx_hrtimer; unsigned long tx_pace_timeout_ns; + struct xsk_buff_pool *xsk_pool; + bool irq_disabled; }; =20 struct prueth_rx_chn { @@ -148,6 +150,7 @@ enum prueth_swdata_type { PRUETH_SWDATA_PAGE, PRUETH_SWDATA_CMD, PRUETH_SWDATA_XDPF, + PRUETH_SWDATA_XSK, }; =20 struct prueth_swdata { @@ -507,4 +510,6 @@ static inline bool prueth_xdp_is_enabled(struct prueth_= emac *emac) return !!READ_ONCE(emac->xdp_prog); } =20 +struct xsk_buff_pool *prueth_get_xsk_pool(struct prueth_emac *emac, u32 qi= d); + #endif /* __NET_TI_ICSSG_PRUETH_H */ --=20 2.43.0