@@ -685,6 +685,86 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
685
685
return err ;
686
686
}
687
687
688
+ /* Create a SG frame descriptor based on a linear skb.
689
+ *
690
+ * This function is used on the Tx path when the skb headroom is not large
691
+ * enough for the HW requirements, thus instead of realloc-ing the skb we
692
+ * create a SG frame descriptor with only one entry.
693
+ */
694
+ static int build_sg_fd_single_buf (struct dpaa2_eth_priv * priv ,
695
+ struct sk_buff * skb ,
696
+ struct dpaa2_fd * fd )
697
+ {
698
+ struct device * dev = priv -> net_dev -> dev .parent ;
699
+ struct dpaa2_eth_sgt_cache * sgt_cache ;
700
+ struct dpaa2_sg_entry * sgt ;
701
+ struct dpaa2_eth_swa * swa ;
702
+ dma_addr_t addr , sgt_addr ;
703
+ void * sgt_buf = NULL ;
704
+ int sgt_buf_size ;
705
+ int err ;
706
+
707
+ /* Prepare the HW SGT structure */
708
+ sgt_cache = this_cpu_ptr (priv -> sgt_cache );
709
+ sgt_buf_size = priv -> tx_data_offset + sizeof (struct dpaa2_sg_entry );
710
+
711
+ if (sgt_cache -> count == 0 )
712
+ sgt_buf = kzalloc (sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN ,
713
+ GFP_ATOMIC );
714
+ else
715
+ sgt_buf = sgt_cache -> buf [-- sgt_cache -> count ];
716
+ if (unlikely (!sgt_buf ))
717
+ return - ENOMEM ;
718
+
719
+ sgt_buf = PTR_ALIGN (sgt_buf , DPAA2_ETH_TX_BUF_ALIGN );
720
+ sgt = (struct dpaa2_sg_entry * )(sgt_buf + priv -> tx_data_offset );
721
+
722
+ addr = dma_map_single (dev , skb -> data , skb -> len , DMA_BIDIRECTIONAL );
723
+ if (unlikely (dma_mapping_error (dev , addr ))) {
724
+ err = - ENOMEM ;
725
+ goto data_map_failed ;
726
+ }
727
+
728
+ /* Fill in the HW SGT structure */
729
+ dpaa2_sg_set_addr (sgt , addr );
730
+ dpaa2_sg_set_len (sgt , skb -> len );
731
+ dpaa2_sg_set_final (sgt , true);
732
+
733
+ /* Store the skb backpointer in the SGT buffer */
734
+ swa = (struct dpaa2_eth_swa * )sgt_buf ;
735
+ swa -> type = DPAA2_ETH_SWA_SINGLE ;
736
+ swa -> single .skb = skb ;
737
+ swa -> sg .sgt_size = sgt_buf_size ;
738
+
739
+ /* Separately map the SGT buffer */
740
+ sgt_addr = dma_map_single (dev , sgt_buf , sgt_buf_size , DMA_BIDIRECTIONAL );
741
+ if (unlikely (dma_mapping_error (dev , sgt_addr ))) {
742
+ err = - ENOMEM ;
743
+ goto sgt_map_failed ;
744
+ }
745
+
746
+ dpaa2_fd_set_offset (fd , priv -> tx_data_offset );
747
+ dpaa2_fd_set_format (fd , dpaa2_fd_sg );
748
+ dpaa2_fd_set_addr (fd , sgt_addr );
749
+ dpaa2_fd_set_len (fd , skb -> len );
750
+ dpaa2_fd_set_ctrl (fd , FD_CTRL_PTA );
751
+
752
+ if (priv -> tx_tstamp && skb_shinfo (skb )-> tx_flags & SKBTX_HW_TSTAMP )
753
+ enable_tx_tstamp (fd , sgt_buf );
754
+
755
+ return 0 ;
756
+
757
+ sgt_map_failed :
758
+ dma_unmap_single (dev , addr , skb -> len , DMA_BIDIRECTIONAL );
759
+ data_map_failed :
760
+ if (sgt_cache -> count >= DPAA2_ETH_SGT_CACHE_SIZE )
761
+ kfree (sgt_buf );
762
+ else
763
+ sgt_cache -> buf [sgt_cache -> count ++ ] = sgt_buf ;
764
+
765
+ return err ;
766
+ }
767
+
688
768
/* Create a frame descriptor based on a linear skb */
689
769
static int build_single_fd (struct dpaa2_eth_priv * priv ,
690
770
struct sk_buff * skb ,
@@ -743,13 +823,16 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
743
823
const struct dpaa2_fd * fd , bool in_napi )
744
824
{
745
825
struct device * dev = priv -> net_dev -> dev .parent ;
746
- dma_addr_t fd_addr ;
826
+ dma_addr_t fd_addr , sg_addr ;
747
827
struct sk_buff * skb = NULL ;
748
828
unsigned char * buffer_start ;
749
829
struct dpaa2_eth_swa * swa ;
750
830
u8 fd_format = dpaa2_fd_get_format (fd );
751
831
u32 fd_len = dpaa2_fd_get_len (fd );
752
832
833
+ struct dpaa2_eth_sgt_cache * sgt_cache ;
834
+ struct dpaa2_sg_entry * sgt ;
835
+
753
836
fd_addr = dpaa2_fd_get_addr (fd );
754
837
buffer_start = dpaa2_iova_to_virt (priv -> iommu_domain , fd_addr );
755
838
swa = (struct dpaa2_eth_swa * )buffer_start ;
@@ -769,16 +852,29 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
769
852
DMA_BIDIRECTIONAL );
770
853
}
771
854
} else if (fd_format == dpaa2_fd_sg ) {
772
- skb = swa -> sg .skb ;
855
+ if (swa -> type == DPAA2_ETH_SWA_SG ) {
856
+ skb = swa -> sg .skb ;
857
+
858
+ /* Unmap the scatterlist */
859
+ dma_unmap_sg (dev , swa -> sg .scl , swa -> sg .num_sg ,
860
+ DMA_BIDIRECTIONAL );
861
+ kfree (swa -> sg .scl );
773
862
774
- /* Unmap the scatterlist */
775
- dma_unmap_sg (dev , swa -> sg .scl , swa -> sg .num_sg ,
776
- DMA_BIDIRECTIONAL );
777
- kfree (swa -> sg .scl );
863
+ /* Unmap the SGT buffer */
864
+ dma_unmap_single (dev , fd_addr , swa -> sg .sgt_size ,
865
+ DMA_BIDIRECTIONAL );
866
+ } else {
867
+ skb = swa -> single .skb ;
778
868
779
- /* Unmap the SGT buffer */
780
- dma_unmap_single (dev , fd_addr , swa -> sg .sgt_size ,
781
- DMA_BIDIRECTIONAL );
869
+ /* Unmap the SGT Buffer */
870
+ dma_unmap_single (dev , fd_addr , swa -> single .sgt_size ,
871
+ DMA_BIDIRECTIONAL );
872
+
873
+ sgt = (struct dpaa2_sg_entry * )(buffer_start +
874
+ priv -> tx_data_offset );
875
+ sg_addr = dpaa2_sg_get_addr (sgt );
876
+ dma_unmap_single (dev , sg_addr , skb -> len , DMA_BIDIRECTIONAL );
877
+ }
782
878
} else {
783
879
netdev_dbg (priv -> net_dev , "Invalid FD format\n" );
784
880
return ;
@@ -808,8 +904,17 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
808
904
}
809
905
810
906
/* Free SGT buffer allocated on tx */
811
- if (fd_format != dpaa2_fd_single )
812
- skb_free_frag (buffer_start );
907
+ if (fd_format != dpaa2_fd_single ) {
908
+ sgt_cache = this_cpu_ptr (priv -> sgt_cache );
909
+ if (swa -> type == DPAA2_ETH_SWA_SG ) {
910
+ skb_free_frag (buffer_start );
911
+ } else {
912
+ if (sgt_cache -> count >= DPAA2_ETH_SGT_CACHE_SIZE )
913
+ kfree (buffer_start );
914
+ else
915
+ sgt_cache -> buf [sgt_cache -> count ++ ] = buffer_start ;
916
+ }
917
+ }
813
918
814
919
/* Move on with skb release */
815
920
napi_consume_skb (skb , in_napi );
@@ -833,22 +938,6 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
833
938
percpu_extras = this_cpu_ptr (priv -> percpu_extras );
834
939
835
940
needed_headroom = dpaa2_eth_needed_headroom (priv , skb );
836
- if (skb_headroom (skb ) < needed_headroom ) {
837
- struct sk_buff * ns ;
838
-
839
- ns = skb_realloc_headroom (skb , needed_headroom );
840
- if (unlikely (!ns )) {
841
- percpu_stats -> tx_dropped ++ ;
842
- goto err_alloc_headroom ;
843
- }
844
- percpu_extras -> tx_reallocs ++ ;
845
-
846
- if (skb -> sk )
847
- skb_set_owner_w (ns , skb -> sk );
848
-
849
- dev_kfree_skb (skb );
850
- skb = ns ;
851
- }
852
941
853
942
/* We'll be holding a back-reference to the skb until Tx Confirmation;
854
943
* we don't want that overwritten by a concurrent Tx with a cloned skb.
@@ -867,6 +956,12 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
867
956
err = build_sg_fd (priv , skb , & fd );
868
957
percpu_extras -> tx_sg_frames ++ ;
869
958
percpu_extras -> tx_sg_bytes += skb -> len ;
959
+ } else if (skb_headroom (skb ) < needed_headroom ) {
960
+ err = build_sg_fd_single_buf (priv , skb , & fd );
961
+ percpu_extras -> tx_sg_frames ++ ;
962
+ percpu_extras -> tx_sg_bytes += skb -> len ;
963
+ percpu_extras -> tx_converted_sg_frames ++ ;
964
+ percpu_extras -> tx_converted_sg_bytes += skb -> len ;
870
965
} else {
871
966
err = build_single_fd (priv , skb , & fd );
872
967
}
@@ -924,7 +1019,6 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
924
1019
return NETDEV_TX_OK ;
925
1020
926
1021
err_build_fd :
927
- err_alloc_headroom :
928
1022
dev_kfree_skb (skb );
929
1023
930
1024
return NETDEV_TX_OK ;
@@ -1161,6 +1255,22 @@ static int refill_pool(struct dpaa2_eth_priv *priv,
1161
1255
return 0 ;
1162
1256
}
1163
1257
1258
+ static void dpaa2_eth_sgt_cache_drain (struct dpaa2_eth_priv * priv )
1259
+ {
1260
+ struct dpaa2_eth_sgt_cache * sgt_cache ;
1261
+ u16 count ;
1262
+ int k , i ;
1263
+
1264
+ for_each_online_cpu (k ) {
1265
+ sgt_cache = per_cpu_ptr (priv -> sgt_cache , k );
1266
+ count = sgt_cache -> count ;
1267
+
1268
+ for (i = 0 ; i < count ; i ++ )
1269
+ kfree (sgt_cache -> buf [i ]);
1270
+ sgt_cache -> count = 0 ;
1271
+ }
1272
+ }
1273
+
1164
1274
static int pull_channel (struct dpaa2_eth_channel * ch )
1165
1275
{
1166
1276
int err ;
@@ -1562,6 +1672,9 @@ static int dpaa2_eth_stop(struct net_device *net_dev)
1562
1672
/* Empty the buffer pool */
1563
1673
drain_pool (priv );
1564
1674
1675
+ /* Empty the Scatter-Gather Buffer cache */
1676
+ dpaa2_eth_sgt_cache_drain (priv );
1677
+
1565
1678
return 0 ;
1566
1679
}
1567
1680
@@ -3846,6 +3959,13 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
3846
3959
goto err_alloc_percpu_extras ;
3847
3960
}
3848
3961
3962
+ priv -> sgt_cache = alloc_percpu (* priv -> sgt_cache );
3963
+ if (!priv -> sgt_cache ) {
3964
+ dev_err (dev , "alloc_percpu(sgt_cache) failed\n" );
3965
+ err = - ENOMEM ;
3966
+ goto err_alloc_sgt_cache ;
3967
+ }
3968
+
3849
3969
err = netdev_init (net_dev );
3850
3970
if (err )
3851
3971
goto err_netdev_init ;
@@ -3914,6 +4034,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
3914
4034
err_alloc_rings :
3915
4035
err_csum :
3916
4036
err_netdev_init :
4037
+ free_percpu (priv -> sgt_cache );
4038
+ err_alloc_sgt_cache :
3917
4039
free_percpu (priv -> percpu_extras );
3918
4040
err_alloc_percpu_extras :
3919
4041
free_percpu (priv -> percpu_stats );
@@ -3959,6 +4081,7 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
3959
4081
fsl_mc_free_irqs (ls_dev );
3960
4082
3961
4083
free_rings (priv );
4084
+ free_percpu (priv -> sgt_cache );
3962
4085
free_percpu (priv -> percpu_stats );
3963
4086
free_percpu (priv -> percpu_extras );
3964
4087
0 commit comments