diff --git a/sys/dev/drm/ati_pcigart.h b/sys/dev/drm/ati_pcigart.h index 0eafcc07745f..c37c95fd8842 100644 --- a/sys/dev/drm/ati_pcigart.h +++ b/sys/dev/drm/ati_pcigart.h @@ -86,6 +86,8 @@ int DRM(ati_pcigart_init)( drm_device_t *dev, } } + DRM_MEMORYBARRIER(); + ret = 1; done: diff --git a/sys/dev/drm/drm.h b/sys/dev/drm/drm.h index 4a51abaf674d..8430e1db8440 100644 --- a/sys/dev/drm/drm.h +++ b/sys/dev/drm/drm.h @@ -45,7 +45,7 @@ #define DRM_IOC_WRITE _IOC_WRITE #define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) -#elif defined(__FreeBSD__) || defined(__NetBSD__) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #if defined(__FreeBSD__) && defined(XFree86Server) /* Prevent name collision when including sys/ioccom.h */ #undef ioctl diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h index 83c028596b96..c91d33cfe305 100644 --- a/sys/dev/drm/drmP.h +++ b/sys/dev/drm/drmP.h @@ -27,6 +27,7 @@ * Authors: * Rickard E. (Rik) Faith * Gareth Hughes + * * $FreeBSD$ */ @@ -101,13 +102,13 @@ typedef struct drm_file drm_file_t; #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) /* Mapping helper macros */ -#define DRM_IOREMAP(map) \ +#define DRM_IOREMAP(map, dev) \ (map)->handle = DRM(ioremap)( dev, map ) -#define DRM_IOREMAP_NOCACHE(map) \ +#define DRM_IOREMAP_NOCACHE(map, dev) \ (map)->handle = DRM(ioremap_nocache)( dev, map ) -#define DRM_IOREMAPFREE(map) \ +#define DRM_IOREMAPFREE(map, dev) \ do { \ if ( (map)->handle && (map)->size ) \ DRM(ioremapfree)( map ); \ @@ -196,7 +197,8 @@ typedef struct drm_buf_entry { drm_buf_t *buflist; int seg_count; int page_order; - unsigned long *seglist; + vm_offset_t *seglist; + dma_addr_t *seglist_bus; drm_freelist_t freelist; } drm_buf_entry_t; @@ -402,11 +404,8 @@ extern void DRM(mem_uninit)(void); extern void *DRM(alloc)(size_t size, int area); extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area); -extern char *DRM(strdup)(const char *s, int area); -extern void DRM(strfree)(char *s, int area); extern void DRM(free)(void *pt, size_t size, int area); extern void *DRM(ioremap)(drm_device_t *dev, drm_local_map_t *map); -extern void *DRM(ioremap_nocache)(drm_device_t *dev, drm_local_map_t *map); extern void DRM(ioremapfree)(drm_local_map_t *map); #if __REALLY_HAVE_AGP @@ -448,7 +447,7 @@ extern void DRM(reclaim_buffers)(drm_device_t *dev, DRMFILE filp); #if __HAVE_DMA_IRQ extern int DRM(irq_install)( drm_device_t *dev, int irq ); extern int DRM(irq_uninstall)( drm_device_t *dev ); -extern void DRM(dma_service)( DRM_IRQ_ARGS ); +extern irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS ); extern void DRM(driver_irq_preinstall)( drm_device_t *dev ); extern void DRM(driver_irq_postinstall)( drm_device_t *dev ); extern void DRM(driver_irq_uninstall)( drm_device_t *dev ); @@ -565,6 +564,12 @@ extern int DRM(sg_alloc)(DRM_IOCTL_ARGS); extern int DRM(sg_free)(DRM_IOCTL_ARGS); #endif +/* consistent PCI memory functions (drm_pci.h) */ +extern void *DRM(pci_alloc)(drm_device_t *dev, size_t size, + size_t align, dma_addr_t maxaddr, + dma_addr_t *busaddr); +extern void DRM(pci_free)(drm_device_t *dev, size_t size, + void *vaddr, dma_addr_t busaddr); #endif /* __KERNEL__ */ #endif /* _DRM_P_H_ */ diff --git a/sys/dev/drm/drm_agpsupport.h b/sys/dev/drm/drm_agpsupport.h index df9ce0a418a9..fc2f4d1e5663 100644 --- a/sys/dev/drm/drm_agpsupport.h +++ b/sys/dev/drm/drm_agpsupport.h @@ -27,6 +27,7 @@ * Author: * Rickard E. (Rik) Faith * Gareth Hughes + * * $FreeBSD$ */ @@ -255,25 +256,6 @@ drm_agp_head_t *DRM(agp_init)(void) head->agpdev = agpdev; agp_get_info(agpdev, &head->info); head->memory = NULL; -#if 0 /* bogus */ - switch (head->agp_info.chipset) { - case INTEL_GENERIC: head->chipset = "Intel"; break; - case INTEL_LX: head->chipset = "Intel 440LX"; break; - case INTEL_BX: head->chipset = "Intel 440BX"; break; - case INTEL_GX: head->chipset = "Intel 440GX"; break; - case INTEL_I810: head->chipset = "Intel i810"; break; - case VIA_GENERIC: head->chipset = "VIA"; break; - case VIA_VP3: head->chipset = "VIA VP3"; break; - case VIA_MVP3: head->chipset = "VIA MVP3"; break; - case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; - case SIS_GENERIC: head->chipset = "SiS"; break; - case AMD_GENERIC: head->chipset = "AMD"; break; - case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; - case ALI_GENERIC: head->chipset = "ALi"; break; - case ALI_M1541: head->chipset = "ALi M1541"; break; - default: - } -#endif DRM_INFO("AGP at 0x%08lx %dMB\n", (long)head->info.ai_aperture_base, (int)(head->info.ai_aperture_size >> 20)); diff --git a/sys/dev/drm/drm_auth.h b/sys/dev/drm/drm_auth.h index 1e08b0517476..03986c52aa87 100644 --- a/sys/dev/drm/drm_auth.h +++ b/sys/dev/drm/drm_auth.h @@ -27,6 +27,7 @@ * Authors: * Rickard E. (Rik) Faith * Gareth Hughes + * * $FreeBSD$ */ diff --git a/sys/dev/drm/drm_bufs.h b/sys/dev/drm/drm_bufs.h index 9fab73feb15a..e77b3bf875b6 100644 --- a/sys/dev/drm/drm_bufs.h +++ b/sys/dev/drm/drm_bufs.h @@ -27,6 +27,7 @@ * Authors: * Rickard E. (Rik) Faith * Gareth Hughes + * * $FreeBSD$ */ @@ -136,12 +137,12 @@ int DRM(addmap)( DRM_IOCTL_ARGS ) #endif } #endif /* __REALLY_HAVE_MTRR */ - DRM_IOREMAP(map); + DRM_IOREMAP(map, dev); break; case _DRM_SHM: map->handle = (void *)DRM(alloc)(map->size, DRM_MEM_SAREA); - DRM_DEBUG( "%ld %d %p\n", + DRM_DEBUG( "%lu %d %p\n", map->size, DRM(order)( map->size ), map->handle ); if ( !map->handle ) { DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); @@ -279,31 +280,33 @@ int DRM(rmmap)( DRM_IOCTL_ARGS ) #if __HAVE_DMA -static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry) +static void DRM(cleanup_buf_error)(drm_device_t *dev, drm_buf_entry_t *entry) { int i; +#if __HAVE_PCI_DMA if (entry->seg_count) { for (i = 0; i < entry->seg_count; i++) { - DRM(free)((void *)entry->seglist[i], - entry->buf_size, - DRM_MEM_DMA); + if (entry->seglist[i] != NULL) + DRM(pci_free)(dev, entry->buf_size, + (void *)entry->seglist[i], + entry->seglist_bus[i]); } DRM(free)(entry->seglist, entry->seg_count * sizeof(*entry->seglist), DRM_MEM_SEGS); + DRM(free)(entry->seglist_bus, entry->seg_count * + sizeof(*entry->seglist_bus), DRM_MEM_SEGS); entry->seg_count = 0; } +#endif /* __HAVE_PCI_DMA */ - if(entry->buf_count) { - for(i = 0; i < entry->buf_count; i++) { - if(entry->buflist[i].dev_private) { - DRM(free)(entry->buflist[i].dev_private, - entry->buflist[i].dev_priv_size, - DRM_MEM_BUFS); - } + if (entry->buf_count) { + for (i = 0; i < entry->buf_count; i++) { + DRM(free)(entry->buflist[i].dev_private, + entry->buflist[i].dev_priv_size, DRM_MEM_BUFS); } DRM(free)(entry->buflist, entry->buf_count * @@ -395,7 +398,9 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request) if(!buf->dev_private) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; - DRM(cleanup_buf_error)(entry); + DRM(cleanup_buf_error)(dev, entry); + DRM_UNLOCK; + return DRM_ERR(ENOMEM); } memset( buf->dev_private, 0, buf->dev_priv_size ); @@ -413,7 +418,7 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request) DRM_MEM_BUFS ); if(!temp_buflist) { /* Free the entry because it isn't valid */ - DRM(cleanup_buf_error)(entry); + DRM(cleanup_buf_error)(dev, entry); DRM_UNLOCK; return DRM_ERR(ENOMEM); } @@ -450,7 +455,7 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request) int total; int page_order; drm_buf_entry_t *entry; - unsigned long page; + vm_offset_t vaddr; drm_buf_t *buf; int alignment; unsigned long offset; @@ -459,6 +464,7 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request) int page_count; unsigned long *temp_pagelist; drm_buf_t **temp_buflist; + dma_addr_t bus_addr; count = request->count; order = DRM(order)(request->size); @@ -482,42 +488,37 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request) return DRM_ERR(ENOMEM); /* May only call once for each order */ } - entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), - DRM_MEM_BUFS ); - if ( !entry->buflist ) { - DRM_UNLOCK; - return DRM_ERR(ENOMEM); - } - memset( entry->buflist, 0, count * sizeof(*entry->buflist) ); + entry->buflist = DRM(alloc)(count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + entry->seglist = DRM(alloc)(count * sizeof(*entry->seglist), + DRM_MEM_SEGS); + entry->seglist_bus = DRM(alloc)(count * sizeof(*entry->seglist_bus), + DRM_MEM_SEGS); - entry->seglist = DRM(alloc)( count * sizeof(*entry->seglist), - DRM_MEM_SEGS ); - if ( !entry->seglist ) { - DRM(free)( entry->buflist, - count * sizeof(*entry->buflist), - DRM_MEM_BUFS ); - DRM_UNLOCK; - return DRM_ERR(ENOMEM); - } - memset( entry->seglist, 0, count * sizeof(*entry->seglist) ); + /* Keep the original pagelist until we know all the allocations + * have succeeded + */ + temp_pagelist = DRM(alloc)((dma->page_count + (count << page_order)) * + sizeof(*dma->pagelist), DRM_MEM_PAGES); - temp_pagelist = DRM(realloc)( dma->pagelist, - dma->page_count * sizeof(*dma->pagelist), - (dma->page_count + (count << page_order)) - * sizeof(*dma->pagelist), - DRM_MEM_PAGES ); - if(!temp_pagelist) { - DRM(free)( entry->buflist, - count * sizeof(*entry->buflist), - DRM_MEM_BUFS ); - DRM(free)( entry->seglist, - count * sizeof(*entry->seglist), - DRM_MEM_SEGS ); + if (entry->buflist == NULL || entry->seglist == NULL || + temp_pagelist == NULL) { + DRM(free)(entry->buflist, count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + DRM(free)(entry->seglist, count * sizeof(*entry->seglist), + DRM_MEM_SEGS); + DRM(free)(entry->seglist_bus, count * + sizeof(*entry->seglist_bus), DRM_MEM_SEGS); DRM_UNLOCK; return DRM_ERR(ENOMEM); } - dma->pagelist = temp_pagelist; + bzero(entry->buflist, count * sizeof(*entry->buflist)); + bzero(entry->seglist, count * sizeof(*entry->seglist)); + + memcpy(temp_pagelist, dma->pagelist, dma->page_count * + sizeof(*dma->pagelist)); + DRM_DEBUG( "pagelist: %d entries\n", dma->page_count + (count << page_order) ); @@ -527,15 +528,28 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request) page_count = 0; while ( entry->buf_count < count ) { - page = (unsigned long)DRM(alloc)( size, DRM_MEM_DMA ); - if ( !page ) break; - entry->seglist[entry->seg_count++] = page; + vaddr = (vm_offset_t) DRM(pci_alloc)(dev, size, alignment, + 0xfffffffful, &bus_addr); + if (vaddr == NULL) { + /* Set count correctly so we free the proper amount. */ + entry->buf_count = count; + entry->seg_count = count; + DRM(cleanup_buf_error)(dev, entry); + DRM(free)(temp_pagelist, (dma->page_count + + (count << page_order)) * sizeof(*dma->pagelist), + DRM_MEM_PAGES); + DRM_UNLOCK; + return DRM_ERR(ENOMEM); + } + + entry->seglist_bus[entry->seg_count] = bus_addr; + entry->seglist[entry->seg_count++] = vaddr; for ( i = 0 ; i < (1 << page_order) ; i++ ) { DRM_DEBUG( "page %d @ 0x%08lx\n", dma->page_count + page_count, - page + PAGE_SIZE * i ); - dma->pagelist[dma->page_count + page_count++] - = page + PAGE_SIZE * i; + (long)vaddr + PAGE_SIZE * i ); + temp_pagelist[dma->page_count + page_count++] = + vaddr + PAGE_SIZE * i; } for ( offset = 0 ; offset + size <= total && entry->buf_count < count ; @@ -546,10 +560,28 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request) buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + byte_count + offset); - buf->address = (void *)(page + offset); + buf->address = (void *)(vaddr + offset); + buf->bus_address = bus_addr + offset; buf->next = NULL; buf->pending = 0; buf->filp = NULL; + + buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); + buf->dev_private = DRM(alloc)(sizeof(DRIVER_BUF_PRIV_T), + DRM_MEM_BUFS); + if (buf->dev_private == NULL) { + /* Set count correctly so we free the proper amount. */ + entry->buf_count = count; + entry->seg_count = count; + DRM(cleanup_buf_error)(dev, entry); + DRM(free)(temp_pagelist, (dma->page_count + + (count << page_order)) * + sizeof(*dma->pagelist), DRM_MEM_PAGES ); + DRM_UNLOCK; + return DRM_ERR(ENOMEM); + } + bzero(buf->dev_private, buf->dev_priv_size); + DRM_DEBUG( "buffer %d @ %p\n", entry->buf_count, buf->address ); } @@ -561,9 +593,12 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request) (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), DRM_MEM_BUFS ); - if(!temp_buflist) { + if (temp_buflist == NULL) { /* Free the entry because it isn't valid */ - DRM(cleanup_buf_error)(entry); + DRM(cleanup_buf_error)(dev, entry); + DRM(free)(temp_pagelist, (dma->page_count + + (count << page_order)) * sizeof(*dma->pagelist), + DRM_MEM_PAGES); DRM_UNLOCK; return DRM_ERR(ENOMEM); } @@ -573,6 +608,13 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request) dma->buflist[i + dma->buf_count] = &entry->buflist[i]; } + /* No allocations failed, so now we can replace the orginal pagelist + * with the new one. + */ + DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist), + DRM_MEM_PAGES); + dma->pagelist = temp_pagelist; + dma->buf_count += entry->buf_count; dma->seg_count += entry->seg_count; dma->page_count += entry->seg_count << page_order; @@ -669,7 +711,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request) if(!buf->dev_private) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; - DRM(cleanup_buf_error)(entry); + DRM(cleanup_buf_error)(dev, entry); DRM_UNLOCK; return DRM_ERR(ENOMEM); } @@ -693,7 +735,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request) DRM_MEM_BUFS ); if(!temp_buflist) { /* Free the entry because it isn't valid */ - DRM(cleanup_buf_error)(entry); + DRM(cleanup_buf_error)(dev, entry); DRM_UNLOCK; return DRM_ERR(ENOMEM); } diff --git a/sys/dev/drm/drm_context.h b/sys/dev/drm/drm_context.h index 4e26d7c8b879..3cedfc84330e 100644 --- a/sys/dev/drm/drm_context.h +++ b/sys/dev/drm/drm_context.h @@ -27,6 +27,7 @@ * Authors: * Rickard E. (Rik) Faith * Gareth Hughes + * * $FreeBSD$ */ diff --git a/sys/dev/drm/drm_dma.h b/sys/dev/drm/drm_dma.h index 99cabba80bdd..b4bf9e4688a1 100644 --- a/sys/dev/drm/drm_dma.h +++ b/sys/dev/drm/drm_dma.h @@ -70,6 +70,7 @@ void DRM(dma_takedown)(drm_device_t *dev) /* Clear dma buffers */ for (i = 0; i <= DRM_MAX_ORDER; i++) { +#if __HAVE_PCI_DMA if (dma->bufs[i].seg_count) { DRM_DEBUG("order %d: buf_count = %d," " seg_count = %d\n", @@ -77,22 +78,27 @@ void DRM(dma_takedown)(drm_device_t *dev) dma->bufs[i].buf_count, dma->bufs[i].seg_count); for (j = 0; j < dma->bufs[i].seg_count; j++) { - DRM(free)((void *)dma->bufs[i].seglist[j], - dma->bufs[i].buf_size, - DRM_MEM_DMA); + if (dma->bufs[i].seglist[j] != NULL) + DRM(pci_free)(dev, dma->bufs[i].buf_size, + (void *)dma->bufs[i].seglist[j], + dma->bufs[i].seglist_bus[j]); } DRM(free)(dma->bufs[i].seglist, dma->bufs[i].seg_count * sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS); + DRM(free)(dma->bufs[i].seglist_bus, + dma->bufs[i].seg_count + * sizeof(*dma->bufs[0].seglist_bus), + DRM_MEM_SEGS); } - if(dma->bufs[i].buf_count) { - for(j = 0; j < dma->bufs[i].buf_count; j++) { - if(dma->bufs[i].buflist[j].dev_private) { - DRM(free)(dma->bufs[i].buflist[j].dev_private, +#endif /* __HAVE_PCI_DMA */ + + if (dma->bufs[i].buf_count) { + for (j = 0; j < dma->bufs[i].buf_count; j++) { + DRM(free)(dma->bufs[i].buflist[j].dev_private, dma->bufs[i].buflist[j].dev_priv_size, DRM_MEM_BUFS); - } } DRM(free)(dma->bufs[i].buflist, dma->bufs[i].buf_count * @@ -101,17 +107,10 @@ void DRM(dma_takedown)(drm_device_t *dev) } } - if (dma->buflist) { - DRM(free)(dma->buflist, - dma->buf_count * sizeof(*dma->buflist), - DRM_MEM_BUFS); - } - - if (dma->pagelist) { - DRM(free)(dma->pagelist, - dma->page_count * sizeof(*dma->pagelist), - DRM_MEM_PAGES); - } + DRM(free)(dma->buflist, dma->buf_count * sizeof(*dma->buflist), + DRM_MEM_BUFS); + DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist), + DRM_MEM_PAGES); DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER); dev->dma = NULL; } @@ -161,6 +160,9 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) if ( !irq ) return DRM_ERR(EINVAL); + if (dev->dev_private == NULL) + return DRM_ERR(EINVAL); + DRM_LOCK; if ( dev->irq ) { DRM_UNLOCK; @@ -215,7 +217,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) if ( retcode ) { #elif defined(__NetBSD__) dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY, - (int (*)(DRM_IRQ_ARGS))DRM(dma_service), dev); + (irqreturn_t (*)(DRM_IRQ_ARGS))DRM(dma_service), dev); if ( !dev->irqh ) { #endif DRM_LOCK; diff --git a/sys/dev/drm/drm_drv.h b/sys/dev/drm/drm_drv.h index 464a856de346..6f8f8f4b767a 100644 --- a/sys/dev/drm/drm_drv.h +++ b/sys/dev/drm/drm_drv.h @@ -567,7 +567,7 @@ static int DRM(takedown)( drm_device_t *dev ) mrdesc.mr_base = map->offset; mrdesc.mr_len = map->size; mrdesc.mr_flags = MDF_WRITECOMBINE; - act = MEMRANGE_SET_UPDATE; + act = MEMRANGE_SET_REMOVE; bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME)); retcode = mem_range_attr_set(&mrdesc, &act); map->mtrr=1; diff --git a/sys/dev/drm/drm_memory.h b/sys/dev/drm/drm_memory.h index 0c1f91c52378..f4e1133c66dc 100644 --- a/sys/dev/drm/drm_memory.h +++ b/sys/dev/drm/drm_memory.h @@ -36,408 +36,89 @@ #if defined(__FreeBSD__) || defined(__NetBSD__) #define malloctype DRM(M_DRM) /* The macros conflicted in the MALLOC_DEFINE */ - MALLOC_DEFINE(malloctype, "drm", "DRM Data Structures"); - #undef malloctype #endif -typedef struct drm_mem_stats { - const char *name; - int succeed_count; - int free_count; - int fail_count; - unsigned long bytes_allocated; - unsigned long bytes_freed; -} drm_mem_stats_t; - -static DRM_SPINTYPE DRM(mem_lock); -static unsigned long DRM(ram_available) = 0; /* In pages */ -static unsigned long DRM(ram_used) = 0; -static drm_mem_stats_t DRM(mem_stats)[] = { - [DRM_MEM_DMA] = { "dmabufs" }, - [DRM_MEM_SAREA] = { "sareas" }, - [DRM_MEM_DRIVER] = { "driver" }, - [DRM_MEM_MAGIC] = { "magic" }, - [DRM_MEM_IOCTLS] = { "ioctltab" }, - [DRM_MEM_MAPS] = { "maplist" }, - [DRM_MEM_BUFS] = { "buflist" }, - [DRM_MEM_SEGS] = { "seglist" }, - [DRM_MEM_PAGES] = { "pagelist" }, - [DRM_MEM_FILES] = { "files" }, - [DRM_MEM_QUEUES] = { "queues" }, - [DRM_MEM_CMDS] = { "commands" }, - [DRM_MEM_MAPPINGS] = { "mappings" }, - [DRM_MEM_BUFLISTS] = { "buflists" }, - [DRM_MEM_AGPLISTS] = { "agplist" }, - [DRM_MEM_SGLISTS] = { "sglist" }, - [DRM_MEM_TOTALAGP] = { "totalagp" }, - [DRM_MEM_BOUNDAGP] = { "boundagp" }, - [DRM_MEM_CTXBITMAP] = { "ctxbitmap"}, - [DRM_MEM_STUB] = { "stub" }, - { NULL, 0, } /* Last entry must be null */ -}; - +#ifdef DEBUG_MEMORY +#include "drm_memory_debug.h" +#else void DRM(mem_init)(void) { - drm_mem_stats_t *mem; - #ifdef __NetBSD__ malloc_type_attach(DRM(M_DRM)); #endif - - DRM_SPININIT(DRM(mem_lock), "drm memory"); - - for (mem = DRM(mem_stats); mem->name; ++mem) { - mem->succeed_count = 0; - mem->free_count = 0; - mem->fail_count = 0; - mem->bytes_allocated = 0; - mem->bytes_freed = 0; - } - - DRM(ram_available) = 0; /* si.totalram */ - DRM(ram_used) = 0; } void DRM(mem_uninit)(void) { - DRM_SPINUNINIT(DRM(mem_lock)); } -#ifdef __FreeBSD__ -/* drm_mem_info is called whenever a process reads /dev/drm/mem. */ -static int -DRM(_mem_info)(drm_mem_stats_t *stats, struct sysctl_oid *oidp, void *arg1, - int arg2, struct sysctl_req *req) -{ - drm_mem_stats_t *pt; - char buf[128]; - int error; - - DRM_SYSCTL_PRINT(" total counts " - " | outstanding \n"); - DRM_SYSCTL_PRINT("type alloc freed fail bytes freed" - " | allocs bytes\n\n"); - DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n", - "system", 0, 0, 0, DRM(ram_available)); - DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n", - "locked", 0, 0, 0, DRM(ram_used)); - DRM_SYSCTL_PRINT("\n"); - for (pt = stats; pt->name; pt++) { - DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n", - pt->name, - pt->succeed_count, - pt->free_count, - pt->fail_count, - pt->bytes_allocated, - pt->bytes_freed, - pt->succeed_count - pt->free_count, - (long)pt->bytes_allocated - - (long)pt->bytes_freed); - } - SYSCTL_OUT(req, "", 1); - - return 0; -} - -int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS -{ - int ret; - drm_mem_stats_t *stats; - - stats = malloc(sizeof(DRM(mem_stats)), DRM(M_DRM), M_NOWAIT); - if (stats == NULL) - return ENOMEM; - - DRM_SPINLOCK(&DRM(mem_lock)); - bcopy(DRM(mem_stats), stats, sizeof(DRM(mem_stats))); - DRM_SPINUNLOCK(&DRM(mem_lock)); - - ret = DRM(_mem_info)(stats, oidp, arg1, arg2, req); - - free(stats, DRM(M_DRM)); - return ret; -} -#endif /* __FreeBSD__ */ - void *DRM(alloc)(size_t size, int area) { - void *pt; - - if (!size) { - DRM_MEM_ERROR(area, "Allocating 0 bytes\n"); - return NULL; - } - - if (!(pt = malloc(size, DRM(M_DRM), M_NOWAIT))) { - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[area].fail_count; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return NULL; - } - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[area].succeed_count; - DRM(mem_stats)[area].bytes_allocated += size; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return pt; + return malloc(size, DRM(M_DRM), M_NOWAIT); } void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area) { void *pt; - if (!(pt = DRM(alloc)(size, area))) return NULL; + pt = malloc(size, DRM(M_DRM), M_NOWAIT); + if (pt == NULL) + return NULL; if (oldpt && oldsize) { memcpy(pt, oldpt, oldsize); - DRM(free)(oldpt, oldsize, area); + free(oldpt, DRM(M_DRM)); } return pt; } -char *DRM(strdup)(const char *s, int area) -{ - char *pt; - int length = s ? strlen(s) : 0; - - if (!(pt = DRM(alloc)(length+1, area))) return NULL; - strcpy(pt, s); - return pt; -} - -void DRM(strfree)(char *s, int area) -{ - unsigned int size; - - if (!s) return; - - size = 1 + strlen(s); - DRM(free)((void *)s, size, area); -} - void DRM(free)(void *pt, size_t size, int area) { - int alloc_count; - int free_count; - - if (!pt) - DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n"); - else - free(pt, DRM(M_DRM)); - DRM_SPINLOCK(&DRM(mem_lock)); - DRM(mem_stats)[area].bytes_freed += size; - free_count = ++DRM(mem_stats)[area].free_count; - alloc_count = DRM(mem_stats)[area].succeed_count; - DRM_SPINUNLOCK(&DRM(mem_lock)); - if (free_count > alloc_count) { - DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } + free(pt, DRM(M_DRM)); } void *DRM(ioremap)( drm_device_t *dev, drm_local_map_t *map ) { - void *pt; - - if (!map->size) { - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Mapping 0 bytes at 0x%08lx\n", map->offset); - return NULL; - } -#ifdef __NetBSD__ - map->iot = dev->pa.pa_memt; -#endif - #ifdef __FreeBSD__ - if (!(pt = pmap_mapdev(map->offset, map->size))) { + return pmap_mapdev(map->offset, map->size); #elif defined(__NetBSD__) + map->iot = dev->pa.pa_memt; if (bus_space_map(map->iot, map->offset, map->size, - BUS_SPACE_MAP_LINEAR, &map->ioh)) { -#endif - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; - DRM_SPINUNLOCK(&DRM(mem_lock)); + BUS_SPACE_MAP_LINEAR, &map->ioh)) return NULL; - } -#ifdef __NetBSD__ - pt = bus_space_vaddr(map->iot, map->ioh); + return bus_space_vaddr(map->iot, map->ioh); #endif - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; - DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += map->size; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return pt; } -/* unused so far */ -#if 0 -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) -{ - void *pt; - - if (!size) { - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Mapping 0 bytes at 0x%08lx\n", offset); - return NULL; - } - - /* FIXME FOR BSD */ - if (!(pt = ioremap_nocache(offset, size))) { - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return NULL; - } - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; - DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return pt; -} -#endif - void DRM(ioremapfree)(drm_local_map_t *map) { - int alloc_count; - int free_count; - - if (map->handle == NULL) - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Attempt to free NULL pointer\n"); - else #ifdef __FreeBSD__ - pmap_unmapdev((vm_offset_t) map->handle, map->size); + pmap_unmapdev((vm_offset_t) map->handle, map->size); #elif defined(__NetBSD__) - bus_space_unmap(map->iot, map->ioh, map->size); + bus_space_unmap(map->iot, map->ioh, map->size); #endif - - DRM_SPINLOCK(&DRM(mem_lock)); - DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += map->size; - free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count; - alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; - DRM_SPINUNLOCK(&DRM(mem_lock)); - if (free_count > alloc_count) { - DRM_MEM_ERROR(DRM_MEM_MAPPINGS, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } } #if __REALLY_HAVE_AGP agp_memory *DRM(alloc_agp)(int pages, u32 type) { - agp_memory *handle; - - if (!pages) { - DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n"); - return NULL; - } - - if ((handle = DRM(agp_allocate_memory)(pages, type))) { - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; - DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated - += pages << PAGE_SHIFT; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return handle; - } - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return NULL; + return DRM(agp_allocate_memory)(pages, type); } int DRM(free_agp)(agp_memory *handle, int pages) { - int alloc_count; - int free_count; - - if (!handle) { - DRM_MEM_ERROR(DRM_MEM_TOTALAGP, - "Attempt to free NULL AGP handle\n"); - return DRM_ERR(EINVAL); - } - - if (DRM(agp_free_memory)(handle)) { - DRM_SPINLOCK(&DRM(mem_lock)); - free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count; - alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; - DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed - += pages << PAGE_SHIFT; - DRM_SPINUNLOCK(&DRM(mem_lock)); - if (free_count > alloc_count) { - DRM_MEM_ERROR(DRM_MEM_TOTALAGP, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } - return 0; - } - return DRM_ERR(EINVAL); + return DRM(agp_free_memory)(handle); } int DRM(bind_agp)(agp_memory *handle, unsigned int start) { - int retcode; - device_t dev = DRM_AGP_FIND_DEVICE(); - struct agp_memory_info info; - - if (!dev) - return EINVAL; - - if (!handle) { - DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, - "Attempt to bind NULL AGP handle\n"); - return DRM_ERR(EINVAL); - } - - if (!(retcode = DRM(agp_bind_memory)(handle, start))) { - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; - agp_memory_info(dev, handle, &info); - DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated - += info.ami_size; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return DRM_ERR(0); - } - DRM_SPINLOCK(&DRM(mem_lock)); - ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count; - DRM_SPINUNLOCK(&DRM(mem_lock)); - return DRM_ERR(retcode); + return DRM(agp_bind_memory)(handle, start); } int DRM(unbind_agp)(agp_memory *handle) { - int alloc_count; - int free_count; - int retcode = EINVAL; - device_t dev = DRM_AGP_FIND_DEVICE(); - struct agp_memory_info info; - - if (!dev) - return EINVAL; - - if (!handle) { - DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, - "Attempt to unbind NULL AGP handle\n"); - return DRM_ERR(retcode); - } - - agp_memory_info(dev, handle, &info); - - if ((retcode = DRM(agp_unbind_memory)(handle))) - return DRM_ERR(retcode); - - DRM_SPINLOCK(&DRM(mem_lock)); - free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count; - alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; - DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed - += info.ami_size; - DRM_SPINUNLOCK(&DRM(mem_lock)); - if (free_count > alloc_count) { - DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } - return DRM_ERR(retcode); + return DRM(agp_unbind_memory)(handle); } -#endif +#endif /* __REALLY_HAVE_AGP */ +#endif /* DEBUG_MEMORY */ diff --git a/sys/dev/drm/drm_memory_debug.h b/sys/dev/drm/drm_memory_debug.h new file mode 100644 index 000000000000..3047f9275d8e --- /dev/null +++ b/sys/dev/drm/drm_memory_debug.h @@ -0,0 +1,413 @@ +/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*- + * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Rickard E. (Rik) Faith + * Gareth Hughes + * + * $FreeBSD$ + */ + +#include "drmP.h" + +typedef struct drm_mem_stats { + const char *name; + int succeed_count; + int free_count; + int fail_count; + unsigned long bytes_allocated; + unsigned long bytes_freed; +} drm_mem_stats_t; + +static DRM_SPINTYPE DRM(mem_lock); +static unsigned long DRM(ram_available) = 0; /* In pages */ +static unsigned long DRM(ram_used) = 0; +static drm_mem_stats_t DRM(mem_stats)[] = { + [DRM_MEM_DMA] = { "dmabufs" }, + [DRM_MEM_SAREA] = { "sareas" }, + [DRM_MEM_DRIVER] = { "driver" }, + [DRM_MEM_MAGIC] = { "magic" }, + [DRM_MEM_IOCTLS] = { "ioctltab" }, + [DRM_MEM_MAPS] = { "maplist" }, + [DRM_MEM_BUFS] = { "buflist" }, + [DRM_MEM_SEGS] = { "seglist" }, + [DRM_MEM_PAGES] = { "pagelist" }, + [DRM_MEM_FILES] = { "files" }, + [DRM_MEM_QUEUES] = { "queues" }, + [DRM_MEM_CMDS] = { "commands" }, + [DRM_MEM_MAPPINGS] = { "mappings" }, + [DRM_MEM_BUFLISTS] = { "buflists" }, + [DRM_MEM_AGPLISTS] = { "agplist" }, + [DRM_MEM_SGLISTS] = { "sglist" }, + [DRM_MEM_TOTALAGP] = { "totalagp" }, + [DRM_MEM_BOUNDAGP] = { "boundagp" }, + [DRM_MEM_CTXBITMAP] = { "ctxbitmap"}, + [DRM_MEM_STUB] = { "stub" }, + { NULL, 0, } /* Last entry must be null */ +}; + +void DRM(mem_init)(void) +{ + drm_mem_stats_t *mem; + +#ifdef __NetBSD__ + malloc_type_attach(DRM(M_DRM)); +#endif + + DRM_SPININIT(DRM(mem_lock), "drm memory"); + + for (mem = DRM(mem_stats); mem->name; ++mem) { + mem->succeed_count = 0; + mem->free_count = 0; + mem->fail_count = 0; + mem->bytes_allocated = 0; + mem->bytes_freed = 0; + } + + DRM(ram_available) = 0; /* si.totalram */ + DRM(ram_used) = 0; +} + +void DRM(mem_uninit)(void) +{ + DRM_SPINUNINIT(DRM(mem_lock)); +} + +#ifdef __FreeBSD__ +/* drm_mem_info is called whenever a process reads /dev/drm/mem. */ +static int +DRM(_mem_info)(drm_mem_stats_t *stats, struct sysctl_oid *oidp, void *arg1, + int arg2, struct sysctl_req *req) +{ + drm_mem_stats_t *pt; + char buf[128]; + int error; + + DRM_SYSCTL_PRINT(" total counts " + " | outstanding \n"); + DRM_SYSCTL_PRINT("type alloc freed fail bytes freed" + " | allocs bytes\n\n"); + DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n", + "system", 0, 0, 0, DRM(ram_available)); + DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n", + "locked", 0, 0, 0, DRM(ram_used)); + DRM_SYSCTL_PRINT("\n"); + for (pt = stats; pt->name; pt++) { + DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n", + pt->name, + pt->succeed_count, + pt->free_count, + pt->fail_count, + pt->bytes_allocated, + pt->bytes_freed, + pt->succeed_count - pt->free_count, + (long)pt->bytes_allocated + - (long)pt->bytes_freed); + } + SYSCTL_OUT(req, "", 1); + + return 0; +} + +int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS +{ + int ret; + drm_mem_stats_t *stats; + + stats = malloc(sizeof(DRM(mem_stats)), DRM(M_DRM), M_NOWAIT); + if (stats == NULL) + return ENOMEM; + + DRM_SPINLOCK(&DRM(mem_lock)); + bcopy(DRM(mem_stats), stats, sizeof(DRM(mem_stats))); + DRM_SPINUNLOCK(&DRM(mem_lock)); + + ret = DRM(_mem_info)(stats, oidp, arg1, arg2, req); + + free(stats, DRM(M_DRM)); + return ret; +} +#endif /* __FreeBSD__ */ + +void *DRM(alloc)(size_t size, int area) +{ + void *pt; + + if (!size) { + DRM_MEM_ERROR(area, "Allocating 0 bytes\n"); + return NULL; + } + + if (!(pt = malloc(size, DRM(M_DRM), M_NOWAIT))) { + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[area].fail_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return NULL; + } + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[area].succeed_count; + DRM(mem_stats)[area].bytes_allocated += size; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return pt; +} + +void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area) +{ + void *pt; + + if (!(pt = DRM(alloc)(size, area))) return NULL; + if (oldpt && oldsize) { + memcpy(pt, oldpt, oldsize); + DRM(free)(oldpt, oldsize, area); + } + return pt; +} + +void DRM(free)(void *pt, size_t size, int area) +{ + int alloc_count; + int free_count; + + if (pt == NULL) + return; + free(pt, DRM(M_DRM)); + DRM_SPINLOCK(&DRM(mem_lock)); + DRM(mem_stats)[area].bytes_freed += size; + free_count = ++DRM(mem_stats)[area].free_count; + alloc_count = DRM(mem_stats)[area].succeed_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + if (free_count > alloc_count) { + DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } +} + +void *DRM(ioremap)( drm_device_t *dev, drm_local_map_t *map ) +{ + void *pt; + + if (!map->size) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Mapping 0 bytes at 0x%08lx\n", map->offset); + return NULL; + } +#ifdef __NetBSD__ + map->iot = dev->pa.pa_memt; +#endif + +#ifdef __FreeBSD__ + if (!(pt = pmap_mapdev(map->offset, map->size))) { +#elif defined(__NetBSD__) + if (bus_space_map(map->iot, map->offset, map->size, + BUS_SPACE_MAP_LINEAR, &map->ioh)) { +#endif + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return NULL; + } +#ifdef __NetBSD__ + pt = bus_space_vaddr(map->iot, map->ioh); +#endif + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += map->size; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return pt; +} + +/* unused so far */ +#if 0 +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +{ + void *pt; + + if (!size) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Mapping 0 bytes at 0x%08lx\n", offset); + return NULL; + } + + /* FIXME FOR BSD */ + if (!(pt = ioremap_nocache(offset, size))) { + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return NULL; + } + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return pt; +} +#endif + +void DRM(ioremapfree)(drm_local_map_t *map) +{ + int alloc_count; + int free_count; + + if (map->handle == NULL) + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Attempt to free NULL pointer\n"); + else +#ifdef __FreeBSD__ + pmap_unmapdev((vm_offset_t) map->handle, map->size); +#elif defined(__NetBSD__) + bus_space_unmap(map->iot, map->ioh, map->size); +#endif + + DRM_SPINLOCK(&DRM(mem_lock)); + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += map->size; + free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count; + alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } +} + +#if __REALLY_HAVE_AGP +agp_memory *DRM(alloc_agp)(int pages, u32 type) +{ + agp_memory *handle; + + if (!pages) { + DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n"); + return NULL; + } + + if ((handle = DRM(agp_allocate_memory)(pages, type))) { + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; + DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated + += pages << PAGE_SHIFT; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return handle; + } + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return NULL; +} + +int DRM(free_agp)(agp_memory *handle, int pages) +{ + int alloc_count; + int free_count; + + if (!handle) { + DRM_MEM_ERROR(DRM_MEM_TOTALAGP, + "Attempt to free NULL AGP handle\n"); + return DRM_ERR(EINVAL); + } + + if (DRM(agp_free_memory)(handle)) { + DRM_SPINLOCK(&DRM(mem_lock)); + free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count; + alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; + DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed + += pages << PAGE_SHIFT; + DRM_SPINUNLOCK(&DRM(mem_lock)); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_TOTALAGP, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } + return 0; + } + return DRM_ERR(EINVAL); +} + +int DRM(bind_agp)(agp_memory *handle, unsigned int start) +{ + int retcode; + device_t dev = DRM_AGP_FIND_DEVICE(); + struct agp_memory_info info; + + if (!dev) + return EINVAL; + + if (!handle) { + DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, + "Attempt to bind NULL AGP handle\n"); + return DRM_ERR(EINVAL); + } + + if (!(retcode = DRM(agp_bind_memory)(handle, start))) { + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; + agp_memory_info(dev, handle, &info); + DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated + += info.ami_size; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return DRM_ERR(0); + } + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return DRM_ERR(retcode); +} + +int DRM(unbind_agp)(agp_memory *handle) +{ + int alloc_count; + int free_count; + int retcode = EINVAL; + device_t dev = DRM_AGP_FIND_DEVICE(); + struct agp_memory_info info; + + if (!dev) + return EINVAL; + + if (!handle) { + DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, + "Attempt to unbind NULL AGP handle\n"); + return DRM_ERR(retcode); + } + + agp_memory_info(dev, handle, &info); + + if ((retcode = DRM(agp_unbind_memory)(handle))) + return DRM_ERR(retcode); + + DRM_SPINLOCK(&DRM(mem_lock)); + free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count; + alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; + DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed + += info.ami_size; + DRM_SPINUNLOCK(&DRM(mem_lock)); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } + return DRM_ERR(retcode); +} +#endif diff --git a/sys/dev/drm/drm_os_freebsd.h b/sys/dev/drm/drm_os_freebsd.h index 7acc59fa71d3..745b4e71c5e4 100644 --- a/sys/dev/drm/drm_os_freebsd.h +++ b/sys/dev/drm/drm_os_freebsd.h @@ -1,6 +1,36 @@ +/** + * \file drm_os_freebsd.h + * OS-specific #defines for FreeBSD + * + * \author Eric Anholt + */ + /* + * Copyright 2003 Eric Anholt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * * $FreeBSD$ */ + #include #include #include @@ -27,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -111,10 +142,12 @@ #define DRM_SUSER(p) suser(p) #define DRM_TASKQUEUE_ARGS void *arg, int pending #define DRM_IRQ_ARGS void *arg +typedef void irqreturn_t; +#define IRQ_HANDLED /* nothing */ +#define IRQ_NONE /* nothing */ #define DRM_DEVICE drm_device_t *dev = kdev->si_drv1 #define DRM_MALLOC(size) malloc( size, DRM(M_DRM), M_NOWAIT ) #define DRM_FREE(pt,size) free( pt, DRM(M_DRM) ) -#define DRM_VTOPHYS(addr) vtophys(addr) /* Read/write from bus space, with byteswapping to le if necessary */ #define DRM_READ8(map, offset) *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) @@ -206,10 +239,21 @@ while (!condition) { \ #define DRM_GET_USER_UNCHECKED(val, uaddr) \ ((val) = fuword(uaddr), 0) -#define DRM_WRITEMEMORYBARRIER( map ) \ - bus_space_barrier((map)->iot, (map)->ioh, 0, (map)->size, 0); -#define DRM_READMEMORYBARRIER( map ) \ - bus_space_barrier((map)->iot, (map)->ioh, 0, (map)->size, BUS_SPACE_BARRIER_READ); +/* DRM_READMEMORYBARRIER() prevents reordering of reads. + * DRM_WRITEMEMORYBARRIER() prevents reordering of writes. + * DRM_MEMORYBARRIER() prevents reordering of reads and writes. + */ +#if defined(__i386__) +#define DRM_READMEMORYBARRIER() __asm __volatile( \ + "lock; addl $0,0(%%esp)" : : : "memory"); +#define DRM_WRITEMEMORYBARRIER() __asm __volatile("" : : : "memory"); +#define DRM_MEMORYBARRIER() __asm __volatile( \ + "lock; addl $0,0(%%esp)" : : : "memory"); +#elif defined(__alpha__) +#define DRM_READMEMORYBARRIER() alpha_mb(); +#define DRM_WRITEMEMORYBARRIER() alpha_wmb(); +#define DRM_MEMORYBARRIER() alpha_mb(); +#endif #define PAGE_ALIGN(addr) round_page(addr) @@ -230,7 +274,8 @@ typedef struct drm_chipinfo char *name; } drm_chipinfo_t; -#define cpu_to_le32(x) (x) /* FIXME */ +#define cpu_to_le32(x) htole32(x) +#define le32_to_cpu(x) le32toh(x) typedef unsigned long dma_addr_t; typedef u_int32_t atomic_t; @@ -356,14 +401,11 @@ find_first_zero_bit(volatile void *p, int max) #endif #define DRM_SYSCTL_PRINT(fmt, arg...) \ +do { \ snprintf(buf, sizeof(buf), fmt, ##arg); \ error = SYSCTL_OUT(req, buf, strlen(buf)); \ - if (error) return error; - -#define DRM_SYSCTL_PRINT_RET(ret, fmt, arg...) \ - snprintf(buf, sizeof(buf), fmt, ##arg); \ - error = SYSCTL_OUT(req, buf, strlen(buf)); \ - if (error) { ret; return error; } + if (error) return error; \ +} while (0) #define DRM_FIND_MAP(dest, o) \ @@ -396,5 +438,7 @@ extern drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, extern int DRM(sysctl_init)(drm_device_t *dev); extern int DRM(sysctl_cleanup)(drm_device_t *dev); -/* Memory info sysctl (drm_memory.h) */ +/* Memory info sysctl (drm_memory_debug.h) */ +#ifdef DEBUG_MEMORY extern int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS; +#endif diff --git a/sys/dev/drm/drm_pci.h b/sys/dev/drm/drm_pci.h new file mode 100644 index 000000000000..b853c2a6d32e --- /dev/null +++ b/sys/dev/drm/drm_pci.h @@ -0,0 +1,67 @@ +/** + * \file drm_pci.h + * \brief PCI consistent, DMA-accessible memory functions. + * + * \author Eric Anholt + */ + +/* + * Copyright 2003 Eric Anholt. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * $FreeBSD$ + */ + +#include "dev/drm/drmP.h" + +/**********************************************************************/ +/** \name PCI memory */ +/*@{*/ + +/** + * \brief Allocate a physically contiguous DMA-accessible consistent + * memory block. + */ +void * +DRM(pci_alloc)(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr, + dma_addr_t *busaddr) +{ + void *vaddr; + + vaddr = contigmalloc(size, DRM(M_DRM), M_WAITOK, 0ul, maxaddr, align, + 0); + *busaddr = vtophys(vaddr); + + return vaddr; +} + +/** + * \brief Free a DMA-accessible consistent memory block. + */ +void +DRM(pci_free)(drm_device_t *dev, size_t size, void *vaddr, dma_addr_t busaddr) +{ +#if __FreeBSD_version > 500000 + contigfree(vaddr, size, DRM(M_DRM)); /* Not available on 4.x */ +#endif +} + +/*@}*/ diff --git a/sys/dev/drm/drm_sarea.h b/sys/dev/drm/drm_sarea.h index f3dc8206afc3..093aca65f7b1 100644 --- a/sys/dev/drm/drm_sarea.h +++ b/sys/dev/drm/drm_sarea.h @@ -1,5 +1,11 @@ -/* sarea.h -- SAREA definitions -*- linux-c -*- +/** + * \file drm_sarea.h + * \brief SAREA definitions * + * \author Michel Dänzer + */ + +/* * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * @@ -22,23 +28,23 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * Authors: - * Michel Dänzer - * * $FreeBSD$ */ #ifndef _DRM_SAREA_H_ #define _DRM_SAREA_H_ +/** Maximum number of drawables in the SAREA */ #define SAREA_MAX_DRAWABLES 256 -typedef struct _drm_sarea_drawable_t { +/** SAREA drawable */ +typedef struct drm_sarea_drawable { unsigned int stamp; unsigned int flags; } drm_sarea_drawable_t; -typedef struct _dri_sarea_frame_t { +/** SAREA frame */ +typedef struct drm_sarea_frame { unsigned int x; unsigned int y; unsigned int width; @@ -46,13 +52,14 @@ typedef struct _dri_sarea_frame_t { unsigned int fullscreen; } drm_sarea_frame_t; -typedef struct _drm_sarea_t { - /* first thing is always the drm locking structure */ +/** SAREA */ +typedef struct drm_sarea { + /** first thing is always the DRM locking structure */ drm_hw_lock_t lock; - /* NOT_DONE: Use readers/writer lock for drawable_lock */ + /** \todo Use readers/writer lock for drm_sarea::drawable_lock */ drm_hw_lock_t drawable_lock; - drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; - drm_sarea_frame_t frame; + drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */ + drm_sarea_frame_t frame; /**< frame */ drm_context_t dummy_context; } drm_sarea_t; diff --git a/sys/dev/drm/drm_scatter.h b/sys/dev/drm/drm_scatter.h index 244c9ffe4866..4da0a1b6f1ca 100644 --- a/sys/dev/drm/drm_scatter.h +++ b/sys/dev/drm/drm_scatter.h @@ -25,6 +25,7 @@ * * Authors: * Gareth Hughes + * Eric Anholt * * $FreeBSD$ */ diff --git a/sys/dev/drm/drm_sysctl.h b/sys/dev/drm/drm_sysctl.h index 9d47d2422cdf..aae8fc05cd74 100644 --- a/sys/dev/drm/drm_sysctl.h +++ b/sys/dev/drm/drm_sysctl.h @@ -16,7 +16,9 @@ struct DRM(sysctl_list) { int (*f) DRM_SYSCTL_HANDLER_ARGS; } DRM(sysctl_list)[] = { { "name", DRM(name_info) }, +#ifdef DEBUG_MEMORY { "mem", DRM(mem_info) }, +#endif { "vm", DRM(vm_info) }, { "clients", DRM(clients_info) }, { "bufs", DRM(bufs_info) }, @@ -97,10 +99,10 @@ static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS int error; if (dev->unique) { - DRM_SYSCTL_PRINT("%s 0x%x %s\n", + DRM_SYSCTL_PRINT("%s 0x%x %s", dev->name, dev2udev(dev->devnode), dev->unique); } else { - DRM_SYSCTL_PRINT("%s 0x%x\n", dev->name, dev2udev(dev->devnode)); + DRM_SYSCTL_PRINT("%s 0x%x", dev->name, dev2udev(dev->devnode)); } SYSCTL_OUT(req, "", 1); @@ -113,22 +115,22 @@ static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS drm_device_t *dev = arg1; drm_local_map_t *map; drm_map_list_entry_t *listentry; - const char *types[] = { "FB", "REG", "SHM" }; + const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" }; const char *type; int i=0; char buf[128]; int error; - DRM_SYSCTL_PRINT("slot offset size type flags " - "address mtrr\n\n"); - error = SYSCTL_OUT(req, buf, strlen(buf)); - if (error) return error; + DRM_SYSCTL_PRINT("\nslot offset size type flags " + "address mtrr\n"); if (dev->maplist != NULL) { TAILQ_FOREACH(listentry, dev->maplist, link) { map = listentry->map; - if (map->type < 0 || map->type > 2) type = "??"; - else type = types[map->type]; + if (map->type < 0 || map->type > 4) + type = "??"; + else + type = types[map->type]; DRM_SYSCTL_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", i, map->offset, @@ -137,9 +139,9 @@ static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS map->flags, (unsigned long)map->handle); if (map->mtrr < 0) { - DRM_SYSCTL_PRINT("none\n"); + DRM_SYSCTL_PRINT("no\n"); } else { - DRM_SYSCTL_PRINT("%4d\n", map->mtrr); + DRM_SYSCTL_PRINT("yes\n"); } i++; } @@ -174,7 +176,7 @@ static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS int error; if (!dma) return 0; - DRM_SYSCTL_PRINT(" o size count free segs pages kB\n\n"); + DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n"); for (i = 0; i <= DRM_MAX_ORDER; i++) { if (dma->bufs[i].buf_count) DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n", @@ -220,7 +222,7 @@ static int DRM(_clients_info) DRM_SYSCTL_HANDLER_ARGS char buf[128]; int error; - DRM_SYSCTL_PRINT("a dev pid uid magic ioctls\n\n"); + DRM_SYSCTL_PRINT("\na dev pid uid magic ioctls\n"); TAILQ_FOREACH(priv, &dev->files, link) { DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n", priv->authenticated ? 'y' : 'n', diff --git a/sys/dev/drm/mga.h b/sys/dev/drm/mga.h index 2ee2c3face56..5a4bec9ded97 100644 --- a/sys/dev/drm/mga.h +++ b/sys/dev/drm/mga.h @@ -74,7 +74,7 @@ /* Driver customization: */ #define DRIVER_PRETAKEDOWN() do { \ - if ( dev->dev_private ) mga_do_cleanup_dma( dev ); \ + mga_do_cleanup_dma( dev ); \ } while (0) /* DMA customization: diff --git a/sys/dev/drm/mga_dma.c b/sys/dev/drm/mga_dma.c index 5020f1e465e0..45e6406f205d 100644 --- a/sys/dev/drm/mga_dma.c +++ b/sys/dev/drm/mga_dma.c @@ -556,9 +556,9 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) (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 || @@ -641,15 +641,23 @@ int mga_do_cleanup_dma( drm_device_t *dev ) { DRM_DEBUG( "\n" ); +#if _HAVE_DMA_IRQ + /* Make sure interrupts are disabled here because the uninstall ioctl + * may not have been called from userspace and after dev_private + * is freed, it's too late. + */ + if ( dev->irq ) DRM(irq_uninstall)(dev); +#endif + if ( dev->dev_private ) { 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 ); @@ -668,6 +676,8 @@ int mga_dma_init( DRM_IOCTL_ARGS ) DRM_DEVICE; drm_mga_init_t init; + LOCK_TEST_WITH_RETURN( dev, filp ); + DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) ); switch ( init.func ) { diff --git a/sys/dev/drm/mga_drv.h b/sys/dev/drm/mga_drv.h index b3ebaf629fd4..54c6926598e6 100644 --- a/sys/dev/drm/mga_drv.h +++ b/sys/dev/drm/mga_drv.h @@ -133,7 +133,7 @@ extern int mga_getparam( DRM_IOCTL_ARGS ); extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); extern int mga_warp_init( drm_mga_private_t *dev_priv ); -#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->primary) +#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() #if defined(__linux__) && defined(__alpha__) #define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle)) @@ -144,12 +144,12 @@ extern int mga_warp_init( drm_mga_private_t *dev_priv ); #define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) #define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg))) -#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF( reg ) = val; } while (0) -#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF8( reg ) = val; } while (0) +#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0) +#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0) static inline u32 _MGA_READ(u32 *addr) { - DRM_READMEMORYBARRIER(dev_priv->mmio); + DRM_MEMORYBARRIER(); return *(volatile u32 *)addr; } #else @@ -228,7 +228,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; \ @@ -278,7 +278,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; \ diff --git a/sys/dev/drm/mga_irq.c b/sys/dev/drm/mga_irq.c index 9b2b6918471b..1f8f2c89fdc2 100644 --- a/sys/dev/drm/mga_irq.c +++ b/sys/dev/drm/mga_irq.c @@ -38,7 +38,7 @@ #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" -void mga_dma_service( DRM_IRQ_ARGS ) +irqreturn_t mga_dma_service( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_mga_private_t *dev_priv = @@ -53,7 +53,9 @@ void mga_dma_service( DRM_IRQ_ARGS ) atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); DRM(vbl_send_signals)( dev ); + return IRQ_HANDLED; } + return IRQ_NONE; } int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence) @@ -95,8 +97,9 @@ void mga_driver_irq_postinstall( drm_device_t *dev ) { void mga_driver_irq_uninstall( drm_device_t *dev ) { drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - if ( dev_priv ) { - /* Disable *all* interrupts */ - MGA_WRITE( MGA_IEN, 0 ); - } + if (!dev_priv) + return; + + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); } diff --git a/sys/dev/drm/mga_warp.c b/sys/dev/drm/mga_warp.c index 06aa833f0cb8..035d04589add 100644 --- a/sys/dev/drm/mga_warp.c +++ b/sys/dev/drm/mga_warp.c @@ -29,7 +29,6 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/mga.h" #include "dev/drm/drmP.h" #include "dev/drm/drm.h" diff --git a/sys/dev/drm/r128.h b/sys/dev/drm/r128.h index 29ca82834a22..6d616d50e3ab 100644 --- a/sys/dev/drm/r128.h +++ b/sys/dev/drm/r128.h @@ -49,13 +49,18 @@ #define DRIVER_NAME "r128" #define DRIVER_DESC "ATI Rage 128" -#define DRIVER_DATE "20021029" +#define DRIVER_DATE "20030725" #define DRIVER_MAJOR 2 -#define DRIVER_MINOR 3 +#define DRIVER_MINOR 5 #define DRIVER_PATCHLEVEL 0 - +/* Interface history: + * + * ?? - ?? + * 2.4 - Add support for ycbcr textures (no new ioctls) + * 2.5 - Add FLIP ioctl, disable FULLSCREEN. + */ #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, \ @@ -66,6 +71,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_FLIP)] = { r128_cce_flip, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, \ @@ -87,7 +93,7 @@ } while (0) #define DRIVER_PRETAKEDOWN() do { \ - if ( dev->dev_private ) r128_do_cleanup_cce( dev ); \ + r128_do_cleanup_cce( dev ); \ } while (0) /* DMA customization: diff --git a/sys/dev/drm/r128_cce.c b/sys/dev/drm/r128_cce.c index e97fece6f02c..bec4e23579fb 100644 --- a/sys/dev/drm/r128_cce.c +++ b/sys/dev/drm/r128_cce.c @@ -83,8 +83,6 @@ static u32 r128_cce_microcode[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ); - int R128_READ_PLL(drm_device_t *dev, int addr) { drm_r128_private_t *dev_priv = dev->dev_private; @@ -153,7 +151,7 @@ static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries ) return DRM_ERR(EBUSY); } -int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) +static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) { int i, ret; @@ -353,7 +351,7 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev, R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, entry->busaddr[page_ofs]); DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", - entry->busaddr[page_ofs], + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -541,10 +539,11 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); +#if __REALLY_HAVE_AGP 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) { @@ -553,7 +552,9 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) r128_do_cleanup_cce( dev ); return DRM_ERR(ENOMEM); } - } else { + } else +#endif + { dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset; dev_priv->ring_rptr->handle = @@ -615,26 +616,34 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) int r128_do_cleanup_cce( drm_device_t *dev ) { + +#if _HAVE_DMA_IRQ + /* Make sure interrupts are disabled here because the uninstall ioctl + * may not have been called from userspace and after dev_private + * is freed, it's too late. + */ + if ( dev->irq ) DRM(irq_uninstall)(dev); +#endif + 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 + { 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 ); @@ -651,6 +660,8 @@ int r128_cce_init( DRM_IOCTL_ARGS ) DRM_DEBUG( "\n" ); + LOCK_TEST_WITH_RETURN( dev, filp ); + DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) ); switch ( init.func ) { @@ -771,59 +782,8 @@ int r128_engine_reset( DRM_IOCTL_ARGS ) return r128_do_engine_reset( dev ); } - -/* ================================================================ - * Fullscreen mode - */ - -static int r128_do_init_pageflip( drm_device_t *dev ) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "\n" ); - - dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); - dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); - - R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset ); - R128_WRITE( R128_CRTC_OFFSET_CNTL, - dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL ); - - dev_priv->page_flipping = 1; - dev_priv->current_page = 0; - - return 0; -} - -int r128_do_cleanup_pageflip( drm_device_t *dev ) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "\n" ); - - R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); - R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); - - dev_priv->page_flipping = 0; - dev_priv->current_page = 0; - - return 0; -} - int r128_fullscreen( DRM_IOCTL_ARGS ) { - DRM_DEVICE; - drm_r128_fullscreen_t fs; - - LOCK_TEST_WITH_RETURN( dev, filp ); - - DRM_COPY_FROM_USER_IOCTL( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) ); - - switch ( fs.func ) { - case R128_INIT_FULLSCREEN: - return r128_do_init_pageflip( dev ); - case R128_CLEANUP_FULLSCREEN: - return r128_do_cleanup_pageflip( dev ); - } - return DRM_ERR(EINVAL); } @@ -916,7 +876,7 @@ drm_buf_t *r128_freelist_get( drm_device_t *dev ) DRM_UDELAY( 1 ); } - DRM_ERROR( "returning NULL!\n" ); + DRM_DEBUG( "returning NULL!\n" ); return NULL; } diff --git a/sys/dev/drm/r128_drm.h b/sys/dev/drm/r128_drm.h index be26ca4103f0..45c6bf611509 100644 --- a/sys/dev/drm/r128_drm.h +++ b/sys/dev/drm/r128_drm.h @@ -164,8 +164,10 @@ typedef struct drm_r128_sarea { unsigned int last_dispatch; drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; - int tex_age[R128_NR_TEX_HEAPS]; + unsigned int tex_age[R128_NR_TEX_HEAPS]; int ctx_owner; + int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */ + int pfCurrentPage; /* which buffer is being displayed? */ } drm_r128_sarea_t; @@ -193,6 +195,7 @@ typedef struct drm_r128_sarea { #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) #define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) #define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t) +#define DRM_IOCTL_R128_FLIP DRM_IO( 0x53) typedef struct drm_r128_init { enum { diff --git a/sys/dev/drm/r128_drv.c b/sys/dev/drm/r128_drv.c index 622190ad86e7..b2d6fbcabd8f 100644 --- a/sys/dev/drm/r128_drv.c +++ b/sys/dev/drm/r128_drv.c @@ -75,6 +75,7 @@ drm_chipinfo_t DRM(devicelist)[] = { #include "dev/drm/drm_ioctl.h" #include "dev/drm/drm_lock.h" #include "dev/drm/drm_memory.h" +#include "dev/drm/drm_pci.h" #include "dev/drm/drm_sysctl.h" #include "dev/drm/drm_vm.h" #if __HAVE_SG diff --git a/sys/dev/drm/r128_drv.h b/sys/dev/drm/r128_drv.h index 6252838e5729..14118ffb1de6 100644 --- a/sys/dev/drm/r128_drv.h +++ b/sys/dev/drm/r128_drv.h @@ -149,6 +149,7 @@ extern int r128_do_cleanup_pageflip( drm_device_t *dev ); /* r128_state.c */ extern int r128_cce_clear( DRM_IOCTL_ARGS ); extern int r128_cce_swap( DRM_IOCTL_ARGS ); +extern int r128_cce_flip( DRM_IOCTL_ARGS ); extern int r128_cce_vertex( DRM_IOCTL_ARGS ); extern int r128_cce_indices( DRM_IOCTL_ARGS ); extern int r128_cce_blit( DRM_IOCTL_ARGS ); @@ -345,13 +346,20 @@ extern int r128_cce_indirect( DRM_IOCTL_ARGS ); #define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 #define R128_CCE_VC_CNTL_NUM_SHIFT 16 +#define R128_DATATYPE_VQ 0 +#define R128_DATATYPE_CI4 1 #define R128_DATATYPE_CI8 2 #define R128_DATATYPE_ARGB1555 3 #define R128_DATATYPE_RGB565 4 #define R128_DATATYPE_RGB888 5 #define R128_DATATYPE_ARGB8888 6 #define R128_DATATYPE_RGB332 7 +#define R128_DATATYPE_Y8 8 #define R128_DATATYPE_RGB8 9 +#define R128_DATATYPE_CI16 10 +#define R128_DATATYPE_YVYU422 11 +#define R128_DATATYPE_VYUY422 12 +#define R128_DATATYPE_AYUV444 14 #define R128_DATATYPE_ARGB4444 15 /* Constants */ @@ -442,7 +450,7 @@ do { \ #if defined(__powerpc__) #define r128_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring ) #else -#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->ring_rptr) +#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER() #endif diff --git a/sys/dev/drm/r128_irq.c b/sys/dev/drm/r128_irq.c index 5fb8f22f13ae..df829428430e 100644 --- a/sys/dev/drm/r128_irq.c +++ b/sys/dev/drm/r128_irq.c @@ -38,7 +38,7 @@ #include "dev/drm/r128_drm.h" #include "dev/drm/r128_drv.h" -void r128_dma_service( DRM_IRQ_ARGS ) +irqreturn_t r128_dma_service( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_r128_private_t *dev_priv = @@ -53,7 +53,9 @@ void r128_dma_service( DRM_IRQ_ARGS ) atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); DRM(vbl_send_signals)( dev ); + return IRQ_HANDLED; } + return IRQ_NONE; } int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) @@ -95,8 +97,9 @@ void r128_driver_irq_postinstall( drm_device_t *dev ) { void r128_driver_irq_uninstall( drm_device_t *dev ) { drm_r128_private_t *dev_priv = (drm_r128_private_t *)dev->dev_private; - if ( dev_priv ) { - /* Disable *all* interrupts */ - R128_WRITE( R128_GEN_INT_CNTL, 0 ); - } + if (!dev_priv) + return; + + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); } diff --git a/sys/dev/drm/r128_state.c b/sys/dev/drm/r128_state.c index 9f2210405462..b7b05e23752b 100644 --- a/sys/dev/drm/r128_state.c +++ b/sys/dev/drm/r128_state.c @@ -502,8 +502,16 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS ); - OUT_RING( dev_priv->back_pitch_offset_c ); - OUT_RING( dev_priv->front_pitch_offset_c ); + /* Make this work even if front & back are flipped: + */ + if (dev_priv->current_page == 0) { + OUT_RING( dev_priv->back_pitch_offset_c ); + OUT_RING( dev_priv->front_pitch_offset_c ); + } + else { + OUT_RING( dev_priv->front_pitch_offset_c ); + OUT_RING( dev_priv->back_pitch_offset_c ); + } OUT_RING( (x << 16) | y ); OUT_RING( (x << 16) | y ); @@ -530,7 +538,10 @@ static void r128_cce_dispatch_flip( drm_device_t *dev ) { drm_r128_private_t *dev_priv = dev->dev_private; RING_LOCALS; - DRM_DEBUG( "page=%d\n", dev_priv->current_page ); + DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", + __FUNCTION__, + dev_priv->current_page, + dev_priv->sarea_priv->pfCurrentPage); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... @@ -545,10 +556,8 @@ static void r128_cce_dispatch_flip( drm_device_t *dev ) if ( dev_priv->current_page == 0 ) { OUT_RING( dev_priv->back_offset ); - dev_priv->current_page = 1; } else { OUT_RING( dev_priv->front_offset ); - dev_priv->current_page = 0; } ADVANCE_RING(); @@ -558,6 +567,8 @@ static void r128_cce_dispatch_flip( drm_device_t *dev ) * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -804,6 +815,8 @@ static int r128_cce_dispatch_blit( DRMFILE filp, case R128_DATATYPE_ARGB1555: case R128_DATATYPE_RGB565: case R128_DATATYPE_ARGB4444: + case R128_DATATYPE_YVYU422: + case R128_DATATYPE_VYUY422: dword_shift = 1; break; case R128_DATATYPE_CI8: @@ -1266,6 +1279,62 @@ int r128_cce_clear( DRM_IOCTL_ARGS ) return 0; } +static int r128_do_init_pageflip( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "\n" ); + + dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); + dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); + + R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset ); + R128_WRITE( R128_CRTC_OFFSET_CNTL, + dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL ); + + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + + return 0; +} + +int r128_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "\n" ); + + R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); + R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); + + if (dev_priv->current_page != 0) + r128_cce_dispatch_flip( dev ); + + dev_priv->page_flipping = 0; + return 0; +} + +/* Swapping and flipping are different operations, need different ioctls. + * They can & should be intermixed to support multiple 3d windows. + */ + +int r128_cce_flip( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + LOCK_TEST_WITH_RETURN( dev, filp ); + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + + if (!dev_priv->page_flipping) + r128_do_init_pageflip( dev ); + + r128_cce_dispatch_flip( dev ); + + return 0; +} + int r128_cce_swap( DRM_IOCTL_ARGS ) { DRM_DEVICE; @@ -1280,13 +1349,9 @@ int r128_cce_swap( DRM_IOCTL_ARGS ) if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; - if ( !dev_priv->page_flipping ) { - r128_cce_dispatch_swap( dev ); - dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | - R128_UPLOAD_MASKS); - } else { - r128_cce_dispatch_flip( dev ); - } + r128_cce_dispatch_swap( dev ); + dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | + R128_UPLOAD_MASKS); return 0; } diff --git a/sys/dev/drm/radeon.h b/sys/dev/drm/radeon.h index eaff6cd8212b..c0af52b0d9e1 100644 --- a/sys/dev/drm/radeon.h +++ b/sys/dev/drm/radeon.h @@ -53,7 +53,7 @@ #define DRIVER_DATE "20020828" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 8 +#define DRIVER_MINOR 9 #define DRIVER_PATCHLEVEL 0 /* Interface history: @@ -81,6 +81,8 @@ * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) * 1.8 - Remove need to call cleanup ioctls on last client exit (keith) * Add 'GET' queries for starting additional clients on different VT's. + * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl. + * Add texture rectangle support for r100. */ #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ @@ -89,6 +91,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, \ diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c index ba3aa99b504f..4cabde8231ea 100644 --- a/sys/dev/drm/radeon_cp.c +++ b/sys/dev/drm/radeon_cp.c @@ -906,7 +906,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", - entry->busaddr[page_ofs], + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -977,10 +977,36 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, RADEON_ISYNC_CPSCRATCH_IDLEGUI) ); } +/* Enable or disable PCI GART on the chip */ +static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on ) +{ + u32 tmp = RADEON_READ( RADEON_AIC_CNTL ); + + if ( on ) { + RADEON_WRITE( RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN ); + + /* set PCI GART page-table base address + */ + RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart ); + + /* set address range for PCI address translate + */ + RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start ); + RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start + + dev_priv->agp_size - 1); + + /* Turn off AGP aperture -- is this required for PCIGART? + */ + RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */ + RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */ + } else { + RADEON_WRITE( RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN ); + } +} + static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) { drm_radeon_private_t *dev_priv; - u32 tmp; DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); @@ -1153,10 +1179,11 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); +#if __REALLY_HAVE_AGP 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) { @@ -1165,7 +1192,9 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } - } else { + } else +#endif + { dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset; dev_priv->ring_rptr->handle = @@ -1212,8 +1241,13 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; -#if __REALLY_HAVE_SG - if ( dev_priv->is_pci ) { +#if __REALLY_HAVE_AGP + if ( !dev_priv->is_pci ) { + /* Turn off PCI GART */ + radeon_set_pcigart( dev_priv, 0 ); + } else +#endif + { if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, &dev_priv->bus_pci_gart)) { DRM_ERROR( "failed to init PCI GART!\n" ); @@ -1221,36 +1255,10 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) radeon_do_cleanup_cp(dev); return DRM_ERR(ENOMEM); } - /* Turn on PCI GART - */ - tmp = RADEON_READ( RADEON_AIC_CNTL ) - | RADEON_PCIGART_TRANSLATE_EN; - RADEON_WRITE( RADEON_AIC_CNTL, tmp ); - /* set PCI GART page-table base address - */ - RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart ); - - /* set address range for PCI address translate - */ - RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start ); - RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start - + dev_priv->agp_size - 1); - - /* Turn off AGP aperture -- is this required for PCIGART? - */ - RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */ - RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */ - } else { -#endif /* __REALLY_HAVE_SG */ - /* Turn off PCI GART - */ - tmp = RADEON_READ( RADEON_AIC_CNTL ) - & ~RADEON_PCIGART_TRANSLATE_EN; - RADEON_WRITE( RADEON_AIC_CNTL, tmp ); -#if __REALLY_HAVE_SG + /* Turn on PCI GART */ + radeon_set_pcigart( dev_priv, 1 ); } -#endif /* __REALLY_HAVE_SG */ radeon_cp_load_microcode( dev_priv ); radeon_cp_init_ring_buffer( dev, dev_priv ); @@ -1268,23 +1276,32 @@ int radeon_do_cleanup_cp( drm_device_t *dev ) { DRM_DEBUG( "\n" ); +#if _HAVE_DMA_IRQ + /* Make sure interrupts are disabled here because the uninstall ioctl + * may not have been called from userspace and after dev_private + * is freed, it's too late. + */ + if ( dev->irq ) DRM(irq_uninstall)(dev); +#endif + 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 + { 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), @@ -1295,11 +1312,53 @@ int radeon_do_cleanup_cp( drm_device_t *dev ) return 0; } +/* This code will reinit the Radeon CP hardware after a resume from disc. + * AFAIK, it would be very difficult to pickle the state at suspend time, so + * here we make sure that all Radeon hardware initialisation is re-done without + * affecting running applications. + * + * Charl P. Botha + */ +static int radeon_do_resume_cp( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if ( !dev_priv ) { + DRM_ERROR( "Called with no initialization\n" ); + return DRM_ERR( EINVAL ); + } + + DRM_DEBUG("Starting radeon_do_resume_cp()\n"); + +#if __REALLY_HAVE_AGP + if ( !dev_priv->is_pci ) { + /* Turn off PCI GART */ + radeon_set_pcigart( dev_priv, 0 ); + } else +#endif + { + /* Turn on PCI GART */ + radeon_set_pcigart( dev_priv, 1 ); + } + + radeon_cp_load_microcode( dev_priv ); + radeon_cp_init_ring_buffer( dev, dev_priv ); + + radeon_do_engine_reset( dev ); + + DRM_DEBUG("radeon_do_resume_cp() complete\n"); + + return 0; +} + + int radeon_cp_init( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_radeon_init_t init; + LOCK_TEST_WITH_RETURN( dev, filp ); + DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) ); switch ( init.func ) { @@ -1448,6 +1507,16 @@ int radeon_cp_idle( DRM_IOCTL_ARGS ) return radeon_do_cp_idle( dev_priv ); } +/* Added by Charl P. Botha to call radeon_do_resume_cp(). + */ +int radeon_cp_resume( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + + return radeon_do_resume_cp(dev); +} + + int radeon_engine_reset( DRM_IOCTL_ARGS ) { DRM_DEVICE; diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h index 4ee73e50dd75..c228c9ee264d 100644 --- a/sys/dev/drm/radeon_drm.h +++ b/sys/dev/drm/radeon_drm.h @@ -143,7 +143,10 @@ #define R200_EMIT_PP_CUBIC_OFFSETS_4 70 #define R200_EMIT_PP_CUBIC_FACES_5 71 #define R200_EMIT_PP_CUBIC_OFFSETS_5 72 -#define RADEON_MAX_STATE_PACKETS 73 +#define RADEON_EMIT_PP_TEX_SIZE_0 73 +#define RADEON_EMIT_PP_TEX_SIZE_1 74 +#define RADEON_EMIT_PP_TEX_SIZE_2 75 +#define RADEON_MAX_STATE_PACKETS 76 /* Commands understood by cmd_buffer ioctl. More can be added but @@ -324,12 +327,6 @@ typedef struct { } drm_radeon_state_t; -typedef struct { - unsigned char next, prev; - unsigned char in_use; - int age; -} drm_radeon_tex_region_t; - typedef struct { /* The channel for communication of state information to the * kernel on firing a vertex buffer with either of the @@ -352,8 +349,8 @@ typedef struct { unsigned int last_dispatch; unsigned int last_clear; - drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1]; - int tex_age[RADEON_NR_TEX_HEAPS]; + drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1]; + unsigned int tex_age[RADEON_NR_TEX_HEAPS]; int ctx_owner; int pfState; /* number of 3d windows (0,1,2ormore) */ int pfCurrentPage; /* which buffer is being displayed? */ @@ -393,6 +390,8 @@ typedef struct { #define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t) #define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t) #define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t) +/* added by Charl P. Botha - see radeon_cp.c for details */ +#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO(0x58) typedef struct drm_radeon_init { enum { @@ -532,8 +531,10 @@ typedef struct drm_radeon_indirect { #define RADEON_PARAM_LAST_FRAME 2 #define RADEON_PARAM_LAST_DISPATCH 3 #define RADEON_PARAM_LAST_CLEAR 4 +/* Added with DRM version 1.6. */ #define RADEON_PARAM_IRQ_NR 5 #define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */ +/* Added with DRM version 1.8. */ #define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ #define RADEON_PARAM_STATUS_HANDLE 8 #define RADEON_PARAM_SAREA_HANDLE 9 diff --git a/sys/dev/drm/radeon_drv.c b/sys/dev/drm/radeon_drv.c index 3d83e0151b49..115dab5879e2 100644 --- a/sys/dev/drm/radeon_drv.c +++ b/sys/dev/drm/radeon_drv.c @@ -88,6 +88,7 @@ drm_chipinfo_t DRM(devicelist)[] = { #include "dev/drm/drm_ioctl.h" #include "dev/drm/drm_lock.h" #include "dev/drm/drm_memory.h" +#include "dev/drm/drm_pci.h" #include "dev/drm/drm_vm.h" #include "dev/drm/drm_sysctl.h" #if __HAVE_SG diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h index 0276ebd79b9a..e23ec0feb950 100644 --- a/sys/dev/drm/radeon_drv.h +++ b/sys/dev/drm/radeon_drv.h @@ -161,6 +161,7 @@ extern int radeon_cp_start( DRM_IOCTL_ARGS ); extern int radeon_cp_stop( DRM_IOCTL_ARGS ); extern int radeon_cp_reset( DRM_IOCTL_ARGS ); extern int radeon_cp_idle( DRM_IOCTL_ARGS ); +extern int radeon_cp_resume( DRM_IOCTL_ARGS ); extern int radeon_engine_reset( DRM_IOCTL_ARGS ); extern int radeon_fullscreen( DRM_IOCTL_ARGS ); extern int radeon_cp_buffers( DRM_IOCTL_ARGS ); @@ -583,6 +584,7 @@ extern void radeon_do_release(drm_device_t *dev); #define RADEON_TXFORMAT_ARGB4444 5 #define RADEON_TXFORMAT_ARGB8888 6 #define RADEON_TXFORMAT_RGBA8888 7 +#define RADEON_TXFORMAT_Y8 8 #define RADEON_TXFORMAT_VYUY422 10 #define RADEON_TXFORMAT_YVYU422 11 #define RADEON_TXFORMAT_DXT1 12 @@ -669,6 +671,10 @@ extern void radeon_do_release(drm_device_t *dev); #define R200_RE_POINTSIZE 0x2648 #define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 +#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ +#define RADEON_PP_TEX_SIZE_1 0x1d0c +#define RADEON_PP_TEX_SIZE_2 0x1d14 + #define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 @@ -854,7 +860,7 @@ do { \ #define COMMIT_RING() do { \ /* Flush writes to ring */ \ - DRM_READMEMORYBARRIER( dev_priv->mmio ); \ + DRM_MEMORYBARRIER(); \ GET_RING_HEAD( dev_priv ); \ RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \ /* read from PCI bus to ensure correct posting */ \ diff --git a/sys/dev/drm/radeon_irq.c b/sys/dev/drm/radeon_irq.c index 51e0edb01a0c..bd35bf4625b8 100644 --- a/sys/dev/drm/radeon_irq.c +++ b/sys/dev/drm/radeon_irq.c @@ -56,7 +56,7 @@ * tied to dma at all, this is just a hangover from dri prehistory. */ -void DRM(dma_service)( DRM_IRQ_ARGS ) +irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = @@ -69,7 +69,7 @@ void DRM(dma_service)( DRM_IRQ_ARGS ) stat = RADEON_READ(RADEON_GEN_INT_STATUS) & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); if (!stat) - return; + return IRQ_NONE; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { @@ -85,6 +85,7 @@ void DRM(dma_service)( DRM_IRQ_ARGS ) /* Acknowledge interrupts we handle */ RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); + return IRQ_HANDLED; } static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) @@ -251,8 +252,9 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { void DRM(driver_irq_uninstall)( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; - if ( dev_priv ) { - /* Disable *all* interrupts */ - RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); - } + if (!dev_priv) + return; + + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); } diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c index f038250c7ccc..235fa17ec3e5 100644 --- a/sys/dev/drm/radeon_state.c +++ b/sys/dev/drm/radeon_state.c @@ -294,6 +294,9 @@ static struct { { R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" }, { R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" }, { R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" }, + { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" }, + { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" }, + { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_1" }, }; @@ -887,15 +890,14 @@ typedef struct { static void radeon_cp_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf, - drm_radeon_tcl_prim_t *prim, - drm_clip_rect_t *boxes, - int nbox ) + drm_radeon_tcl_prim_t *prim ) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_clip_rect_t box; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start; int numverts = (int)prim->numverts; + int nbox = sarea_priv->nbox; int i = 0; RING_LOCALS; @@ -915,10 +917,8 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev, do { /* Emit the next cliprect */ if ( i < nbox ) { - if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) - return; - - radeon_emit_clip_rect( dev_priv, &box ); + radeon_emit_clip_rect( dev_priv, + &sarea_priv->boxes[i] ); } /* Emit the vertex buffer rendering commands */ @@ -997,18 +997,17 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, static void radeon_cp_dispatch_indices( drm_device_t *dev, drm_buf_t *elt_buf, - drm_radeon_tcl_prim_t *prim, - drm_clip_rect_t *boxes, - int nbox ) + drm_radeon_tcl_prim_t *prim ) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_clip_rect_t box; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int offset = dev_priv->agp_buffers_offset + prim->offset; u32 *data; int dwords; int i = 0; int start = prim->start + RADEON_INDEX_PRIM_OFFSET; int count = (prim->finish - start) / sizeof(u16); + int nbox = sarea_priv->nbox; DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", prim->prim, @@ -1047,12 +1046,9 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, (count << RADEON_NUM_VERTICES_SHIFT) ); do { - if ( i < nbox ) { - if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) - return; - - radeon_emit_clip_rect( dev_priv, &box ); - } + if ( i < nbox ) + radeon_emit_clip_rect( dev_priv, + &sarea_priv->boxes[i] ); radeon_cp_dispatch_indirect( dev, elt_buf, prim->start, @@ -1452,9 +1448,7 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS ) prim.numverts = vertex.count; prim.vc_format = dev_priv->sarea_priv->vc_format; - radeon_cp_dispatch_vertex( dev, buf, &prim, - dev_priv->sarea_priv->boxes, - dev_priv->sarea_priv->nbox ); + radeon_cp_dispatch_vertex( dev, buf, &prim ); } if (vertex.discard) { @@ -1552,9 +1546,7 @@ int radeon_cp_indices( DRM_IOCTL_ARGS ) prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ prim.vc_format = dev_priv->sarea_priv->vc_format; - radeon_cp_dispatch_indices( dev, buf, &prim, - dev_priv->sarea_priv->boxes, - dev_priv->sarea_priv->nbox ); + radeon_cp_dispatch_indices( dev, buf, &prim ); if (elts.discard) { radeon_cp_discard_buffer( dev, buf ); } @@ -1771,16 +1763,12 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS ) tclprim.offset = prim.numverts * 64; tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ - radeon_cp_dispatch_indices( dev, buf, &tclprim, - sarea_priv->boxes, - sarea_priv->nbox); + radeon_cp_dispatch_indices( dev, buf, &tclprim ); } else { tclprim.numverts = prim.numverts; tclprim.offset = 0; /* not used */ - radeon_cp_dispatch_vertex( dev, buf, &tclprim, - sarea_priv->boxes, - sarea_priv->nbox); + radeon_cp_dispatch_vertex( dev, buf, &tclprim ); } if (sarea_priv->nbox == 1)