@@ -1884,8 +1884,8 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
1884
1884
bytes_compl += buf -> skb -> len ;
1885
1885
pkts_compl ++ ;
1886
1886
dev_kfree_skb_any (buf -> skb );
1887
- } else if (buf -> type == MVNETA_TYPE_XDP_TX ||
1888
- buf -> type == MVNETA_TYPE_XDP_NDO ) {
1887
+ } else if (( buf -> type == MVNETA_TYPE_XDP_TX ||
1888
+ buf -> type == MVNETA_TYPE_XDP_NDO ) && buf -> xdpf ) {
1889
1889
if (napi && buf -> type == MVNETA_TYPE_XDP_TX )
1890
1890
xdp_return_frame_rx_napi (buf -> xdpf );
1891
1891
else
@@ -2079,47 +2079,87 @@ mvneta_xdp_put_buff(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
2079
2079
2080
2080
static int
2081
2081
mvneta_xdp_submit_frame (struct mvneta_port * pp , struct mvneta_tx_queue * txq ,
2082
- struct xdp_frame * xdpf , bool dma_map )
2082
+ struct xdp_frame * xdpf , int * nxmit_byte , bool dma_map )
2083
2083
{
2084
- struct mvneta_tx_desc * tx_desc ;
2085
- struct mvneta_tx_buf * buf ;
2086
- dma_addr_t dma_addr ;
2084
+ struct skb_shared_info * sinfo = xdp_get_shared_info_from_frame (xdpf );
2085
+ struct device * dev = pp -> dev -> dev .parent ;
2086
+ struct mvneta_tx_desc * tx_desc = NULL ;
2087
+ int i , num_frames = 1 ;
2088
+ struct page * page ;
2089
+
2090
+ if (unlikely (xdp_frame_has_frags (xdpf )))
2091
+ num_frames += sinfo -> nr_frags ;
2087
2092
2088
- if (txq -> count >= txq -> tx_stop_threshold )
2093
+ if (txq -> count + num_frames >= txq -> size )
2089
2094
return MVNETA_XDP_DROPPED ;
2090
2095
2091
- tx_desc = mvneta_txq_next_desc_get (txq );
2096
+ for (i = 0 ; i < num_frames ; i ++ ) {
2097
+ struct mvneta_tx_buf * buf = & txq -> buf [txq -> txq_put_index ];
2098
+ skb_frag_t * frag = NULL ;
2099
+ int len = xdpf -> len ;
2100
+ dma_addr_t dma_addr ;
2092
2101
2093
- buf = & txq -> buf [txq -> txq_put_index ];
2094
- if (dma_map ) {
2095
- /* ndo_xdp_xmit */
2096
- dma_addr = dma_map_single (pp -> dev -> dev .parent , xdpf -> data ,
2097
- xdpf -> len , DMA_TO_DEVICE );
2098
- if (dma_mapping_error (pp -> dev -> dev .parent , dma_addr )) {
2099
- mvneta_txq_desc_put (txq );
2100
- return MVNETA_XDP_DROPPED ;
2102
+ if (unlikely (i )) { /* paged area */
2103
+ frag = & sinfo -> frags [i - 1 ];
2104
+ len = skb_frag_size (frag );
2101
2105
}
2102
- buf -> type = MVNETA_TYPE_XDP_NDO ;
2103
- } else {
2104
- struct page * page = virt_to_page (xdpf -> data );
2105
2106
2106
- dma_addr = page_pool_get_dma_addr (page ) +
2107
- sizeof (* xdpf ) + xdpf -> headroom ;
2108
- dma_sync_single_for_device (pp -> dev -> dev .parent , dma_addr ,
2109
- xdpf -> len , DMA_BIDIRECTIONAL );
2110
- buf -> type = MVNETA_TYPE_XDP_TX ;
2107
+ tx_desc = mvneta_txq_next_desc_get (txq );
2108
+ if (dma_map ) {
2109
+ /* ndo_xdp_xmit */
2110
+ void * data ;
2111
+
2112
+ data = unlikely (frag ) ? skb_frag_address (frag )
2113
+ : xdpf -> data ;
2114
+ dma_addr = dma_map_single (dev , data , len ,
2115
+ DMA_TO_DEVICE );
2116
+ if (dma_mapping_error (dev , dma_addr )) {
2117
+ mvneta_txq_desc_put (txq );
2118
+ goto unmap ;
2119
+ }
2120
+
2121
+ buf -> type = MVNETA_TYPE_XDP_NDO ;
2122
+ } else {
2123
+ page = unlikely (frag ) ? skb_frag_page (frag )
2124
+ : virt_to_page (xdpf -> data );
2125
+ dma_addr = page_pool_get_dma_addr (page );
2126
+ if (unlikely (frag ))
2127
+ dma_addr += skb_frag_off (frag );
2128
+ else
2129
+ dma_addr += sizeof (* xdpf ) + xdpf -> headroom ;
2130
+ dma_sync_single_for_device (dev , dma_addr , len ,
2131
+ DMA_BIDIRECTIONAL );
2132
+ buf -> type = MVNETA_TYPE_XDP_TX ;
2133
+ }
2134
+ buf -> xdpf = unlikely (i ) ? NULL : xdpf ;
2135
+
2136
+ tx_desc -> command = unlikely (i ) ? 0 : MVNETA_TXD_F_DESC ;
2137
+ tx_desc -> buf_phys_addr = dma_addr ;
2138
+ tx_desc -> data_size = len ;
2139
+ * nxmit_byte += len ;
2140
+
2141
+ mvneta_txq_inc_put (txq );
2111
2142
}
2112
- buf -> xdpf = xdpf ;
2113
2143
2114
- tx_desc -> command = MVNETA_TXD_FLZ_DESC ;
2115
- tx_desc -> buf_phys_addr = dma_addr ;
2116
- tx_desc -> data_size = xdpf -> len ;
2144
+ /*last descriptor */
2145
+ if ( likely ( tx_desc ))
2146
+ tx_desc -> command |= MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD ;
2117
2147
2118
- mvneta_txq_inc_put (txq );
2119
- txq -> pending ++ ;
2120
- txq -> count ++ ;
2148
+ txq -> pending += num_frames ;
2149
+ txq -> count += num_frames ;
2121
2150
2122
2151
return MVNETA_XDP_TX ;
2152
+
2153
+ unmap :
2154
+ for (i -- ; i >= 0 ; i -- ) {
2155
+ mvneta_txq_desc_put (txq );
2156
+ tx_desc = txq -> descs + txq -> next_desc_to_proc ;
2157
+ dma_unmap_single (dev , tx_desc -> buf_phys_addr ,
2158
+ tx_desc -> data_size ,
2159
+ DMA_TO_DEVICE );
2160
+ }
2161
+
2162
+ return MVNETA_XDP_DROPPED ;
2123
2163
}
2124
2164
2125
2165
static int
@@ -2128,8 +2168,8 @@ mvneta_xdp_xmit_back(struct mvneta_port *pp, struct xdp_buff *xdp)
2128
2168
struct mvneta_pcpu_stats * stats = this_cpu_ptr (pp -> stats );
2129
2169
struct mvneta_tx_queue * txq ;
2130
2170
struct netdev_queue * nq ;
2171
+ int cpu , nxmit_byte = 0 ;
2131
2172
struct xdp_frame * xdpf ;
2132
- int cpu ;
2133
2173
u32 ret ;
2134
2174
2135
2175
xdpf = xdp_convert_buff_to_frame (xdp );
@@ -2141,10 +2181,10 @@ mvneta_xdp_xmit_back(struct mvneta_port *pp, struct xdp_buff *xdp)
2141
2181
nq = netdev_get_tx_queue (pp -> dev , txq -> id );
2142
2182
2143
2183
__netif_tx_lock (nq , cpu );
2144
- ret = mvneta_xdp_submit_frame (pp , txq , xdpf , false);
2184
+ ret = mvneta_xdp_submit_frame (pp , txq , xdpf , & nxmit_byte , false);
2145
2185
if (ret == MVNETA_XDP_TX ) {
2146
2186
u64_stats_update_begin (& stats -> syncp );
2147
- stats -> es .ps .tx_bytes += xdpf -> len ;
2187
+ stats -> es .ps .tx_bytes += nxmit_byte ;
2148
2188
stats -> es .ps .tx_packets ++ ;
2149
2189
stats -> es .ps .xdp_tx ++ ;
2150
2190
u64_stats_update_end (& stats -> syncp );
@@ -2183,11 +2223,11 @@ mvneta_xdp_xmit(struct net_device *dev, int num_frame,
2183
2223
2184
2224
__netif_tx_lock (nq , cpu );
2185
2225
for (i = 0 ; i < num_frame ; i ++ ) {
2186
- ret = mvneta_xdp_submit_frame (pp , txq , frames [i ], true);
2226
+ ret = mvneta_xdp_submit_frame (pp , txq , frames [i ], & nxmit_byte ,
2227
+ true);
2187
2228
if (ret != MVNETA_XDP_TX )
2188
2229
break ;
2189
2230
2190
- nxmit_byte += frames [i ]-> len ;
2191
2231
nxmit ++ ;
2192
2232
}
2193
2233
0 commit comments