diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2008-05-06 19:24:57 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2008-05-06 19:24:57 +0000 |
commit | 1eed9bf6c704ac401ae8e0657f2ca1d96647174d (patch) | |
tree | 4da41d2b4ec815b7a1074b9bfe30b41916a6a242 /sys/dev | |
parent | 0d12c3f56a9965c9c1fbab7d8a961c9e121bc885 (diff) |
Kill vtophys in drm.
The code we inherited from FreeBSD used vtophys is a fair few places,
nuke that and replace with bus_dma. technically _DRM_SHM should be
managed with uao_create(), but until we move away from mmap and into an
ioctl to map, this will do.
This also paves the way for amd64 support (it lacks vtophys).
ok kettenis, miod looked at it a while back too.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 14 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_bufs.c | 32 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_scatter.c | 104 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_vm.c | 16 |
4 files changed, 156 insertions, 10 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h index f93246c0e93..2b0cc8e7f64 100644 --- a/sys/dev/pci/drm/drmP.h +++ b/sys/dev/pci/drm/drmP.h @@ -668,12 +668,26 @@ typedef struct drm_agp_head { unsigned long page_mask; } drm_agp_head_t; +#ifdef __OpenBSD__ +struct drm_sg_dmamem { + bus_dma_tag_t sg_tag; + bus_dmamap_t sg_map; + bus_dma_segment_t *sg_segs; + int sg_nsegs; + size_t sg_size; + caddr_t sg_kva; +}; +#endif + typedef struct drm_sg_mem { unsigned long handle; void *virtual; int pages; dma_addr_t *busaddr; drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */ +#ifdef __OpenBSD__ + struct drm_sg_dmamem *mem; +#endif } drm_sg_mem_t; typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t; diff --git a/sys/dev/pci/drm/drm_bufs.c b/sys/dev/pci/drm/drm_bufs.c index 3451b7c63f1..e98da50ceb6 100644 --- a/sys/dev/pci/drm/drm_bufs.c +++ b/sys/dev/pci/drm/drm_bufs.c @@ -207,6 +207,7 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, map->mtrr = 1; #endif break; +#ifndef __OpenBSD__ case _DRM_SHM: map->handle = malloc(map->size, M_DRM, M_NOWAIT); DRM_DEBUG( "%lu %d %p\n", @@ -224,12 +225,14 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, DRM_UNLOCK(); free(map->handle, M_DRM); free(map, M_DRM); + DRM_LOCK(); return EBUSY; } dev->lock.hw_lock = map->handle; /* Pointer to lock */ DRM_UNLOCK(); } break; +#endif case _DRM_AGP: /*valid = 0;*/ /* In some cases (i810 driver), user space may have already @@ -276,6 +279,9 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, } map->offset = map->offset + dev->sg->handle; break; +#ifdef __OpenBSD__ + case _DRM_SHM: +#endif case _DRM_CONSISTENT: /* Unfortunately, we don't get any alignment specification from * the caller, so we have to guess. drm_pci_alloc requires @@ -294,6 +300,22 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, } map->handle = map->dmah->vaddr; map->offset = map->dmah->busaddr; +#ifdef __OpenBSD__ + if (map->type == _DRM_SHM && + map->flags & _DRM_CONTAINS_LOCK) { + DRM_LOCK(); + /* Prevent a 2nd X Server from creating a 2nd lock */ + if (dev->lock.hw_lock != NULL) { + DRM_UNLOCK(); + drm_pci_free(dev, map->dmah); + free(map, M_DRM); + DRM_LOCK(); + return EBUSY; + } + dev->lock.hw_lock = map->handle; + DRM_UNLOCK(); + } +#endif break; default: DRM_ERROR("Bad map type %d\n", map->type); @@ -343,9 +365,10 @@ drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv) request->mtrr = map->mtrr; request->handle = map->handle; - if (request->type != _DRM_SHM) { +#ifndef __OpenBSD__ + if (request->type != _DRM_SHM) +#endif request->handle = (void *)request->offset; - } return 0; } @@ -375,12 +398,17 @@ drm_rmmap(drm_device_t *dev, drm_local_map_t *map) } #endif break; +#ifndef __OpenBSD__ case _DRM_SHM: free(map->handle, M_DRM); break; +#endif case _DRM_AGP: case _DRM_SCATTER_GATHER: break; +#ifdef __OpenBSD__ + case _DRM_SHM: +#endif case _DRM_CONSISTENT: drm_pci_free(dev, map->dmah); break; diff --git a/sys/dev/pci/drm/drm_scatter.c b/sys/dev/pci/drm/drm_scatter.c index 5ce642fb5d2..3f9a691b610 100644 --- a/sys/dev/pci/drm/drm_scatter.c +++ b/sys/dev/pci/drm/drm_scatter.c @@ -36,13 +36,24 @@ #include "drmP.h" #define DEBUG_SCATTER 0 +struct drm_sg_dmamem *drm_sg_dmamem_alloc(drm_device_t *, size_t); +void drm_sg_dmamem_free(struct drm_sg_dmamem *); void drm_sg_cleanup(drm_sg_mem_t *entry) { - free((void *)entry->handle, M_DRM); - free(entry->busaddr, M_DRM); - free(entry, M_DRM); + if (entry) { +#ifdef __OpenBSD__ + if (entry->mem) + drm_sg_dmamem_free(entry->mem); +#else + if (entry->handle) + free((void *)entry->handle, M_DRM); +#endif + if (entry->busaddr) + free(entry->busaddr, M_DRM); + free(entry, M_DRM); + } } int @@ -71,9 +82,20 @@ drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request) return ENOMEM; } +#ifdef __OpenBSD__ + if ((entry->mem = drm_sg_dmamem_alloc(dev, pages)) == NULL) { + drm_sg_cleanup(entry); + return ENOMEM; + } + + entry->handle = (unsigned long)entry->mem->sg_kva; + + for (i = 0; i < pages; i++) + entry->busaddr[i] = entry->mem->sg_map->dm_segs[i].ds_addr; +#else entry->handle = (long)malloc(pages << PAGE_SHIFT, M_DRM, M_WAITOK | M_ZERO); - if (entry->handle == 0) { + if (entry->handle == NULL) { drm_sg_cleanup(entry); return ENOMEM; } @@ -81,6 +103,7 @@ drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request) for (i = 0; i < pages; i++) { entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE); } +#endif DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); @@ -131,3 +154,76 @@ drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv) return 0; } + +/* + * allocate `pages' pages of dma memory for use in + * scatter/gather + */ +struct drm_sg_dmamem* +drm_sg_dmamem_alloc(drm_device_t *dev, size_t pages) +{ + struct drm_sg_dmamem *dsd = NULL; + bus_size_t size = pages << PAGE_SHIFT; + int ret = 0; + + printf("size = %d\n", size); + + dsd = malloc(sizeof(*dsd), M_DRM, M_NOWAIT | M_ZERO); + if (dsd == NULL) + return (NULL); + + dsd->sg_segs = malloc(sizeof(*dsd->sg_segs) * pages, M_DRM, + M_NOWAIT | M_ZERO); + if (dsd->sg_segs == NULL) + goto dsdfree; + + dsd->sg_tag = dev->pa.pa_dmat; + dsd->sg_size = size; + + if (bus_dmamap_create(dev->pa.pa_dmat, size, pages, PAGE_SIZE, 0, + BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &dsd->sg_map) != 0) + goto segsfree; + + if ((ret = bus_dmamem_alloc(dev->pa.pa_dmat, size, PAGE_SIZE, 0, + dsd->sg_segs, pages, &dsd->sg_nsegs, BUS_DMA_NOWAIT)) != 0) { + printf("alloc failed, value= %d\n",ret); + goto destroy; + } + + if (bus_dmamem_map(dev->pa.pa_dmat, dsd->sg_segs, dsd->sg_nsegs, size, + &dsd->sg_kva, BUS_DMA_NOWAIT) != 0) + goto free; + + if (bus_dmamap_load(dev->pa.pa_dmat, dsd->sg_map, dsd->sg_kva, size, + NULL, BUS_DMA_NOWAIT) != 0) + goto unmap; + + bzero(dsd->sg_kva, size); + + return (dsd); + +unmap: + bus_dmamem_unmap(dev->pa.pa_dmat, dsd->sg_kva, size); +free: + bus_dmamem_free(dev->pa.pa_dmat, dsd->sg_segs, dsd->sg_nsegs); +destroy: + bus_dmamap_destroy(dev->pa.pa_dmat, dsd->sg_map); +segsfree: + free(dsd->sg_segs, M_DRM); + +dsdfree: + free(dsd, M_DRM); + + return (NULL); +} + +void +drm_sg_dmamem_free(struct drm_sg_dmamem *mem) +{ + bus_dmamap_unload(mem->sg_tag, mem->sg_map); + bus_dmamem_unmap(mem->sg_tag, mem->sg_kva, mem->sg_size); + bus_dmamem_free(mem->sg_tag, mem->sg_segs, mem->sg_nsegs); + bus_dmamap_destroy(mem->sg_tag, mem->sg_map); + free(mem->sg_segs, M_DRM); + free(mem, M_DRM); +} diff --git a/sys/dev/pci/drm/drm_vm.c b/sys/dev/pci/drm/drm_vm.c index cbc3039f3ea..550f7b9a14f 100644 --- a/sys/dev/pci/drm/drm_vm.c +++ b/sys/dev/pci/drm/drm_vm.c @@ -118,17 +118,25 @@ drm_mmap(dev_t kdev, off_t offset, int prot) case _DRM_AGP: phys = offset; break; - case _DRM_CONSISTENT: #ifdef __FreeBSD__ + case _DRM_CONSISTENT: phys = vtophys((char *)map->handle + (offset - map->offset)); -#else - phys = vtophys((paddr_t)map->handle + (offset - map->offset)); -#endif break; case _DRM_SCATTER_GATHER: case _DRM_SHM: phys = vtophys(offset); break; +#else + /* XXX unify all the bus_dmamem_mmap bits */ + case _DRM_SCATTER_GATHER: + return bus_dmamem_mmap(dev->pa.pa_dmat, dev->sg->mem->sg_segs, + dev->sg->mem->sg_nsegs, offset - dev->sg->handle, prot, + BUS_DMA_NOWAIT); + case _DRM_SHM: + case _DRM_CONSISTENT: + return bus_dmamem_mmap(dev->pa.pa_dmat, &map->dmah->seg, 1, + offset - map->offset, prot, BUS_DMA_NOWAIT); +#endif default: DRM_ERROR("bad map type %d\n", type); return -1; /* This should never happen. */ |