1 | // SPDX-License-Identifier: GPL-2.0-only |
---|---|
2 | #include <linux/acpi.h> |
3 | #include <linux/acpi_iort.h> |
4 | #include <linux/device.h> |
5 | #include <linux/dma-direct.h> |
6 | |
7 | void acpi_arch_dma_setup(struct device *dev) |
8 | { |
9 | int ret; |
10 | u64 end, mask; |
11 | u64 size = 0; |
12 | const struct bus_dma_region *map = NULL; |
13 | |
14 | /* |
15 | * If @dev is expected to be DMA-capable then the bus code that created |
16 | * it should have initialised its dma_mask pointer by this point. For |
17 | * now, we'll continue the legacy behaviour of coercing it to the |
18 | * coherent mask if not, but we'll no longer do so quietly. |
19 | */ |
20 | if (!dev->dma_mask) { |
21 | dev_warn(dev, "DMA mask not set\n"); |
22 | dev->dma_mask = &dev->coherent_dma_mask; |
23 | } |
24 | |
25 | if (dev->coherent_dma_mask) |
26 | size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); |
27 | else |
28 | size = 1ULL << 32; |
29 | |
30 | ret = acpi_dma_get_range(dev, map: &map); |
31 | if (!ret && map) { |
32 | const struct bus_dma_region *r = map; |
33 | |
34 | for (end = 0; r->size; r++) { |
35 | if (r->dma_start + r->size - 1 > end) |
36 | end = r->dma_start + r->size - 1; |
37 | } |
38 | |
39 | size = end + 1; |
40 | dev->dma_range_map = map; |
41 | } |
42 | |
43 | if (ret == -ENODEV) |
44 | ret = iort_dma_get_ranges(dev, size: &size); |
45 | if (!ret) { |
46 | /* |
47 | * Limit coherent and dma mask based on size retrieved from |
48 | * firmware. |
49 | */ |
50 | end = size - 1; |
51 | mask = DMA_BIT_MASK(ilog2(end) + 1); |
52 | dev->bus_dma_limit = end; |
53 | dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask); |
54 | *dev->dma_mask = min(*dev->dma_mask, mask); |
55 | } |
56 | } |
57 |