diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/include/asm/dma-mapping.h | 8 | ||||
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 51 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 12 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/vio.c | 3 |
5 files changed, 62 insertions, 14 deletions
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 5b579b951503..863cd84eb1a2 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -64,6 +64,7 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) | |||
64 | { | 64 | { |
65 | return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); | 65 | return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); |
66 | } | 66 | } |
67 | |||
67 | #else | 68 | #else |
68 | static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) | 69 | static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) |
69 | { | 70 | { |
@@ -86,6 +87,13 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) | |||
86 | } | 87 | } |
87 | #endif | 88 | #endif |
88 | 89 | ||
90 | /* The ARM override for dma_max_pfn() */ | ||
91 | static inline unsigned long dma_max_pfn(struct device *dev) | ||
92 | { | ||
93 | return PHYS_PFN_OFFSET + dma_to_pfn(dev, *dev->dma_mask); | ||
94 | } | ||
95 | #define dma_max_pfn(dev) dma_max_pfn(dev) | ||
96 | |||
89 | /* | 97 | /* |
90 | * DMA errors are defined by all-bits-set in the DMA address. | 98 | * DMA errors are defined by all-bits-set in the DMA address. |
91 | */ | 99 | */ |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 1272ed202dde..644d91f73b00 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -159,7 +159,7 @@ EXPORT_SYMBOL(arm_coherent_dma_ops); | |||
159 | 159 | ||
160 | static u64 get_coherent_dma_mask(struct device *dev) | 160 | static u64 get_coherent_dma_mask(struct device *dev) |
161 | { | 161 | { |
162 | u64 mask = (u64)arm_dma_limit; | 162 | u64 mask = (u64)DMA_BIT_MASK(32); |
163 | 163 | ||
164 | if (dev) { | 164 | if (dev) { |
165 | mask = dev->coherent_dma_mask; | 165 | mask = dev->coherent_dma_mask; |
@@ -173,10 +173,30 @@ static u64 get_coherent_dma_mask(struct device *dev) | |||
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | if ((~mask) & (u64)arm_dma_limit) { | 176 | /* |
177 | dev_warn(dev, "coherent DMA mask %#llx is smaller " | 177 | * If the mask allows for more memory than we can address, |
178 | "than system GFP_DMA mask %#llx\n", | 178 | * and we actually have that much memory, then fail the |
179 | mask, (u64)arm_dma_limit); | 179 | * allocation. |
180 | */ | ||
181 | if (sizeof(mask) != sizeof(dma_addr_t) && | ||
182 | mask > (dma_addr_t)~0 && | ||
183 | dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) { | ||
184 | dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n", | ||
185 | mask); | ||
186 | dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n"); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Now check that the mask, when translated to a PFN, | ||
192 | * fits within the allowable addresses which we can | ||
193 | * allocate. | ||
194 | */ | ||
195 | if (dma_to_pfn(dev, mask) < arm_dma_pfn_limit) { | ||
196 | 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", | ||
197 | mask, | ||
198 | dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1, | ||
199 | arm_dma_pfn_limit + 1); | ||
180 | return 0; | 200 | return 0; |
181 | } | 201 | } |
182 | } | 202 | } |
@@ -1007,8 +1027,27 @@ void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | |||
1007 | */ | 1027 | */ |
1008 | int dma_supported(struct device *dev, u64 mask) | 1028 | int dma_supported(struct device *dev, u64 mask) |
1009 | { | 1029 | { |
1010 | if (mask < (u64)arm_dma_limit) | 1030 | unsigned long limit; |
1031 | |||
1032 | /* | ||
1033 | * If the mask allows for more memory than we can address, | ||
1034 | * and we actually have that much memory, then we must | ||
1035 | * indicate that DMA to this device is not supported. | ||
1036 | */ | ||
1037 | if (sizeof(mask) != sizeof(dma_addr_t) && | ||
1038 | mask > (dma_addr_t)~0 && | ||
1039 | dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) | ||
1040 | return 0; | ||
1041 | |||
1042 | /* | ||
1043 | * Translate the device's DMA mask to a PFN limit. This | ||
1044 | * PFN number includes the page which we can DMA to. | ||
1045 | */ | ||
1046 | limit = dma_to_pfn(dev, mask); | ||
1047 | |||
1048 | if (limit < arm_dma_pfn_limit) | ||
1011 | return 0; | 1049 | return 0; |
1050 | |||
1012 | return 1; | 1051 | return 1; |
1013 | } | 1052 | } |
1014 | EXPORT_SYMBOL(dma_supported); | 1053 | EXPORT_SYMBOL(dma_supported); |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index ca907f805c57..3e8f106ee5fe 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -209,6 +209,7 @@ EXPORT_SYMBOL(arm_dma_zone_size); | |||
209 | * so a successful GFP_DMA allocation will always satisfy this. | 209 | * so a successful GFP_DMA allocation will always satisfy this. |
210 | */ | 210 | */ |
211 | phys_addr_t arm_dma_limit; | 211 | phys_addr_t arm_dma_limit; |
212 | unsigned long arm_dma_pfn_limit; | ||
212 | 213 | ||
213 | static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole, | 214 | static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole, |
214 | unsigned long dma_size) | 215 | unsigned long dma_size) |
@@ -231,6 +232,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc) | |||
231 | arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1; | 232 | arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1; |
232 | } else | 233 | } else |
233 | arm_dma_limit = 0xffffffff; | 234 | arm_dma_limit = 0xffffffff; |
235 | arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT; | ||
234 | #endif | 236 | #endif |
235 | } | 237 | } |
236 | 238 | ||
@@ -418,12 +420,10 @@ void __init bootmem_init(void) | |||
418 | * This doesn't seem to be used by the Linux memory manager any | 420 | * This doesn't seem to be used by the Linux memory manager any |
419 | * more, but is used by ll_rw_block. If we can get rid of it, we | 421 | * more, but is used by ll_rw_block. If we can get rid of it, we |
420 | * also get rid of some of the stuff above as well. | 422 | * also get rid of some of the stuff above as well. |
421 | * | ||
422 | * Note: max_low_pfn and max_pfn reflect the number of _pages_ in | ||
423 | * the system, not the maximum PFN. | ||
424 | */ | 423 | */ |
425 | max_low_pfn = max_low - PHYS_PFN_OFFSET; | 424 | min_low_pfn = min; |
426 | max_pfn = max_high - PHYS_PFN_OFFSET; | 425 | max_low_pfn = max_low; |
426 | max_pfn = max_high; | ||
427 | } | 427 | } |
428 | 428 | ||
429 | /* | 429 | /* |
@@ -529,7 +529,7 @@ static inline void free_area_high(unsigned long pfn, unsigned long end) | |||
529 | static void __init free_highpages(void) | 529 | static void __init free_highpages(void) |
530 | { | 530 | { |
531 | #ifdef CONFIG_HIGHMEM | 531 | #ifdef CONFIG_HIGHMEM |
532 | unsigned long max_low = max_low_pfn + PHYS_PFN_OFFSET; | 532 | unsigned long max_low = max_low_pfn; |
533 | struct memblock_region *mem, *res; | 533 | struct memblock_region *mem, *res; |
534 | 534 | ||
535 | /* set highmem page free */ | 535 | /* set highmem page free */ |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index d5a4e9ad8f0f..d5a982d15a88 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -81,8 +81,10 @@ extern __init void add_static_vm_early(struct static_vm *svm); | |||
81 | 81 | ||
82 | #ifdef CONFIG_ZONE_DMA | 82 | #ifdef CONFIG_ZONE_DMA |
83 | extern phys_addr_t arm_dma_limit; | 83 | extern phys_addr_t arm_dma_limit; |
84 | extern unsigned long arm_dma_pfn_limit; | ||
84 | #else | 85 | #else |
85 | #define arm_dma_limit ((phys_addr_t)~0) | 86 | #define arm_dma_limit ((phys_addr_t)~0) |
87 | #define arm_dma_pfn_limit (~0ul >> PAGE_SHIFT) | ||
86 | #endif | 88 | #endif |
87 | 89 | ||
88 | extern phys_addr_t arm_lowmem_limit; | 90 | extern phys_addr_t arm_lowmem_limit; |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index f99cefbd84e3..e7d0c88f621a 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -1419,8 +1419,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1419 | 1419 | ||
1420 | /* needed to ensure proper operation of coherent allocations | 1420 | /* needed to ensure proper operation of coherent allocations |
1421 | * later, in case driver doesn't set it explicitly */ | 1421 | * later, in case driver doesn't set it explicitly */ |
1422 | dma_set_mask(&viodev->dev, DMA_BIT_MASK(64)); | 1422 | dma_set_mask_and_coherent(&viodev->dev, DMA_BIT_MASK(64)); |
1423 | dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1424 | } | 1423 | } |
1425 | 1424 | ||
1426 | /* register with generic device framework */ | 1425 | /* register with generic device framework */ |