@@ -174,8 +174,8 @@ bool amd_iommu_snp_en;
174174EXPORT_SYMBOL (amd_iommu_snp_en );
175175
176176LIST_HEAD (amd_iommu_pci_seg_list ); /* list of all PCI segments */
177- LIST_HEAD (amd_iommu_list ); /* list of all AMD IOMMUs in the
178- system */
177+ LIST_HEAD (amd_iommu_list ); /* list of all AMD IOMMUs in the system */
178+ LIST_HEAD ( amd_ivhd_dev_flags_list ); /* list of all IVHD device entry settings */
179179
180180/* Number of IOMMUs present in the system */
181181static int amd_iommus_present ;
@@ -984,6 +984,14 @@ static void iommu_enable_gt(struct amd_iommu *iommu)
984984}
985985
986986/* sets a specific bit in the device table entry. */
987+ static void set_dte_bit (struct dev_table_entry * dte , u8 bit )
988+ {
989+ int i = (bit >> 6 ) & 0x03 ;
990+ int _bit = bit & 0x3f ;
991+
992+ dte -> data [i ] |= (1UL << _bit );
993+ }
994+
987995static void __set_dev_entry_bit (struct dev_table_entry * dev_table ,
988996 u16 devid , u8 bit )
989997{
@@ -1136,6 +1144,19 @@ static bool copy_device_table(void)
11361144 return true;
11371145}
11381146
1147+ static bool search_ivhd_dte_flags (u16 segid , u16 first , u16 last )
1148+ {
1149+ struct ivhd_dte_flags * e ;
1150+
1151+ for_each_ivhd_dte_flags (e ) {
1152+ if ((e -> segid == segid ) &&
1153+ (e -> devid_first == first ) &&
1154+ (e -> devid_last == last ))
1155+ return true;
1156+ }
1157+ return false;
1158+ }
1159+
11391160void amd_iommu_apply_erratum_63 (struct amd_iommu * iommu , u16 devid )
11401161{
11411162 int sysmgt ;
@@ -1151,27 +1172,66 @@ void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid)
11511172 * This function takes the device specific flags read from the ACPI
11521173 * table and sets up the device table entry with that information
11531174 */
1154- static void __init set_dev_entry_from_acpi (struct amd_iommu * iommu ,
1155- u16 devid , u32 flags , u32 ext_flags )
1175+ static void __init
1176+ set_dev_entry_from_acpi_range (struct amd_iommu * iommu , u16 first , u16 last ,
1177+ u32 flags , u32 ext_flags )
11561178{
1157- if (flags & ACPI_DEVFLAG_INITPASS )
1158- set_dev_entry_bit (iommu , devid , DEV_ENTRY_INIT_PASS );
1159- if (flags & ACPI_DEVFLAG_EXTINT )
1160- set_dev_entry_bit (iommu , devid , DEV_ENTRY_EINT_PASS );
1161- if (flags & ACPI_DEVFLAG_NMI )
1162- set_dev_entry_bit (iommu , devid , DEV_ENTRY_NMI_PASS );
1163- if (flags & ACPI_DEVFLAG_SYSMGT1 )
1164- set_dev_entry_bit (iommu , devid , DEV_ENTRY_SYSMGT1 );
1165- if (flags & ACPI_DEVFLAG_SYSMGT2 )
1166- set_dev_entry_bit (iommu , devid , DEV_ENTRY_SYSMGT2 );
1167- if (flags & ACPI_DEVFLAG_LINT0 )
1168- set_dev_entry_bit (iommu , devid , DEV_ENTRY_LINT0_PASS );
1169- if (flags & ACPI_DEVFLAG_LINT1 )
1170- set_dev_entry_bit (iommu , devid , DEV_ENTRY_LINT1_PASS );
1179+ int i ;
1180+ struct dev_table_entry dte = {};
1181+
1182+ /* Parse IVHD DTE setting flags and store information */
1183+ if (flags ) {
1184+ struct ivhd_dte_flags * d ;
11711185
1172- amd_iommu_apply_erratum_63 (iommu , devid );
1186+ if (search_ivhd_dte_flags (iommu -> pci_seg -> id , first , last ))
1187+ return ;
11731188
1174- amd_iommu_set_rlookup_table (iommu , devid );
1189+ d = kzalloc (sizeof (struct ivhd_dte_flags ), GFP_KERNEL );
1190+ if (!d )
1191+ return ;
1192+
1193+ pr_debug ("%s: devid range %#x:%#x\n" , __func__ , first , last );
1194+
1195+ if (flags & ACPI_DEVFLAG_INITPASS )
1196+ set_dte_bit (& dte , DEV_ENTRY_INIT_PASS );
1197+ if (flags & ACPI_DEVFLAG_EXTINT )
1198+ set_dte_bit (& dte , DEV_ENTRY_EINT_PASS );
1199+ if (flags & ACPI_DEVFLAG_NMI )
1200+ set_dte_bit (& dte , DEV_ENTRY_NMI_PASS );
1201+ if (flags & ACPI_DEVFLAG_SYSMGT1 )
1202+ set_dte_bit (& dte , DEV_ENTRY_SYSMGT1 );
1203+ if (flags & ACPI_DEVFLAG_SYSMGT2 )
1204+ set_dte_bit (& dte , DEV_ENTRY_SYSMGT2 );
1205+ if (flags & ACPI_DEVFLAG_LINT0 )
1206+ set_dte_bit (& dte , DEV_ENTRY_LINT0_PASS );
1207+ if (flags & ACPI_DEVFLAG_LINT1 )
1208+ set_dte_bit (& dte , DEV_ENTRY_LINT1_PASS );
1209+
1210+ /* Apply erratum 63, which needs info in initial_dte */
1211+ if (FIELD_GET (DTE_DATA1_SYSMGT_MASK , dte .data [1 ]) == 0x1 )
1212+ dte .data [0 ] |= DTE_FLAG_IW ;
1213+
1214+ memcpy (& d -> dte , & dte , sizeof (dte ));
1215+ d -> segid = iommu -> pci_seg -> id ;
1216+ d -> devid_first = first ;
1217+ d -> devid_last = last ;
1218+ list_add_tail (& d -> list , & amd_ivhd_dev_flags_list );
1219+ }
1220+
1221+ for (i = first ; i <= last ; i ++ ) {
1222+ if (flags ) {
1223+ struct dev_table_entry * dev_table = get_dev_table (iommu );
1224+
1225+ memcpy (& dev_table [i ], & dte , sizeof (dte ));
1226+ }
1227+ amd_iommu_set_rlookup_table (iommu , i );
1228+ }
1229+ }
1230+
1231+ static void __init set_dev_entry_from_acpi (struct amd_iommu * iommu ,
1232+ u16 devid , u32 flags , u32 ext_flags )
1233+ {
1234+ set_dev_entry_from_acpi_range (iommu , devid , devid , flags , ext_flags );
11751235}
11761236
11771237int __init add_special_device (u8 type , u8 id , u32 * devid , bool cmd_line )
@@ -1332,9 +1392,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
13321392 case IVHD_DEV_ALL :
13331393
13341394 DUMP_printk (" DEV_ALL\t\t\tsetting: %#02x\n" , e -> flags );
1335-
1336- for (dev_i = 0 ; dev_i <= pci_seg -> last_bdf ; ++ dev_i )
1337- set_dev_entry_from_acpi (iommu , dev_i , e -> flags , 0 );
1395+ set_dev_entry_from_acpi_range (iommu , 0 , pci_seg -> last_bdf , e -> flags , 0 );
13381396 break ;
13391397 case IVHD_DEV_SELECT :
13401398
@@ -1428,14 +1486,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
14281486
14291487 devid = e -> devid ;
14301488 for (dev_i = devid_start ; dev_i <= devid ; ++ dev_i ) {
1431- if (alias ) {
1489+ if (alias )
14321490 pci_seg -> alias_table [dev_i ] = devid_to ;
1433- set_dev_entry_from_acpi (iommu ,
1434- devid_to , flags , ext_flags );
1435- }
1436- set_dev_entry_from_acpi (iommu , dev_i ,
1437- flags , ext_flags );
14381491 }
1492+ set_dev_entry_from_acpi_range (iommu , devid_start , devid , flags , ext_flags );
1493+ set_dev_entry_from_acpi (iommu , devid_to , flags , ext_flags );
14391494 break ;
14401495 case IVHD_DEV_SPECIAL : {
14411496 u8 handle , type ;
0 commit comments