You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: drivers/iommu/iommu.c
+26-5Lines changed: 26 additions & 5 deletions
Original file line number
Diff line number
Diff line change
@@ -1109,35 +1109,43 @@ static int iommu_create_device_fw_mappings(struct iommu_domain *domain,
1109
1109
1110
1110
/* We need to consider overlapping regions for different devices */
1111
1111
list_for_each_entry(entry, &mappings, list) {
1112
-
dma_addr_tstart, end, addr;
1112
+
dma_addr_tstart, end, addr, iova;
1113
1113
size_tmap_size=0;
1114
1114
1115
1115
if (entry->type==IOMMU_RESV_DIRECT)
1116
1116
dev->iommu->require_direct=1;
1117
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1118
+
dev->iommu->require_translated=1;
1117
1119
1118
1120
if ((entry->type!=IOMMU_RESV_DIRECT&&
1119
-
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE) ||
1121
+
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE&&
1122
+
entry->type!=IOMMU_RESV_TRANSLATED) ||
1120
1123
!iommu_is_dma_domain(domain))
1121
1124
continue;
1122
1125
1123
1126
start=ALIGN(entry->start, pg_size);
1124
1127
end=ALIGN(entry->start+entry->length, pg_size);
1125
1128
1126
-
for (addr=start; addr <= end; addr+=pg_size) {
1129
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1130
+
iova=ALIGN(entry->dva, pg_size);
1131
+
else
1132
+
iova=start;
1133
+
1134
+
for (addr=start; addr <= end; addr+=pg_size, iova+=pg_size) {
1127
1135
phys_addr_tphys_addr;
1128
1136
1129
1137
if (addr==end)
1130
1138
goto map_end;
1131
1139
1132
-
phys_addr=iommu_iova_to_phys(domain, addr);
1140
+
phys_addr=iommu_iova_to_phys(domain, iova);
1133
1141
if (!phys_addr) {
1134
1142
map_size+=pg_size;
1135
1143
continue;
1136
1144
}
1137
1145
1138
1146
map_end:
1139
1147
if (map_size) {
1140
-
ret=iommu_map(domain, addr-map_size,
1148
+
ret=iommu_map(domain, iova-map_size,
1141
1149
addr-map_size, map_size,
1142
1150
entry->prot, GFP_KERNEL);
1143
1151
if (ret)
@@ -2235,6 +2243,19 @@ static int __iommu_device_set_domain(struct iommu_group *group,
2235
2243
"Firmware has requested this device have a 1:1 IOMMU mapping, rejecting configuring the device without a 1:1 mapping. Contact your platform vendor.\n");
2236
2244
return-EINVAL;
2237
2245
}
2246
+
/*
2247
+
* If the device requires IOMMU_RESV_TRANSLATED then we cannot allow
2248
+
* the identy or blocking domain to be attached as it does not contain
2249
+
* the required translated mapping.
2250
+
*/
2251
+
if (dev->iommu->require_translated&&
2252
+
(new_domain->type==IOMMU_DOMAIN_IDENTITY||
2253
+
new_domain->type==IOMMU_DOMAIN_BLOCKED||
2254
+
new_domain==group->blocking_domain)) {
2255
+
dev_warn(dev,
2256
+
"Firmware has requested this device have a translated IOMMU mapping, rejecting configuring the device without a translated mapping. Contact your platform vendor.\n");
0 commit comments