mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 21:53:44 +00:00
of/address: Return an error when no valid dma-ranges are found
commitf6933c01e4
upstream. Commit7a8b64d17e
("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:7a8b64d17e
("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0a3e60b3fe
commit
ad7e46427f
@ -965,8 +965,19 @@ int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map)
|
||||
}
|
||||
|
||||
of_dma_range_parser_init(&parser, node);
|
||||
for_each_of_range(&parser, &range)
|
||||
for_each_of_range(&parser, &range) {
|
||||
if (range.cpu_addr == OF_BAD_ADDR) {
|
||||
pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n",
|
||||
range.bus_addr, node);
|
||||
continue;
|
||||
}
|
||||
num_ranges++;
|
||||
}
|
||||
|
||||
if (!num_ranges) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL);
|
||||
if (!r) {
|
||||
@ -975,18 +986,16 @@ int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map)
|
||||
}
|
||||
|
||||
/*
|
||||
* Record all info in the generic DMA ranges array for struct device.
|
||||
* Record all info in the generic DMA ranges array for struct device,
|
||||
* returning an error if we don't find any parsable ranges.
|
||||
*/
|
||||
*map = r;
|
||||
of_dma_range_parser_init(&parser, node);
|
||||
for_each_of_range(&parser, &range) {
|
||||
pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
|
||||
range.bus_addr, range.cpu_addr, range.size);
|
||||
if (range.cpu_addr == OF_BAD_ADDR) {
|
||||
pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n",
|
||||
range.bus_addr, node);
|
||||
if (range.cpu_addr == OF_BAD_ADDR)
|
||||
continue;
|
||||
}
|
||||
r->cpu_start = range.cpu_addr;
|
||||
r->dma_start = range.bus_addr;
|
||||
r->size = range.size;
|
||||
|
Loading…
Reference in New Issue
Block a user