@@ -98,11 +98,20 @@ void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
9898{
9999 struct cppi5_host_desc_t * first_desc , * next_desc ;
100100 dma_addr_t buf_dma , next_desc_dma ;
101+ struct prueth_swdata * swdata ;
102+ struct page * page ;
101103 u32 buf_dma_len ;
102104
103105 first_desc = desc ;
104106 next_desc = first_desc ;
105107
108+ swdata = cppi5_hdesc_get_swdata (desc );
109+ if (swdata -> type == PRUETH_SWDATA_PAGE ) {
110+ page = swdata -> data .page ;
111+ page_pool_recycle_direct (page -> pp , swdata -> data .page );
112+ goto free_desc ;
113+ }
114+
106115 cppi5_hdesc_get_obuf (first_desc , & buf_dma , & buf_dma_len );
107116 k3_udma_glue_tx_cppi5_to_dma_addr (tx_chn -> tx_chn , & buf_dma );
108117
@@ -126,6 +135,7 @@ void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
126135 k3_cppi_desc_pool_free (tx_chn -> desc_pool , next_desc );
127136 }
128137
138+ free_desc :
129139 k3_cppi_desc_pool_free (tx_chn -> desc_pool , first_desc );
130140}
131141EXPORT_SYMBOL_GPL (prueth_xmit_free );
@@ -139,6 +149,7 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
139149 struct prueth_swdata * swdata ;
140150 struct prueth_tx_chn * tx_chn ;
141151 unsigned int total_bytes = 0 ;
152+ struct xdp_frame * xdpf ;
142153 struct sk_buff * skb ;
143154 dma_addr_t desc_dma ;
144155 int res , num_tx = 0 ;
@@ -161,16 +172,28 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
161172 desc_tx = k3_cppi_desc_pool_dma2virt (tx_chn -> desc_pool ,
162173 desc_dma );
163174 swdata = cppi5_hdesc_get_swdata (desc_tx );
164- prueth_xmit_free (tx_chn , desc_tx );
165- if (swdata -> type != PRUETH_SWDATA_SKB )
175+
176+ switch (swdata -> type ) {
177+ case PRUETH_SWDATA_SKB :
178+ skb = swdata -> data .skb ;
179+ dev_sw_netstats_tx_add (skb -> dev , 1 , skb -> len );
180+ total_bytes += skb -> len ;
181+ napi_consume_skb (skb , budget );
182+ break ;
183+ case PRUETH_SWDATA_XDPF :
184+ xdpf = swdata -> data .xdpf ;
185+ dev_sw_netstats_tx_add (ndev , 1 , xdpf -> len );
186+ total_bytes += xdpf -> len ;
187+ xdp_return_frame (xdpf );
188+ break ;
189+ default :
190+ netdev_err (ndev , "tx_complete: invalid swdata type %d\n" , swdata -> type );
191+ prueth_xmit_free (tx_chn , desc_tx );
192+ ndev -> stats .tx_dropped ++ ;
166193 continue ;
194+ }
167195
168- skb = swdata -> data .skb ;
169- ndev = skb -> dev ;
170- ndev -> stats .tx_packets ++ ;
171- ndev -> stats .tx_bytes += skb -> len ;
172- total_bytes += skb -> len ;
173- napi_consume_skb (skb , budget );
196+ prueth_xmit_free (tx_chn , desc_tx );
174197 num_tx ++ ;
175198 }
176199
@@ -529,7 +552,153 @@ void emac_rx_timestamp(struct prueth_emac *emac,
529552 ssh -> hwtstamp = ns_to_ktime (ns );
530553}
531554
532- static int emac_rx_packet (struct prueth_emac * emac , u32 flow_id )
555+ /**
556+ * emac_xmit_xdp_frame - transmits an XDP frame
557+ * @emac: emac device
558+ * @xdpf: data to transmit
559+ * @page: page from page pool if already DMA mapped
560+ * @q_idx: queue id
561+ *
562+ * Return: XDP state
563+ */
564+ u32 emac_xmit_xdp_frame (struct prueth_emac * emac ,
565+ struct xdp_frame * xdpf ,
566+ struct page * page ,
567+ unsigned int q_idx )
568+ {
569+ struct cppi5_host_desc_t * first_desc ;
570+ struct net_device * ndev = emac -> ndev ;
571+ struct prueth_tx_chn * tx_chn ;
572+ dma_addr_t desc_dma , buf_dma ;
573+ struct prueth_swdata * swdata ;
574+ u32 * epib ;
575+ int ret ;
576+
577+ if (q_idx >= PRUETH_MAX_TX_QUEUES ) {
578+ netdev_err (ndev , "xdp tx: invalid q_id %d\n" , q_idx );
579+ return ICSSG_XDP_CONSUMED ; /* drop */
580+ }
581+
582+ tx_chn = & emac -> tx_chns [q_idx ];
583+
584+ first_desc = k3_cppi_desc_pool_alloc (tx_chn -> desc_pool );
585+ if (!first_desc ) {
586+ netdev_dbg (ndev , "xdp tx: failed to allocate descriptor\n" );
587+ goto drop_free_descs ; /* drop */
588+ }
589+
590+ if (page ) { /* already DMA mapped by page_pool */
591+ buf_dma = page_pool_get_dma_addr (page );
592+ buf_dma += xdpf -> headroom + sizeof (struct xdp_frame );
593+ } else { /* Map the linear buffer */
594+ buf_dma = dma_map_single (tx_chn -> dma_dev , xdpf -> data , xdpf -> len , DMA_TO_DEVICE );
595+ if (dma_mapping_error (tx_chn -> dma_dev , buf_dma )) {
596+ netdev_err (ndev , "xdp tx: failed to map data buffer\n" );
597+ goto drop_free_descs ; /* drop */
598+ }
599+ }
600+
601+ cppi5_hdesc_init (first_desc , CPPI5_INFO0_HDESC_EPIB_PRESENT ,
602+ PRUETH_NAV_PS_DATA_SIZE );
603+ cppi5_hdesc_set_pkttype (first_desc , 0 );
604+ epib = first_desc -> epib ;
605+ epib [0 ] = 0 ;
606+ epib [1 ] = 0 ;
607+
608+ /* set dst tag to indicate internal qid at the firmware which is at
609+ * bit8..bit15. bit0..bit7 indicates port num for directed
610+ * packets in case of switch mode operation
611+ */
612+ cppi5_desc_set_tags_ids (& first_desc -> hdr , 0 , (emac -> port_id | (q_idx << 8 )));
613+ k3_udma_glue_tx_dma_to_cppi5_addr (tx_chn -> tx_chn , & buf_dma );
614+ cppi5_hdesc_attach_buf (first_desc , buf_dma , xdpf -> len , buf_dma , xdpf -> len );
615+ swdata = cppi5_hdesc_get_swdata (first_desc );
616+ if (page ) {
617+ swdata -> type = PRUETH_SWDATA_PAGE ;
618+ swdata -> data .page = page ;
619+ } else {
620+ swdata -> type = PRUETH_SWDATA_XDPF ;
621+ swdata -> data .xdpf = xdpf ;
622+ }
623+
624+ cppi5_hdesc_set_pktlen (first_desc , xdpf -> len );
625+ desc_dma = k3_cppi_desc_pool_virt2dma (tx_chn -> desc_pool , first_desc );
626+
627+ ret = k3_udma_glue_push_tx_chn (tx_chn -> tx_chn , first_desc , desc_dma );
628+ if (ret ) {
629+ netdev_err (ndev , "xdp tx: push failed: %d\n" , ret );
630+ goto drop_free_descs ;
631+ }
632+
633+ return ICSSG_XDP_TX ;
634+
635+ drop_free_descs :
636+ prueth_xmit_free (tx_chn , first_desc );
637+ return ICSSG_XDP_CONSUMED ;
638+ }
639+ EXPORT_SYMBOL_GPL (emac_xmit_xdp_frame );
640+
641+ /**
642+ * emac_run_xdp - run an XDP program
643+ * @emac: emac device
644+ * @xdp: XDP buffer containing the frame
645+ * @page: page with RX data if already DMA mapped
646+ * @len: Rx descriptor packet length
647+ *
648+ * Return: XDP state
649+ */
650+ static u32 emac_run_xdp (struct prueth_emac * emac , struct xdp_buff * xdp ,
651+ struct page * page , u32 * len )
652+ {
653+ struct net_device * ndev = emac -> ndev ;
654+ struct bpf_prog * xdp_prog ;
655+ struct xdp_frame * xdpf ;
656+ u32 pkt_len = * len ;
657+ u32 act , result ;
658+ int q_idx , err ;
659+
660+ xdp_prog = READ_ONCE (emac -> xdp_prog );
661+ act = bpf_prog_run_xdp (xdp_prog , xdp );
662+ switch (act ) {
663+ case XDP_PASS :
664+ return ICSSG_XDP_PASS ;
665+ case XDP_TX :
666+ /* Send packet to TX ring for immediate transmission */
667+ xdpf = xdp_convert_buff_to_frame (xdp );
668+ if (unlikely (!xdpf )) {
669+ ndev -> stats .tx_dropped ++ ;
670+ goto drop ;
671+ }
672+
673+ q_idx = smp_processor_id () % emac -> tx_ch_num ;
674+ result = emac_xmit_xdp_frame (emac , xdpf , page , q_idx );
675+ if (result == ICSSG_XDP_CONSUMED )
676+ goto drop ;
677+
678+ dev_sw_netstats_rx_add (ndev , xdpf -> len );
679+ return result ;
680+ case XDP_REDIRECT :
681+ err = xdp_do_redirect (emac -> ndev , xdp , xdp_prog );
682+ if (err )
683+ goto drop ;
684+
685+ dev_sw_netstats_rx_add (ndev , pkt_len );
686+ return ICSSG_XDP_REDIR ;
687+ default :
688+ bpf_warn_invalid_xdp_action (emac -> ndev , xdp_prog , act );
689+ fallthrough ;
690+ case XDP_ABORTED :
691+ drop :
692+ trace_xdp_exception (emac -> ndev , xdp_prog , act );
693+ fallthrough ; /* handle aborts by dropping packet */
694+ case XDP_DROP :
695+ ndev -> stats .rx_dropped ++ ;
696+ page_pool_recycle_direct (emac -> rx_chns .pg_pool , page );
697+ return ICSSG_XDP_CONSUMED ;
698+ }
699+ }
700+
701+ static int emac_rx_packet (struct prueth_emac * emac , u32 flow_id , u32 * xdp_state )
533702{
534703 struct prueth_rx_chn * rx_chn = & emac -> rx_chns ;
535704 u32 buf_dma_len , pkt_len , port_id = 0 ;
@@ -540,10 +709,12 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
540709 struct page * page , * new_page ;
541710 struct page_pool * pool ;
542711 struct sk_buff * skb ;
712+ struct xdp_buff xdp ;
543713 u32 * psdata ;
544714 void * pa ;
545715 int ret ;
546716
717+ * xdp_state = 0 ;
547718 pool = rx_chn -> pg_pool ;
548719 ret = k3_udma_glue_pop_rx_chn (rx_chn -> rx_chn , flow_id , & desc_dma );
549720 if (ret ) {
@@ -584,9 +755,21 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
584755 goto requeue ;
585756 }
586757
587- /* prepare skb and send to n/w stack */
588758 pa = page_address (page );
589- skb = napi_build_skb (pa , PAGE_SIZE );
759+ if (emac -> xdp_prog ) {
760+ xdp_init_buff (& xdp , PAGE_SIZE , & rx_chn -> xdp_rxq );
761+ xdp_prepare_buff (& xdp , pa , PRUETH_HEADROOM , pkt_len , false);
762+
763+ * xdp_state = emac_run_xdp (emac , & xdp , page , & pkt_len );
764+ if (* xdp_state == ICSSG_XDP_PASS )
765+ skb = xdp_build_skb_from_buff (& xdp );
766+ else
767+ goto requeue ;
768+ } else {
769+ /* prepare skb and send to n/w stack */
770+ skb = napi_build_skb (pa , PAGE_SIZE );
771+ }
772+
590773 if (!skb ) {
591774 ndev -> stats .rx_dropped ++ ;
592775 page_pool_recycle_direct (pool , page );
@@ -849,13 +1032,23 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma)
8491032 struct prueth_tx_chn * tx_chn = data ;
8501033 struct cppi5_host_desc_t * desc_tx ;
8511034 struct prueth_swdata * swdata ;
1035+ struct xdp_frame * xdpf ;
8521036 struct sk_buff * skb ;
8531037
8541038 desc_tx = k3_cppi_desc_pool_dma2virt (tx_chn -> desc_pool , desc_dma );
8551039 swdata = cppi5_hdesc_get_swdata (desc_tx );
856- if (swdata -> type == PRUETH_SWDATA_SKB ) {
1040+
1041+ switch (swdata -> type ) {
1042+ case PRUETH_SWDATA_SKB :
8571043 skb = swdata -> data .skb ;
8581044 dev_kfree_skb_any (skb );
1045+ break ;
1046+ case PRUETH_SWDATA_XDPF :
1047+ xdpf = swdata -> data .xdpf ;
1048+ xdp_return_frame (xdpf );
1049+ break ;
1050+ default :
1051+ break ;
8591052 }
8601053
8611054 prueth_xmit_free (tx_chn , desc_tx );
@@ -892,15 +1085,18 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
8921085 PRUETH_RX_FLOW_DATA_SR1 : PRUETH_RX_FLOW_DATA ;
8931086 int flow = emac -> is_sr1 ?
8941087 PRUETH_MAX_RX_FLOWS_SR1 : PRUETH_MAX_RX_FLOWS ;
1088+ int xdp_state_or = 0 ;
8951089 int num_rx = 0 ;
8961090 int cur_budget ;
1091+ u32 xdp_state ;
8971092 int ret ;
8981093
8991094 while (flow -- ) {
9001095 cur_budget = budget - num_rx ;
9011096
9021097 while (cur_budget -- ) {
903- ret = emac_rx_packet (emac , flow );
1098+ ret = emac_rx_packet (emac , flow , & xdp_state );
1099+ xdp_state_or |= xdp_state ;
9041100 if (ret )
9051101 break ;
9061102 num_rx ++ ;
@@ -910,6 +1106,9 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
9101106 break ;
9111107 }
9121108
1109+ if (xdp_state_or & ICSSG_XDP_REDIR )
1110+ xdp_do_flush ();
1111+
9131112 if (num_rx < budget && napi_complete_done (napi_rx , num_rx )) {
9141113 if (unlikely (emac -> rx_pace_timeout_ns )) {
9151114 hrtimer_start (& emac -> rx_hrtimer ,
0 commit comments