[PATCH] powerpc: IOMMU support for honoring dma_mask

Some devices don't support full 32-bit DMA address space, which we currently
assume. Add the required mask-passing to the IOMMU allocators.

Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by Olof Johansson and committed by Paul Mackerras 7daa411b f4ffaa45

+69 -20
+26 -10
arch/powerpc/kernel/iommu.c
··· 61 static unsigned long iommu_range_alloc(struct iommu_table *tbl, 62 unsigned long npages, 63 unsigned long *handle, 64 unsigned int align_order) 65 { 66 unsigned long n, end, i, start; ··· 98 */ 99 if (start >= limit) 100 start = largealloc ? tbl->it_largehint : tbl->it_hint; 101 - 102 again: 103 104 n = find_next_zero_bit(tbl->it_map, limit, start); 105 ··· 163 164 static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, 165 unsigned int npages, enum dma_data_direction direction, 166 - unsigned int align_order) 167 { 168 unsigned long entry, flags; 169 dma_addr_t ret = DMA_ERROR_CODE; 170 - 171 spin_lock_irqsave(&(tbl->it_lock), flags); 172 173 - entry = iommu_range_alloc(tbl, npages, NULL, align_order); 174 175 if (unlikely(entry == DMA_ERROR_CODE)) { 176 spin_unlock_irqrestore(&(tbl->it_lock), flags); ··· 249 250 int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 251 struct scatterlist *sglist, int nelems, 252 - enum dma_data_direction direction) 253 { 254 dma_addr_t dma_next = 0, dma_addr; 255 unsigned long flags; ··· 287 vaddr = (unsigned long)page_address(s->page) + s->offset; 288 npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); 289 npages >>= PAGE_SHIFT; 290 - entry = iommu_range_alloc(tbl, npages, &handle, 0); 291 292 DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); 293 ··· 492 * byte within the page as vaddr. 493 */ 494 dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 495 - size_t size, enum dma_data_direction direction) 496 { 497 dma_addr_t dma_handle = DMA_ERROR_CODE; 498 unsigned long uaddr; ··· 506 npages >>= PAGE_SHIFT; 507 508 if (tbl) { 509 - dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0); 510 if (dma_handle == DMA_ERROR_CODE) { 511 if (printk_ratelimit()) { 512 printk(KERN_INFO "iommu_alloc failed, " ··· 536 * to the dma address (mapping) of the first page. 537 */ 538 void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 539 - dma_addr_t *dma_handle, gfp_t flag) 540 { 541 void *ret = NULL; 542 dma_addr_t mapping; ··· 566 memset(ret, 0, size); 567 568 /* Set up tces to cover the allocated range */ 569 - mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order); 570 if (mapping == DMA_ERROR_CODE) { 571 free_pages((unsigned long)ret, order); 572 ret = NULL;
··· 61 static unsigned long iommu_range_alloc(struct iommu_table *tbl, 62 unsigned long npages, 63 unsigned long *handle, 64 + unsigned long mask, 65 unsigned int align_order) 66 { 67 unsigned long n, end, i, start; ··· 97 */ 98 if (start >= limit) 99 start = largealloc ? tbl->it_largehint : tbl->it_hint; 100 + 101 again: 102 + 103 + if (limit + tbl->it_offset > mask) { 104 + limit = mask - tbl->it_offset + 1; 105 + /* If we're constrained on address range, first try 106 + * at the masked hint to avoid O(n) search complexity, 107 + * but on second pass, start at 0. 108 + */ 109 + if ((start & mask) >= limit || pass > 0) 110 + start = 0; 111 + else 112 + start &= mask; 113 + } 114 115 n = find_next_zero_bit(tbl->it_map, limit, start); 116 ··· 150 151 static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, 152 unsigned int npages, enum dma_data_direction direction, 153 + unsigned long mask, unsigned int align_order) 154 { 155 unsigned long entry, flags; 156 dma_addr_t ret = DMA_ERROR_CODE; 157 + 158 spin_lock_irqsave(&(tbl->it_lock), flags); 159 160 + entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order); 161 162 if (unlikely(entry == DMA_ERROR_CODE)) { 163 spin_unlock_irqrestore(&(tbl->it_lock), flags); ··· 236 237 int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 238 struct scatterlist *sglist, int nelems, 239 + unsigned long mask, enum dma_data_direction direction) 240 { 241 dma_addr_t dma_next = 0, dma_addr; 242 unsigned long flags; ··· 274 vaddr = (unsigned long)page_address(s->page) + s->offset; 275 npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); 276 npages >>= PAGE_SHIFT; 277 + entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0); 278 279 DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); 280 ··· 479 * byte within the page as vaddr. 480 */ 481 dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 482 + size_t size, unsigned long mask, 483 + enum dma_data_direction direction) 484 { 485 dma_addr_t dma_handle = DMA_ERROR_CODE; 486 unsigned long uaddr; ··· 492 npages >>= PAGE_SHIFT; 493 494 if (tbl) { 495 + dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 496 + mask >> PAGE_SHIFT, 0); 497 if (dma_handle == DMA_ERROR_CODE) { 498 if (printk_ratelimit()) { 499 printk(KERN_INFO "iommu_alloc failed, " ··· 521 * to the dma address (mapping) of the first page. 522 */ 523 void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 524 + dma_addr_t *dma_handle, unsigned long mask, gfp_t flag) 525 { 526 void *ret = NULL; 527 dma_addr_t mapping; ··· 551 memset(ret, 0, size); 552 553 /* Set up tces to cover the allocated range */ 554 + mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, 555 + mask >> PAGE_SHIFT, order); 556 if (mapping == DMA_ERROR_CODE) { 557 free_pages((unsigned long)ret, order); 558 ret = NULL;
+36 -4
arch/powerpc/kernel/pci_iommu.c
··· 59 } 60 61 62 /* Allocates a contiguous real buffer and creates mappings over it. 63 * Returns the virtual address of the buffer and sets dma_handle 64 * to the dma address (mapping) of the first page. ··· 86 dma_addr_t *dma_handle, gfp_t flag) 87 { 88 return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle, 89 - flag); 90 } 91 92 static void pci_iommu_free_coherent(struct device *hwdev, size_t size, ··· 104 static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, 105 size_t size, enum dma_data_direction direction) 106 { 107 - return iommu_map_single(devnode_table(hwdev), vaddr, size, direction); 108 } 109 110 ··· 120 int nelems, enum dma_data_direction direction) 121 { 122 return iommu_map_sg(pdev, devnode_table(pdev), sglist, 123 - nelems, direction); 124 } 125 126 static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, ··· 132 /* We support DMA to/from any memory page via the iommu */ 133 static int pci_iommu_dma_supported(struct device *dev, u64 mask) 134 { 135 - return 1; 136 } 137 138 void pci_iommu_init(void)
··· 59 } 60 61 62 + static inline unsigned long device_to_mask(struct device *hwdev) 63 + { 64 + struct pci_dev *pdev; 65 + 66 + if (!hwdev) { 67 + pdev = ppc64_isabridge_dev; 68 + if (!pdev) /* This is the best guess we can do */ 69 + return 0xfffffffful; 70 + } else 71 + pdev = to_pci_dev(hwdev); 72 + 73 + if (pdev->dma_mask) 74 + return pdev->dma_mask; 75 + 76 + /* Assume devices without mask can take 32 bit addresses */ 77 + return 0xfffffffful; 78 + } 79 + 80 + 81 /* Allocates a contiguous real buffer and creates mappings over it. 82 * Returns the virtual address of the buffer and sets dma_handle 83 * to the dma address (mapping) of the first page. ··· 67 dma_addr_t *dma_handle, gfp_t flag) 68 { 69 return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle, 70 + device_to_mask(hwdev), flag); 71 } 72 73 static void pci_iommu_free_coherent(struct device *hwdev, size_t size, ··· 85 static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, 86 size_t size, enum dma_data_direction direction) 87 { 88 + return iommu_map_single(devnode_table(hwdev), vaddr, size, 89 + device_to_mask(hwdev), direction); 90 } 91 92 ··· 100 int nelems, enum dma_data_direction direction) 101 { 102 return iommu_map_sg(pdev, devnode_table(pdev), sglist, 103 + nelems, device_to_mask(pdev), direction); 104 } 105 106 static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, ··· 112 /* We support DMA to/from any memory page via the iommu */ 113 static int pci_iommu_dma_supported(struct device *dev, u64 mask) 114 { 115 + struct iommu_table *tbl = devnode_table(dev); 116 + 117 + if (!tbl || tbl->it_offset > mask) { 118 + printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n"); 119 + if (tbl) 120 + printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n", 121 + mask, tbl->it_offset); 122 + else 123 + printk(KERN_INFO "mask: 0x%08lx, table unavailable\n", 124 + mask); 125 + return 0; 126 + } else 127 + return 1; 128 } 129 130 void pci_iommu_init(void)
+3 -3
arch/powerpc/kernel/vio.c
··· 202 size_t size, enum dma_data_direction direction) 203 { 204 return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size, 205 - direction); 206 } 207 208 static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle, ··· 216 int nelems, enum dma_data_direction direction) 217 { 218 return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist, 219 - nelems, direction); 220 } 221 222 static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist, ··· 229 dma_addr_t *dma_handle, gfp_t flag) 230 { 231 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, 232 - dma_handle, flag); 233 } 234 235 static void vio_free_coherent(struct device *dev, size_t size,
··· 202 size_t size, enum dma_data_direction direction) 203 { 204 return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size, 205 + ~0ul, direction); 206 } 207 208 static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle, ··· 216 int nelems, enum dma_data_direction direction) 217 { 218 return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist, 219 + nelems, ~0ul, direction); 220 } 221 222 static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist, ··· 229 dma_addr_t *dma_handle, gfp_t flag) 230 { 231 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, 232 + dma_handle, ~0ul, flag); 233 } 234 235 static void vio_free_coherent(struct device *dev, size_t size,
+4 -3
include/asm-powerpc/iommu.h
··· 70 extern struct iommu_table *iommu_init_table(struct iommu_table * tbl); 71 72 extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 73 - struct scatterlist *sglist, int nelems, 74 enum dma_data_direction direction); 75 extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, 76 int nelems, enum dma_data_direction direction); 77 78 extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 79 - dma_addr_t *dma_handle, gfp_t flag); 80 extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, 81 void *vaddr, dma_addr_t dma_handle); 82 extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 83 - size_t size, enum dma_data_direction direction); 84 extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, 85 size_t size, enum dma_data_direction direction); 86
··· 70 extern struct iommu_table *iommu_init_table(struct iommu_table * tbl); 71 72 extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 73 + struct scatterlist *sglist, int nelems, unsigned long mask, 74 enum dma_data_direction direction); 75 extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, 76 int nelems, enum dma_data_direction direction); 77 78 extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 79 + dma_addr_t *dma_handle, unsigned long mask, gfp_t flag); 80 extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, 81 void *vaddr, dma_addr_t dma_handle); 82 extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 83 + size_t size, unsigned long mask, 84 + enum dma_data_direction direction); 85 extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, 86 size_t size, enum dma_data_direction direction); 87