@@ -44,9 +44,40 @@ static inline struct page *io_zcrx_iov_page(const struct net_iov *niov)
4444{
4545 struct io_zcrx_area * area = io_zcrx_iov_to_area (niov );
4646
47+ lockdep_assert (!area -> mem .is_dmabuf );
48+
4749 return area -> mem .pages [net_iov_idx (niov )];
4850}
4951
52+ static int io_populate_area_dma (struct io_zcrx_ifq * ifq ,
53+ struct io_zcrx_area * area ,
54+ struct sg_table * sgt , unsigned long off )
55+ {
56+ struct scatterlist * sg ;
57+ unsigned i , niov_idx = 0 ;
58+
59+ for_each_sgtable_dma_sg (sgt , sg , i ) {
60+ dma_addr_t dma = sg_dma_address (sg );
61+ unsigned long sg_len = sg_dma_len (sg );
62+ unsigned long sg_off = min (sg_len , off );
63+
64+ off -= sg_off ;
65+ sg_len -= sg_off ;
66+ dma += sg_off ;
67+
68+ while (sg_len && niov_idx < area -> nia .num_niovs ) {
69+ struct net_iov * niov = & area -> nia .niovs [niov_idx ];
70+
71+ if (net_mp_niov_set_dma_addr (niov , dma ))
72+ return - EFAULT ;
73+ sg_len -= PAGE_SIZE ;
74+ dma += PAGE_SIZE ;
75+ niov_idx ++ ;
76+ }
77+ }
78+ return 0 ;
79+ }
80+
5081static void io_release_dmabuf (struct io_zcrx_mem * mem )
5182{
5283 if (!IS_ENABLED (CONFIG_DMA_SHARED_BUFFER ))
@@ -121,41 +152,18 @@ static int io_import_dmabuf(struct io_zcrx_ifq *ifq,
121152
122153static int io_zcrx_map_area_dmabuf (struct io_zcrx_ifq * ifq , struct io_zcrx_area * area )
123154{
124- unsigned long off = area -> mem .dmabuf_offset ;
125- struct scatterlist * sg ;
126- unsigned i , niov_idx = 0 ;
127-
128155 if (!IS_ENABLED (CONFIG_DMA_SHARED_BUFFER ))
129156 return - EINVAL ;
130-
131- for_each_sgtable_dma_sg (area -> mem .sgt , sg , i ) {
132- dma_addr_t dma = sg_dma_address (sg );
133- unsigned long sg_len = sg_dma_len (sg );
134- unsigned long sg_off = min (sg_len , off );
135-
136- off -= sg_off ;
137- sg_len -= sg_off ;
138- dma += sg_off ;
139-
140- while (sg_len && niov_idx < area -> nia .num_niovs ) {
141- struct net_iov * niov = & area -> nia .niovs [niov_idx ];
142-
143- if (net_mp_niov_set_dma_addr (niov , dma ))
144- return 0 ;
145- sg_len -= PAGE_SIZE ;
146- dma += PAGE_SIZE ;
147- niov_idx ++ ;
148- }
149- }
150- return niov_idx ;
157+ return io_populate_area_dma (ifq , area , area -> mem .sgt ,
158+ area -> mem .dmabuf_offset );
151159}
152160
153161static int io_import_umem (struct io_zcrx_ifq * ifq ,
154162 struct io_zcrx_mem * mem ,
155163 struct io_uring_zcrx_area_reg * area_reg )
156164{
157165 struct page * * pages ;
158- int nr_pages ;
166+ int nr_pages , ret ;
159167
160168 if (area_reg -> dmabuf_fd )
161169 return - EINVAL ;
@@ -166,6 +174,12 @@ static int io_import_umem(struct io_zcrx_ifq *ifq,
166174 if (IS_ERR (pages ))
167175 return PTR_ERR (pages );
168176
177+ ret = sg_alloc_table_from_pages (& mem -> page_sg_table , pages , nr_pages ,
178+ 0 , nr_pages << PAGE_SHIFT ,
179+ GFP_KERNEL_ACCOUNT );
180+ if (ret )
181+ return ret ;
182+
169183 mem -> pages = pages ;
170184 mem -> nr_folios = nr_pages ;
171185 mem -> size = area_reg -> len ;
@@ -180,6 +194,7 @@ static void io_release_area_mem(struct io_zcrx_mem *mem)
180194 }
181195 if (mem -> pages ) {
182196 unpin_user_pages (mem -> pages , mem -> nr_folios );
197+ sg_free_table (& mem -> page_sg_table );
183198 kvfree (mem -> pages );
184199 }
185200}
@@ -201,84 +216,54 @@ static int io_import_area(struct io_zcrx_ifq *ifq,
201216 return io_import_umem (ifq , mem , area_reg );
202217}
203218
204- static void io_zcrx_unmap_umem (struct io_zcrx_ifq * ifq ,
205- struct io_zcrx_area * area , int nr_mapped )
206- {
207- int i ;
208-
209- for (i = 0 ; i < nr_mapped ; i ++ ) {
210- netmem_ref netmem = net_iov_to_netmem (& area -> nia .niovs [i ]);
211- dma_addr_t dma = page_pool_get_dma_addr_netmem (netmem );
212-
213- dma_unmap_page_attrs (ifq -> dev , dma , PAGE_SIZE ,
214- DMA_FROM_DEVICE , IO_DMA_ATTR );
215- }
216- }
217-
218- static void __io_zcrx_unmap_area (struct io_zcrx_ifq * ifq ,
219- struct io_zcrx_area * area , int nr_mapped )
219+ static void io_zcrx_unmap_area (struct io_zcrx_ifq * ifq ,
220+ struct io_zcrx_area * area )
220221{
221222 int i ;
222223
223- if ( area -> mem . is_dmabuf )
224- io_release_dmabuf ( & area -> mem );
225- else
226- io_zcrx_unmap_umem ( ifq , area , nr_mapped ) ;
224+ guard ( mutex )( & ifq -> dma_lock );
225+ if (! area -> is_mapped )
226+ return ;
227+ area -> is_mapped = false ;
227228
228229 for (i = 0 ; i < area -> nia .num_niovs ; i ++ )
229230 net_mp_niov_set_dma_addr (& area -> nia .niovs [i ], 0 );
230- }
231-
232- static void io_zcrx_unmap_area (struct io_zcrx_ifq * ifq , struct io_zcrx_area * area )
233- {
234- guard (mutex )(& ifq -> dma_lock );
235231
236- if (area -> is_mapped )
237- __io_zcrx_unmap_area (ifq , area , area -> nia .num_niovs );
238- area -> is_mapped = false;
232+ if (area -> mem .is_dmabuf ) {
233+ io_release_dmabuf (& area -> mem );
234+ } else {
235+ dma_unmap_sgtable (ifq -> dev , & area -> mem .page_sg_table ,
236+ DMA_FROM_DEVICE , IO_DMA_ATTR );
237+ }
239238}
240239
241- static int io_zcrx_map_area_umem (struct io_zcrx_ifq * ifq , struct io_zcrx_area * area )
240+ static unsigned io_zcrx_map_area_umem (struct io_zcrx_ifq * ifq , struct io_zcrx_area * area )
242241{
243- int i ;
244-
245- for (i = 0 ; i < area -> nia .num_niovs ; i ++ ) {
246- struct net_iov * niov = & area -> nia .niovs [i ];
247- dma_addr_t dma ;
242+ int ret ;
248243
249- dma = dma_map_page_attrs (ifq -> dev , area -> mem .pages [i ], 0 ,
250- PAGE_SIZE , DMA_FROM_DEVICE , IO_DMA_ATTR );
251- if (dma_mapping_error (ifq -> dev , dma ))
252- break ;
253- if (net_mp_niov_set_dma_addr (niov , dma )) {
254- dma_unmap_page_attrs (ifq -> dev , dma , PAGE_SIZE ,
255- DMA_FROM_DEVICE , IO_DMA_ATTR );
256- break ;
257- }
258- }
259- return i ;
244+ ret = dma_map_sgtable (ifq -> dev , & area -> mem .page_sg_table ,
245+ DMA_FROM_DEVICE , IO_DMA_ATTR );
246+ if (ret < 0 )
247+ return ret ;
248+ return io_populate_area_dma (ifq , area , & area -> mem .page_sg_table , 0 );
260249}
261250
262251static int io_zcrx_map_area (struct io_zcrx_ifq * ifq , struct io_zcrx_area * area )
263252{
264- unsigned nr ;
253+ int ret ;
265254
266255 guard (mutex )(& ifq -> dma_lock );
267256 if (area -> is_mapped )
268257 return 0 ;
269258
270259 if (area -> mem .is_dmabuf )
271- nr = io_zcrx_map_area_dmabuf (ifq , area );
260+ ret = io_zcrx_map_area_dmabuf (ifq , area );
272261 else
273- nr = io_zcrx_map_area_umem (ifq , area );
262+ ret = io_zcrx_map_area_umem (ifq , area );
274263
275- if (nr != area -> nia .num_niovs ) {
276- __io_zcrx_unmap_area (ifq , area , nr );
277- return - EINVAL ;
278- }
279-
280- area -> is_mapped = true;
281- return 0 ;
264+ if (ret == 0 )
265+ area -> is_mapped = true;
266+ return ret ;
282267}
283268
284269static void io_zcrx_sync_for_device (const struct page_pool * pool ,
@@ -941,9 +926,54 @@ static struct net_iov *io_zcrx_alloc_fallback(struct io_zcrx_area *area)
941926 return niov ;
942927}
943928
929+ struct io_copy_cache {
930+ struct page * page ;
931+ unsigned long offset ;
932+ size_t size ;
933+ };
934+
935+ static ssize_t io_copy_page (struct io_copy_cache * cc , struct page * src_page ,
936+ unsigned int src_offset , size_t len )
937+ {
938+ size_t copied = 0 ;
939+
940+ len = min (len , cc -> size );
941+
942+ while (len ) {
943+ void * src_addr , * dst_addr ;
944+ struct page * dst_page = cc -> page ;
945+ unsigned dst_offset = cc -> offset ;
946+ size_t n = len ;
947+
948+ if (folio_test_partial_kmap (page_folio (dst_page )) ||
949+ folio_test_partial_kmap (page_folio (src_page ))) {
950+ dst_page = nth_page (dst_page , dst_offset / PAGE_SIZE );
951+ dst_offset = offset_in_page (dst_offset );
952+ src_page = nth_page (src_page , src_offset / PAGE_SIZE );
953+ src_offset = offset_in_page (src_offset );
954+ n = min (PAGE_SIZE - src_offset , PAGE_SIZE - dst_offset );
955+ n = min (n , len );
956+ }
957+
958+ dst_addr = kmap_local_page (dst_page ) + dst_offset ;
959+ src_addr = kmap_local_page (src_page ) + src_offset ;
960+
961+ memcpy (dst_addr , src_addr , n );
962+
963+ kunmap_local (src_addr );
964+ kunmap_local (dst_addr );
965+
966+ cc -> size -= n ;
967+ cc -> offset += n ;
968+ len -= n ;
969+ copied += n ;
970+ }
971+ return copied ;
972+ }
973+
944974static ssize_t io_zcrx_copy_chunk (struct io_kiocb * req , struct io_zcrx_ifq * ifq ,
945- void * src_base , struct page * src_page ,
946- unsigned int src_offset , size_t len )
975+ struct page * src_page , unsigned int src_offset ,
976+ size_t len )
947977{
948978 struct io_zcrx_area * area = ifq -> area ;
949979 size_t copied = 0 ;
@@ -953,39 +983,32 @@ static ssize_t io_zcrx_copy_chunk(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
953983 return - EFAULT ;
954984
955985 while (len ) {
956- size_t copy_size = min_t (size_t , PAGE_SIZE , len );
957- const int dst_off = 0 ;
986+ struct io_copy_cache cc ;
958987 struct net_iov * niov ;
959- struct page * dst_page ;
960- void * dst_addr ;
988+ size_t n ;
961989
962990 niov = io_zcrx_alloc_fallback (area );
963991 if (!niov ) {
964992 ret = - ENOMEM ;
965993 break ;
966994 }
967995
968- dst_page = io_zcrx_iov_page (niov );
969- dst_addr = kmap_local_page (dst_page );
970- if (src_page )
971- src_base = kmap_local_page (src_page );
996+ cc .page = io_zcrx_iov_page (niov );
997+ cc .offset = 0 ;
998+ cc .size = PAGE_SIZE ;
972999
973- memcpy ( dst_addr , src_base + src_offset , copy_size );
1000+ n = io_copy_page ( & cc , src_page , src_offset , len );
9741001
975- if (src_page )
976- kunmap_local (src_base );
977- kunmap_local (dst_addr );
978-
979- if (!io_zcrx_queue_cqe (req , niov , ifq , dst_off , copy_size )) {
1002+ if (!io_zcrx_queue_cqe (req , niov , ifq , 0 , n )) {
9801003 io_zcrx_return_niov (niov );
9811004 ret = - ENOSPC ;
9821005 break ;
9831006 }
9841007
9851008 io_zcrx_get_niov_uref (niov );
986- src_offset += copy_size ;
987- len -= copy_size ;
988- copied += copy_size ;
1009+ src_offset += n ;
1010+ len -= n ;
1011+ copied += n ;
9891012 }
9901013
9911014 return copied ? copied : ret ;
@@ -995,19 +1018,8 @@ static int io_zcrx_copy_frag(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
9951018 const skb_frag_t * frag , int off , int len )
9961019{
9971020 struct page * page = skb_frag_page (frag );
998- u32 p_off , p_len , t , copied = 0 ;
999- int ret = 0 ;
10001021
1001- off += skb_frag_off (frag );
1002-
1003- skb_frag_foreach_page (frag , off , len ,
1004- page , p_off , p_len , t ) {
1005- ret = io_zcrx_copy_chunk (req , ifq , NULL , page , p_off , p_len );
1006- if (ret < 0 )
1007- return copied ? copied : ret ;
1008- copied += ret ;
1009- }
1010- return copied ;
1022+ return io_zcrx_copy_chunk (req , ifq , page , off + skb_frag_off (frag ), len );
10111023}
10121024
10131025static int io_zcrx_recv_frag (struct io_kiocb * req , struct io_zcrx_ifq * ifq ,
@@ -1064,8 +1076,9 @@ io_zcrx_recv_skb(read_descriptor_t *desc, struct sk_buff *skb,
10641076 size_t to_copy ;
10651077
10661078 to_copy = min_t (size_t , skb_headlen (skb ) - offset , len );
1067- copied = io_zcrx_copy_chunk (req , ifq , skb -> data , NULL ,
1068- offset , to_copy );
1079+ copied = io_zcrx_copy_chunk (req , ifq , virt_to_page (skb -> data ),
1080+ offset_in_page (skb -> data ) + offset ,
1081+ to_copy );
10691082 if (copied < 0 ) {
10701083 ret = copied ;
10711084 goto out ;
0 commit comments