@@ -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,82 @@ 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 ;
254+
255+ p2p = rcu_dereference_protected (pdev -> p2pdma , 1 );
256+ if (p2p )
257+ /* PCI device was "rebound" to the driver */
258+ return & p2p -> mem ;
241259
242260 p2p = devm_kzalloc (& pdev -> dev , sizeof (* p2p ), GFP_KERNEL );
243261 if (!p2p )
244- return - ENOMEM ;
262+ return ERR_PTR ( - ENOMEM ) ;
245263
246264 xa_init (& p2p -> map_types );
265+ p2p -> mem .owner = & pdev -> dev ;
266+ /* On all p2p platforms bus_offset is the same for all BARs */
267+ p2p -> mem .bus_offset =
268+ pci_bus_address (pdev , 0 ) - pci_resource_start (pdev , 0 );
247269
248- p2p -> pool = gen_pool_create ( PAGE_SHIFT , dev_to_node ( & pdev -> dev ) );
249- if (! p2p -> pool )
250- goto out ;
270+ ret = devm_add_action_or_reset ( & pdev -> dev , pci_p2pdma_release , pdev );
271+ if (ret )
272+ goto out_p2p ;
251273
252- error = devm_add_action_or_reset (& pdev -> dev , pci_p2pdma_release , pdev );
253- if (error )
254- goto out_pool_destroy ;
274+ rcu_assign_pointer (pdev -> p2pdma , p2p );
275+ return & p2p -> mem ;
255276
256- error = sysfs_create_group (& pdev -> dev .kobj , & p2pmem_group );
257- if (error )
277+ out_p2p :
278+ devm_kfree (& pdev -> dev , p2p );
279+ return ERR_PTR (ret );
280+ }
281+ EXPORT_SYMBOL_GPL (pci_p2pdma_enable );
282+
283+ static int pci_p2pdma_setup_pool (struct pci_dev * pdev )
284+ {
285+ struct pci_p2pdma * p2pdma ;
286+ int ret ;
287+
288+ p2pdma = rcu_dereference_protected (pdev -> p2pdma , 1 );
289+ if (p2pdma -> pool )
290+ /* We already setup pools, do nothing, */
291+ return 0 ;
292+
293+ p2pdma -> pool = gen_pool_create (PAGE_SHIFT , dev_to_node (& pdev -> dev ));
294+ if (!p2pdma -> pool )
295+ return - ENOMEM ;
296+
297+ ret = sysfs_create_group (& pdev -> dev .kobj , & p2pmem_group );
298+ if (ret )
258299 goto out_pool_destroy ;
259300
260- rcu_assign_pointer (pdev -> p2pdma , p2p );
261301 return 0 ;
262302
263303out_pool_destroy :
264- gen_pool_destroy (p2p -> pool );
265- out :
266- devm_kfree (& pdev -> dev , p2p );
267- return error ;
304+ gen_pool_destroy (p2pdma -> pool );
305+ p2pdma -> pool = NULL ;
306+ return ret ;
268307}
269308
270309static void pci_p2pdma_unmap_mappings (void * data )
@@ -276,7 +315,7 @@ static void pci_p2pdma_unmap_mappings(void *data)
276315 * unmap_mapping_range() on the inode, teardown any existing userspace
277316 * mappings and prevent new ones from being created.
278317 */
279- sysfs_remove_file_from_group (& p2p_pgmap -> mem . owner -> kobj ,
318+ sysfs_remove_file_from_group (& p2p_pgmap -> mem -> owner -> kobj ,
280319 & p2pmem_alloc_attr .attr ,
281320 p2pmem_group .name );
282321}
@@ -295,6 +334,7 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
295334 u64 offset )
296335{
297336 struct pci_p2pdma_pagemap * p2p_pgmap ;
337+ struct p2pdma_provider * mem ;
298338 struct dev_pagemap * pgmap ;
299339 struct pci_p2pdma * p2pdma ;
300340 void * addr ;
@@ -312,25 +352,33 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
312352 if (size + offset > pci_resource_len (pdev , bar ))
313353 return - EINVAL ;
314354
315- if (!pdev -> p2pdma ) {
316- error = pci_p2pdma_setup (pdev );
355+ p2pdma = rcu_dereference_protected (pdev -> p2pdma , 1 );
356+ if (!p2pdma ) {
357+ mem = pci_p2pdma_enable (pdev );
358+ if (IS_ERR (mem ))
359+ return PTR_ERR (mem );
360+
361+ error = pci_p2pdma_setup_pool (pdev );
317362 if (error )
318363 return error ;
319- }
364+
365+ p2pdma = rcu_dereference_protected (pdev -> p2pdma , 1 );
366+ } else
367+ mem = & p2pdma -> mem ;
320368
321369 p2p_pgmap = devm_kzalloc (& pdev -> dev , sizeof (* p2p_pgmap ), GFP_KERNEL );
322- if (!p2p_pgmap )
323- return - ENOMEM ;
370+ if (!p2p_pgmap ) {
371+ error = - ENOMEM ;
372+ goto free_pool ;
373+ }
324374
325375 pgmap = & p2p_pgmap -> pgmap ;
326376 pgmap -> range .start = pci_resource_start (pdev , bar ) + offset ;
327377 pgmap -> range .end = pgmap -> range .start + size - 1 ;
328378 pgmap -> nr_range = 1 ;
329379 pgmap -> type = MEMORY_DEVICE_PCI_P2PDMA ;
330380 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 );
381+ p2p_pgmap -> mem = mem ;
334382
335383 addr = devm_memremap_pages (& pdev -> dev , pgmap );
336384 if (IS_ERR (addr )) {
@@ -343,7 +391,6 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
343391 if (error )
344392 goto pages_free ;
345393
346- p2pdma = rcu_dereference_protected (pdev -> p2pdma , 1 );
347394 error = gen_pool_add_owner (p2pdma -> pool , (unsigned long )addr ,
348395 pci_bus_address (pdev , bar ) + offset ,
349396 range_len (& pgmap -> range ), dev_to_node (& pdev -> dev ),
@@ -359,7 +406,10 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
359406pages_free :
360407 devm_memunmap_pages (& pdev -> dev , pgmap );
361408pgmap_free :
362- devm_kfree (& pdev -> dev , pgmap );
409+ devm_kfree (& pdev -> dev , p2p_pgmap );
410+ free_pool :
411+ sysfs_remove_group (& pdev -> dev .kobj , & p2pmem_group );
412+ gen_pool_destroy (p2pdma -> pool );
363413 return error ;
364414}
365415EXPORT_SYMBOL_GPL (pci_p2pdma_add_resource );
@@ -1008,11 +1058,11 @@ void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state,
10081058{
10091059 struct pci_p2pdma_pagemap * p2p_pgmap = to_p2p_pgmap (page_pgmap (page ));
10101060
1011- if (state -> mem == & p2p_pgmap -> mem )
1061+ if (state -> mem == p2p_pgmap -> mem )
10121062 return ;
10131063
1014- state -> mem = & p2p_pgmap -> mem ;
1015- state -> map = pci_p2pdma_map_type (& p2p_pgmap -> mem , dev );
1064+ state -> mem = p2p_pgmap -> mem ;
1065+ state -> map = pci_p2pdma_map_type (p2p_pgmap -> mem , dev );
10161066}
10171067
10181068/**
0 commit comments