diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-12-06 07:30:42 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-12-09 18:24:26 -0500 |
commit | 9f28cde0bc643186d32744ce69d12222e8588fe7 (patch) | |
tree | 708995a3df4183d75957b486c3994004e016459a /arch | |
parent | 11d4bb1bd067f9d01d18f620ccfad516dc579593 (diff) |
ARM: another fix for the DMA mapping checks
Peter reports that OMAP audio broke with the recent fix for these
checks, caused by OMAP audio using a 64-bit DMA mask. We should
allow 64-bit DMA masks even with 32-bit dma_addr_t if we can be sure
the amount of RAM we have won't allow the 32-bit dma_addr_t to
overflow. Unfortunately, the checks to detect overflow were not
correct.
Tested-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 91 |
1 files changed, 40 insertions, 51 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f6b6bfa88ecf..f61a5707823a 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -158,13 +158,49 @@ struct dma_map_ops arm_coherent_dma_ops = { | |||
158 | }; | 158 | }; |
159 | EXPORT_SYMBOL(arm_coherent_dma_ops); | 159 | EXPORT_SYMBOL(arm_coherent_dma_ops); |
160 | 160 | ||
161 | static int __dma_supported(struct device *dev, u64 mask, bool warn) | ||
162 | { | ||
163 | unsigned long max_dma_pfn; | ||
164 | |||
165 | /* | ||
166 | * If the mask allows for more memory than we can address, | ||
167 | * and we actually have that much memory, then we must | ||
168 | * indicate that DMA to this device is not supported. | ||
169 | */ | ||
170 | if (sizeof(mask) != sizeof(dma_addr_t) && | ||
171 | mask > (dma_addr_t)~0 && | ||
172 | dma_to_pfn(dev, ~0) < max_pfn) { | ||
173 | if (warn) { | ||
174 | dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n", | ||
175 | mask); | ||
176 | dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n"); | ||
177 | } | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | max_dma_pfn = min(max_pfn, arm_dma_pfn_limit); | ||
182 | |||
183 | /* | ||
184 | * Translate the device's DMA mask to a PFN limit. This | ||
185 | * PFN number includes the page which we can DMA to. | ||
186 | */ | ||
187 | if (dma_to_pfn(dev, mask) < max_dma_pfn) { | ||
188 | if (warn) | ||
189 | dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n", | ||
190 | mask, | ||
191 | dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1, | ||
192 | max_dma_pfn + 1); | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | return 1; | ||
197 | } | ||
198 | |||
161 | static u64 get_coherent_dma_mask(struct device *dev) | 199 | static u64 get_coherent_dma_mask(struct device *dev) |
162 | { | 200 | { |
163 | u64 mask = (u64)DMA_BIT_MASK(32); | 201 | u64 mask = (u64)DMA_BIT_MASK(32); |
164 | 202 | ||
165 | if (dev) { | 203 | if (dev) { |
166 | unsigned long max_dma_pfn; | ||
167 | |||
168 | mask = dev->coherent_dma_mask; | 204 | mask = dev->coherent_dma_mask; |
169 | 205 | ||
170 | /* | 206 | /* |
@@ -176,34 +212,8 @@ static u64 get_coherent_dma_mask(struct device *dev) | |||
176 | return 0; | 212 | return 0; |
177 | } | 213 | } |
178 | 214 | ||
179 | max_dma_pfn = min(max_pfn, arm_dma_pfn_limit); | 215 | if (!__dma_supported(dev, mask, true)) |
180 | |||
181 | /* | ||
182 | * If the mask allows for more memory than we can address, | ||
183 | * and we actually have that much memory, then fail the | ||
184 | * allocation. | ||
185 | */ | ||
186 | if (sizeof(mask) != sizeof(dma_addr_t) && | ||
187 | mask > (dma_addr_t)~0 && | ||
188 | dma_to_pfn(dev, ~0) > max_dma_pfn) { | ||
189 | dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n", | ||
190 | mask); | ||
191 | dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n"); | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Now check that the mask, when translated to a PFN, | ||
197 | * fits within the allowable addresses which we can | ||
198 | * allocate. | ||
199 | */ | ||
200 | if (dma_to_pfn(dev, mask) < max_dma_pfn) { | ||
201 | dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n", | ||
202 | mask, | ||
203 | dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1, | ||
204 | arm_dma_pfn_limit + 1); | ||
205 | return 0; | 216 | return 0; |
206 | } | ||
207 | } | 217 | } |
208 | 218 | ||
209 | return mask; | 219 | return mask; |
@@ -1032,28 +1042,7 @@ void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | |||
1032 | */ | 1042 | */ |
1033 | int dma_supported(struct device *dev, u64 mask) | 1043 | int dma_supported(struct device *dev, u64 mask) |
1034 | { | 1044 | { |
1035 | unsigned long limit; | 1045 | return __dma_supported(dev, mask, false); |
1036 | |||
1037 | /* | ||
1038 | * If the mask allows for more memory than we can address, | ||
1039 | * and we actually have that much memory, then we must | ||
1040 | * indicate that DMA to this device is not supported. | ||
1041 | */ | ||
1042 | if (sizeof(mask) != sizeof(dma_addr_t) && | ||
1043 | mask > (dma_addr_t)~0 && | ||
1044 | dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) | ||
1045 | return 0; | ||
1046 | |||
1047 | /* | ||
1048 | * Translate the device's DMA mask to a PFN limit. This | ||
1049 | * PFN number includes the page which we can DMA to. | ||
1050 | */ | ||
1051 | limit = dma_to_pfn(dev, mask); | ||
1052 | |||
1053 | if (limit < arm_dma_pfn_limit) | ||
1054 | return 0; | ||
1055 | |||
1056 | return 1; | ||
1057 | } | 1046 | } |
1058 | EXPORT_SYMBOL(dma_supported); | 1047 | EXPORT_SYMBOL(dma_supported); |
1059 | 1048 | ||