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
@@ -1147,35 +1147,43 @@ static int iommu_create_device_fw_mappings(struct iommu_domain *domain,
1147
1147
1148
1148
/* We need to consider overlapping regions for different devices */
1149
1149
list_for_each_entry(entry, &mappings, list) {
1150
-
dma_addr_tstart, end, addr;
1150
+
dma_addr_tstart, end, addr, iova;
1151
1151
size_tmap_size=0;
1152
1152
1153
1153
if (entry->type==IOMMU_RESV_DIRECT)
1154
1154
dev->iommu->require_direct=1;
1155
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1156
+
dev->iommu->require_translated=1;
1155
1157
1156
1158
if ((entry->type!=IOMMU_RESV_DIRECT&&
1157
-
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE) ||
1159
+
entry->type!=IOMMU_RESV_DIRECT_RELAXABLE&&
1160
+
entry->type!=IOMMU_RESV_TRANSLATED) ||
1158
1161
!iommu_is_dma_domain(domain))
1159
1162
continue;
1160
1163
1161
1164
start=ALIGN(entry->start, pg_size);
1162
1165
end=ALIGN(entry->start+entry->length, pg_size);
1163
1166
1164
-
for (addr=start; addr <= end; addr+=pg_size) {
1167
+
if (entry->type==IOMMU_RESV_TRANSLATED)
1168
+
iova=ALIGN(entry->dva, pg_size);
1169
+
else
1170
+
iova=start;
1171
+
1172
+
for (addr=start; addr <= end; addr+=pg_size, iova+=pg_size) {
1165
1173
phys_addr_tphys_addr;
1166
1174
1167
1175
if (addr==end)
1168
1176
goto map_end;
1169
1177
1170
-
phys_addr=iommu_iova_to_phys(domain, addr);
1178
+
phys_addr=iommu_iova_to_phys(domain, iova);
1171
1179
if (!phys_addr) {
1172
1180
map_size+=pg_size;
1173
1181
continue;
1174
1182
}
1175
1183
1176
1184
map_end:
1177
1185
if (map_size) {
1178
-
ret=iommu_map(domain, addr-map_size,
1186
+
ret=iommu_map(domain, iova-map_size,
1179
1187
addr-map_size, map_size,
1180
1188
entry->prot, GFP_KERNEL);
1181
1189
if (ret)
@@ -2284,6 +2292,19 @@ static int __iommu_device_set_domain(struct iommu_group *group,
2284
2292
"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");
2285
2293
return-EINVAL;
2286
2294
}
2295
+
/*
2296
+
* If the device requires IOMMU_RESV_TRANSLATED then we cannot allow
2297
+
* the identy or blocking domain to be attached as it does not contain
2298
+
* the required translated mapping.
2299
+
*/
2300
+
if (dev->iommu->require_translated&&
2301
+
(new_domain->type==IOMMU_DOMAIN_IDENTITY||
2302
+
new_domain->type==IOMMU_DOMAIN_BLOCKED||
2303
+
new_domain==group->blocking_domain)) {
2304
+
dev_warn(dev,
2305
+
"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