@@ -126,6 +126,14 @@ static const struct virtnet_stat_desc virtnet_rq_stats_desc[] = {
126
126
#define VIRTNET_SQ_STATS_LEN ARRAY_SIZE(virtnet_sq_stats_desc)
127
127
#define VIRTNET_RQ_STATS_LEN ARRAY_SIZE(virtnet_rq_stats_desc)
128
128
129
+ /* The dma information of pages allocated at a time. */
130
+ struct virtnet_rq_dma {
131
+ dma_addr_t addr ;
132
+ u32 ref ;
133
+ u16 len ;
134
+ u16 need_sync ;
135
+ };
136
+
129
137
/* Internal representation of a send virtqueue */
130
138
struct send_queue {
131
139
/* Virtqueue associated with this send _queue */
@@ -175,6 +183,12 @@ struct receive_queue {
175
183
char name [16 ];
176
184
177
185
struct xdp_rxq_info xdp_rxq ;
186
+
187
+ /* Record the last dma info to free after new pages is allocated. */
188
+ struct virtnet_rq_dma * last_dma ;
189
+
190
+ /* Do dma by self */
191
+ bool do_dma ;
178
192
};
179
193
180
194
/* This structure can contain rss message with maximum settings for indirection table and keysize
@@ -562,6 +576,156 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
562
576
return skb ;
563
577
}
564
578
579
+ static void virtnet_rq_unmap (struct receive_queue * rq , void * buf , u32 len )
580
+ {
581
+ struct page * page = virt_to_head_page (buf );
582
+ struct virtnet_rq_dma * dma ;
583
+ void * head ;
584
+ int offset ;
585
+
586
+ head = page_address (page );
587
+
588
+ dma = head ;
589
+
590
+ -- dma -> ref ;
591
+
592
+ if (dma -> ref ) {
593
+ if (dma -> need_sync && len ) {
594
+ offset = buf - (head + sizeof (* dma ));
595
+
596
+ virtqueue_dma_sync_single_range_for_cpu (rq -> vq , dma -> addr , offset ,
597
+ len , DMA_FROM_DEVICE );
598
+ }
599
+
600
+ return ;
601
+ }
602
+
603
+ virtqueue_dma_unmap_single_attrs (rq -> vq , dma -> addr , dma -> len ,
604
+ DMA_FROM_DEVICE , DMA_ATTR_SKIP_CPU_SYNC );
605
+ put_page (page );
606
+ }
607
+
608
+ static void * virtnet_rq_get_buf (struct receive_queue * rq , u32 * len , void * * ctx )
609
+ {
610
+ void * buf ;
611
+
612
+ buf = virtqueue_get_buf_ctx (rq -> vq , len , ctx );
613
+ if (buf && rq -> do_dma )
614
+ virtnet_rq_unmap (rq , buf , * len );
615
+
616
+ return buf ;
617
+ }
618
+
619
+ static void * virtnet_rq_detach_unused_buf (struct receive_queue * rq )
620
+ {
621
+ void * buf ;
622
+
623
+ buf = virtqueue_detach_unused_buf (rq -> vq );
624
+ if (buf && rq -> do_dma )
625
+ virtnet_rq_unmap (rq , buf , 0 );
626
+
627
+ return buf ;
628
+ }
629
+
630
+ static void virtnet_rq_init_one_sg (struct receive_queue * rq , void * buf , u32 len )
631
+ {
632
+ struct virtnet_rq_dma * dma ;
633
+ dma_addr_t addr ;
634
+ u32 offset ;
635
+ void * head ;
636
+
637
+ if (!rq -> do_dma ) {
638
+ sg_init_one (rq -> sg , buf , len );
639
+ return ;
640
+ }
641
+
642
+ head = page_address (rq -> alloc_frag .page );
643
+
644
+ offset = buf - head ;
645
+
646
+ dma = head ;
647
+
648
+ addr = dma -> addr - sizeof (* dma ) + offset ;
649
+
650
+ sg_init_table (rq -> sg , 1 );
651
+ rq -> sg [0 ].dma_address = addr ;
652
+ rq -> sg [0 ].length = len ;
653
+ }
654
+
655
+ static void * virtnet_rq_alloc (struct receive_queue * rq , u32 size , gfp_t gfp )
656
+ {
657
+ struct page_frag * alloc_frag = & rq -> alloc_frag ;
658
+ struct virtnet_rq_dma * dma ;
659
+ void * buf , * head ;
660
+ dma_addr_t addr ;
661
+
662
+ if (unlikely (!skb_page_frag_refill (size , alloc_frag , gfp )))
663
+ return NULL ;
664
+
665
+ head = page_address (alloc_frag -> page );
666
+
667
+ if (rq -> do_dma ) {
668
+ dma = head ;
669
+
670
+ /* new pages */
671
+ if (!alloc_frag -> offset ) {
672
+ if (rq -> last_dma ) {
673
+ /* Now, the new page is allocated, the last dma
674
+ * will not be used. So the dma can be unmapped
675
+ * if the ref is 0.
676
+ */
677
+ virtnet_rq_unmap (rq , rq -> last_dma , 0 );
678
+ rq -> last_dma = NULL ;
679
+ }
680
+
681
+ dma -> len = alloc_frag -> size - sizeof (* dma );
682
+
683
+ addr = virtqueue_dma_map_single_attrs (rq -> vq , dma + 1 ,
684
+ dma -> len , DMA_FROM_DEVICE , 0 );
685
+ if (virtqueue_dma_mapping_error (rq -> vq , addr ))
686
+ return NULL ;
687
+
688
+ dma -> addr = addr ;
689
+ dma -> need_sync = virtqueue_dma_need_sync (rq -> vq , addr );
690
+
691
+ /* Add a reference to dma to prevent the entire dma from
692
+ * being released during error handling. This reference
693
+ * will be freed after the pages are no longer used.
694
+ */
695
+ get_page (alloc_frag -> page );
696
+ dma -> ref = 1 ;
697
+ alloc_frag -> offset = sizeof (* dma );
698
+
699
+ rq -> last_dma = dma ;
700
+ }
701
+
702
+ ++ dma -> ref ;
703
+ }
704
+
705
+ buf = head + alloc_frag -> offset ;
706
+
707
+ get_page (alloc_frag -> page );
708
+ alloc_frag -> offset += size ;
709
+
710
+ return buf ;
711
+ }
712
+
713
+ static void virtnet_rq_set_premapped (struct virtnet_info * vi )
714
+ {
715
+ int i ;
716
+
717
+ /* disable for big mode */
718
+ if (!vi -> mergeable_rx_bufs && vi -> big_packets )
719
+ return ;
720
+
721
+ for (i = 0 ; i < vi -> max_queue_pairs ; i ++ ) {
722
+ if (virtqueue_set_dma_premapped (vi -> rq [i ].vq ))
723
+ continue ;
724
+
725
+ vi -> rq [i ].do_dma = true;
726
+ }
727
+ }
728
+
565
729
static void free_old_xmit_skbs (struct send_queue * sq , bool in_napi )
566
730
{
567
731
unsigned int len ;
@@ -917,7 +1081,7 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
917
1081
void * buf ;
918
1082
int off ;
919
1083
920
- buf = virtqueue_get_buf (rq -> vq , & buflen );
1084
+ buf = virtnet_rq_get_buf (rq , & buflen , NULL );
921
1085
if (unlikely (!buf ))
922
1086
goto err_buf ;
923
1087
@@ -1137,7 +1301,7 @@ static void mergeable_buf_free(struct receive_queue *rq, int num_buf,
1137
1301
int len ;
1138
1302
1139
1303
while (num_buf -- > 1 ) {
1140
- buf = virtqueue_get_buf (rq -> vq , & len );
1304
+ buf = virtnet_rq_get_buf (rq , & len , NULL );
1141
1305
if (unlikely (!buf )) {
1142
1306
pr_debug ("%s: rx error: %d buffers missing\n" ,
1143
1307
dev -> name , num_buf );
@@ -1245,7 +1409,7 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
1245
1409
return - EINVAL ;
1246
1410
1247
1411
while (-- * num_buf > 0 ) {
1248
- buf = virtqueue_get_buf_ctx (rq -> vq , & len , & ctx );
1412
+ buf = virtnet_rq_get_buf (rq , & len , & ctx );
1249
1413
if (unlikely (!buf )) {
1250
1414
pr_debug ("%s: rx error: %d buffers out of %d missing\n" ,
1251
1415
dev -> name , * num_buf ,
@@ -1474,7 +1638,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
1474
1638
while (-- num_buf ) {
1475
1639
int num_skb_frags ;
1476
1640
1477
- buf = virtqueue_get_buf_ctx (rq -> vq , & len , & ctx );
1641
+ buf = virtnet_rq_get_buf (rq , & len , & ctx );
1478
1642
if (unlikely (!buf )) {
1479
1643
pr_debug ("%s: rx error: %d buffers out of %d missing\n" ,
1480
1644
dev -> name , num_buf ,
@@ -1633,7 +1797,6 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
1633
1797
static int add_recvbuf_small (struct virtnet_info * vi , struct receive_queue * rq ,
1634
1798
gfp_t gfp )
1635
1799
{
1636
- struct page_frag * alloc_frag = & rq -> alloc_frag ;
1637
1800
char * buf ;
1638
1801
unsigned int xdp_headroom = virtnet_get_headroom (vi );
1639
1802
void * ctx = (void * )(unsigned long )xdp_headroom ;
@@ -1642,17 +1805,21 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq,
1642
1805
1643
1806
len = SKB_DATA_ALIGN (len ) +
1644
1807
SKB_DATA_ALIGN (sizeof (struct skb_shared_info ));
1645
- if (unlikely (!skb_page_frag_refill (len , alloc_frag , gfp )))
1808
+
1809
+ buf = virtnet_rq_alloc (rq , len , gfp );
1810
+ if (unlikely (!buf ))
1646
1811
return - ENOMEM ;
1647
1812
1648
- buf = (char * )page_address (alloc_frag -> page ) + alloc_frag -> offset ;
1649
- get_page (alloc_frag -> page );
1650
- alloc_frag -> offset += len ;
1651
- sg_init_one (rq -> sg , buf + VIRTNET_RX_PAD + xdp_headroom ,
1652
- vi -> hdr_len + GOOD_PACKET_LEN );
1813
+ virtnet_rq_init_one_sg (rq , buf + VIRTNET_RX_PAD + xdp_headroom ,
1814
+ vi -> hdr_len + GOOD_PACKET_LEN );
1815
+
1653
1816
err = virtqueue_add_inbuf_ctx (rq -> vq , rq -> sg , 1 , buf , ctx , gfp );
1654
- if (err < 0 )
1817
+ if (err < 0 ) {
1818
+ if (rq -> do_dma )
1819
+ virtnet_rq_unmap (rq , buf , 0 );
1655
1820
put_page (virt_to_head_page (buf ));
1821
+ }
1822
+
1656
1823
return err ;
1657
1824
}
1658
1825
@@ -1729,23 +1896,22 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi,
1729
1896
unsigned int headroom = virtnet_get_headroom (vi );
1730
1897
unsigned int tailroom = headroom ? sizeof (struct skb_shared_info ) : 0 ;
1731
1898
unsigned int room = SKB_DATA_ALIGN (headroom + tailroom );
1732
- char * buf ;
1899
+ unsigned int len , hole ;
1733
1900
void * ctx ;
1901
+ char * buf ;
1734
1902
int err ;
1735
- unsigned int len , hole ;
1736
1903
1737
1904
/* Extra tailroom is needed to satisfy XDP's assumption. This
1738
1905
* means rx frags coalescing won't work, but consider we've
1739
1906
* disabled GSO for XDP, it won't be a big issue.
1740
1907
*/
1741
1908
len = get_mergeable_buf_len (rq , & rq -> mrg_avg_pkt_len , room );
1742
- if (unlikely (!skb_page_frag_refill (len + room , alloc_frag , gfp )))
1909
+
1910
+ buf = virtnet_rq_alloc (rq , len + room , gfp );
1911
+ if (unlikely (!buf ))
1743
1912
return - ENOMEM ;
1744
1913
1745
- buf = (char * )page_address (alloc_frag -> page ) + alloc_frag -> offset ;
1746
1914
buf += headroom ; /* advance address leaving hole at front of pkt */
1747
- get_page (alloc_frag -> page );
1748
- alloc_frag -> offset += len + room ;
1749
1915
hole = alloc_frag -> size - alloc_frag -> offset ;
1750
1916
if (hole < len + room ) {
1751
1917
/* To avoid internal fragmentation, if there is very likely not
@@ -1759,11 +1925,15 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi,
1759
1925
alloc_frag -> offset += hole ;
1760
1926
}
1761
1927
1762
- sg_init_one (rq -> sg , buf , len );
1928
+ virtnet_rq_init_one_sg (rq , buf , len );
1929
+
1763
1930
ctx = mergeable_len_to_ctx (len + room , headroom );
1764
1931
err = virtqueue_add_inbuf_ctx (rq -> vq , rq -> sg , 1 , buf , ctx , gfp );
1765
- if (err < 0 )
1932
+ if (err < 0 ) {
1933
+ if (rq -> do_dma )
1934
+ virtnet_rq_unmap (rq , buf , 0 );
1766
1935
put_page (virt_to_head_page (buf ));
1936
+ }
1767
1937
1768
1938
return err ;
1769
1939
}
@@ -1884,13 +2054,13 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
1884
2054
void * ctx ;
1885
2055
1886
2056
while (stats .packets < budget &&
1887
- (buf = virtqueue_get_buf_ctx (rq -> vq , & len , & ctx ))) {
2057
+ (buf = virtnet_rq_get_buf (rq , & len , & ctx ))) {
1888
2058
receive_buf (vi , rq , buf , len , ctx , xdp_xmit , & stats );
1889
2059
stats .packets ++ ;
1890
2060
}
1891
2061
} else {
1892
2062
while (stats .packets < budget &&
1893
- (buf = virtqueue_get_buf (rq -> vq , & len )) != NULL ) {
2063
+ (buf = virtnet_rq_get_buf (rq , & len , NULL )) != NULL ) {
1894
2064
receive_buf (vi , rq , buf , len , NULL , xdp_xmit , & stats );
1895
2065
stats .packets ++ ;
1896
2066
}
@@ -3662,8 +3832,11 @@ static void free_receive_page_frags(struct virtnet_info *vi)
3662
3832
{
3663
3833
int i ;
3664
3834
for (i = 0 ; i < vi -> max_queue_pairs ; i ++ )
3665
- if (vi -> rq [i ].alloc_frag .page )
3835
+ if (vi -> rq [i ].alloc_frag .page ) {
3836
+ if (vi -> rq [i ].do_dma && vi -> rq [i ].last_dma )
3837
+ virtnet_rq_unmap (& vi -> rq [i ], vi -> rq [i ].last_dma , 0 );
3666
3838
put_page (vi -> rq [i ].alloc_frag .page );
3839
+ }
3667
3840
}
3668
3841
3669
3842
static void virtnet_sq_free_unused_buf (struct virtqueue * vq , void * buf )
@@ -3700,9 +3873,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
3700
3873
}
3701
3874
3702
3875
for (i = 0 ; i < vi -> max_queue_pairs ; i ++ ) {
3703
- struct virtqueue * vq = vi -> rq [i ].vq ;
3704
- while ((buf = virtqueue_detach_unused_buf (vq )) != NULL )
3705
- virtnet_rq_free_unused_buf (vq , buf );
3876
+ struct receive_queue * rq = & vi -> rq [i ];
3877
+
3878
+ while ((buf = virtnet_rq_detach_unused_buf (rq )) != NULL )
3879
+ virtnet_rq_free_unused_buf (rq -> vq , buf );
3706
3880
cond_resched ();
3707
3881
}
3708
3882
}
@@ -3876,6 +4050,8 @@ static int init_vqs(struct virtnet_info *vi)
3876
4050
if (ret )
3877
4051
goto err_free ;
3878
4052
4053
+ virtnet_rq_set_premapped (vi );
4054
+
3879
4055
cpus_read_lock ();
3880
4056
virtnet_set_affinity (vi );
3881
4057
cpus_read_unlock ();
0 commit comments