@@ -25,11 +25,12 @@ struct pci_p2pdma {
2525 struct gen_pool * pool ;
2626 bool p2pmem_published ;
2727 struct xarray map_types ;
28+ struct p2pdma_provider mem ;
2829};
2930
3031struct pci_p2pdma_pagemap {
3132 struct dev_pagemap pgmap ;
32- struct p2pdma_provider mem ;
33+ struct p2pdma_provider * mem ;
3334};
3435
3536static struct pci_p2pdma_pagemap * to_p2p_pgmap (struct dev_pagemap * pgmap )
@@ -204,7 +205,7 @@ static void p2pdma_page_free(struct page *page)
204205 struct pci_p2pdma_pagemap * pgmap = to_p2p_pgmap (page_pgmap (page ));
205206 /* safe to dereference while a reference is held to the percpu ref */
206207 struct pci_p2pdma * p2pdma = rcu_dereference_protected (
207- to_pci_dev (pgmap -> mem . owner )-> p2pdma , 1 );
208+ to_pci_dev (pgmap -> mem -> owner )-> p2pdma , 1 );
208209 struct percpu_ref * ref ;
209210
210211 gen_pool_free_owner (p2pdma -> pool , (uintptr_t )page_to_virt (page ),
@@ -227,44 +228,77 @@ static void pci_p2pdma_release(void *data)
227228
228229 /* Flush and disable pci_alloc_p2p_mem() */
229230 pdev -> p2pdma = NULL ;
230- synchronize_rcu ();
231+ if (p2pdma -> pool )
232+ synchronize_rcu ();
233+ xa_destroy (& p2pdma -> map_types );
234+
235+ if (!p2pdma -> pool )
236+ return ;
231237
232238 gen_pool_destroy (p2pdma -> pool );
233239 sysfs_remove_group (& pdev -> dev .kobj , & p2pmem_group );
234- xa_destroy (& p2pdma -> map_types );
235240}
236241
237- static int pci_p2pdma_setup (struct pci_dev * pdev )
242+ /**
243+ * pci_p2pdma_enable - Enable peer-to-peer DMA support for a PCI device
244+ * @pdev: The PCI device to enable P2PDMA for
245+ *
246+ * This function initializes the peer-to-peer DMA infrastructure for a PCI
247+ * device. It allocates and sets up the necessary data structures to support
248+ * P2PDMA operations, including mapping type tracking.
249+ */
250+ struct p2pdma_provider * pci_p2pdma_enable (struct pci_dev * pdev )
238251{
239- int error = - ENOMEM ;
240252 struct pci_p2pdma * p2p ;
253+ int ret ;
241254
242255 p2p = devm_kzalloc (& pdev -> dev , sizeof (* p2p ), GFP_KERNEL );
243256 if (!p2p )
244- return - ENOMEM ;
257+ return ERR_PTR ( - ENOMEM ) ;
245258
246259 xa_init (& p2p -> map_types );
260+ p2p -> mem .owner = & pdev -> dev ;
261+ /* On all p2p platforms bus_offset is the same for all BARs */
262+ p2p -> mem .bus_offset =
263+ pci_bus_address (pdev , 0 ) - pci_resource_start (pdev , 0 );
247264
248- p2p -> pool = gen_pool_create ( PAGE_SHIFT , dev_to_node ( & pdev -> dev ) );
249- if (! p2p -> pool )
250- goto out ;
265+ ret = devm_add_action_or_reset ( & pdev -> dev , pci_p2pdma_release , pdev );
266+ if (ret )
267+ goto out_p2p ;
251268
252- error = devm_add_action_or_reset (& pdev -> dev , pci_p2pdma_release , pdev );
253- if (error )
254- goto out_pool_destroy ;
269+ rcu_assign_pointer (pdev -> p2pdma , p2p );
270+ return & p2p -> mem ;
255271
256- error = sysfs_create_group (& pdev -> dev .kobj , & p2pmem_group );
257- if (error )
272+ out_p2p :
273+ devm_kfree (& pdev -> dev , p2p );
274+ return ERR_PTR (ret );
275+ }
276+ EXPORT_SYMBOL_GPL (pci_p2pdma_enable );
277+
278+ static int pci_p2pdma_setup_pool (struct pci_dev * pdev )
279+ {
280+ struct pci_p2pdma * p2pdma ;
281+ int ret ;
282+
283+ p2pdma = rcu_dereference_protected (pdev -> p2pdma , 1 );
284+ if (p2pdma -> pool )
285+ /* We already setup pools, do nothing, */
286+ return 0 ;
287+
288+ p2pdma -> pool = gen_pool_create (PAGE_SHIFT , dev_to_node (& pdev -> dev ));
289+ if (!p2pdma -> pool )
290+ return - ENOMEM ;
291+
292+ ret = sysfs_create_group (& pdev -> dev .kobj , & p2pmem_group );
293+ if (ret )
258294 goto out_pool_destroy ;
259295
260- rcu_assign_pointer (pdev -> p2pdma , p2p );
261296 return 0 ;
262297
263298out_pool_destroy :
264- gen_pool_destroy (p2p -> pool );
265- out :
266- devm_kfree (& pdev -> dev , p2p );
267- return error ;
299+ gen_pool_destroy (p2pdma -> pool );
300+ p2pdma -> pool = NULL ;
301+ return ret ;
268302}
269303
270304static void pci_p2pdma_unmap_mappings (void * data )
@@ -276,7 +310,7 @@ static void pci_p2pdma_unmap_mappings(void *data)
276310 * unmap_mapping_range() on the inode, teardown any existing userspace
277311 * mappings and prevent new ones from being created.
278312 */
279- sysfs_remove_file_from_group (& p2p_pgmap -> mem . owner -> kobj ,
313+ sysfs_remove_file_from_group (& p2p_pgmap -> mem -> owner -> kobj ,
280314 & p2pmem_alloc_attr .attr ,
281315 p2pmem_group .name );
282316}
@@ -295,6 +329,7 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
295329 u64 offset )
296330{
297331 struct pci_p2pdma_pagemap * p2p_pgmap ;
332+ struct p2pdma_provider * mem ;
298333 struct dev_pagemap * pgmap ;
299334 struct pci_p2pdma * p2pdma ;
300335 void * addr ;
@@ -312,25 +347,30 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
312347 if (size + offset > pci_resource_len (pdev , bar ))
313348 return - EINVAL ;
314349
315- if (!pdev -> p2pdma ) {
316- error = pci_p2pdma_setup (pdev );
350+ p2pdma = rcu_dereference_protected (pdev -> p2pdma , 1 );
351+ if (!p2pdma ) {
352+ mem = pci_p2pdma_enable (pdev );
353+ if (IS_ERR (mem ))
354+ return PTR_ERR (mem );
355+
356+ error = pci_p2pdma_setup_pool (pdev );
317357 if (error )
318358 return error ;
319359 }
320360
321361 p2p_pgmap = devm_kzalloc (& pdev -> dev , sizeof (* p2p_pgmap ), GFP_KERNEL );
322- if (!p2p_pgmap )
323- return - ENOMEM ;
362+ if (!p2p_pgmap ) {
363+ error = - ENOMEM ;
364+ goto free_pool ;
365+ }
324366
325367 pgmap = & p2p_pgmap -> pgmap ;
326368 pgmap -> range .start = pci_resource_start (pdev , bar ) + offset ;
327369 pgmap -> range .end = pgmap -> range .start + size - 1 ;
328370 pgmap -> nr_range = 1 ;
329371 pgmap -> type = MEMORY_DEVICE_PCI_P2PDMA ;
330372 pgmap -> ops = & p2pdma_pgmap_ops ;
331- p2p_pgmap -> mem .owner = & pdev -> dev ;
332- p2p_pgmap -> mem .bus_offset =
333- pci_bus_address (pdev , bar ) - pci_resource_start (pdev , bar );
373+ p2p_pgmap -> mem = mem ;
334374
335375 addr = devm_memremap_pages (& pdev -> dev , pgmap );
336376 if (IS_ERR (addr )) {
@@ -343,7 +383,6 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
343383 if (error )
344384 goto pages_free ;
345385
346- p2pdma = rcu_dereference_protected (pdev -> p2pdma , 1 );
347386 error = gen_pool_add_owner (p2pdma -> pool , (unsigned long )addr ,
348387 pci_bus_address (pdev , bar ) + offset ,
349388 range_len (& pgmap -> range ), dev_to_node (& pdev -> dev ),
@@ -359,7 +398,10 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
359398pages_free :
360399 devm_memunmap_pages (& pdev -> dev , pgmap );
361400pgmap_free :
362- devm_kfree (& pdev -> dev , pgmap );
401+ devm_kfree (& pdev -> dev , p2p_pgmap );
402+ free_pool :
403+ sysfs_remove_group (& pdev -> dev .kobj , & p2pmem_group );
404+ gen_pool_destroy (p2pdma -> pool );
363405 return error ;
364406}
365407EXPORT_SYMBOL_GPL (pci_p2pdma_add_resource );
@@ -1008,11 +1050,11 @@ void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state,
10081050{
10091051 struct pci_p2pdma_pagemap * p2p_pgmap = to_p2p_pgmap (page_pgmap (page ));
10101052
1011- if (state -> mem == & p2p_pgmap -> mem )
1053+ if (state -> mem == p2p_pgmap -> mem )
10121054 return ;
10131055
1014- state -> mem = & p2p_pgmap -> mem ;
1015- state -> map = pci_p2pdma_map_type (& p2p_pgmap -> mem , dev );
1056+ state -> mem = p2p_pgmap -> mem ;
1057+ state -> map = pci_p2pdma_map_type (p2p_pgmap -> mem , dev );
10161058}
10171059
10181060/**
0 commit comments