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
@@ -1173,35 +1173,43 @@ static int iommu_create_device_fw_mappings(struct iommu_domain *domain,
1173
1173
1174
1174
/* We need to consider overlapping regions for different devices */
1175
1175
list_for_each_entry(entry, &mappings, list) {
1176
-
dma_addr_tstart, end, addr;
1176
+
dma_addr_tstart, end, addr, iova;
1177
1177
size_tmap_size=0;
1178
1178
1179
1179
if (entry->type==IOMMU_RESV_DIRECT)
1180
1180
dev->iommu->require_direct=1;
1181
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1182
+
dev->iommu->require_translated=1;
1181
1183
1182
1184
if ((entry->type!=IOMMU_RESV_DIRECT&&
1183
-
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE) ||
1185
+
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE&&
1186
+
entry->type!=IOMMU_RESV_TRANSLATED) ||
1184
1187
!iommu_is_dma_domain(domain))
1185
1188
continue;
1186
1189
1187
1190
start=ALIGN(entry->start, pg_size);
1188
1191
end=ALIGN(entry->start+entry->length, pg_size);
1189
1192
1190
-
for (addr=start; addr <= end; addr+=pg_size) {
1193
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1194
+
iova=ALIGN(entry->dva, pg_size);
1195
+
else
1196
+
iova=start;
1197
+
1198
+
for (addr=start; addr <= end; addr+=pg_size, iova+=pg_size) {
1191
1199
phys_addr_tphys_addr;
1192
1200
1193
1201
if (addr==end)
1194
1202
goto map_end;
1195
1203
1196
-
phys_addr=iommu_iova_to_phys(domain, addr);
1204
+
phys_addr=iommu_iova_to_phys(domain, iova);
1197
1205
if (!phys_addr) {
1198
1206
map_size+=pg_size;
1199
1207
continue;
1200
1208
}
1201
1209
1202
1210
map_end:
1203
1211
if (map_size) {
1204
-
ret=iommu_map(domain, addr-map_size,
1212
+
ret=iommu_map(domain, iova-map_size,
1205
1213
addr-map_size, map_size,
1206
1214
entry->prot, GFP_KERNEL);
1207
1215
if (ret)
@@ -2303,6 +2311,19 @@ static int __iommu_device_set_domain(struct iommu_group *group,
2303
2311
"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");
2304
2312
return-EINVAL;
2305
2313
}
2314
+
/*
2315
+
* If the device requires IOMMU_RESV_TRANSLATED then we cannot allow
2316
+
* the identy or blocking domain to be attached as it does not contain
2317
+
* the required translated mapping.
2318
+
*/
2319
+
if (dev->iommu->require_translated&&
2320
+
(new_domain->type==IOMMU_DOMAIN_IDENTITY||
2321
+
new_domain->type==IOMMU_DOMAIN_BLOCKED||
2322
+
new_domain==group->blocking_domain)) {
2323
+
dev_warn(dev,
2324
+
"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