diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-03-27 19:00:46 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-03-27 19:00:46 +0000 |
commit | 7eab1c3354287ce572c4e83fa13c6714c57cd03c (patch) | |
tree | 3a330b542a0b978b4499569bafafecb4de31c9d0 /sys/dev | |
parent | 6b9d819b8bcb1c0c17f40578151e34adc84133c9 (diff) |
Rework the dma buffer api a bit to make it smaller and to have less
duplicated code. Also, switch the dma_lock to a rwlock (it never should
have been a spinlock) and move it and some other accounting data into
the dma structure, not the main softc.
Finally, the funcitons in drm_dma are tiny, move them in with the rest
of the dma_bufs api in drm_bufs and remove the file.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 44 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_bufs.c | 237 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_dma.c | 135 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_drv.c | 23 | ||||
-rw-r--r-- | sys/dev/pci/drm/files.drm | 3 | ||||
-rw-r--r-- | sys/dev/pci/drm/mga_dma.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/drm/savage_bci.c | 2 |
7 files changed, 161 insertions, 287 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h index 9f8a2ed7b57..9ef2b8aa426 100644 --- a/sys/dev/pci/drm/drmP.h +++ b/sys/dev/pci/drm/drmP.h @@ -284,13 +284,15 @@ struct drm_lock_data { * not concurrently accessed, so no locking is needed. */ typedef struct drm_device_dma { - drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; - int buf_count; - drm_buf_t **buflist; /* Vector of pointers info bufs */ - int seg_count; - int page_count; - unsigned long *pagelist; - unsigned long byte_count; + struct rwlock dma_lock; + drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; + drm_buf_t **buflist; /* Vector of pointers info bufs */ + unsigned long *pagelist; + unsigned long byte_count; + int buf_use; /* Buffers in use -- cannot alloc */ + int buf_count; + int page_count; + int seg_count; enum { _DRM_DMA_USE_AGP = 0x01, _DRM_DMA_USE_SG = 0x02 @@ -437,13 +439,11 @@ struct drm_device { int if_version; /* Highest interface version set */ /* Locks */ - DRM_SPINTYPE dma_lock; /* protects dev->dma */ DRM_SPINTYPE irq_lock; /* protects irq condition checks */ struct rwlock dev_lock; /* protects everything else */ /* Usage Counters */ int open_count; /* Outstanding files open */ - int buf_use; /* Buffers in use -- cannot alloc */ /* Authentication */ SPLAY_HEAD(drm_file_tree, drm_file) files; @@ -543,23 +543,23 @@ void drm_write32(drm_local_map_t *, unsigned long, u_int32_t); int drm_lock_take(struct drm_lock_data *, unsigned int); int drm_lock_free(struct drm_lock_data *, unsigned int); -/* Buffer management support (drm_bufs.c) */ +/* Buffer management and DMA support (drm_bufs.c) */ +int drm_order(unsigned long); +int drm_rmmap_ioctl(struct drm_device *, void *, struct drm_file *); void drm_rmmap(struct drm_device *, drm_local_map_t *); void drm_rmmap_locked(struct drm_device *, drm_local_map_t *); -int drm_order(unsigned long); +int drm_addmap_ioctl(struct drm_device *, void *, struct drm_file *); int drm_addmap(struct drm_device *, unsigned long, unsigned long, enum drm_map_type, enum drm_map_flags, drm_local_map_t **); -int drm_addbufs_pci(struct drm_device *, struct drm_buf_desc *); -int drm_addbufs_sg(struct drm_device *, struct drm_buf_desc *); -int drm_addbufs_agp(struct drm_device *, struct drm_buf_desc *); - -/* DMA support (drm_dma.c) */ +int drm_addbufs(struct drm_device *, struct drm_buf_desc *); +int drm_freebufs(struct drm_device *, void *, struct drm_file *); +int drm_mapbufs(struct drm_device *, void *, struct drm_file *); +int drm_dma(struct drm_device *, void *, struct drm_file *); int drm_dma_setup(struct drm_device *); void drm_dma_takedown(struct drm_device *); void drm_cleanup_buf(struct drm_device *, drm_buf_entry_t *); void drm_free_buffer(struct drm_device *, drm_buf_t *); void drm_reclaim_buffers(struct drm_device *, struct drm_file *); -#define drm_core_reclaim_buffers drm_reclaim_buffers /* IRQ support (drm_irq.c) */ int drm_irq_install(struct drm_device *); @@ -609,16 +609,6 @@ int drm_addctx(struct drm_device *, void *, struct drm_file *); int drm_getctx(struct drm_device *, void *, struct drm_file *); int drm_rmctx(struct drm_device *, void *, struct drm_file *); -/* Buffer management support (drm_bufs.c) */ -int drm_addmap_ioctl(struct drm_device *, void *, struct drm_file *); -int drm_rmmap_ioctl(struct drm_device *, void *, struct drm_file *); -int drm_addbufs_ioctl(struct drm_device *, void *, struct drm_file *); -int drm_freebufs(struct drm_device *, void *, struct drm_file *); -int drm_mapbufs(struct drm_device *, void *, struct drm_file *); - -/* DMA support (drm_dma.c) */ -int drm_dma(struct drm_device *, void *, struct drm_file *); - /* IRQ support (drm_irq.c) */ int drm_control(struct drm_device *, void *, struct drm_file *); int drm_wait_vblank(struct drm_device *, void *, struct drm_file *); diff --git a/sys/dev/pci/drm/drm_bufs.c b/sys/dev/pci/drm/drm_bufs.c index 236ca48a5d4..18fb26907f9 100644 --- a/sys/dev/pci/drm/drm_bufs.c +++ b/sys/dev/pci/drm/drm_bufs.c @@ -37,9 +37,9 @@ #include "drmP.h" -int drm_do_addbufs_agp(struct drm_device *, drm_buf_desc_t *); -int drm_do_addbufs_pci(struct drm_device *, drm_buf_desc_t *); -int drm_do_addbufs_sg(struct drm_device *, drm_buf_desc_t *); +int drm_addbufs_pci(struct drm_device *, struct drm_buf_desc *); +int drm_addbufs_sg(struct drm_device *, struct drm_buf_desc *); +int drm_addbufs_agp(struct drm_device *, struct drm_buf_desc *); /* * Compute order. Can be made faster. @@ -346,10 +346,112 @@ drm_rmmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) return 0; } +/* + * DMA buffers api. + * + * The implementation used to be significantly more complicated, but the + * complexity has been moved into the drivers as different buffer management + * schemes evolved. + * + * This api is going to die eventually. + */ + +int +drm_dma_setup(struct drm_device *dev) +{ + + dev->dma = drm_calloc(1, sizeof(*dev->dma)); + if (dev->dma == NULL) + return (ENOMEM); + + rw_init(&dev->dma->dma_lock, "drmdma"); + + return (0); +} + +void +drm_cleanup_buf(struct drm_device *dev, drm_buf_entry_t *entry) +{ + int i; + + if (entry->seg_count) { + for (i = 0; i < entry->seg_count; i++) + drm_dmamem_free(dev->dmat, entry->seglist[i]); + drm_free(entry->seglist); + + entry->seg_count = 0; + } + + if (entry->buf_count) { + for (i = 0; i < entry->buf_count; i++) { + drm_free(entry->buflist[i].dev_private); + } + drm_free(entry->buflist); + + entry->buf_count = 0; + } +} + +void +drm_dma_takedown(struct drm_device *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i; + if (dma == NULL) + return; + /* Clear dma buffers */ + for (i = 0; i <= DRM_MAX_ORDER; i++) + drm_cleanup_buf(dev, &dma->bufs[i]); + + drm_free(dma->buflist); + drm_free(dma->pagelist); + drm_free(dev->dma); + dev->dma = NULL; +} + + +void +drm_free_buffer(struct drm_device *dev, drm_buf_t *buf) +{ + if (buf == NULL) + return; + + buf->pending = 0; + buf->file_priv= NULL; + buf->used = 0; +} + +void +drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + if (dma == NULL) + return; + for (i = 0; i < dma->buf_count; i++) { + if (dma->buflist[i]->file_priv == file_priv) + drm_free_buffer(dev, dma->buflist[i]); + } +} + +/* Call into the driver-specific DMA handler */ int -drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request) +drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + + if (dev->driver->dma_ioctl != NULL) { + return (dev->driver->dma_ioctl(dev, data, file_priv)); + } else { + DRM_DEBUG("DMA ioctl on driver with no dma handler\n"); + return EINVAL; + } +} + +int +drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request) { drm_device_dma_t *dma = dev->dma; drm_buf_entry_t *entry; @@ -481,7 +583,7 @@ drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request) } int -drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request) +drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request) { drm_device_dma_t *dma = dev->dma; int count; @@ -624,7 +726,7 @@ drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request) } int -drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request) +drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request) { drm_device_dma_t *dma = dev->dma; drm_buf_entry_t *entry; @@ -728,118 +830,41 @@ drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request) } int -drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request) -{ - int order, ret; - - - if (request->count < 0 || request->count > 4096) - return EINVAL; - - order = drm_order(request->size); - if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) - return EINVAL; - - DRM_SPINLOCK(&dev->dma_lock); - - /* No more allocations after first buffer-using ioctl. */ - if (dev->buf_use != 0) { - DRM_SPINUNLOCK(&dev->dma_lock); - return EBUSY; - } - /* No more than one allocation per order */ - if (dev->dma->bufs[order].buf_count != 0) { - DRM_SPINUNLOCK(&dev->dma_lock); - return ENOMEM; - } - - ret = drm_do_addbufs_agp(dev, request); - - DRM_SPINUNLOCK(&dev->dma_lock); - - return ret; -} - -int -drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request) -{ - int order, ret; - - - if (request->count < 0 || request->count > 4096) - return EINVAL; - - order = drm_order(request->size); - if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) - return EINVAL; - - DRM_SPINLOCK(&dev->dma_lock); - - /* No more allocations after first buffer-using ioctl. */ - if (dev->buf_use != 0) { - DRM_SPINUNLOCK(&dev->dma_lock); - return EBUSY; - } - /* No more than one allocation per order */ - if (dev->dma->bufs[order].buf_count != 0) { - DRM_SPINUNLOCK(&dev->dma_lock); - return ENOMEM; - } - - ret = drm_do_addbufs_sg(dev, request); - - DRM_SPINUNLOCK(&dev->dma_lock); - - return ret; -} - -int -drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request) +drm_addbufs(struct drm_device *dev, struct drm_buf_desc *request) { - int order, ret; + struct drm_device_dma *dma = dev->dma; + int order, ret; if (request->count < 0 || request->count > 4096) - return EINVAL; + return (EINVAL); order = drm_order(request->size); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) - return EINVAL; + return (EINVAL); - DRM_SPINLOCK(&dev->dma_lock); + rw_enter_write(&dma->dma_lock); /* No more allocations after first buffer-using ioctl. */ - if (dev->buf_use != 0) { - DRM_SPINUNLOCK(&dev->dma_lock); - return EBUSY; + if (dma->buf_use != 0) { + rw_exit_write(&dma->dma_lock); + return (EBUSY); } /* No more than one allocation per order */ - if (dev->dma->bufs[order].buf_count != 0) { - DRM_SPINUNLOCK(&dev->dma_lock); - return ENOMEM; + if (dma->bufs[order].buf_count != 0) { + rw_exit_write(&dma->dma_lock); + return (ENOMEM); } - ret = drm_do_addbufs_pci(dev, request); - - DRM_SPINUNLOCK(&dev->dma_lock); - - return ret; -} - -int -drm_addbufs_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_buf_desc *request = data; - int err; - if (request->flags & _DRM_AGP_BUFFER) - err = drm_addbufs_agp(dev, request); + ret = drm_addbufs_agp(dev, request); else if (request->flags & _DRM_SG_BUFFER) - err = drm_addbufs_sg(dev, request); + ret = drm_addbufs_sg(dev, request); else - err = drm_addbufs_pci(dev, request); + ret = drm_addbufs_pci(dev, request); + + rw_exit_write(&dma->dma_lock); - return err; + return (ret); } int @@ -852,7 +877,7 @@ drm_freebufs(struct drm_device *dev, void *data, struct drm_file *file_priv) DRM_DEBUG("%d\n", request->count); - DRM_SPINLOCK(&dev->dma_lock); + rw_enter_write(&dma->dma_lock); for (i = 0; i < request->count; i++) { if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) { retcode = EFAULT; @@ -873,7 +898,7 @@ drm_freebufs(struct drm_device *dev, void *data, struct drm_file *file_priv) } drm_free_buffer(dev, buf); } - DRM_SPINUNLOCK(&dev->dma_lock); + rw_exit_write(&dma->dma_lock); return retcode; } @@ -899,9 +924,9 @@ drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv) vms = curproc->p_vmspace; - DRM_SPINLOCK(&dev->dma_lock); - dev->buf_use++; /* Can't allocate more after this call */ - DRM_SPINUNLOCK(&dev->dma_lock); + rw_enter_write(&dma->dma_lock); + dev->dma->buf_use++; /* Can't allocate more after this call */ + rw_exit_write(&dma->dma_lock); if (request->count < dma->buf_count) goto done; diff --git a/sys/dev/pci/drm/drm_dma.c b/sys/dev/pci/drm/drm_dma.c deleted file mode 100644 index 1e60bae4ea7..00000000000 --- a/sys/dev/pci/drm/drm_dma.c +++ /dev/null @@ -1,135 +0,0 @@ -/*- - * Copyright 1999, 2000 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 <faith@valinux.com> - * Gareth Hughes <gareth@valinux.com> - * - */ - -/** @file drm_dma.c - * Support code for DMA buffer management. - * - * The implementation used to be significantly more complicated, but the - * complexity has been moved into the drivers as different buffer management - * schemes evolved. - */ - -#include "drmP.h" - -int -drm_dma_setup(struct drm_device *dev) -{ - - dev->dma = drm_calloc(1, sizeof(*dev->dma)); - if (dev->dma == NULL) - return ENOMEM; - - dev->buf_use = 0; - - DRM_SPININIT(&dev->dma_lock, "drmdma"); - - return 0; -} - -void -drm_cleanup_buf(struct drm_device *dev, drm_buf_entry_t *entry) -{ - int i; - - if (entry->seg_count) { - for (i = 0; i < entry->seg_count; i++) - drm_dmamem_free(dev->dmat, entry->seglist[i]); - drm_free(entry->seglist); - - entry->seg_count = 0; - } - - if (entry->buf_count) { - for (i = 0; i < entry->buf_count; i++) { - drm_free(entry->buflist[i].dev_private); - } - drm_free(entry->buflist); - - entry->buf_count = 0; - } -} - -void -drm_dma_takedown(struct drm_device *dev) -{ - drm_device_dma_t *dma = dev->dma; - int i; - - if (dma == NULL) - return; - - /* Clear dma buffers */ - for (i = 0; i <= DRM_MAX_ORDER; i++) - drm_cleanup_buf(dev, &dma->bufs[i]); - - drm_free(dma->buflist); - drm_free(dma->pagelist); - drm_free(dev->dma); - dev->dma = NULL; -} - - -void -drm_free_buffer(struct drm_device *dev, drm_buf_t *buf) -{ - if (buf == NULL) - return; - - buf->pending = 0; - buf->file_priv= NULL; - buf->used = 0; -} - -void -drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) -{ - drm_device_dma_t *dma = dev->dma; - int i; - - if (dma == NULL) - return; - for (i = 0; i < dma->buf_count; i++) { - if (dma->buflist[i]->file_priv == file_priv) - drm_free_buffer(dev, dma->buflist[i]); - } -} - -/* Call into the driver-specific DMA handler */ -int -drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - - if (dev->driver->dma_ioctl != NULL) { - return (dev->driver->dma_ioctl(dev, data, file_priv)); - } else { - DRM_DEBUG("DMA ioctl on driver with no dma handler\n"); - return EINVAL; - } -} diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c index 48ddf17b0cf..093ccedbad5 100644 --- a/sys/dev/pci/drm/drm_drv.c +++ b/sys/dev/pci/drm/drm_drv.c @@ -287,9 +287,8 @@ drm_firstopen(struct drm_device *dev) dev->driver->firstopen(dev); if (dev->driver->flags & DRIVER_DMA) { - i = drm_dma_setup(dev); - if (i != 0) - return i; + if ((i = drm_dma_setup(dev)) != 0) + return (i); } dev->magicid = 1; @@ -618,7 +617,7 @@ drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, case DRM_IOCTL_RM_CTX: return (drm_rmctx(dev, data, file_priv)); case DRM_IOCTL_ADD_BUFS: - return (drm_addbufs_ioctl(dev, data, file_priv)); + return (drm_addbufs(dev, (struct drm_buf_desc *)data)); case DRM_IOCTL_CONTROL: return (drm_control(dev, data, file_priv)); case DRM_IOCTL_AGP_ACQUIRE: @@ -701,18 +700,14 @@ drmmmap(dev_t kdev, off_t offset, int prot) if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) { drm_device_dma_t *dma = dev->dma; + paddr_t phys = -1; - DRM_SPINLOCK(&dev->dma_lock); + rw_enter_write(&dma->dma_lock); + if (dma->pagelist != NULL) + phys = atop(dma->pagelist[offset >> PAGE_SHIFT]); + rw_exit_write(&dma->dma_lock); - if (dma->pagelist != NULL) { - paddr_t phys = dma->pagelist[offset >> PAGE_SHIFT]; - - DRM_SPINUNLOCK(&dev->dma_lock); - return (atop(phys)); - } else { - DRM_SPINUNLOCK(&dev->dma_lock); - return (-1); - } + return (phys); } /* diff --git a/sys/dev/pci/drm/files.drm b/sys/dev/pci/drm/files.drm index 1168862a425..daf993fbb55 100644 --- a/sys/dev/pci/drm/files.drm +++ b/sys/dev/pci/drm/files.drm @@ -1,5 +1,5 @@ # $NetBSD: files.drm,v 1.2 2007/03/28 11:29:37 jmcneill Exp $ -# $OpenBSD: files.drm,v 1.13 2009/03/26 22:40:06 oga Exp $ +# $OpenBSD: files.drm,v 1.14 2009/03/27 19:00:45 oga Exp $ # direct rendering modules define drmbase {} @@ -8,7 +8,6 @@ attach drm at drmbase file dev/pci/drm/drm_agpsupport.c drm file dev/pci/drm/drm_bufs.c drm file dev/pci/drm/drm_context.c drm -file dev/pci/drm/drm_dma.c drm file dev/pci/drm/drm_drv.c drm needs-flag file dev/pci/drm/drm_heap.c inteldrm | radeondrm file dev/pci/drm/drm_irq.c drm diff --git a/sys/dev/pci/drm/mga_dma.c b/sys/dev/pci/drm/mga_dma.c index 295a39b4911..366da653f23 100644 --- a/sys/dev/pci/drm/mga_dma.c +++ b/sys/dev/pci/drm/mga_dma.c @@ -510,7 +510,7 @@ static int mga_do_agp_dma_bootstrap(struct drm_device *dev, req.flags = _DRM_AGP_BUFFER; req.agp_start = offset; - err = drm_addbufs_agp(dev, &req); + err = drm_addbufs(dev, &req); if (err) { DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); return err; @@ -621,7 +621,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev, req.count = bin_count; req.size = dma_bs->secondary_bin_size; - err = drm_addbufs_pci(dev, &req); + err = drm_addbufs(dev, &req); if (!err) { break; } diff --git a/sys/dev/pci/drm/savage_bci.c b/sys/dev/pci/drm/savage_bci.c index d0a0e4bb775..4327ad4a84d 100644 --- a/sys/dev/pci/drm/savage_bci.c +++ b/sys/dev/pci/drm/savage_bci.c @@ -1007,5 +1007,5 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) } } - drm_core_reclaim_buffers(dev, file_priv); + drm_reclaim_buffers(dev, file_priv); } |