Skip to content

Commit a1df829

Browse files
mfischerctmarinas
authored andcommitted
ACPI/IORT: Do not blindly trust DMA masks from firmware
Address issue observed on real world system with suboptimal IORT table where DMA masks of PCI devices would get set to 0 as result. iort_dma_setup() would query the root complex'/named component IORT entry for a DMA mask, and use that over the one the device has been configured with earlier. Ideally we want to use the minimum mask of what the IORT contains for the root complex and what the device was configured with. Fixes: 5ac65e8 ("ACPI/IORT: Support address size limit for root complexes") Signed-off-by: Moritz Fischer <[email protected]> Reviewed-by: Robin Murphy <[email protected]> Acked-by: Lorenzo Pieralisi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 519ea6f commit a1df829

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

drivers/acpi/arm64/iort.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,11 @@ static int nc_dma_get_range(struct device *dev, u64 *size)
11071107

11081108
ncomp = (struct acpi_iort_named_component *)node->node_data;
11091109

1110+
if (!ncomp->memory_address_limit) {
1111+
pr_warn(FW_BUG "Named component missing memory address limit\n");
1112+
return -EINVAL;
1113+
}
1114+
11101115
*size = ncomp->memory_address_limit >= 64 ? U64_MAX :
11111116
1ULL<<ncomp->memory_address_limit;
11121117

@@ -1126,6 +1131,11 @@ static int rc_dma_get_range(struct device *dev, u64 *size)
11261131

11271132
rc = (struct acpi_iort_root_complex *)node->node_data;
11281133

1134+
if (!rc->memory_address_limit) {
1135+
pr_warn(FW_BUG "Root complex missing memory address limit\n");
1136+
return -EINVAL;
1137+
}
1138+
11291139
*size = rc->memory_address_limit >= 64 ? U64_MAX :
11301140
1ULL<<rc->memory_address_limit;
11311141

@@ -1173,8 +1183,8 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
11731183
end = dmaaddr + size - 1;
11741184
mask = DMA_BIT_MASK(ilog2(end) + 1);
11751185
dev->bus_dma_limit = end;
1176-
dev->coherent_dma_mask = mask;
1177-
*dev->dma_mask = mask;
1186+
dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
1187+
*dev->dma_mask = min(*dev->dma_mask, mask);
11781188
}
11791189

11801190
*dma_addr = dmaaddr;

0 commit comments

Comments
 (0)