* Improved DRM support for cant_use_aperture platforms @ 2003-05-10 10:09 David Mosberger 2003-05-10 13:12 ` Dave Jones 2003-05-11 11:43 ` Michel Dänzer 0 siblings, 2 replies; 27+ messages in thread From: David Mosberger @ 2003-05-10 10:09 UTC (permalink / raw) To: davej; +Cc: linux-kernel Hi Dave, This patch is rather big, but actually very straight-forward: it adds a "agp dev" argument to DRM_IOREMAP(), DRM_IOREMAP_NOCACHE(), and DRM_IOREMAPFREE() and then uses it in drm_memory.h to support platforms where CPU accesses to the AGP space are not translated by the GART (true for ia64 and alpha, not true for x86, I don't know about the other platforms). On platforms where cant_use_aperture is always false, this whole patch will look like a no-op. On ia64, it works. Don't know about other platforms, but it should simplify things for Alpha at least (and if it breaks a platform, I shall be happy to work with the respective maintainer to get fix back to working). Thanks, --david diff -Nru a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h --- a/drivers/char/drm/drmP.h Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/drmP.h Sat May 10 01:47:43 2003 @@ -225,16 +225,16 @@ if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; } /* Mapping helper macros */ -#define DRM_IOREMAP(map) \ - (map)->handle = DRM(ioremap)( (map)->offset, (map)->size ) +#define DRM_IOREMAP(map, dev) \ + (map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) ) -#define DRM_IOREMAP_NOCACHE(map) \ - (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size) +#define DRM_IOREMAP_NOCACHE(map, dev) \ + (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev)) -#define DRM_IOREMAPFREE(map) \ - do { \ - if ( (map)->handle && (map)->size ) \ - DRM(ioremapfree)( (map)->handle, (map)->size ); \ +#define DRM_IOREMAPFREE(map, dev) \ + do { \ + if ( (map)->handle && (map)->size ) \ + DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \ } while (0) #define DRM_FIND_MAP(_map, _o) \ @@ -652,9 +652,10 @@ extern unsigned long DRM(alloc_pages)(int order, int area); extern void DRM(free_pages)(unsigned long address, int order, int area); -extern void *DRM(ioremap)(unsigned long offset, unsigned long size); -extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size); -extern void DRM(ioremapfree)(void *pt, unsigned long size); +extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev); +extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, + drm_device_t *dev); +extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP extern agp_memory *DRM(alloc_agp)(int pages, u32 type); diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h --- a/drivers/char/drm/drm_bufs.h Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/drm_bufs.h Sat May 10 01:47:43 2003 @@ -123,7 +123,7 @@ MTRR_TYPE_WRCOMB, 1 ); } #endif - map->handle = DRM(ioremap)( map->offset, map->size ); + map->handle = DRM(ioremap)( map->offset, map->size, dev ); break; case _DRM_SHM: @@ -245,7 +245,7 @@ DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h --- a/drivers/char/drm/drm_drv.h Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/drm_drv.h Sat May 10 01:47:43 2003 @@ -454,7 +454,7 @@ DRM_DEBUG( "mtrr_del=%d\n", retcode ); } #endif - DRM(ioremapfree)( map->handle, map->size ); + DRM(ioremapfree)( map->handle, map->size, dev ); break; case _DRM_SHM: vfree(map->handle); diff -Nru a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h --- a/drivers/char/drm/drm_memory.h Sat May 10 01:47:42 2003 +++ b/drivers/char/drm/drm_memory.h Sat May 10 01:47:43 2003 @@ -31,6 +31,10 @@ #include <linux/config.h> #include "drmP.h" +#include <linux/vmalloc.h> + +#include <asm/agp.h> +#include <asm/tlbflush.h> /* Cut down version of drm_memory_debug.h, which used to be called * drm_memory.h. If you want the debug functionality, change 0 to 1 @@ -38,6 +42,150 @@ */ #define DEBUG_MEMORY 0 +#if __REALLY_HAVE_AGP + +/* + * Find the drm_map that covers the range [offset, offset+size). + */ +static inline drm_map_t * +drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + struct list_head *list; + drm_map_list_t *r_list; + drm_map_t *map; + + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *) list; + map = r_list->map; + if (!map) + continue; + if (map->offset <= offset && (offset + size) <= (map->offset + map->size)) + return map; + } + return NULL; +} + +static inline void * +agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE; + struct drm_agp_mem *agpmem; + struct page **page_map; + void *addr; + + size = PAGE_ALIGN(size); + + for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) + if (agpmem->bound <= offset + && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size)) + break; + if (!agpmem) + return NULL; + + /* + * OK, we're mapping AGP space on a chipset/platform on which memory accesses by + * the CPU do not get remapped by the GART. We fix this by using the kernel's + * page-table instead (that's probably faster anyhow...). + */ + /* note: use vmalloc() because num_pages could be large... */ + page_map = vmalloc(num_pages * sizeof(struct page *)); + if (!page_map) + return NULL; + + phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; + for (i = 0; i < num_pages; ++i) + page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); + addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); + vfree(page_map); + if (!addr) + return NULL; + + flush_tlb_kernel_range((unsigned long) addr, (unsigned long) addr + size); + return addr; +} + +static inline unsigned long +drm_follow_page (void *vaddr) +{ + pgd_t *pgd = pgd_offset_k((unsigned long) vaddr); + pmd_t *pmd = pmd_offset(pgd, (unsigned long) vaddr); + pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr); + return pte_pfn(*ptep) << PAGE_SHIFT; +} + +#else /* !__REALLY_HAVE_AGP */ + +static inline void * +agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + return NULL; +} + +#endif /* !__REALLY_HAVE_AGP */ + +static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev) +{ + int remap_aperture = 0; + +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + remap_aperture = 1; + } +#endif + if (remap_aperture) + return agp_remap(offset, size, dev); + else + return ioremap(offset, size); +} + +static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size, + drm_device_t *dev) +{ + int remap_aperture = 0; + +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + remap_aperture = 1; + } +#endif + if (remap_aperture) + return agp_remap(offset, size, dev); + else + return ioremap_nocache(offset, size); +} + +static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev) +{ + int unmap_aperture = 0; +#if __REALLY_HAVE_AGP + /* + * This is a bit ugly. It would be much cleaner if the DRM API would use separate + * routines for handling mappings in the AGP space. Hopefully this can be done in + * a future revision of the interface... + */ + if (dev->agp->cant_use_aperture + && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END)) + { + unsigned long offset; + drm_map_t *map; + + offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK); + map = drm_lookup_map(offset, size, dev); + if (map && map->type == _DRM_AGP) + unmap_aperture = 1; + } +#endif + if (unmap_aperture) + vunmap(pt); + else + iounmap(pt); +} #if DEBUG_MEMORY #include "drm_memory_debug.h" @@ -118,19 +266,19 @@ free_pages(address, order); } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) { - return ioremap(offset, size); + return drm_ioremap(offset, size, dev); } -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) { - return ioremap_nocache(offset, size); + return drm_ioremap_nocache(offset, size, dev); } -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) { - iounmap(pt); + drm_ioremapfree(pt, size, dev); } #if __REALLY_HAVE_AGP diff -Nru a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h --- a/drivers/char/drm/drm_memory_debug.h Sat May 10 01:47:42 2003 +++ b/drivers/char/drm/drm_memory_debug.h Sat May 10 01:47:42 2003 @@ -269,7 +269,7 @@ } } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) { void *pt; @@ -279,7 +279,7 @@ return NULL; } - if (!(pt = ioremap(offset, size))) { + if (!(pt = drm_ioremap(offset, size, dev))) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -292,7 +292,7 @@ return pt; } -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) { void *pt; @@ -302,7 +302,7 @@ return NULL; } - if (!(pt = ioremap_nocache(offset, size))) { + if (!(pt = drm_ioremap_nocache(offset, size, dev))) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -315,7 +315,7 @@ return pt; } -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) { int alloc_count; int free_count; @@ -324,7 +324,7 @@ DRM_MEM_ERROR(DRM_MEM_MAPPINGS, "Attempt to free NULL pointer\n"); else - iounmap(pt); + drm_ioremapfree(pt, size, dev); spin_lock(&DRM(mem_lock)); DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h --- a/drivers/char/drm/drm_vm.h Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/drm_vm.h Sat May 10 01:47:43 2003 @@ -107,12 +107,12 @@ * Get the page, inc the use count, and return it */ offset = (baddr - agpmem->bound) >> PAGE_SHIFT; - agpmem->memory->memory[offset] &= dev->agp->page_mask; page = virt_to_page(__va(agpmem->memory->memory[offset])); get_page(page); - DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n", - baddr, __va(agpmem->memory->memory[offset]), offset); + DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", + baddr, __va(agpmem->memory->memory[offset]), offset, + atomic_read(&page->count)); return page; } @@ -206,7 +206,7 @@ DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); @@ -420,15 +420,16 @@ switch (map->type) { case _DRM_AGP: -#if defined(__alpha__) +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { /* - * On Alpha we can't talk to bus dma address from the - * CPU, so for memory of type DRM_AGP, we'll deal with - * sorting out the real physical pages and mappings - * in nopage() + * On some platforms we can't talk to bus dma address from the CPU, so for + * memory of type DRM_AGP, we'll deal with sorting out the real physical + * pages and mappings in nopage() */ vma->vm_ops = &DRM(vm_ops); break; + } #endif /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: @@ -439,15 +440,15 @@ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; } -#elif defined(__ia64__) - if (map->type != _DRM_AGP) - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); #elif defined(__powerpc__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; #endif vma->vm_flags |= VM_IO; /* not in core dump */ } +#if defined(__ia64__) + if (map->type != _DRM_AGP) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#endif offset = DRIVER_GET_REG_OFS(); #ifdef __sparc__ if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, diff -Nru a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c --- a/drivers/char/drm/gamma_dma.c Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/gamma_dma.c Sat May 10 01:47:43 2003 @@ -612,7 +612,7 @@ } else { DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->buffers, dev ); buf = dma->buflist[GLINT_DRI_BUF_COUNT]; pgt = buf->address; @@ -651,7 +651,7 @@ drm_gamma_private_t *dev_priv = dev->dev_private; if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t), DRM_MEM_DRIVER ); diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c --- a/drivers/char/drm/i810_dma.c Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/i810_dma.c Sat May 10 01:47:43 2003 @@ -246,7 +246,7 @@ if(dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -263,7 +263,7 @@ drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; if ( buf_priv->kernel_virtual && buf->total ) - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -333,7 +333,7 @@ *buf_priv->in_use = I810_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -386,7 +386,7 @@ dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c --- a/drivers/char/drm/i830_dma.c Sat May 10 01:47:42 2003 +++ b/drivers/char/drm/i830_dma.c Sat May 10 01:47:42 2003 @@ -246,7 +246,7 @@ if (dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -264,7 +264,7 @@ drm_buf_t *buf = dma->buflist[ i ]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; if ( buf_priv->kernel_virtual && buf->total ) - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -340,7 +340,7 @@ *buf_priv->in_use = I830_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -394,7 +394,7 @@ dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; diff -Nru a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c --- a/drivers/char/drm/mga_dma.c Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/mga_dma.c Sat May 10 01:47:43 2003 @@ -554,9 +554,9 @@ (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); - DRM_IOREMAP( dev_priv->warp ); - DRM_IOREMAP( dev_priv->primary ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->warp, dev ); + DRM_IOREMAP( dev_priv->primary, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->warp->handle || !dev_priv->primary->handle || @@ -651,11 +651,11 @@ drm_mga_private_t *dev_priv = dev->dev_private; if ( dev_priv->warp != NULL ) - DRM_IOREMAPFREE( dev_priv->warp ); + DRM_IOREMAPFREE( dev_priv->warp, dev ); if ( dev_priv->primary != NULL ) - DRM_IOREMAPFREE( dev_priv->primary ); + DRM_IOREMAPFREE( dev_priv->primary, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); if ( dev_priv->head != NULL ) { mga_freelist_cleanup( dev ); diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h --- a/drivers/char/drm/mga_drv.h Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/mga_drv.h Sat May 10 01:47:43 2003 @@ -226,7 +226,7 @@ if ( MGA_VERBOSE ) { \ DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \ (n), __FUNCTION__ ); \ - DRM_INFO( " space=0x%x req=0x%x\n", \ + DRM_INFO( " space=0x%x req=0x%Zx\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ prim = dev_priv->prim.start; \ @@ -276,7 +276,7 @@ #define DMA_WRITE( offset, val ) \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04x\n", \ + DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \ (u32)(val), write + (offset) * sizeof(u32) ); \ } \ *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \ diff -Nru a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c --- a/drivers/char/drm/r128_cce.c Sat May 10 01:47:42 2003 +++ b/drivers/char/drm/r128_cce.c Sat May 10 01:47:42 2003 @@ -350,8 +350,8 @@ R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -540,9 +540,9 @@ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cce_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cce_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -629,11 +629,11 @@ if ( !dev_priv->is_pci ) { #endif if ( dev_priv->cce_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cce_ring ); + DRM_IOREMAPFREE( dev_priv->cce_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); #if __REALLY_HAVE_SG } else { if (!DRM(ati_pcigart_cleanup)( dev, diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c --- a/drivers/char/drm/radeon_cp.c Sat May 10 01:47:43 2003 +++ b/drivers/char/drm/radeon_cp.c Sat May 10 01:47:43 2003 @@ -903,8 +903,8 @@ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -1152,9 +1152,9 @@ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cp_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cp_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cp_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -1279,11 +1279,11 @@ if ( !dev_priv->is_pci ) { if ( dev_priv->cp_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cp_ring ); + DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); } else { #if __REALLY_HAVE_SG if (!DRM(ati_pcigart_cleanup)( dev, diff -Nru a/include/asm-alpha/agp.h b/include/asm-alpha/agp.h --- a/include/asm-alpha/agp.h Sat May 10 01:47:42 2003 +++ b/include/asm-alpha/agp.h Sat May 10 01:47:42 2003 @@ -10,4 +10,11 @@ #define flush_agp_mappings() #define flush_agp_cache() mb() +/* + * Page-protection value to be used for AGP memory mapped into kernel space. For + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to + * be an uncached mapping (such as write-combining). + */ +#define PAGE_AGP PAGE_KERNEL_NOCACHE /* XXX fix me */ + #endif diff -Nru a/include/asm-i386/agp.h b/include/asm-i386/agp.h --- a/include/asm-i386/agp.h Sat May 10 01:47:42 2003 +++ b/include/asm-i386/agp.h Sat May 10 01:47:42 2003 @@ -20,4 +20,11 @@ worth it. Would need a page for it. */ #define flush_agp_cache() asm volatile("wbinvd":::"memory") +/* + * Page-protection value to be used for AGP memory mapped into kernel space. For + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to + * be an uncached mapping (such as write-combining). + */ +#define PAGE_AGP PAGE_KERNEL_NOCACHE + #endif diff -Nru a/include/asm-sparc64/agp.h b/include/asm-sparc64/agp.h --- a/include/asm-sparc64/agp.h Sat May 10 01:47:42 2003 +++ b/include/asm-sparc64/agp.h Sat May 10 01:47:42 2003 @@ -8,4 +8,11 @@ #define flush_agp_mappings() #define flush_agp_cache() mb() +/* + * Page-protection value to be used for AGP memory mapped into kernel space. For + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to + * be an uncached mapping (such as write-combining). + */ +#define PAGE_AGP PAGE_KERNEL_NOCACHE + #endif diff -Nru a/include/asm-x86_64/agp.h b/include/asm-x86_64/agp.h --- a/include/asm-x86_64/agp.h Sat May 10 01:47:42 2003 +++ b/include/asm-x86_64/agp.h Sat May 10 01:47:42 2003 @@ -20,4 +20,11 @@ worth it. Would need a page for it. */ #define flush_agp_cache() asm volatile("wbinvd":::"memory") +/* + * Page-protection value to be used for AGP memory mapped into kernel space. For + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to + * be an uncached mapping (such as write-combining). + */ +#define PAGE_AGP PAGE_KERNEL_NOCACHE + #endif ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-10 10:09 Improved DRM support for cant_use_aperture platforms David Mosberger @ 2003-05-10 13:12 ` Dave Jones 2003-05-11 11:43 ` Michel Dänzer 1 sibling, 0 replies; 27+ messages in thread From: Dave Jones @ 2003-05-10 13:12 UTC (permalink / raw) To: davidm; +Cc: linux-kernel On Sat, May 10, 2003 at 03:09:16AM -0700, David Mosberger wrote: > Hi Dave, > > This patch is rather big, but actually very straight-forward: it adds > a "agp dev" argument to DRM_IOREMAP(), DRM_IOREMAP_NOCACHE(), and > DRM_IOREMAPFREE() and then uses it in drm_memory.h to support > platforms where CPU accesses to the AGP space are not translated by > the GART That's one to run by the dri-devel@lists.sf.net folks. Dave ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-10 10:09 Improved DRM support for cant_use_aperture platforms David Mosberger 2003-05-10 13:12 ` Dave Jones @ 2003-05-11 11:43 ` Michel Dänzer 2003-05-11 18:09 ` David Mosberger 1 sibling, 1 reply; 27+ messages in thread From: Michel Dänzer @ 2003-05-11 11:43 UTC (permalink / raw) To: davidm; +Cc: davej, linux-kernel, dri-devel On Sam, 2003-05-10 at 12:09, David Mosberger wrote: > > This patch is rather big, but actually very straight-forward: it adds > a "agp dev" argument to DRM_IOREMAP(), DRM_IOREMAP_NOCACHE(), and > DRM_IOREMAPFREE() and then uses it in drm_memory.h to support > platforms where CPU accesses to the AGP space are not translated by > the GART (true for ia64 and alpha, not true for x86, I don't know > about the other platforms). On platforms where cant_use_aperture is > always false, this whole patch will look like a no-op. On ia64, it > works. Don't know about other platforms, but it should simplify > things for Alpha at least (and if it breaks a platform, I shall be > happy to work with the respective maintainer to get fix back to > working). I'd love to commit this to DRI CVS, but there'd have to be fallbacks for older kernels (this is against 2.4.20-ben8): gcc -I/home/michdaen/src/dri-cvs/xc-trunk/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel -D__KERNEL__ -I/home/michdaen/src/linux-2.4.20-ben8-xfs-lolat/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -I/home/michdaen/src/linux-2.4.20-ben8-xfs-lolat/arch/ppc -fsigned-char -msoft-float -pipe -ffixed-r2 -Wno-uninitialized -mmultiple -mstring -DMODULE -nostdinc -iwithprefix include -DKBUILD_BASENAME=radeon_drv -c -o radeon_drv.o radeon_drv.c In file included from radeon_drv.c:49: drm_memory.h:37:21: asm/agp.h: No such file or directory drm_memory.h:38:26: asm/tlbflush.h: No such file or directory In file included from radeon_drv.c:49: drm_memory.h: In function `agp_remap': drm_memory.h:98: warning: implicit declaration of function `pfn_to_page' drm_memory.h:98: warning: assignment makes pointer from integer without a cast drm_memory.h:99: warning: implicit declaration of function `vmap' drm_memory.h:99: `PAGE_AGP' undeclared (first use in this function) drm_memory.h:99: (Each undeclared identifier is reported only once drm_memory.h:99: for each function it appears in.) drm_memory.h:99: warning: assignment makes pointer from integer without a cast drm_memory.h:104: warning: implicit declaration of function `flush_tlb_kernel_range' drm_memory.h: In function `drm_follow_page': drm_memory.h:113: warning: implicit declaration of function `pte_offset_kernel' drm_memory.h:113: warning: initialization makes pointer from integer without a cast drm_memory.h:114: warning: implicit declaration of function `pte_pfn' drm_memory.h: In function `drm_ioremapfree': drm_memory.h:186: warning: implicit declaration of function `vunmap' make[3]: *** [radeon_drv.o] Error 1 -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-11 11:43 ` Michel Dänzer @ 2003-05-11 18:09 ` David Mosberger 2003-05-11 19:55 ` Dave Jones 0 siblings, 1 reply; 27+ messages in thread From: David Mosberger @ 2003-05-11 18:09 UTC (permalink / raw) To: Michel Dänzer; +Cc: davidm, davej, linux-kernel, dri-devel >>>>> On 11 May 2003 13:43:36 +0200, Michel Dänzer <michel@daenzer.net> said: Michel> On Sam, 2003-05-10 at 12:09, David Mosberger wrote: >> This patch is rather big, but actually very straight-forward: it >> adds a "agp dev" argument to DRM_IOREMAP(), >> DRM_IOREMAP_NOCACHE(), and DRM_IOREMAPFREE() and then uses it in >> drm_memory.h to support platforms where CPU accesses to the AGP >> space are not translated by the GART (true for ia64 and alpha, >> not true for x86, I don't know about the other platforms). On >> platforms where cant_use_aperture is always false, this whole >> patch will look like a no-op. On ia64, it works. Don't know >> about other platforms, but it should simplify things for Alpha at >> least (and if it breaks a platform, I shall be happy to work with >> the respective maintainer to get fix back to working). Michel> I'd love to commit this to DRI CVS, Great! Michel> but there'd have to be fallbacks for older kernels (this is Michel> against 2.4.20-ben8): OK, we have a chicken & egg problem then: I could obviously add Linux kernel version checks where needed, but to do that, the patch first needs to go into the kernel. Dave, would you mind applying the patch to your tree? Then once Linus picked it up, I can send a new patch to dri-devel. Or does someone have a better suggestion? --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-11 18:09 ` David Mosberger @ 2003-05-11 19:55 ` Dave Jones 2003-05-11 21:55 ` Michel Dänzer 0 siblings, 1 reply; 27+ messages in thread From: Dave Jones @ 2003-05-11 19:55 UTC (permalink / raw) To: davidm; +Cc: Michel D?nzer, linux-kernel, dri-devel On Sun, May 11, 2003 at 11:09:00AM -0700, David Mosberger wrote: > Michel> but there'd have to be fallbacks for older kernels (this is > Michel> against 2.4.20-ben8): > > OK, we have a chicken & egg problem then: I could obviously add Linux > kernel version checks where needed, but to do that, the patch first > needs to go into the kernel. Dave, would you mind applying the patch > to your tree? Then once Linus picked it up, I can send a new patch to > dri-devel. Or does someone have a better suggestion? With Linus doing the DRI sync-ups himself, maybe just pushing it his way directly would work.. I'll roll it into the next 2.5-dj for some extra testing, but I'm not going to be the one who pushes that linuswards unless I get asked by the DRI folks. Dave ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-11 19:55 ` Dave Jones @ 2003-05-11 21:55 ` Michel Dänzer 2003-05-12 18:53 ` David Mosberger 0 siblings, 1 reply; 27+ messages in thread From: Michel Dänzer @ 2003-05-11 21:55 UTC (permalink / raw) To: Dave Jones; +Cc: davidm, linux-kernel, dri-devel On Son, 2003-05-11 at 21:55, Dave Jones wrote: > On Sun, May 11, 2003 at 11:09:00AM -0700, David Mosberger wrote: > > Michel> but there'd have to be fallbacks for older kernels (this is > > Michel> against 2.4.20-ben8): > > > > OK, we have a chicken & egg problem then: I could obviously add Linux > > kernel version checks where needed, but to do that, the patch first > > needs to go into the kernel. Mind elaborating on that? I don't see such a problem as you don't need version checks for anything the patch itself adds, only for kernel infrastructure that isn't available in older kernels (down to 2.4). > > Dave, would you mind applying the patch to your tree? Then once > > Linus picked it up, I can send a new patch to dri-devel. Or does > > someone have a better suggestion? > > With Linus doing the DRI sync-ups himself, maybe just pushing it his > way directly would work.. It's my impression that he prefers just merging from DRI CVS to pushing something back, so putting it in there first seems like it would be the easiest way to me. -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-11 21:55 ` Michel Dänzer @ 2003-05-12 18:53 ` David Mosberger 2003-05-12 19:48 ` [Dri-devel] " Michel Dänzer 0 siblings, 1 reply; 27+ messages in thread From: David Mosberger @ 2003-05-12 18:53 UTC (permalink / raw) To: Michel Dänzer; +Cc: Dave Jones, davidm, linux-kernel, dri-devel >>>>> On 11 May 2003 23:55:33 +0200, Michel Dänzer <michel@daenzer.net> said: >> OK, we have a chicken & egg problem then: I could obviously add >> Linux kernel version checks where needed, but to do that, the >> patch first needs to go into the kernel. Michel> Mind elaborating on that? I don't see such a problem as you Michel> don't need version checks for anything the patch itself Michel> adds, only for kernel infrastructure that isn't available in Michel> older kernels (down to 2.4). OK, I'm confused then: earlier on, you reported this error: asm/agp.h: No such file or directory My patch adds the following to asm-i386/agp.h: diff -Nru a/include/asm-i386/agp.h b/include/asm-i386/agp.h --- a/include/asm-i386/agp.h Sat May 10 01:47:42 2003 +++ b/include/asm-i386/agp.h Sat May 10 01:47:42 2003 @@ -20,4 +20,11 @@ worth it. Would need a page for it. */ #define flush_agp_cache() asm volatile("wbinvd":::"memory") +/* + * Page-protection value to be used for AGP memory mapped into kernel space. For + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to + * be an uncached mapping (such as write-combining). + */ +#define PAGE_AGP PAGE_KERNEL_NOCACHE + #endif So, either you're using a platform which I don't know supports AGP, or the patch didn't apply cleanly (perhaps because you're using an old kernel that doesn't have asm/agp.h yet?). Could you shed some light? Once I understand why things are failing for you, I shall be happy to update the patch accordingly. --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Dri-devel] Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 18:53 ` David Mosberger @ 2003-05-12 19:48 ` Michel Dänzer 2003-05-12 20:19 ` David Mosberger 2003-05-12 20:40 ` David Mosberger 0 siblings, 2 replies; 27+ messages in thread From: Michel Dänzer @ 2003-05-12 19:48 UTC (permalink / raw) To: davidm; +Cc: Dave Jones, linux-kernel, dri-devel On Mon, 2003-05-12 at 20:53, David Mosberger wrote: > >>>>> On 11 May 2003 23:55:33 +0200, Michel Dänzer <michel@daenzer.net> said: > > >> OK, we have a chicken & egg problem then: I could obviously add > >> Linux kernel version checks where needed, but to do that, the > >> patch first needs to go into the kernel. > > Michel> Mind elaborating on that? I don't see such a problem as you > Michel> don't need version checks for anything the patch itself > Michel> adds, only for kernel infrastructure that isn't available in > Michel> older kernels (down to 2.4). > > OK, I'm confused then: earlier on, you reported this error: > > asm/agp.h: No such file or directory > > My patch adds the following to asm-i386/agp.h: > > diff -Nru a/include/asm-i386/agp.h b/include/asm-i386/agp.h > --- a/include/asm-i386/agp.h Sat May 10 01:47:42 2003 > +++ b/include/asm-i386/agp.h Sat May 10 01:47:42 2003 > @@ -20,4 +20,11 @@ > worth it. Would need a page for it. */ > #define flush_agp_cache() asm volatile("wbinvd":::"memory") > > +/* > + * Page-protection value to be used for AGP memory mapped into kernel space. For > + * platforms which use coherent AGP DMA, this can be PAGE_KERNEL. For others, it needs to > + * be an uncached mapping (such as write-combining). > + */ > +#define PAGE_AGP PAGE_KERNEL_NOCACHE > + > #endif > > So, either you're using a platform which I don't know supports AGP, or > the patch didn't apply cleanly (perhaps because you're using an old > kernel that doesn't have asm/agp.h yet?). That's it. So we have to check the version before #including <asm/agp.h>. Then, we can do something like #ifndef PAGE_AGP #define PAGE_AGP PAGE_KERNEL_NOCACHE #endif Or am I missing something? This is the easy part though, you probably know better than I what to do about the functions you use that aren't available in 2.4 yet. :) -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Dri-devel] Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 19:48 ` [Dri-devel] " Michel Dänzer @ 2003-05-12 20:19 ` David Mosberger 2003-05-12 21:21 ` Michel Dänzer 2003-05-12 20:40 ` David Mosberger 1 sibling, 1 reply; 27+ messages in thread From: David Mosberger @ 2003-05-12 20:19 UTC (permalink / raw) To: Michel Dänzer; +Cc: davidm, Dave Jones, linux-kernel, dri-devel >>>>> On 12 May 2003 21:48:31 +0200, Michel Dänzer <michel@daenzer.net> said: >> using an old kernel that doesn't have asm/agp.h yet?). Michel> That's it. OK, thanks for clarifying. Michel> So we have to check the version before #including Michel> <asm/agp.h>. Then, we can do something like Michel> #ifndef PAGE_AGP #define PAGE_AGP PAGE_KERNEL_NOCACHE #endif Michel> Or am I missing something? Basically correct, except that the patch also needs an improved version of vmap(), which was introduced in 2.5.68 only (IIRC). I'll update my patch so it is a no-op unless you have a kernel >= 2.5.68. --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 20:19 ` David Mosberger @ 2003-05-12 21:21 ` Michel Dänzer 2003-05-12 21:51 ` David Mosberger 0 siblings, 1 reply; 27+ messages in thread From: Michel Dänzer @ 2003-05-12 21:21 UTC (permalink / raw) To: davidm; +Cc: Dave Jones, linux-kernel, dri-devel [-- Attachment #1: Type: text/plain, Size: 1299 bytes --] On Mon, 2003-05-12 at 22:19, David Mosberger wrote: > >>>>> On 12 May 2003 21:48:31 +0200, Michel Dänzer <michel@daenzer.net> said: > > >> using an old kernel that doesn't have asm/agp.h yet?). > > Michel> That's it. > > OK, thanks for clarifying. > > Michel> So we have to check the version before #including > Michel> <asm/agp.h>. Then, we can do something like > > Michel> #ifndef PAGE_AGP #define PAGE_AGP PAGE_KERNEL_NOCACHE #endif > > Michel> Or am I missing something? > > Basically correct, except that the patch also needs an improved > version of vmap(), which was introduced in 2.5.68 only (IIRC). I'll > update my patch so it is a no-op unless you have a kernel >= 2.5.68. Hmm, isn't there a way to make it work with older kernels as well? For reference, we've been using http://www.penguinppc.org/~daenzer/DRI/drm-ioremapagp.diff by Benjamin Herrenschmidt for a while for Apple UniNorth northbridges. I was hoping to replace it with a cleaner solution like yours. Anyway, after applying your second patch, things looked much better, and the attached patch against the DRI CVS trunk builds without warnings here. -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer [-- Attachment #2: drm-cant_use_aperture.diff --] [-- Type: text/x-patch, Size: 26592 bytes --] Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c,v retrieving revision 1.9 diff -p -u -r1.9 mga_dma.c --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c 26 Apr 2003 22:28:55 -0000 1.9 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c 12 May 2003 20:59:24 -0000 @@ -554,9 +554,9 @@ static int mga_do_init_dma( drm_device_t (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); - DRM_IOREMAP( dev_priv->warp ); - DRM_IOREMAP( dev_priv->primary ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->warp, dev ); + DRM_IOREMAP( dev_priv->primary, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->warp->handle || !dev_priv->primary->handle || @@ -651,11 +651,11 @@ int mga_do_cleanup_dma( drm_device_t *de drm_mga_private_t *dev_priv = dev->dev_private; if ( dev_priv->warp != NULL ) - DRM_IOREMAPFREE( dev_priv->warp ); + DRM_IOREMAPFREE( dev_priv->warp, dev ); if ( dev_priv->primary != NULL ) - DRM_IOREMAPFREE( dev_priv->primary ); + DRM_IOREMAPFREE( dev_priv->primary, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); if ( dev_priv->head != NULL ) { mga_freelist_cleanup( dev ); Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h,v retrieving revision 1.8 diff -p -u -r1.8 mga_drv.h --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h 26 Apr 2003 23:32:00 -0000 1.8 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h 12 May 2003 20:59:24 -0000 @@ -226,7 +226,7 @@ do { \ if ( MGA_VERBOSE ) { \ DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \ (n), __FUNCTION__ ); \ - DRM_INFO( " space=0x%x req=0x%x\n", \ + DRM_INFO( " space=0x%x req=0x%Zx\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ prim = dev_priv->prim.start; \ @@ -276,7 +276,7 @@ do { \ #define DMA_WRITE( offset, val ) \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04x\n", \ + DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \ (u32)(val), write + (offset) * sizeof(u32) ); \ } \ *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \ Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c,v retrieving revision 1.7 diff -p -u -r1.7 r128_cce.c --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c 26 Apr 2003 22:28:56 -0000 1.7 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c 12 May 2003 20:59:24 -0000 @@ -350,8 +353,8 @@ static void r128_cce_init_ring_buffer( d R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -540,9 +543,9 @@ static int r128_do_init_cce( drm_device_ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cce_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cce_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -625,23 +622,22 @@ int r128_do_cleanup_cce( drm_device_t *d if ( dev->dev_private ) { drm_r128_private_t *dev_priv = dev->dev_private; -#if __REALLY_HAVE_SG +#if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) { -#endif if ( dev_priv->cce_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cce_ring ); + DRM_IOREMAPFREE( dev_priv->cce_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); -#if __REALLY_HAVE_SG - } else { + DRM_IOREMAPFREE( dev_priv->buffers, dev ); + } else +#endif /* __REALLY_HAVE_AGP + { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) DRM_ERROR( "failed to cleanup PCI GART!\n" ); } -#endif DRM(free)( dev->dev_private, sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c,v retrieving revision 1.25 diff -p -u -r1.25 radeon_cp.c --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c 6 May 2003 21:10:33 -0000 1.25 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c 12 May 2003 20:59:27 -0000 @@ -1152,9 +1152,9 @@ static int radeon_do_init_cp( drm_device init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cp_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cp_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cp_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -1277,20 +1273,21 @@ int radeon_do_cleanup_cp( drm_device_t * if ( dev->dev_private ) { drm_radeon_private_t *dev_priv = dev->dev_private; +#if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) { if ( dev_priv->cp_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cp_ring ); + DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); - } else { -#if __REALLY_HAVE_SG + DRM_IOREMAPFREE( dev_priv->buffers, dev ); + } else +#endif /* __REALLY_HAVE_AGP */ + { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) DRM_ERROR( "failed to cleanup PCI GART!\n" ); -#endif /* __REALLY_HAVE_SG */ } DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v retrieving revision 1.71 diff -p -u -r1.71 drmP.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h 26 Apr 2003 21:22:07 -0000 1.71 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h 12 May 2003 20:59:27 -0000 @@ -251,16 +251,16 @@ static inline struct page * vmalloc_to_p if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; } /* Mapping helper macros */ -#define DRM_IOREMAP(map) \ - (map)->handle = DRM(ioremap)( (map)->offset, (map)->size ) +#define DRM_IOREMAP(map, dev) \ + (map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) ) -#define DRM_IOREMAP_NOCACHE(map) \ - (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size) +#define DRM_IOREMAP_NOCACHE(map, dev) \ + (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev)) -#define DRM_IOREMAPFREE(map) \ - do { \ - if ( (map)->handle && (map)->size ) \ - DRM(ioremapfree)( (map)->handle, (map)->size ); \ +#define DRM_IOREMAPFREE(map, dev) \ + do { \ + if ( (map)->handle && (map)->size ) \ + DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \ } while (0) #define DRM_FIND_MAP(_map, _o) \ @@ -682,9 +682,10 @@ extern void DRM(free)(void *pt, siz extern unsigned long DRM(alloc_pages)(int order, int area); extern void DRM(free_pages)(unsigned long address, int order, int area); -extern void *DRM(ioremap)(unsigned long offset, unsigned long size); -extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size); -extern void DRM(ioremapfree)(void *pt, unsigned long size); +extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev); +extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, + drm_device_t *dev); +extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP extern agp_memory *DRM(alloc_agp)(int pages, u32 type); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h,v retrieving revision 1.20 diff -p -u -r1.20 drm_bufs.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h 28 Apr 2003 16:20:31 -0000 1.20 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h 12 May 2003 20:59:27 -0000 @@ -124,7 +124,7 @@ int DRM(addmap)( struct inode *inode, st MTRR_TYPE_WRCOMB, 1 ); } #endif - map->handle = DRM(ioremap)( map->offset, map->size ); + map->handle = DRM(ioremap)( map->offset, map->size, dev ); break; case _DRM_SHM: @@ -246,7 +246,7 @@ int DRM(rmmap)(struct inode *inode, stru DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h,v retrieving revision 1.35 diff -p -u -r1.35 drm_drv.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h 27 Apr 2003 09:53:58 -0000 1.35 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h 12 May 2003 20:59:27 -0000 @@ -454,7 +454,7 @@ static int DRM(takedown)( drm_device_t * DRM_DEBUG( "mtrr_del=%d\n", retcode ); } #endif - DRM(ioremapfree)( map->handle, map->size ); + DRM(ioremapfree)( map->handle, map->size, dev ); break; case _DRM_SHM: vfree(map->handle); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h,v retrieving revision 1.11 diff -p -u -r1.11 drm_memory.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h 26 Apr 2003 21:33:43 -0000 1.11 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h 12 May 2003 20:59:27 -0000 @@ -32,6 +32,7 @@ #define __NO_VERSION__ #include <linux/config.h> #include "drmP.h" +#include <linux/vmalloc.h> /* Cut down version of drm_memory_debug.h, which used to be called * drm_memory.h. If you want the debug functionality, change 0 to 1 @@ -39,6 +40,158 @@ */ #define DEBUG_MEMORY 0 +/* Need at least kernel v2.5.68 to get the 4-argument version of vmap(). */ +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + +#include <asm/agp.h> +#include <asm/tlbflush.h> + +#ifndef PAGE_AGP +# define PAGE_AGP PAGE_KERNEL_NOCACHE +#endif + +/* + * Find the drm_map that covers the range [offset, offset+size). + */ +static inline drm_map_t * +drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + struct list_head *list; + drm_map_list_t *r_list; + drm_map_t *map; + + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *) list; + map = r_list->map; + if (!map) + continue; + if (map->offset <= offset && (offset + size) <= (map->offset + map->size)) + return map; + } + return NULL; +} + +static inline void * +agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE; + struct drm_agp_mem *agpmem; + struct page **page_map; + void *addr; + + size = PAGE_ALIGN(size); + + for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) + if (agpmem->bound <= offset + && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size)) + break; + if (!agpmem) + return NULL; + + /* + * OK, we're mapping AGP space on a chipset/platform on which memory accesses by + * the CPU do not get remapped by the GART. We fix this by using the kernel's + * page-table instead (that's probably faster anyhow...). + */ + /* note: use vmalloc() because num_pages could be large... */ + page_map = vmalloc(num_pages * sizeof(struct page *)); + if (!page_map) + return NULL; + + phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; + for (i = 0; i < num_pages; ++i) + page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); + addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); + vfree(page_map); + if (!addr) + return NULL; + + flush_tlb_kernel_range((unsigned long) addr, (unsigned long) addr + size); + return addr; +} + +static inline unsigned long +drm_follow_page (void *vaddr) +{ + pgd_t *pgd = pgd_offset_k((unsigned long) vaddr); + pmd_t *pmd = pmd_offset(pgd, (unsigned long) vaddr); + pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr); + return pte_pfn(*ptep) << PAGE_SHIFT; +} + +#else /* !__REALLY_HAVE_AGP */ + +static inline void * +agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + return NULL; +} + +#endif /* !__REALLY_HAVE_AGP */ + +static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev) +{ + int remap_aperture = 0; + +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + remap_aperture = 1; + } +#endif + if (remap_aperture) + return agp_remap(offset, size, dev); + else + return ioremap(offset, size); +} + +static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size, + drm_device_t *dev) +{ + int remap_aperture = 0; + +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + remap_aperture = 1; + } +#endif + if (remap_aperture) + return agp_remap(offset, size, dev); + else + return ioremap_nocache(offset, size); +} + +static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev) +{ +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + int unmap_aperture = 0; + /* + * This is a bit ugly. It would be much cleaner if the DRM API would use separate + * routines for handling mappings in the AGP space. Hopefully this can be done in + * a future revision of the interface... + */ + if (dev->agp->cant_use_aperture + && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END)) + { + unsigned long offset; + drm_map_t *map; + + offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK); + map = drm_lookup_map(offset, size, dev); + if (map && map->type == _DRM_AGP) + unmap_aperture = 1; + } + if (unmap_aperture) + vunmap(pt); + else +#endif + iounmap(pt); +} #if DEBUG_MEMORY #include "drm_memory_debug.h" @@ -119,19 +272,19 @@ void DRM(free_pages)(unsigned long addre free_pages(address, order); } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) { - return ioremap(offset, size); + return drm_ioremap(offset, size, dev); } -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) { - return ioremap_nocache(offset, size); + return drm_ioremap_nocache(offset, size, dev); } -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) { - iounmap(pt); + drm_ioremapfree(pt, size, dev); } #if __REALLY_HAVE_AGP Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h,v retrieving revision 1.2 diff -p -u -r1.2 drm_memory_debug.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h 26 Apr 2003 21:33:43 -0000 1.2 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h 12 May 2003 20:59:27 -0000 @@ -270,7 +270,7 @@ void DRM(free_pages)(unsigned long addre } } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) { void *pt; @@ -280,7 +280,7 @@ void *DRM(ioremap)(unsigned long offset, return NULL; } - if (!(pt = ioremap(offset, size))) { + if (!(pt = drm_ioremap(offset, size, dev))) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -293,7 +293,7 @@ void *DRM(ioremap)(unsigned long offset, return pt; } -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) { void *pt; @@ -303,7 +303,7 @@ void *DRM(ioremap_nocache)(unsigned long return NULL; } - if (!(pt = ioremap_nocache(offset, size))) { + if (!(pt = drm_ioremap_nocache(offset, size, dev))) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -316,7 +316,7 @@ void *DRM(ioremap_nocache)(unsigned long return pt; } -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) { int alloc_count; int free_count; @@ -325,7 +325,7 @@ void DRM(ioremapfree)(void *pt, unsigned DRM_MEM_ERROR(DRM_MEM_MAPPINGS, "Attempt to free NULL pointer\n"); else - iounmap(pt); + drm_ioremapfree(pt, size, dev); spin_lock(&DRM(mem_lock)); DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h,v retrieving revision 1.21 diff -p -u -r1.21 drm_vm.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h 8 Apr 2003 01:30:41 -0000 1.21 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h 12 May 2003 20:59:27 -0000 @@ -108,12 +108,12 @@ struct page *DRM(vm_nopage)(struct vm_ar * Get the page, inc the use count, and return it */ offset = (baddr - agpmem->bound) >> PAGE_SHIFT; - agpmem->memory->memory[offset] &= dev->agp->page_mask; page = virt_to_page(__va(agpmem->memory->memory[offset])); get_page(page); - DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n", - baddr, __va(agpmem->memory->memory[offset]), offset); + DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", + baddr, __va(agpmem->memory->memory[offset]), offset, + atomic_read(&page->count)); return page; } @@ -207,7 +207,7 @@ void DRM(vm_shm_close)(struct vm_area_st DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); @@ -421,15 +421,16 @@ int DRM(mmap)(struct file *filp, struct switch (map->type) { case _DRM_AGP: -#if defined(__alpha__) +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { /* - * On Alpha we can't talk to bus dma address from the - * CPU, so for memory of type DRM_AGP, we'll deal with - * sorting out the real physical pages and mappings - * in nopage() + * On some platforms we can't talk to bus dma address from the CPU, so for + * memory of type DRM_AGP, we'll deal with sorting out the real physical + * pages and mappings in nopage() */ vma->vm_ops = &DRM(vm_ops); break; + } #endif /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: @@ -440,15 +441,15 @@ int DRM(mmap)(struct file *filp, struct pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; } -#elif defined(__ia64__) - if (map->type != _DRM_AGP) - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); #elif defined(__powerpc__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; #endif vma->vm_flags |= VM_IO; /* not in core dump */ } +#if defined(__ia64__) + if (map->type != _DRM_AGP) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#endif offset = DRIVER_GET_REG_OFS(); #ifdef __sparc__ if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c,v retrieving revision 1.26 diff -p -u -r1.26 gamma_dma.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c 26 Apr 2003 22:28:53 -0000 1.26 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c 12 May 2003 20:59:28 -0000 @@ -618,7 +618,7 @@ static int gamma_do_init_dma( drm_device } else { DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->buffers, dev ); buf = dma->buflist[GLINT_DRI_BUF_COUNT]; pgt = buf->address; @@ -657,7 +657,7 @@ int gamma_do_cleanup_dma( drm_device_t * drm_gamma_private_t *dev_priv = dev->dev_private; if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t), DRM_MEM_DRIVER ); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c,v retrieving revision 1.46 diff -p -u -r1.46 i810_dma.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c 26 Apr 2003 22:28:53 -0000 1.46 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c 12 May 2003 20:59:28 -0000 @@ -253,7 +253,7 @@ int i810_dma_cleanup(drm_device_t *dev) if(dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -270,7 +270,7 @@ int i810_dma_cleanup(drm_device_t *dev) drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; if ( buf_priv->kernel_virtual && buf->total ) - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -340,7 +340,7 @@ static int i810_freelist_init(drm_device *buf_priv->in_use = I810_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -393,7 +393,7 @@ static int i810_dma_initialize(drm_devic dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c,v retrieving revision 1.20 diff -p -u -r1.20 i830_dma.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c 26 Apr 2003 22:28:53 -0000 1.20 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c 12 May 2003 20:59:28 -0000 @@ -253,7 +253,7 @@ int i830_dma_cleanup(drm_device_t *dev) if (dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -271,7 +271,7 @@ int i830_dma_cleanup(drm_device_t *dev) drm_buf_t *buf = dma->buflist[ i ]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; if ( buf_priv->kernel_virtual && buf->total ) - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -347,7 +347,7 @@ static int i830_freelist_init(drm_device *buf_priv->in_use = I830_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -401,7 +401,7 @@ static int i830_dma_initialize(drm_devic dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 21:21 ` Michel Dänzer @ 2003-05-12 21:51 ` David Mosberger 2003-05-12 21:57 ` Christoph Hellwig 2003-05-13 0:34 ` Michel Dänzer 0 siblings, 2 replies; 27+ messages in thread From: David Mosberger @ 2003-05-12 21:51 UTC (permalink / raw) To: Michel Dänzer; +Cc: davidm, Dave Jones, linux-kernel, dri-devel Michel> Hmm, isn't there a way to make it work with older kernels as Michel> well? For reference, we've been using Michel> http://www.penguinppc.org/~daenzer/DRI/drm-ioremapagp.diff Michel> by Benjamin Herrenschmidt for a while for Apple UniNorth Michel> northbridges. It should be possible to add vmap() and vunmap() to kernel/vmalloc.c on older kernels. I think those are the only dependencies (apart from PAGE_AGP, which is taken care of by the latest patch). Michel> I was hoping to replace it with a cleaner solution like Michel> yours. Is there someone else on this list who would be able to look into backporting vmap()/vunmap() to 2.4? I don't use 2.4 with any regularity anymore, but I suppose if nobody else is interested, I could look into it. Michel> Anyway, after applying your second patch, things looked much Michel> better, and the attached patch against the DRI CVS trunk Michel> builds without warnings here. Great! Does this mean that next time Linus does a pull he'll pick up this stuff? --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 21:51 ` David Mosberger @ 2003-05-12 21:57 ` Christoph Hellwig 2003-05-12 22:08 ` Andrew Morton 2003-05-13 0:34 ` Michel Dänzer 1 sibling, 1 reply; 27+ messages in thread From: Christoph Hellwig @ 2003-05-12 21:57 UTC (permalink / raw) To: davidm; +Cc: Michel Dänzer, Dave Jones, linux-kernel, dri-devel On Mon, May 12, 2003 at 02:51:08PM -0700, David Mosberger wrote: > Is there someone else on this list who would be able to look into > backporting vmap()/vunmap() to 2.4? I don't use 2.4 with any > regularity anymore, but I suppose if nobody else is interested, I > could look into it. I did that for the XFS tree ages ago, it's also in the -ac and -aa (the latter still has the old three-arg version) now. I will submit it to Marcelo as soon as 2.4.21 is out (so with the current 2.4 merge rate it'll be in in about 6 month..) ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 21:57 ` Christoph Hellwig @ 2003-05-12 22:08 ` Andrew Morton 2003-05-12 22:20 ` Christoph Hellwig 0 siblings, 1 reply; 27+ messages in thread From: Andrew Morton @ 2003-05-12 22:08 UTC (permalink / raw) To: Christoph Hellwig; +Cc: davidm, michel, davej, linux-kernel, dri-devel Christoph Hellwig <hch@infradead.org> wrote: > > On Mon, May 12, 2003 at 02:51:08PM -0700, David Mosberger wrote: > > Is there someone else on this list who would be able to look into > > backporting vmap()/vunmap() to 2.4? I don't use 2.4 with any > > regularity anymore, but I suppose if nobody else is interested, I > > could look into it. > > I did that for the XFS tree ages ago, it's also in the -ac and -aa (the latter > still has the old three-arg version) now. I will submit it to Marcelo as soon > as 2.4.21 is out (so with the current 2.4 merge rate it'll be in in about 6 month..) > That 2.5 vmap rework introduced a subtle race-bug-goes-oops in vmalloc()/vfree(). The below patch from Bill fixes it up. From: William Lee Irwin III <wli@holomorphy.com> The new vmalloc() semantics from 2.5.32 had a race window. As things stand, the presence of a vm_area in the vmlist protects from allocators other than the owner examining the ptes in that area. This puts an ordering constraint on unmapping, so that allocators are required to unmap areas before removing them from the list or otherwise dropping the lock. Currently, unmap_vm_area() is done outside the lock and after the area is removed, which as we've seen from Felix von Leitner's test is oopsable. The following patch folds calls to unmap_vm_area() into remove_vm_area() to reinstate what are essentially the 2.4.x semantics of vfree(). This renders a number of unmap_vm_area() calls unnecessary (and in fact oopsable since they wipe ptes from later allocations). It's an open question as to whether this is sufficiently performant, but it is the minimally invasive approach. The more performant alternative is to provide the right API hooks to wipe the vmalloc() area clean before removing them from the list, using the ownership of the area to eliminate holding the vmlist_lock for the duration of the unmapping. If it proves to be necessary wli is on standby to implement it. 25-akpm/arch/i386/mm/ioremap.c | 1 - 25-akpm/arch/sparc64/kernel/module.c | 2 ++ 25-akpm/arch/x86_64/kernel/module.c | 2 +- 25-akpm/arch/x86_64/mm/ioremap.c | 1 - 25-akpm/mm/vmalloc.c | 3 +-- 5 files changed, 4 insertions(+), 5 deletions(-) diff -puN arch/i386/mm/ioremap.c~vmalloc-race-fix arch/i386/mm/ioremap.c --- 25/arch/i386/mm/ioremap.c~vmalloc-race-fix Mon May 12 14:17:19 2003 +++ 25-akpm/arch/i386/mm/ioremap.c Mon May 12 14:17:19 2003 @@ -222,7 +222,6 @@ void iounmap(void *addr) return; } - unmap_vm_area(p); if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff -puN arch/sparc64/kernel/module.c~vmalloc-race-fix arch/sparc64/kernel/module.c --- 25/arch/sparc64/kernel/module.c~vmalloc-race-fix Mon May 12 14:17:19 2003 +++ 25-akpm/arch/sparc64/kernel/module.c Mon May 12 14:17:19 2003 @@ -138,7 +138,9 @@ void *module_alloc(unsigned long size) /* Free memory returned from module_core_alloc/module_init_alloc */ void module_free(struct module *mod, void *module_region) { + write_lock(&vmlist_lock); module_unmap(module_region); + write_unlock(&vmlist_lock); /* FIXME: If module_region == mod->init_region, trim exception table entries. */ } diff -puN arch/x86_64/kernel/module.c~vmalloc-race-fix arch/x86_64/kernel/module.c --- 25/arch/x86_64/kernel/module.c~vmalloc-race-fix Mon May 12 14:17:19 2003 +++ 25-akpm/arch/x86_64/kernel/module.c Mon May 12 14:17:19 2003 @@ -48,7 +48,6 @@ void module_free(struct module *mod, voi for (prevp = &mod_vmlist ; (map = *prevp) ; prevp = &map->next) { if ((unsigned long)map->addr == addr) { *prevp = map->next; - write_unlock(&vmlist_lock); goto found; } } @@ -57,6 +56,7 @@ void module_free(struct module *mod, voi return; found: unmap_vm_area(map); + write_unlock(&vmlist_lock); if (map->pages) { for (i = 0; i < map->nr_pages; i++) if (map->pages[i]) diff -puN arch/x86_64/mm/ioremap.c~vmalloc-race-fix arch/x86_64/mm/ioremap.c --- 25/arch/x86_64/mm/ioremap.c~vmalloc-race-fix Mon May 12 14:17:19 2003 +++ 25-akpm/arch/x86_64/mm/ioremap.c Mon May 12 14:17:19 2003 @@ -222,7 +222,6 @@ void iounmap(void *addr) return; } - unmap_vm_area(p); if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff -puN mm/vmalloc.c~vmalloc-race-fix mm/vmalloc.c --- 25/mm/vmalloc.c~vmalloc-race-fix Mon May 12 14:17:19 2003 +++ 25-akpm/mm/vmalloc.c Mon May 12 14:17:19 2003 @@ -260,6 +260,7 @@ struct vm_struct *remove_vm_area(void *a return NULL; found: + unmap_vm_area(tmp); *p = tmp->next; write_unlock(&vmlist_lock); return tmp; @@ -283,8 +284,6 @@ void __vunmap(void *addr, int deallocate addr); return; } - - unmap_vm_area(area); if (deallocate_pages) { int i; _ ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 22:08 ` Andrew Morton @ 2003-05-12 22:20 ` Christoph Hellwig 0 siblings, 0 replies; 27+ messages in thread From: Christoph Hellwig @ 2003-05-12 22:20 UTC (permalink / raw) To: Andrew Morton Cc: Christoph Hellwig, davidm, michel, davej, linux-kernel, dri-devel Note that the 2.4 vmap implementation in the XFS tree doesn't have this problem. It's cludged into the old vmalloc design instead of beeing based on Linus' suggestion whiches buggy implementation (by me) opened this race. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 21:51 ` David Mosberger 2003-05-12 21:57 ` Christoph Hellwig @ 2003-05-13 0:34 ` Michel Dänzer 2003-05-13 1:09 ` David Mosberger 2003-05-13 7:43 ` David Mosberger 1 sibling, 2 replies; 27+ messages in thread From: Michel Dänzer @ 2003-05-13 0:34 UTC (permalink / raw) To: davidm; +Cc: Dave Jones, linux-kernel, dri-devel [-- Attachment #1: Type: text/plain, Size: 1524 bytes --] On Mon, 2003-05-12 at 23:51, David Mosberger wrote: > Michel> Hmm, isn't there a way to make it work with older kernels as > Michel> well? For reference, we've been using > Michel> http://www.penguinppc.org/~daenzer/DRI/drm-ioremapagp.diff > Michel> by Benjamin Herrenschmidt for a while for Apple UniNorth > Michel> northbridges. > > It should be possible to add vmap() and vunmap() to kernel/vmalloc.c > on older kernels. I think those are the only dependencies There are a couple more, like pte_offset_kernel(), pte_pfn(), pfn_to_page() and flush_tlb_kernel_range(). Getting this working with 2.4 seems like a lot of work and/or ugly. :\ > (apart from PAGE_AGP, which is taken care of by the latest patch). Not quite, PAGE_KERNEL_NOCACHE isn't defined on all architectures either. > Michel> Anyway, after applying your second patch, things looked much > Michel> better, and the attached patch against the DRI CVS trunk > Michel> builds without warnings here. > > Great! Does this mean that next time Linus does a pull he'll pick up > this stuff? No, I haven't committed it yet. I'd like to find a solution for PAGE_AGP first at least. Looks like we have to wait for Linus to merge the asm/agp.h part of your patch first? Meanwhile, here's another version of the DRI CVS patch, I got rid of the local variable in the drm_ioremap* functions. -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer [-- Attachment #2: drm-cant_use_aperture.diff --] [-- Type: text/x-patch, Size: 26240 bytes --] Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v retrieving revision 1.71 diff -p -u -r1.71 drmP.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h 26 Apr 2003 21:22:07 -0000 1.71 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h 13 May 2003 00:16:33 -0000 @@ -251,16 +253,16 @@ static inline struct page * vmalloc_to_p if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; } /* Mapping helper macros */ -#define DRM_IOREMAP(map) \ - (map)->handle = DRM(ioremap)( (map)->offset, (map)->size ) +#define DRM_IOREMAP(map, dev) \ + (map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) ) + +#define DRM_IOREMAP_NOCACHE(map, dev) \ + (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev)) + +#define DRM_IOREMAPFREE(map, dev) \ + do { \ + if ( (map)->handle && (map)->size ) \ + DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \ + } while (0) - -#define DRM_IOREMAP_NOCACHE(map) \ - (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size) - -#define DRM_IOREMAPFREE(map) \ - do { \ - if ( (map)->handle && (map)->size ) \ - DRM(ioremapfree)( (map)->handle, (map)->size ); \ - } while (0) #define DRM_FIND_MAP(_map, _o) \ @@ -682,9 +693,10 @@ extern void DRM(free)(void *pt, siz extern unsigned long DRM(alloc_pages)(int order, int area); extern void DRM(free_pages)(unsigned long address, int order, int area); -extern void *DRM(ioremap)(unsigned long offset, unsigned long size); -extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size); -extern void DRM(ioremapfree)(void *pt, unsigned long size); +extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev); +extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, + drm_device_t *dev); +extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP extern agp_memory *DRM(alloc_agp)(int pages, u32 type); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h,v retrieving revision 1.20 diff -p -u -r1.20 drm_bufs.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h 28 Apr 2003 16:20:31 -0000 1.20 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h 13 May 2003 00:16:33 -0000 @@ -124,7 +124,7 @@ int DRM(addmap)( struct inode *inode, st MTRR_TYPE_WRCOMB, 1 ); } #endif - map->handle = DRM(ioremap)( map->offset, map->size ); + map->handle = DRM(ioremap)( map->offset, map->size, dev ); break; case _DRM_SHM: @@ -246,7 +246,7 @@ int DRM(rmmap)(struct inode *inode, stru DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h,v retrieving revision 1.35 diff -p -u -r1.35 drm_drv.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h 27 Apr 2003 09:53:58 -0000 1.35 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h 13 May 2003 00:16:34 -0000 @@ -454,7 +454,7 @@ static int DRM(takedown)( drm_device_t * DRM_DEBUG( "mtrr_del=%d\n", retcode ); } #endif - DRM(ioremapfree)( map->handle, map->size ); + DRM(ioremapfree)( map->handle, map->size, dev ); break; case _DRM_SHM: vfree(map->handle); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h,v retrieving revision 1.11 diff -p -u -r1.11 drm_memory.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h 26 Apr 2003 21:33:43 -0000 1.11 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory.h 13 May 2003 00:16:34 -0000 @@ -32,6 +32,7 @@ #define __NO_VERSION__ #include <linux/config.h> #include "drmP.h" +#include <linux/vmalloc.h> /* Cut down version of drm_memory_debug.h, which used to be called * drm_memory.h. If you want the debug functionality, change 0 to 1 @@ -39,6 +40,141 @@ */ #define DEBUG_MEMORY 0 +/* Need at least kernel v2.5.68 to get the 4-argument version of vmap(). */ +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + +#include <asm/agp.h> +#include <asm/tlbflush.h> + +#ifndef PAGE_AGP +# define PAGE_AGP PAGE_KERNEL_NOCACHE +#endif + +/* + * Find the drm_map that covers the range [offset, offset+size). + */ +static inline drm_map_t * +drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + struct list_head *list; + drm_map_list_t *r_list; + drm_map_t *map; + + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *) list; + map = r_list->map; + if (!map) + continue; + if (map->offset <= offset && (offset + size) <= (map->offset + map->size)) + return map; + } + return NULL; +} + +static inline void * +agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev) +{ + unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE; + struct drm_agp_mem *agpmem; + struct page **page_map; + void *addr; + + size = PAGE_ALIGN(size); + + for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) + if (agpmem->bound <= offset + && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size)) + break; + if (!agpmem) + return NULL; + + /* + * OK, we're mapping AGP space on a chipset/platform on which memory accesses by + * the CPU do not get remapped by the GART. We fix this by using the kernel's + * page-table instead (that's probably faster anyhow...). + */ + /* note: use vmalloc() because num_pages could be large... */ + page_map = vmalloc(num_pages * sizeof(struct page *)); + if (!page_map) + return NULL; + + phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; + for (i = 0; i < num_pages; ++i) + page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); + addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); + vfree(page_map); + if (!addr) + return NULL; + + flush_tlb_kernel_range((unsigned long) addr, (unsigned long) addr + size); + return addr; +} + +static inline unsigned long +drm_follow_page (void *vaddr) +{ + pgd_t *pgd = pgd_offset_k((unsigned long) vaddr); + pmd_t *pmd = pmd_offset(pgd, (unsigned long) vaddr); + pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr); + return pte_pfn(*ptep) << PAGE_SHIFT; +} + +#endif /* __REALLY_HAVE_AGP */ + +static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev) +{ +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + return agp_remap(offset, size, dev); + } +#endif + + return ioremap(offset, size); +} + +static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size, + drm_device_t *dev) +{ +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + if (dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + return agp_remap(offset, size, dev); + } +#endif + + return ioremap_nocache(offset, size); +} + +static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev) +{ +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + /* + * This is a bit ugly. It would be much cleaner if the DRM API would use separate + * routines for handling mappings in the AGP space. Hopefully this can be done in + * a future revision of the interface... + */ + if (dev->agp->cant_use_aperture + && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END)) + { + unsigned long offset; + drm_map_t *map; + + offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK); + map = drm_lookup_map(offset, size, dev); + if (map && map->type == _DRM_AGP) { + vunmap(pt); + return; + } + } +#endif + + iounmap(pt); +} #if DEBUG_MEMORY #include "drm_memory_debug.h" @@ -119,19 +255,19 @@ void DRM(free_pages)(unsigned long addre free_pages(address, order); } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) { - return ioremap(offset, size); + return drm_ioremap(offset, size, dev); } -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) { - return ioremap_nocache(offset, size); + return drm_ioremap_nocache(offset, size, dev); } -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) { - iounmap(pt); + drm_ioremapfree(pt, size, dev); } #if __REALLY_HAVE_AGP Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h,v retrieving revision 1.2 diff -p -u -r1.2 drm_memory_debug.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h 26 Apr 2003 21:33:43 -0000 1.2 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_memory_debug.h 13 May 2003 00:16:34 -0000 @@ -270,7 +270,7 @@ void DRM(free_pages)(unsigned long addre } } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) { void *pt; @@ -280,7 +280,7 @@ void *DRM(ioremap)(unsigned long offset, return NULL; } - if (!(pt = ioremap(offset, size))) { + if (!(pt = drm_ioremap(offset, size, dev))) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -293,7 +293,7 @@ void *DRM(ioremap)(unsigned long offset, return pt; } -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) { void *pt; @@ -303,7 +303,7 @@ void *DRM(ioremap_nocache)(unsigned long return NULL; } - if (!(pt = ioremap_nocache(offset, size))) { + if (!(pt = drm_ioremap_nocache(offset, size, dev))) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; spin_unlock(&DRM(mem_lock)); @@ -316,7 +316,7 @@ void *DRM(ioremap_nocache)(unsigned long return pt; } -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) { int alloc_count; int free_count; @@ -325,7 +325,7 @@ void DRM(ioremapfree)(void *pt, unsigned DRM_MEM_ERROR(DRM_MEM_MAPPINGS, "Attempt to free NULL pointer\n"); else - iounmap(pt); + drm_ioremapfree(pt, size, dev); spin_lock(&DRM(mem_lock)); DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h,v retrieving revision 1.21 diff -p -u -r1.21 drm_vm.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h 8 Apr 2003 01:30:41 -0000 1.21 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h 13 May 2003 00:16:35 -0000 @@ -108,12 +108,12 @@ struct page *DRM(vm_nopage)(struct vm_ar * Get the page, inc the use count, and return it */ offset = (baddr - agpmem->bound) >> PAGE_SHIFT; - agpmem->memory->memory[offset] &= dev->agp->page_mask; page = virt_to_page(__va(agpmem->memory->memory[offset])); get_page(page); - DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n", - baddr, __va(agpmem->memory->memory[offset]), offset); + DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", + baddr, __va(agpmem->memory->memory[offset]), offset, + atomic_read(&page->count)); return page; } @@ -207,7 +207,7 @@ void DRM(vm_shm_close)(struct vm_area_st DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); @@ -421,15 +430,16 @@ int DRM(mmap)(struct file *filp, struct switch (map->type) { case _DRM_AGP: -#if defined(__alpha__) +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { /* - * On Alpha we can't talk to bus dma address from the - * CPU, so for memory of type DRM_AGP, we'll deal with - * sorting out the real physical pages and mappings - * in nopage() + * On some platforms we can't talk to bus dma address from the CPU, so for + * memory of type DRM_AGP, we'll deal with sorting out the real physical + * pages and mappings in nopage() */ vma->vm_ops = &DRM(vm_ops); break; + } #endif /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: @@ -440,15 +453,15 @@ int DRM(mmap)(struct file *filp, struct pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; } -#elif defined(__ia64__) - if (map->type != _DRM_AGP) - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); #elif defined(__powerpc__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; #endif vma->vm_flags |= VM_IO; /* not in core dump */ } +#if defined(__ia64__) + if (map->type != _DRM_AGP) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#endif offset = DRIVER_GET_REG_OFS(); #ifdef __sparc__ if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c,v retrieving revision 1.26 diff -p -u -r1.26 gamma_dma.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c 26 Apr 2003 22:28:53 -0000 1.26 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c 13 May 2003 00:16:37 -0000 @@ -618,7 +618,7 @@ static int gamma_do_init_dma( drm_device } else { DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->buffers, dev ); buf = dma->buflist[GLINT_DRI_BUF_COUNT]; pgt = buf->address; @@ -657,7 +657,7 @@ int gamma_do_cleanup_dma( drm_device_t * drm_gamma_private_t *dev_priv = dev->dev_private; if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t), DRM_MEM_DRIVER ); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c,v retrieving revision 1.46 diff -p -u -r1.46 i810_dma.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c 26 Apr 2003 22:28:53 -0000 1.46 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c 13 May 2003 00:16:37 -0000 @@ -253,7 +253,7 @@ int i810_dma_cleanup(drm_device_t *dev) if(dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -270,7 +270,7 @@ int i810_dma_cleanup(drm_device_t *dev) drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; if ( buf_priv->kernel_virtual && buf->total ) - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -340,7 +340,7 @@ static int i810_freelist_init(drm_device *buf_priv->in_use = I810_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -393,7 +393,7 @@ static int i810_dma_initialize(drm_devic dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c,v retrieving revision 1.20 diff -p -u -r1.20 i830_dma.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c 26 Apr 2003 22:28:53 -0000 1.20 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c 13 May 2003 00:16:37 -0000 @@ -253,7 +253,7 @@ int i830_dma_cleanup(drm_device_t *dev) if (dev_priv->ring.virtual_start) { DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, - dev_priv->ring.Size); + dev_priv->ring.Size, dev); } if (dev_priv->hw_status_page) { pci_free_consistent(dev->pdev, PAGE_SIZE, @@ -271,7 +271,7 @@ int i830_dma_cleanup(drm_device_t *dev) drm_buf_t *buf = dma->buflist[ i ]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; if ( buf_priv->kernel_virtual && buf->total ) - DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev); } } return 0; @@ -347,7 +347,7 @@ static int i830_freelist_init(drm_device *buf_priv->in_use = I830_BUF_FREE; buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, - buf->total); + buf->total, dev); } return 0; } @@ -401,7 +401,7 @@ static int i830_dma_initialize(drm_devic dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + init->ring_start, - init->ring_size); + init->ring_size, dev); if (dev_priv->ring.virtual_start == NULL) { dev->dev_private = (void *) dev_priv; Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c,v retrieving revision 1.9 diff -p -u -r1.9 mga_dma.c --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c 26 Apr 2003 22:28:55 -0000 1.9 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_dma.c 13 May 2003 00:16:37 -0000 @@ -554,9 +554,9 @@ static int mga_do_init_dma( drm_device_t (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); - DRM_IOREMAP( dev_priv->warp ); - DRM_IOREMAP( dev_priv->primary ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->warp, dev ); + DRM_IOREMAP( dev_priv->primary, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->warp->handle || !dev_priv->primary->handle || @@ -651,11 +651,11 @@ int mga_do_cleanup_dma( drm_device_t *de drm_mga_private_t *dev_priv = dev->dev_private; if ( dev_priv->warp != NULL ) - DRM_IOREMAPFREE( dev_priv->warp ); + DRM_IOREMAPFREE( dev_priv->warp, dev ); if ( dev_priv->primary != NULL ) - DRM_IOREMAPFREE( dev_priv->primary ); + DRM_IOREMAPFREE( dev_priv->primary, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPFREE( dev_priv->buffers, dev ); if ( dev_priv->head != NULL ) { mga_freelist_cleanup( dev ); Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h,v retrieving revision 1.8 diff -p -u -r1.8 mga_drv.h --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h 26 Apr 2003 23:32:00 -0000 1.8 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h 13 May 2003 00:16:37 -0000 @@ -226,7 +226,7 @@ do { \ if ( MGA_VERBOSE ) { \ DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \ (n), __FUNCTION__ ); \ - DRM_INFO( " space=0x%x req=0x%x\n", \ + DRM_INFO( " space=0x%x req=0x%Zx\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ prim = dev_priv->prim.start; \ @@ -276,7 +276,7 @@ do { \ #define DMA_WRITE( offset, val ) \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04x\n", \ + DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \ (u32)(val), write + (offset) * sizeof(u32) ); \ } \ *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \ Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c,v retrieving revision 1.7 diff -p -u -r1.7 r128_cce.c --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c 26 Apr 2003 22:28:56 -0000 1.7 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c 13 May 2003 00:16:37 -0000 @@ -350,8 +357,8 @@ static void r128_cce_init_ring_buffer( d R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -540,9 +547,9 @@ static int r128_do_init_cce( drm_device_ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cce_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cce_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -625,23 +632,22 @@ int r128_do_cleanup_cce( drm_device_t *d if ( dev->dev_private ) { drm_r128_private_t *dev_priv = dev->dev_private; -#if __REALLY_HAVE_SG +#if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) { -#endif if ( dev_priv->cce_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cce_ring ); + DRM_IOREMAPFREE( dev_priv->cce_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); -#if __REALLY_HAVE_SG - } else { + DRM_IOREMAPFREE( dev_priv->buffers, dev ); + } else +#endif /* __REALLY_HAVE_AGP + { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) DRM_ERROR( "failed to cleanup PCI GART!\n" ); } -#endif DRM(free)( dev->dev_private, sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c,v retrieving revision 1.25 diff -p -u -r1.25 radeon_cp.c --- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c 6 May 2003 21:10:33 -0000 1.25 +++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c 13 May 2003 00:16:37 -0000 @@ -1152,9 +1152,9 @@ static int radeon_do_init_cp( drm_device init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cp_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAP( dev_priv->cp_ring, dev ); + DRM_IOREMAP( dev_priv->ring_rptr, dev ); + DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->cp_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -1277,20 +1279,21 @@ int radeon_do_cleanup_cp( drm_device_t * if ( dev->dev_private ) { drm_radeon_private_t *dev_priv = dev->dev_private; +#if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) { if ( dev_priv->cp_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cp_ring ); + DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers ); - } else { -#if __REALLY_HAVE_SG + DRM_IOREMAPFREE( dev_priv->buffers, dev ); + } else +#endif /* __REALLY_HAVE_AGP */ + { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) DRM_ERROR( "failed to cleanup PCI GART!\n" ); -#endif /* __REALLY_HAVE_SG */ } DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-13 0:34 ` Michel Dänzer @ 2003-05-13 1:09 ` David Mosberger 2003-05-13 13:33 ` Ivan Kokshaysky 2003-05-13 7:43 ` David Mosberger 1 sibling, 1 reply; 27+ messages in thread From: David Mosberger @ 2003-05-13 1:09 UTC (permalink / raw) To: Michel Dänzer; +Cc: davidm, Dave Jones, linux-kernel, dri-devel Michel> There are a couple more, like pte_offset_kernel(), Michel> pte_pfn(), pfn_to_page() and Michel> flush_tlb_kernel_range(). Getting this working with 2.4 Michel> seems like a lot of work and/or ugly. :\ Just goes to show how quickly one gets used to 2.5... ;-) Let me take a look at these. >> (apart from PAGE_AGP, which is taken care of by the latest >> patch). Michel> Not quite, PAGE_KERNEL_NOCACHE isn't defined on all Michel> architectures either. OK, I believe the only other architecture that sets "cant_use_aperture" is Alpha. I asked some Alpha folks several months ago about my patch, but never got a conclusive answer. IIRC, on Alpha the physical address itself determines cacheablity. If so, we can use PAGE_KERNEL (which is universal) instead of PAGE_KERNEL_NOCACHE. Clearly the patch needs to be tested on Alpha. The upside is that it should let the Alpha folks get rid of a lot of ugliness in the ioremap() code. --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-13 1:09 ` David Mosberger @ 2003-05-13 13:33 ` Ivan Kokshaysky 2003-05-13 16:20 ` David Mosberger 0 siblings, 1 reply; 27+ messages in thread From: Ivan Kokshaysky @ 2003-05-13 13:33 UTC (permalink / raw) To: davidm Cc: Wiedemeier, Jeff, Michel Dänzer, Dave Jones, linux-kernel, dri-devel On Mon, May 12, 2003 at 06:09:16PM -0700, David Mosberger wrote: > OK, I believe the only other architecture that sets > "cant_use_aperture" is Alpha. Note that some Alphas may have "cant_use_aperture" cleared. I mean Nautilus - unfortunate product of Athlon northbridge and EV6 interbreeding... I've just managed to get agpgart working to some degree on one of these beasts (UP1500), but with so many ugly and fragile hacks that I'm not sure that I ever want to submit this. ;-) > I asked some Alpha folks several months > ago about my patch, but never got a conclusive answer. IIRC, on Alpha > the physical address itself determines cacheablity. If so, we can use > PAGE_KERNEL (which is universal) instead of PAGE_KERNEL_NOCACHE. Yes. > Clearly the patch needs to be tested on Alpha. The upside is that it > should let the Alpha folks get rid of a lot of ugliness in the > ioremap() code. That would be great. [Cc'd to Jeff, who wrote Alpha AGP code] Ivan. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-13 13:33 ` Ivan Kokshaysky @ 2003-05-13 16:20 ` David Mosberger 2003-05-14 9:41 ` Ivan Kokshaysky 0 siblings, 1 reply; 27+ messages in thread From: David Mosberger @ 2003-05-13 16:20 UTC (permalink / raw) To: Ivan Kokshaysky Cc: davidm, Wiedemeier, Jeff, Michel Dänzer, Dave Jones, linux-kernel, dri-devel >>>>> On Tue, 13 May 2003 17:33:47 +0400, Ivan Kokshaysky <ink@jurassic.park.msu.ru> said: Ivan> On Mon, May 12, 2003 at 06:09:16PM -0700, David Mosberger Ivan> wrote: >> OK, I believe the only other architecture that sets >> "cant_use_aperture" is Alpha. Ivan> Note that some Alphas may have "cant_use_aperture" cleared. "Interesting". Ivan> I mean Nautilus - unfortunate product of Athlon northbridge Ivan> and EV6 interbreeding... I've just managed to get agpgart Ivan> working to some degree on one of these beasts (UP1500), but Ivan> with so many ugly and fragile hacks that I'm not sure that I Ivan> ever want to submit this. ;-) If cant_use_aperture isn't set, my patch won't help, but it shouldn't hurt anything either. I.e., you should be no worse off than before. What's the nature of those "ugly and fragile" hacks? Are you saying that CPU accesses to AGP space aren't remapped in the "normal" (PC) way? Or is it something entirely different? >> I asked some Alpha folks several months ago about my patch, but >> never got a conclusive answer. IIRC, on Alpha the physical >> address itself determines cacheablity. If so, we can use >> PAGE_KERNEL (which is universal) instead of PAGE_KERNEL_NOCACHE. Ivan> Yes. Thanks for confirming. --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-13 16:20 ` David Mosberger @ 2003-05-14 9:41 ` Ivan Kokshaysky 2003-05-14 10:27 ` Michel Dänzer 2003-05-14 17:09 ` David Mosberger 0 siblings, 2 replies; 27+ messages in thread From: Ivan Kokshaysky @ 2003-05-14 9:41 UTC (permalink / raw) To: davidm Cc: Wiedemeier, Jeff, Michel Dänzer, Dave Jones, linux-kernel, dri-devel On Tue, May 13, 2003 at 09:20:09AM -0700, David Mosberger wrote: > Ivan> Note that some Alphas may have "cant_use_aperture" cleared. > > "Interesting". Yep. ;-) > If cant_use_aperture isn't set, my patch won't help, but it shouldn't > hurt anything either. I.e., you should be no worse off than before. Sure. Basically, I'll only need to re-diff. > What's the nature of those "ugly and fragile" hacks? Are you saying > that CPU accesses to AGP space aren't remapped in the "normal" (PC) > way? Or is it something entirely different? Ok, you asked for it... :-) As you know, Alpha architecture is entirely cache coherent by design, i.e. there are no such things as non-cacheable mappings or cache flushing in hardware. Native Alpha Titan/Marvel AGP controllers are also cache coherent (kind of AGP extension of traditional Alpha PCI IOMMU). However, the "normal" PC AGP implementation isn't - this applies to AMD-751/761 AGP controllers on Nautilus as well. The AGP window on these chipsets is accessible by CPU *only* in the system memory address space, i.e. it's always cacheable and thus totally useless on Alpha. Fortunately, AMD northbridges (at least 761) have some features that allow *limited* access to system memory, including AGP space, through EV6 non-cacheable IO address space (using "magic" 16 Gb offset). Limitations: - quadword writes corrupt ECC. EV6 doesn't generate ECC for IO space, but the chipset expects ECC from CPU on full quad writes (narrower writes are ok since the chipset does read-modify-write and updates ECC by itself). This wouldn't be a big deal since nobody should access pages mapped into AGP, but there are occasional speculative loads which hit data with bad ECC that causing the machine checks. So I must handle these machine checks properly - check that the page is AGP and then either scrub the affected location to fix ECC or dismiss the machine check. - according to AMD specs, reads to this "non-cacheable" region are not supported. Not quite true, as quadword loads (ldq/ldq_u) do work (verified on 761, 751 needs testing). Narrower loads indeed don't work. Fortunately, AGP space reads seem to be sort of exotic (in both kernel and userspace drivers), so they can be easily found and converted to ldq/ldq_u. In addition I cannot trust PALcode error handler on UP1500 - sometimes it does bogus things... By now I have all this crap running more or less stable with radeon 7200 card. Machine check handling needs some improvements though. Ivan. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-14 9:41 ` Ivan Kokshaysky @ 2003-05-14 10:27 ` Michel Dänzer 2003-05-14 17:09 ` David Mosberger 1 sibling, 0 replies; 27+ messages in thread From: Michel Dänzer @ 2003-05-14 10:27 UTC (permalink / raw) To: Ivan Kokshaysky Cc: davidm, Wiedemeier, Jeff, Dave Jones, linux-kernel, dri-devel On Mit, 2003-05-14 at 11:41, Ivan Kokshaysky wrote: > On Tue, May 13, 2003 at 09:20:09AM -0700, David Mosberger wrote: > > > What's the nature of those "ugly and fragile" hacks? Are you saying > > that CPU accesses to AGP space aren't remapped in the "normal" (PC) > > way? Or is it something entirely different? > > Ok, you asked for it... :-) > As you know, Alpha architecture is entirely cache coherent > by design, i.e. there are no such things as non-cacheable mappings > or cache flushing in hardware. Native Alpha Titan/Marvel AGP controllers > are also cache coherent (kind of AGP extension of traditional > Alpha PCI IOMMU). > However, the "normal" PC AGP implementation isn't - this applies > to AMD-751/761 AGP controllers on Nautilus as well. > The AGP window on these chipsets is accessible by CPU *only* in the > system memory address space, i.e. it's always cacheable and thus > totally useless on Alpha. Set cant_use_aperture and use David's patch then? :) -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-14 9:41 ` Ivan Kokshaysky 2003-05-14 10:27 ` Michel Dänzer @ 2003-05-14 17:09 ` David Mosberger 1 sibling, 0 replies; 27+ messages in thread From: David Mosberger @ 2003-05-14 17:09 UTC (permalink / raw) To: Ivan Kokshaysky Cc: davidm, Wiedemeier, Jeff, Michel Dänzer, Dave Jones, linux-kernel, dri-devel >>>>> On Wed, 14 May 2003 13:41:41 +0400, Ivan Kokshaysky <ink@jurassic.park.msu.ru> said: >> What's the nature of those "ugly and fragile" hacks? Are you saying >> that CPU accesses to AGP space aren't remapped in the "normal" (PC) >> way? Or is it something entirely different? Ivan> Ok, you asked for it... :-) My golly, I don't envy you! --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-13 0:34 ` Michel Dänzer 2003-05-13 1:09 ` David Mosberger @ 2003-05-13 7:43 ` David Mosberger 2003-05-14 14:08 ` Michel Dänzer 1 sibling, 1 reply; 27+ messages in thread From: David Mosberger @ 2003-05-13 7:43 UTC (permalink / raw) To: Michel Dänzer; +Cc: davidm, Dave Jones, linux-kernel, dri-devel >>>>> On 13 May 2003 02:34:41 +0200, Michel Dänzer <michel@daenzer.net> said: >> It should be possible to add vmap() and vunmap() to kernel/vmalloc.c >> on older kernels. I think those are the only dependencies Michel> There are a couple more, like pte_offset_kernel(), pte_pfn(), Michel> pfn_to_page() and flush_tlb_kernel_range(). Getting this working with Michel> 2.4 seems like a lot of work and/or ugly. :\ Actually, it turns out I'm really not well positioned to do this, because the ia64 agp patch for 2.4 looks very different from the 2.5 and your tree looks rather different from the DRM stuff that's in the official Linux tree (correct me if I'm wrong here). Anyhow, this should get you close to compiling (and working, hopefully), modulo vmap/vunmap: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) # define pte_offset_kernel(dir, address) pte_offset(dir, address) # define pte_pfn(pte) (pte_page(pte) - mem_map) # define flush_tlb_kernel_range(s,e) flush_tlb_all() #endif The above definition of pte_pfn() is not truly platform-independent, but I believe it works on all platforms that support AGP. The problem is that we can't just use page_address(), because the physical address in the PTE may not be a valid memory address (it could be an I/O address). --david ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-13 7:43 ` David Mosberger @ 2003-05-14 14:08 ` Michel Dänzer 2003-05-15 15:59 ` David Mosberger 0 siblings, 1 reply; 27+ messages in thread From: Michel Dänzer @ 2003-05-14 14:08 UTC (permalink / raw) To: davidm; +Cc: Dave Jones, linux-kernel, dri-devel On Die, 2003-05-13 at 09:43, David Mosberger wrote: > >>>>> On 13 May 2003 02:34:41 +0200, Michel Dänzer <michel@daenzer.net> said: > > >> It should be possible to add vmap() and vunmap() to kernel/vmalloc.c > >> on older kernels. I think those are the only dependencies > > Michel> There are a couple more, like pte_offset_kernel(), pte_pfn(), > Michel> pfn_to_page() and flush_tlb_kernel_range(). Getting this working with > Michel> 2.4 seems like a lot of work and/or ugly. :\ > > Actually, it turns out I'm really not well positioned to do this, > because the ia64 agp patch for 2.4 looks very different from the 2.5 > and your tree looks rather different from the DRM stuff that's in the > official Linux tree (correct me if I'm wrong here). > > Anyhow, this should get you close to compiling (and working, > hopefully), modulo vmap/vunmap: > > #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) > # define pte_offset_kernel(dir, address) pte_offset(dir, address) > # define pte_pfn(pte) (pte_page(pte) - mem_map) > # define flush_tlb_kernel_range(s,e) flush_tlb_all() > #endif [...] > The above definition of pte_pfn() is not truly platform-independent, > but I believe it works on all platforms that support AGP. Looks like it should work on sane PPC systems as well. :) # define pfn_to_page(pfn) (mem_map + (pfn)) is also needed. After some more thinking, the way to go for deciding whether or not to use the new code probably isn't by checking the version but by using some Makefile trickery as there is already for do_munmap and remap_page_range. Once that is in place, it looks like I can finally commit it. :) -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-14 14:08 ` Michel Dänzer @ 2003-05-15 15:59 ` David Mosberger 2003-05-15 22:37 ` Michel Dänzer 0 siblings, 1 reply; 27+ messages in thread From: David Mosberger @ 2003-05-15 15:59 UTC (permalink / raw) To: Michel Dänzer Cc: davidm, Dave Jones, linux-kernel, dri-devel, Jeff.Wiedemeier Hi Michel, In regards to the Alpha platform: Jeff Wiedemeier was able to get things to work after applying the attached small patch. He says: What was happening is that the offset was a system-relative representation of the address and the (agpmem->bound) was bus-relative, so it couldn't find the right agpmem. This patch makes the offset bus-relative before the scan (and with this patch, DRI/DRM is working on a Marvel...) If it looks OK to you, can you add it? Thanks, --david diff -Nuar pre/drivers/char/drm/drm_memory.h post/drivers/char/drm/drm_memory.h --- pre/drivers/char/drm/drm_memory.h Wed May 14 20:04:17 2003 +++ post/drivers/char/drm/drm_memory.h Wed May 14 20:05:31 2003 @@ -75,6 +75,10 @@ size = PAGE_ALIGN(size); +#ifdef __alpha__ + offset -= dev->hose->mem_space->start; +#endif + for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) if (agpmem->bound <= offset && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size)) ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: Improved DRM support for cant_use_aperture platforms 2003-05-15 15:59 ` David Mosberger @ 2003-05-15 22:37 ` Michel Dänzer 2003-05-16 23:50 ` [Dri-devel] " Michel Dänzer 0 siblings, 1 reply; 27+ messages in thread From: Michel Dänzer @ 2003-05-15 22:37 UTC (permalink / raw) To: davidm; +Cc: Dave Jones, linux-kernel, dri-devel, Jeff.Wiedemeier On Thu, 2003-05-15 at 17:59, David Mosberger wrote: > > In regards to the Alpha platform: Jeff Wiedemeier was able to get things > to work after applying the attached small patch. He says: > > What was happening is that the offset was a system-relative > representation of the address and the (agpmem->bound) was > bus-relative, so it couldn't find the right agpmem. > > This patch makes the offset bus-relative before the scan (and with > this patch, DRI/DRM is working on a Marvel...) > > If it looks OK to you, can you add it? Sure, thanks. http://www.penguinppc.org/~daenzer/DRI/drm-cant_use_aperture.diff is more or less what I'd like to commit. Comments appreciated. -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Dri-devel] Re: Improved DRM support for cant_use_aperture platforms 2003-05-15 22:37 ` Michel Dänzer @ 2003-05-16 23:50 ` Michel Dänzer 0 siblings, 0 replies; 27+ messages in thread From: Michel Dänzer @ 2003-05-16 23:50 UTC (permalink / raw) To: davidm; +Cc: Dave Jones, linux-kernel, dri-devel, Jeff.Wiedemeier On Fri, 2003-05-16 at 00:37, Michel Dänzer wrote: > > http://www.penguinppc.org/~daenzer/DRI/drm-cant_use_aperture.diff > > is more or less what I'd like to commit. Comments appreciated. I just committed it, thanks to everyone involved. -- Earthling Michel Dänzer \ Debian (powerpc), XFree86 and DRI developer Software libre enthusiast \ http://svcs.affero.net/rm.php?r=daenzer ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Dri-devel] Re: Improved DRM support for cant_use_aperture platforms 2003-05-12 19:48 ` [Dri-devel] " Michel Dänzer 2003-05-12 20:19 ` David Mosberger @ 2003-05-12 20:40 ` David Mosberger 1 sibling, 0 replies; 27+ messages in thread From: David Mosberger @ 2003-05-12 20:40 UTC (permalink / raw) To: Michel Dänzer; +Cc: davidm, Dave Jones, linux-kernel, dri-devel OK, could you try with this patch applied on top of my previous patch? Checking against KERNEL_VERSION(2,5,68) ensures that we have the new (4-wargument) vmap() call and the "#ifndef PAGE_AGP" part ensures that things will compile fine until the kernel's asm/agp.h gets updated. --david ===== drivers/char/drm/drm_memory.h 1.16 vs edited ===== --- 1.16/drivers/char/drm/drm_memory.h Sat May 10 01:32:08 2003 +++ edited/drivers/char/drm/drm_memory.h Mon May 12 13:37:57 2003 @@ -42,7 +42,12 @@ */ #define DEBUG_MEMORY 0 -#if __REALLY_HAVE_AGP +/* Need at least kernel v2.5.68 to get the 4-argument version of vmap(). */ +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) + +#ifndef PAGE_AGP +# define PAGE_AGP PAGE_KERNEL_NOCACHE +#endif /* * Find the drm_map that covers the range [offset, offset+size). @@ -127,7 +132,7 @@ { int remap_aperture = 0; -#if __REALLY_HAVE_AGP +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) if (dev->agp->cant_use_aperture) { drm_map_t *map = drm_lookup_map(offset, size, dev); @@ -146,7 +151,7 @@ { int remap_aperture = 0; -#if __REALLY_HAVE_AGP +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) if (dev->agp->cant_use_aperture) { drm_map_t *map = drm_lookup_map(offset, size, dev); @@ -163,7 +168,7 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev) { int unmap_aperture = 0; -#if __REALLY_HAVE_AGP +#if __REALLY_HAVE_AGP && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) /* * This is a bit ugly. It would be much cleaner if the DRM API would use separate * routines for handling mappings in the AGP space. Hopefully this can be done in ^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2003-05-16 23:38 UTC | newest] Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-05-10 10:09 Improved DRM support for cant_use_aperture platforms David Mosberger 2003-05-10 13:12 ` Dave Jones 2003-05-11 11:43 ` Michel Dänzer 2003-05-11 18:09 ` David Mosberger 2003-05-11 19:55 ` Dave Jones 2003-05-11 21:55 ` Michel Dänzer 2003-05-12 18:53 ` David Mosberger 2003-05-12 19:48 ` [Dri-devel] " Michel Dänzer 2003-05-12 20:19 ` David Mosberger 2003-05-12 21:21 ` Michel Dänzer 2003-05-12 21:51 ` David Mosberger 2003-05-12 21:57 ` Christoph Hellwig 2003-05-12 22:08 ` Andrew Morton 2003-05-12 22:20 ` Christoph Hellwig 2003-05-13 0:34 ` Michel Dänzer 2003-05-13 1:09 ` David Mosberger 2003-05-13 13:33 ` Ivan Kokshaysky 2003-05-13 16:20 ` David Mosberger 2003-05-14 9:41 ` Ivan Kokshaysky 2003-05-14 10:27 ` Michel Dänzer 2003-05-14 17:09 ` David Mosberger 2003-05-13 7:43 ` David Mosberger 2003-05-14 14:08 ` Michel Dänzer 2003-05-15 15:59 ` David Mosberger 2003-05-15 22:37 ` Michel Dänzer 2003-05-16 23:50 ` [Dri-devel] " Michel Dänzer 2003-05-12 20:40 ` David Mosberger
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).