@@ -19,7 +19,7 @@ MODULE_PARM_DESC(
19
19
20
20
struct iommufd_attach {
21
21
struct iommufd_hw_pagetable * hwpt ;
22
- struct list_head device_list ;
22
+ struct xarray device_array ;
23
23
};
24
24
25
25
static void iommufd_group_release (struct kref * kref )
@@ -297,6 +297,20 @@ u32 iommufd_device_to_id(struct iommufd_device *idev)
297
297
}
298
298
EXPORT_SYMBOL_NS_GPL (iommufd_device_to_id , "IOMMUFD" );
299
299
300
+ static unsigned int iommufd_group_device_num (struct iommufd_group * igroup )
301
+ {
302
+ struct iommufd_device * idev ;
303
+ unsigned int count = 0 ;
304
+ unsigned long index ;
305
+
306
+ lockdep_assert_held (& igroup -> lock );
307
+
308
+ if (igroup -> attach )
309
+ xa_for_each (& igroup -> attach -> device_array , index , idev )
310
+ count ++ ;
311
+ return count ;
312
+ }
313
+
300
314
#ifdef CONFIG_IRQ_MSI_IOMMU
301
315
static int iommufd_group_setup_msi (struct iommufd_group * igroup ,
302
316
struct iommufd_hwpt_paging * hwpt_paging )
@@ -371,12 +385,7 @@ iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
371
385
/* Check if idev is attached to igroup->hwpt */
372
386
static bool iommufd_device_is_attached (struct iommufd_device * idev )
373
387
{
374
- struct iommufd_device * cur ;
375
-
376
- list_for_each_entry (cur , & idev -> igroup -> attach -> device_list , group_item )
377
- if (cur == idev )
378
- return true;
379
- return false;
388
+ return xa_load (& idev -> igroup -> attach -> device_array , idev -> obj .id );
380
389
}
381
390
382
391
static int iommufd_hwpt_attach_device (struct iommufd_hw_pagetable * hwpt ,
@@ -510,20 +519,27 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
510
519
rc = - ENOMEM ;
511
520
goto err_unlock ;
512
521
}
513
- INIT_LIST_HEAD (& attach -> device_list );
522
+ xa_init (& attach -> device_array );
514
523
}
515
524
516
525
old_hwpt = attach -> hwpt ;
517
526
527
+ rc = xa_insert (& attach -> device_array , idev -> obj .id , XA_ZERO_ENTRY ,
528
+ GFP_KERNEL );
529
+ if (rc ) {
530
+ WARN_ON (rc == - EBUSY && !old_hwpt );
531
+ goto err_free_attach ;
532
+ }
533
+
518
534
if (old_hwpt && old_hwpt != hwpt ) {
519
535
rc = - EINVAL ;
520
- goto err_free_attach ;
536
+ goto err_release_devid ;
521
537
}
522
538
523
539
if (attach_resv ) {
524
540
rc = iommufd_device_attach_reserved_iova (idev , hwpt_paging );
525
541
if (rc )
526
- goto err_free_attach ;
542
+ goto err_release_devid ;
527
543
}
528
544
529
545
/*
@@ -541,12 +557,15 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
541
557
igroup -> attach = attach ;
542
558
}
543
559
refcount_inc (& hwpt -> obj .users );
544
- list_add_tail (& idev -> group_item , & attach -> device_list );
560
+ WARN_ON (xa_is_err (xa_store (& attach -> device_array , idev -> obj .id ,
561
+ idev , GFP_KERNEL )));
545
562
mutex_unlock (& igroup -> lock );
546
563
return 0 ;
547
564
err_unresv :
548
565
if (attach_resv )
549
566
iopt_remove_reserved_iova (& hwpt_paging -> ioas -> iopt , idev -> dev );
567
+ err_release_devid :
568
+ xa_release (& attach -> device_array , idev -> obj .id );
550
569
err_free_attach :
551
570
if (iommufd_group_first_attach (igroup , pasid ))
552
571
kfree (attach );
@@ -568,8 +587,8 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev, ioasid_t pasid)
568
587
hwpt = attach -> hwpt ;
569
588
hwpt_paging = find_hwpt_paging (hwpt );
570
589
571
- list_del ( & idev -> group_item );
572
- if (list_empty (& attach -> device_list )) {
590
+ xa_erase ( & attach -> device_array , idev -> obj . id );
591
+ if (xa_empty (& attach -> device_array )) {
573
592
iommufd_hwpt_detach_device (hwpt , idev , pasid );
574
593
igroup -> attach = NULL ;
575
594
kfree (attach );
@@ -599,10 +618,11 @@ iommufd_group_remove_reserved_iova(struct iommufd_group *igroup,
599
618
struct iommufd_hwpt_paging * hwpt_paging )
600
619
{
601
620
struct iommufd_device * cur ;
621
+ unsigned long index ;
602
622
603
623
lockdep_assert_held (& igroup -> lock );
604
624
605
- list_for_each_entry ( cur , & igroup -> attach -> device_list , group_item )
625
+ xa_for_each ( & igroup -> attach -> device_array , index , cur )
606
626
iopt_remove_reserved_iova (& hwpt_paging -> ioas -> iopt , cur -> dev );
607
627
}
608
628
@@ -612,14 +632,14 @@ iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup,
612
632
{
613
633
struct iommufd_hwpt_paging * old_hwpt_paging ;
614
634
struct iommufd_device * cur ;
635
+ unsigned long index ;
615
636
int rc ;
616
637
617
638
lockdep_assert_held (& igroup -> lock );
618
639
619
640
old_hwpt_paging = find_hwpt_paging (igroup -> attach -> hwpt );
620
641
if (!old_hwpt_paging || hwpt_paging -> ioas != old_hwpt_paging -> ioas ) {
621
- list_for_each_entry (cur ,
622
- & igroup -> attach -> device_list , group_item ) {
642
+ xa_for_each (& igroup -> attach -> device_array , index , cur ) {
623
643
rc = iopt_table_enforce_dev_resv_regions (
624
644
& hwpt_paging -> ioas -> iopt , cur -> dev , NULL );
625
645
if (rc )
@@ -660,7 +680,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
660
680
661
681
old_hwpt = attach -> hwpt ;
662
682
663
- WARN_ON (!old_hwpt || list_empty (& attach -> device_list ));
683
+ WARN_ON (!old_hwpt || xa_empty (& attach -> device_array ));
664
684
665
685
if (!iommufd_device_is_attached (idev )) {
666
686
rc = - EINVAL ;
@@ -689,9 +709,9 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
689
709
690
710
attach -> hwpt = hwpt ;
691
711
692
- num_devices = list_count_nodes ( & attach -> device_list );
712
+ num_devices = iommufd_group_device_num ( igroup );
693
713
/*
694
- * Move the refcounts held by the device_list to the new hwpt. Retain a
714
+ * Move the refcounts held by the device_array to the new hwpt. Retain a
695
715
* refcount for this thread as the caller will free it.
696
716
*/
697
717
refcount_add (num_devices , & hwpt -> obj .users );
0 commit comments