Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

of/address: Return an error when no valid dma-ranges are found

Commit 7a8b64d17e35 ("of/address: use range parser for of_dma_get_range")
converted the parsing of dma-range properties to use code shared with the
PCI range parser. The intent was to introduce no functional changes however
in the case where we fail to translate the first resource instead of
returning -EINVAL the new code we return 0. Restore the previous behaviour
by returning an error if we find no valid ranges, the original code only
handled the first range but subsequently support for parsing all supplied
ranges was added.

This avoids confusing code using the parsed ranges which doesn't expect to
successfully parse ranges but have only a list terminator returned, this
fixes breakage with so far as I can tell all DMA for on SoC devices on the
Socionext Synquacer platform which has a firmware supplied DT. A bisect
identified the original conversion as triggering the issues there.

Fixes: 7a8b64d17e35 ("of/address: use range parser for of_dma_get_range")
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: Luca Di Stefano <luca.distefano@linaro.org>
Cc: 993612@bugs.debian.org
Cc: stable@kernel.org
Link: https://lore.kernel.org/r/20230126-synquacer-boot-v2-1-cb80fd23c4e2@kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>

authored by

Mark Brown and committed by
Rob Herring
f6933c01 241d2fb5

+15 -6
+15 -6
drivers/of/address.c
··· 965 965 } 966 966 967 967 of_dma_range_parser_init(&parser, node); 968 - for_each_of_range(&parser, &range) 968 + for_each_of_range(&parser, &range) { 969 + if (range.cpu_addr == OF_BAD_ADDR) { 970 + pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n", 971 + range.bus_addr, node); 972 + continue; 973 + } 969 974 num_ranges++; 975 + } 976 + 977 + if (!num_ranges) { 978 + ret = -EINVAL; 979 + goto out; 980 + } 970 981 971 982 r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL); 972 983 if (!r) { ··· 986 975 } 987 976 988 977 /* 989 - * Record all info in the generic DMA ranges array for struct device. 978 + * Record all info in the generic DMA ranges array for struct device, 979 + * returning an error if we don't find any parsable ranges. 990 980 */ 991 981 *map = r; 992 982 of_dma_range_parser_init(&parser, node); 993 983 for_each_of_range(&parser, &range) { 994 984 pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", 995 985 range.bus_addr, range.cpu_addr, range.size); 996 - if (range.cpu_addr == OF_BAD_ADDR) { 997 - pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n", 998 - range.bus_addr, node); 986 + if (range.cpu_addr == OF_BAD_ADDR) 999 987 continue; 1000 - } 1001 988 r->cpu_start = range.cpu_addr; 1002 989 r->dma_start = range.bus_addr; 1003 990 r->size = range.size;