summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-06-16 02:22:23 +0300
committerJakub Kicinski <kuba@kernel.org>2026-06-16 02:22:24 +0300
commitc02fca0bef5d1081173219f276df643abdb825ab (patch)
tree8934332e65e12972a178d1f493ca4f4768428fec
parentc66f8511a8109fa50767941b26d3623e316fde02 (diff)
parentf9691288413ceb4fc72f3ccc4d8e42adf66eb28d (diff)
downloadlinux-c02fca0bef5d1081173219f276df643abdb825ab.tar.xz
Merge branch 'icssg-xdp-zero-copy-bug-fixes'
Meghana Malladi says: ==================== ICSSG XDP zero copy bug fixes [part] This patch series fixes bugs introduced while adding xdp zero copy support in the icssg driver. Patch 1: Fix wakeup handling for Rx when available CPPI descriptor is zero Patch 2,3: Fix destination tag in CPPI descriptor to enable proper Tx xmit for HSR offload mode with XDP and zero copy ==================== Link: https://patch.msgid.link/20260611185744.2498070-1-m-malladi@ti.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_common.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index a28a608f9bf4..82ddef9c17d5 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -105,6 +105,7 @@ static int emac_xsk_xmit_zc(struct prueth_emac *emac,
struct xdp_desc xdp_desc;
int num_tx = 0, pkt_len;
int descs_avail, ret;
+ u32 dst_tag_id;
u32 *epib;
int i;
@@ -137,9 +138,17 @@ static int emac_xsk_xmit_zc(struct prueth_emac *emac,
epib[0] = 0;
epib[1] = 0;
cppi5_hdesc_set_pktlen(host_desc, pkt_len);
- cppi5_desc_set_tags_ids(&host_desc->hdr, 0,
- (emac->port_id | (q_idx << 8)));
+ dst_tag_id = emac->port_id | (q_idx << 8);
+ if (emac->prueth->is_hsr_offload_mode &&
+ (ndev->features & NETIF_F_HW_HSR_DUP))
+ dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG;
+
+ if (emac->prueth->is_hsr_offload_mode &&
+ (ndev->features & NETIF_F_HW_HSR_TAG_INS))
+ epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS;
+
+ cppi5_desc_set_tags_ids(&host_desc->hdr, 0, dst_tag_id);
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);
@@ -696,6 +705,7 @@ u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
dma_addr_t desc_dma, buf_dma;
struct prueth_swdata *swdata;
struct page *page;
+ u32 dst_tag_id;
u32 *epib;
int ret;
@@ -737,9 +747,25 @@ u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
/* set dst tag to indicate internal qid at the firmware which is at
* bit8..bit15. bit0..bit7 indicates port num for directed
- * packets in case of switch mode operation
+ * packets in case of switch mode operation and port num 0
+ * for undirected packets in case of HSR offload mode.
+ *
+ * XDP_TX frames arrive on a slave port with the HSR tag already
+ * stripped by the PRU firmware. Like skb TX via hsr0, they must
+ * be sent as undirected so the PRU duplicates them to both ports
+ * and re-inserts the HSR sequence tag.
*/
- cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8)));
+ dst_tag_id = emac->port_id | (q_idx << 8);
+
+ if (emac->prueth->is_hsr_offload_mode &&
+ (ndev->features & NETIF_F_HW_HSR_DUP))
+ dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG;
+
+ if (emac->prueth->is_hsr_offload_mode &&
+ (ndev->features & NETIF_F_HW_HSR_TAG_INS))
+ epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS;
+
+ cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id);
k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
cppi5_hdesc_attach_buf(first_desc, buf_dma, xdpf->len, buf_dma, xdpf->len);
swdata = cppi5_hdesc_get_swdata(first_desc);
@@ -927,6 +953,7 @@ static int emac_rx_packet_zc(struct prueth_emac *emac, u32 flow_id,
struct cppi5_host_desc_t *desc_rx;
struct prueth_swdata *swdata;
dma_addr_t desc_dma, buf_dma;
+ int avail_desc, alloc_budget;
struct xdp_buff *xdp;
int xdp_status = 0;
int count = 0;
@@ -993,16 +1020,13 @@ static int emac_rx_packet_zc(struct prueth_emac *emac, u32 flow_id,
if (xdp_status & ICSSG_XDP_REDIR)
xdp_do_flush();
- /* Allocate xsk buffers from the pool for the "count" number of
- * packets processed in order to be able to receive more packets.
- */
- ret = prueth_rx_alloc_zc(emac, count);
+ avail_desc = k3_cppi_desc_pool_avail(rx_chn->desc_pool);
+ alloc_budget = min_t(int, budget, avail_desc);
+
+ ret = prueth_rx_alloc_zc(emac, alloc_budget);
if (xsk_uses_need_wakeup(rx_chn->xsk_pool)) {
- /* If the user space doesn't provide enough buffers then it must
- * explicitly wake up the kernel when new buffers are available
- */
- if (ret < count)
+ if (ret < alloc_budget)
xsk_set_rx_need_wakeup(rx_chn->xsk_pool);
else
xsk_clear_rx_need_wakeup(rx_chn->xsk_pool);