Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: fix for non-coherent DMA PowerPC

This patch fixes bits of the DRM so to make the radeon DRI work on
non-cache coherent PCI DMA variants of the PowerPC processors.

It moves the few places that needs change to wrappers to that
other architectures with similar issues can easily add their
own changes to those wrappers, at least until we have more useful
generic kernel API.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dave Airlie <airlied@linux.ie>

authored by

Benjamin Herrenschmidt and committed by
Dave Airlie
6876b3ba 2b46278b

+31 -6
+6
drivers/char/drm/ati_pcigart.c
··· 168 168 } 169 169 } 170 170 171 + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) 172 + dma_sync_single_for_device(&dev->pdev->dev, 173 + bus_address, 174 + max_pages * sizeof(u32), 175 + PCI_DMA_TODEVICE); 176 + 171 177 ret = 1; 172 178 173 179 #if defined(__i386__) || defined(__x86_64__)
+10 -1
drivers/char/drm/drm_scatter.c
··· 36 36 37 37 #define DEBUG_SCATTER 0 38 38 39 + static inline void *drm_vmalloc_dma(unsigned long size) 40 + { 41 + #if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) 42 + return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE); 43 + #else 44 + return vmalloc_32(size); 45 + #endif 46 + } 47 + 39 48 void drm_sg_cleanup(struct drm_sg_mem * entry) 40 49 { 41 50 struct page *page; ··· 113 104 } 114 105 memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr)); 115 106 116 - entry->virtual = vmalloc_32(pages << PAGE_SHIFT); 107 + entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT); 117 108 if (!entry->virtual) { 118 109 drm_free(entry->busaddr, 119 110 entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
+15 -5
drivers/char/drm/drm_vm.c
··· 54 54 pgprot_val(tmp) |= _PAGE_NO_CACHE; 55 55 if (map_type == _DRM_REGISTERS) 56 56 pgprot_val(tmp) |= _PAGE_GUARDED; 57 - #endif 58 - #if defined(__ia64__) 57 + #elif defined(__ia64__) 59 58 if (efi_range_is_wc(vma->vm_start, vma->vm_end - 60 59 vma->vm_start)) 61 60 tmp = pgprot_writecombine(tmp); 62 61 else 63 62 tmp = pgprot_noncached(tmp); 63 + #elif defined(__sparc__) 64 + tmp = pgprot_noncached(tmp); 65 + #endif 66 + return tmp; 67 + } 68 + 69 + static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) 70 + { 71 + pgprot_t tmp = vm_get_page_prot(vma->vm_flags); 72 + 73 + #if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) 74 + tmp |= _PAGE_NO_CACHE; 64 75 #endif 65 76 return tmp; 66 77 } ··· 614 603 offset = dev->driver->get_reg_ofs(dev); 615 604 vma->vm_flags |= VM_IO; /* not in core dump */ 616 605 vma->vm_page_prot = drm_io_prot(map->type, vma); 617 - #ifdef __sparc__ 618 - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 619 - #endif 620 606 if (io_remap_pfn_range(vma, vma->vm_start, 621 607 (map->offset + offset) >> PAGE_SHIFT, 622 608 vma->vm_end - vma->vm_start, ··· 632 624 page_to_pfn(virt_to_page(map->handle)), 633 625 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 634 626 return -EAGAIN; 627 + vma->vm_page_prot = drm_dma_prot(map->type, vma); 635 628 /* fall through to _DRM_SHM */ 636 629 case _DRM_SHM: 637 630 vma->vm_ops = &drm_vm_shm_ops; ··· 640 631 /* Don't let this area swap. Change when 641 632 DRM_KERNEL advisory is supported. */ 642 633 vma->vm_flags |= VM_RESERVED; 634 + vma->vm_page_prot = drm_dma_prot(map->type, vma); 643 635 break; 644 636 case _DRM_SCATTER_GATHER: 645 637 vma->vm_ops = &drm_vm_sg_ops;