aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-12-06 07:30:42 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-12-09 18:24:26 -0500
commit9f28cde0bc643186d32744ce69d12222e8588fe7 (patch)
tree708995a3df4183d75957b486c3994004e016459a /arch
parent11d4bb1bd067f9d01d18f620ccfad516dc579593 (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.c91
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};
159EXPORT_SYMBOL(arm_coherent_dma_ops); 159EXPORT_SYMBOL(arm_coherent_dma_ops);
160 160
161static 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
161static u64 get_coherent_dma_mask(struct device *dev) 199static 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 */
1033int dma_supported(struct device *dev, u64 mask) 1043int 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}
1058EXPORT_SYMBOL(dma_supported); 1047EXPORT_SYMBOL(dma_supported);
1059 1048