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
@@ -1188,35 +1188,43 @@ static int iommu_create_device_fw_mappings(struct iommu_domain *domain,
1188
1188
1189
1189
/* We need to consider overlapping regions for different devices */
1190
1190
list_for_each_entry(entry, &mappings, list) {
1191
-
dma_addr_tstart, end, addr;
1191
+
dma_addr_tstart, end, addr, iova;
1192
1192
size_tmap_size=0;
1193
1193
1194
1194
if (entry->type==IOMMU_RESV_DIRECT)
1195
1195
dev->iommu->require_direct=1;
1196
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1197
+
dev->iommu->require_translated=1;
1196
1198
1197
1199
if ((entry->type!=IOMMU_RESV_DIRECT&&
1198
-
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE) ||
1200
+
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE&&
1201
+
entry->type!=IOMMU_RESV_TRANSLATED) ||
1199
1202
!iommu_is_dma_domain(domain))
1200
1203
continue;
1201
1204
1202
1205
start=ALIGN(entry->start, pg_size);
1203
1206
end=ALIGN(entry->start+entry->length, pg_size);
1204
1207
1205
-
for (addr=start; addr <= end; addr+=pg_size) {
1208
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1209
+
iova=ALIGN(entry->dva, pg_size);
1210
+
else
1211
+
iova=start;
1212
+
1213
+
for (addr=start; addr <= end; addr+=pg_size, iova+=pg_size) {
1206
1214
phys_addr_tphys_addr;
1207
1215
1208
1216
if (addr==end)
1209
1217
goto map_end;
1210
1218
1211
-
phys_addr=iommu_iova_to_phys(domain, addr);
1219
+
phys_addr=iommu_iova_to_phys(domain, iova);
1212
1220
if (!phys_addr) {
1213
1221
map_size+=pg_size;
1214
1222
continue;
1215
1223
}
1216
1224
1217
1225
map_end:
1218
1226
if (map_size) {
1219
-
ret=iommu_map(domain, addr-map_size,
1227
+
ret=iommu_map(domain, iova-map_size,
1220
1228
addr-map_size, map_size,
1221
1229
entry->prot, GFP_KERNEL);
1222
1230
if (ret)
@@ -2319,6 +2327,19 @@ static int __iommu_device_set_domain(struct iommu_group *group,
2319
2327
"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");
2320
2328
return-EINVAL;
2321
2329
}
2330
+
/*
2331
+
* If the device requires IOMMU_RESV_TRANSLATED then we cannot allow
2332
+
* the identy or blocking domain to be attached as it does not contain
2333
+
* the required translated mapping.
2334
+
*/
2335
+
if (dev->iommu->require_translated&&
2336
+
(new_domain->type==IOMMU_DOMAIN_IDENTITY||
2337
+
new_domain->type==IOMMU_DOMAIN_BLOCKED||
2338
+
new_domain==group->blocking_domain)) {
2339
+
dev_warn(dev,
2340
+
"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