@@ -316,8 +316,18 @@ struct dmar_atsr_unit {
316
316
u8 include_all :1 ; /* include all ports */
317
317
};
318
318
319
+ struct dmar_satc_unit {
320
+ struct list_head list ; /* list of SATC units */
321
+ struct acpi_dmar_header * hdr ; /* ACPI header */
322
+ struct dmar_dev_scope * devices ; /* target devices */
323
+ struct intel_iommu * iommu ; /* the corresponding iommu */
324
+ int devices_cnt ; /* target device count */
325
+ u8 atc_required :1 ; /* ATS is required */
326
+ };
327
+
319
328
static LIST_HEAD (dmar_atsr_units );
320
329
static LIST_HEAD (dmar_rmrr_units );
330
+ static LIST_HEAD (dmar_satc_units );
321
331
322
332
#define for_each_rmrr_units (rmrr ) \
323
333
list_for_each_entry(rmrr, &dmar_rmrr_units, list)
@@ -3716,6 +3726,57 @@ int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3716
3726
return 0 ;
3717
3727
}
3718
3728
3729
+ static struct dmar_satc_unit * dmar_find_satc (struct acpi_dmar_satc * satc )
3730
+ {
3731
+ struct dmar_satc_unit * satcu ;
3732
+ struct acpi_dmar_satc * tmp ;
3733
+
3734
+ list_for_each_entry_rcu (satcu , & dmar_satc_units , list ,
3735
+ dmar_rcu_check ()) {
3736
+ tmp = (struct acpi_dmar_satc * )satcu -> hdr ;
3737
+ if (satc -> segment != tmp -> segment )
3738
+ continue ;
3739
+ if (satc -> header .length != tmp -> header .length )
3740
+ continue ;
3741
+ if (memcmp (satc , tmp , satc -> header .length ) == 0 )
3742
+ return satcu ;
3743
+ }
3744
+
3745
+ return NULL ;
3746
+ }
3747
+
3748
+ int dmar_parse_one_satc (struct acpi_dmar_header * hdr , void * arg )
3749
+ {
3750
+ struct acpi_dmar_satc * satc ;
3751
+ struct dmar_satc_unit * satcu ;
3752
+
3753
+ if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled )
3754
+ return 0 ;
3755
+
3756
+ satc = container_of (hdr , struct acpi_dmar_satc , header );
3757
+ satcu = dmar_find_satc (satc );
3758
+ if (satcu )
3759
+ return 0 ;
3760
+
3761
+ satcu = kzalloc (sizeof (* satcu ) + hdr -> length , GFP_KERNEL );
3762
+ if (!satcu )
3763
+ return - ENOMEM ;
3764
+
3765
+ satcu -> hdr = (void * )(satcu + 1 );
3766
+ memcpy (satcu -> hdr , hdr , hdr -> length );
3767
+ satcu -> atc_required = satc -> flags & 0x1 ;
3768
+ satcu -> devices = dmar_alloc_dev_scope ((void * )(satc + 1 ),
3769
+ (void * )satc + satc -> header .length ,
3770
+ & satcu -> devices_cnt );
3771
+ if (satcu -> devices_cnt && !satcu -> devices ) {
3772
+ kfree (satcu );
3773
+ return - ENOMEM ;
3774
+ }
3775
+ list_add_rcu (& satcu -> list , & dmar_satc_units );
3776
+
3777
+ return 0 ;
3778
+ }
3779
+
3719
3780
static int intel_iommu_add (struct dmar_drhd_unit * dmaru )
3720
3781
{
3721
3782
int sp , ret ;
@@ -3823,6 +3884,7 @@ static void intel_iommu_free_dmars(void)
3823
3884
{
3824
3885
struct dmar_rmrr_unit * rmrru , * rmrr_n ;
3825
3886
struct dmar_atsr_unit * atsru , * atsr_n ;
3887
+ struct dmar_satc_unit * satcu , * satc_n ;
3826
3888
3827
3889
list_for_each_entry_safe (rmrru , rmrr_n , & dmar_rmrr_units , list ) {
3828
3890
list_del (& rmrru -> list );
@@ -3834,6 +3896,11 @@ static void intel_iommu_free_dmars(void)
3834
3896
list_del (& atsru -> list );
3835
3897
intel_iommu_free_atsr (atsru );
3836
3898
}
3899
+ list_for_each_entry_safe (satcu , satc_n , & dmar_satc_units , list ) {
3900
+ list_del (& satcu -> list );
3901
+ dmar_free_dev_scope (& satcu -> devices , & satcu -> devices_cnt );
3902
+ kfree (satcu );
3903
+ }
3837
3904
}
3838
3905
3839
3906
int dmar_find_matched_atsr_unit (struct pci_dev * dev )
@@ -3885,8 +3952,10 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
3885
3952
int ret ;
3886
3953
struct dmar_rmrr_unit * rmrru ;
3887
3954
struct dmar_atsr_unit * atsru ;
3955
+ struct dmar_satc_unit * satcu ;
3888
3956
struct acpi_dmar_atsr * atsr ;
3889
3957
struct acpi_dmar_reserved_memory * rmrr ;
3958
+ struct acpi_dmar_satc * satc ;
3890
3959
3891
3960
if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING )
3892
3961
return 0 ;
@@ -3927,6 +3996,23 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
3927
3996
break ;
3928
3997
}
3929
3998
}
3999
+ list_for_each_entry (satcu , & dmar_satc_units , list ) {
4000
+ satc = container_of (satcu -> hdr , struct acpi_dmar_satc , header );
4001
+ if (info -> event == BUS_NOTIFY_ADD_DEVICE ) {
4002
+ ret = dmar_insert_dev_scope (info , (void * )(satc + 1 ),
4003
+ (void * )satc + satc -> header .length ,
4004
+ satc -> segment , satcu -> devices ,
4005
+ satcu -> devices_cnt );
4006
+ if (ret > 0 )
4007
+ break ;
4008
+ else if (ret < 0 )
4009
+ return ret ;
4010
+ } else if (info -> event == BUS_NOTIFY_REMOVED_DEVICE ) {
4011
+ if (dmar_remove_dev_scope (info , satc -> segment ,
4012
+ satcu -> devices , satcu -> devices_cnt ))
4013
+ break ;
4014
+ }
4015
+ }
3930
4016
3931
4017
return 0 ;
3932
4018
}
@@ -4270,6 +4356,9 @@ int __init intel_iommu_init(void)
4270
4356
if (list_empty (& dmar_atsr_units ))
4271
4357
pr_info ("No ATSR found\n" );
4272
4358
4359
+ if (list_empty (& dmar_satc_units ))
4360
+ pr_info ("No SATC found\n" );
4361
+
4273
4362
if (dmar_map_gfx )
4274
4363
intel_iommu_gfx_mapped = 1 ;
4275
4364
0 commit comments