diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2008-09-18 09:54:23 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-19 06:59:34 -0400 |
commit | 832a90c30485117d65180cc9a8d9869c1b158570 (patch) | |
tree | e8a183e647252766d178bb297854d1e1862553ac | |
parent | bbd001c73cb92aa8f779ae44bb89d8a5dee74ad5 (diff) |
AMD IOMMU: use coherent_dma_mask in alloc_coherent
The alloc_coherent implementation for AMD IOMMU currently uses
*dev->dma_mask per default. This patch changes it to prefer
dev->coherent_dma_mask if it is set.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index db64482b1796..6f7b97445738 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -483,9 +483,10 @@ static unsigned long dma_mask_to_pages(unsigned long mask) | |||
483 | static unsigned long dma_ops_alloc_addresses(struct device *dev, | 483 | static unsigned long dma_ops_alloc_addresses(struct device *dev, |
484 | struct dma_ops_domain *dom, | 484 | struct dma_ops_domain *dom, |
485 | unsigned int pages, | 485 | unsigned int pages, |
486 | unsigned long align_mask) | 486 | unsigned long align_mask, |
487 | u64 dma_mask) | ||
487 | { | 488 | { |
488 | unsigned long limit = dma_mask_to_pages(*dev->dma_mask); | 489 | unsigned long limit = dma_mask_to_pages(dma_mask); |
489 | unsigned long address; | 490 | unsigned long address; |
490 | unsigned long size = dom->aperture_size >> PAGE_SHIFT; | 491 | unsigned long size = dom->aperture_size >> PAGE_SHIFT; |
491 | unsigned long boundary_size; | 492 | unsigned long boundary_size; |
@@ -919,7 +920,8 @@ static dma_addr_t __map_single(struct device *dev, | |||
919 | phys_addr_t paddr, | 920 | phys_addr_t paddr, |
920 | size_t size, | 921 | size_t size, |
921 | int dir, | 922 | int dir, |
922 | bool align) | 923 | bool align, |
924 | u64 dma_mask) | ||
923 | { | 925 | { |
924 | dma_addr_t offset = paddr & ~PAGE_MASK; | 926 | dma_addr_t offset = paddr & ~PAGE_MASK; |
925 | dma_addr_t address, start; | 927 | dma_addr_t address, start; |
@@ -933,7 +935,8 @@ static dma_addr_t __map_single(struct device *dev, | |||
933 | if (align) | 935 | if (align) |
934 | align_mask = (1UL << get_order(size)) - 1; | 936 | align_mask = (1UL << get_order(size)) - 1; |
935 | 937 | ||
936 | address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask); | 938 | address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask, |
939 | dma_mask); | ||
937 | if (unlikely(address == bad_dma_address)) | 940 | if (unlikely(address == bad_dma_address)) |
938 | goto out; | 941 | goto out; |
939 | 942 | ||
@@ -997,10 +1000,13 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, | |||
997 | struct protection_domain *domain; | 1000 | struct protection_domain *domain; |
998 | u16 devid; | 1001 | u16 devid; |
999 | dma_addr_t addr; | 1002 | dma_addr_t addr; |
1003 | u64 dma_mask; | ||
1000 | 1004 | ||
1001 | if (!check_device(dev)) | 1005 | if (!check_device(dev)) |
1002 | return bad_dma_address; | 1006 | return bad_dma_address; |
1003 | 1007 | ||
1008 | dma_mask = *dev->dma_mask; | ||
1009 | |||
1004 | get_device_resources(dev, &iommu, &domain, &devid); | 1010 | get_device_resources(dev, &iommu, &domain, &devid); |
1005 | 1011 | ||
1006 | if (iommu == NULL || domain == NULL) | 1012 | if (iommu == NULL || domain == NULL) |
@@ -1008,7 +1014,8 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, | |||
1008 | return (dma_addr_t)paddr; | 1014 | return (dma_addr_t)paddr; |
1009 | 1015 | ||
1010 | spin_lock_irqsave(&domain->lock, flags); | 1016 | spin_lock_irqsave(&domain->lock, flags); |
1011 | addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false); | 1017 | addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false, |
1018 | dma_mask); | ||
1012 | if (addr == bad_dma_address) | 1019 | if (addr == bad_dma_address) |
1013 | goto out; | 1020 | goto out; |
1014 | 1021 | ||
@@ -1080,10 +1087,13 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, | |||
1080 | struct scatterlist *s; | 1087 | struct scatterlist *s; |
1081 | phys_addr_t paddr; | 1088 | phys_addr_t paddr; |
1082 | int mapped_elems = 0; | 1089 | int mapped_elems = 0; |
1090 | u64 dma_mask; | ||
1083 | 1091 | ||
1084 | if (!check_device(dev)) | 1092 | if (!check_device(dev)) |
1085 | return 0; | 1093 | return 0; |
1086 | 1094 | ||
1095 | dma_mask = *dev->dma_mask; | ||
1096 | |||
1087 | get_device_resources(dev, &iommu, &domain, &devid); | 1097 | get_device_resources(dev, &iommu, &domain, &devid); |
1088 | 1098 | ||
1089 | if (!iommu || !domain) | 1099 | if (!iommu || !domain) |
@@ -1095,7 +1105,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, | |||
1095 | paddr = sg_phys(s); | 1105 | paddr = sg_phys(s); |
1096 | 1106 | ||
1097 | s->dma_address = __map_single(dev, iommu, domain->priv, | 1107 | s->dma_address = __map_single(dev, iommu, domain->priv, |
1098 | paddr, s->length, dir, false); | 1108 | paddr, s->length, dir, false, |
1109 | dma_mask); | ||
1099 | 1110 | ||
1100 | if (s->dma_address) { | 1111 | if (s->dma_address) { |
1101 | s->dma_length = s->length; | 1112 | s->dma_length = s->length; |
@@ -1168,6 +1179,7 @@ static void *alloc_coherent(struct device *dev, size_t size, | |||
1168 | struct protection_domain *domain; | 1179 | struct protection_domain *domain; |
1169 | u16 devid; | 1180 | u16 devid; |
1170 | phys_addr_t paddr; | 1181 | phys_addr_t paddr; |
1182 | u64 dma_mask = dev->coherent_dma_mask; | ||
1171 | 1183 | ||
1172 | if (!check_device(dev)) | 1184 | if (!check_device(dev)) |
1173 | return NULL; | 1185 | return NULL; |
@@ -1187,10 +1199,13 @@ static void *alloc_coherent(struct device *dev, size_t size, | |||
1187 | return virt_addr; | 1199 | return virt_addr; |
1188 | } | 1200 | } |
1189 | 1201 | ||
1202 | if (!dma_mask) | ||
1203 | dma_mask = *dev->dma_mask; | ||
1204 | |||
1190 | spin_lock_irqsave(&domain->lock, flags); | 1205 | spin_lock_irqsave(&domain->lock, flags); |
1191 | 1206 | ||
1192 | *dma_addr = __map_single(dev, iommu, domain->priv, paddr, | 1207 | *dma_addr = __map_single(dev, iommu, domain->priv, paddr, |
1193 | size, DMA_BIDIRECTIONAL, true); | 1208 | size, DMA_BIDIRECTIONAL, true, dma_mask); |
1194 | 1209 | ||
1195 | if (*dma_addr == bad_dma_address) { | 1210 | if (*dma_addr == bad_dma_address) { |
1196 | free_pages((unsigned long)virt_addr, get_order(size)); | 1211 | free_pages((unsigned long)virt_addr, get_order(size)); |