summaryrefslogtreecommitdiff
path: root/shared/radeon_irq.c
AgeCommit message (Collapse)Author
2004-09-27Fix the shared directory I accidentally stomped onJon Smirl
2004-09-27First check in for DRM that splits core from personality modulesJon Smirl
2004-08-24Merged drmfntbl-0-0-2Dave Airlie
2004-07-25sync up with current 2.6 kernel bk tree - mostly __user annotationsDave Airlie
2003-10-17- Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle themEric Anholt
from __HAVE_DMA. This will be useful for adding vblank sync support to sis and tdfx. Rename dma_service to irq_handler, which is more accurately what it is. - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have the right number of underscores. This may have been a problem in the case that the server died without doing its DRM_IOCTL_CONTROL to uninit.
2003-07-29IRQ code cleanup suggested by Linus TorvaldsMichel Daenzer
i830 build fix
2003-07-25Compile fixes for recent 2.5/2.6 Linux kernels. I hope this doesn't breakMichel Daenzer
the i830 driver or the BSDs. :)
2003-04-26Ensure driver has been initialized (dev_private != NULL) before installingLeif Delgass
irq handler in DRM(irq_install). Modify all drivers to ensure irq handler is removed before cleanup and cleanup is called at takedown. Remove unused buffer private struct fields in i810, i830. Check for lock on init/cleanup in all drivers except i810/i830. The current DDX for i810 and i830 doesn't hold the lock on kernel init (FIXME?).
2003-03-28merged drm-filp-0-1-branchKeith Whitwell
2003-02-04only acknowledge interrupts we handle - others could be used outside theMichel Daenzer
DRM
2002-12-04further vertical blank interrupt cleanups: remove unused variable,Michel Daenzer
non-ambiguous variable names, don't express subtraction in unnecessarily complicated ways
2002-12-03vertical blank interrupt cleanups: use spinlock instead of semaphore, sendMichel Daenzer
signal directly from interrupt handler instead of using a taskqueue (based on feedback by Linus Torvalds)
2002-11-30vertical blank ioctl can send signal instead of blockingMichel Daenzer
2002-10-01fix wait condition for vertical blank IRQsMichel Daenzer
2002-09-29Move os-dependent stuff out of radeon_irq.cKeith Whitwell
2002-09-29Fix up BSD irq handling.Eric Anholt
2002-09-27make SW interrupts more robust: write sequence number to scratch register,Michel Daenzer
acknowledge any lost interrupts before waiting
2002-09-26DRM(vblank_wait) is driver specificMichel Daenzer
2002-09-25common ioctl to wait for vertical blank IRQsMichel Daenzer
2002-09-23merged r200-0-2-branch to trunkKeith Whitwell
* * 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 * PRECISION INSIGHT 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. */ #include <linux/config.h> #include <linux/vmalloc.h> #include "drmP.h" #define DEBUG_SCATTER 0 void DRM(sg_cleanup)( drm_sg_mem_t *entry ) { struct page *page; int i; for ( i = 0 ; i < entry->pages ; i++ ) { page = entry->pagelist[i]; if ( page ) ClearPageReserved( page ); } vfree( entry->virtual ); DRM(free)( entry->busaddr, entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES ); DRM(free)( entry->pagelist, entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); } int DRM(sg_alloc)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_scatter_gather_t __user *argp = (void __user *)arg; drm_scatter_gather_t request; drm_sg_mem_t *entry; unsigned long pages, i, j; DRM_DEBUG( "%s\n", __FUNCTION__ ); if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL; if ( dev->sg ) return -EINVAL; if ( copy_from_user( &request, argp, sizeof(request) ) ) return -EFAULT; entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS ); if ( !entry ) return -ENOMEM; memset( entry, 0, sizeof(*entry) ); pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages ); entry->pages = pages; entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); if ( !entry->pagelist ) { DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return -ENOMEM; } memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr), DRM_MEM_PAGES ); if ( !entry->busaddr ) { DRM(free)( entry->pagelist, entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return -ENOMEM; } memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); if ( !entry->virtual ) { DRM(free)( entry->busaddr, entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES ); DRM(free)( entry->pagelist, entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return -ENOMEM; } /* This also forces the mapping of COW pages, so our page list * will be valid. Please don't remove it... */ memset( entry->virtual, 0, pages << PAGE_SHIFT ); entry->handle = (unsigned long)entry->virtual; DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) { entry->pagelist[j] = vmalloc_to_page((void *)i); if (!entry->pagelist[j]) goto failed; SetPageReserved(entry->pagelist[j]); } request.handle = entry->handle; if ( copy_to_user( argp, &request, sizeof(request) ) ) { DRM(sg_cleanup)( entry ); return -EFAULT; } dev->sg = entry; #if DEBUG_SCATTER /* Verify that each page points to its virtual address, and vice * versa. */ { int error = 0; for ( i = 0 ; i < pages ; i++ ) { unsigned long *tmp; tmp = page_address( entry->pagelist[i] ); for ( j = 0 ; j < PAGE_SIZE / sizeof(unsigned long) ; j++, tmp++ ) { *tmp = 0xcafebabe; } tmp = (unsigned long *)((u8 *)entry->virtual + (PAGE_SIZE * i)); for( j = 0 ; j < PAGE_SIZE / sizeof(unsigned long) ; j++, tmp++ ) { if ( *tmp != 0xcafebabe && error == 0 ) { error = 1; DRM_ERROR( "Scatter allocation error, " "pagelist does not match " "virtual mapping\n" ); } } tmp = page_address( entry->pagelist[i] ); for(j = 0 ; j < PAGE_SIZE / sizeof(unsigned long) ; j++, tmp++) { *tmp = 0; } } if (error == 0) DRM_ERROR( "Scatter allocation matches pagelist\n" ); } #endif return 0; failed: DRM(sg_cleanup)( entry ); return -ENOMEM; } int DRM(sg_free)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_scatter_gather_t request; drm_sg_mem_t *entry; if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL; if ( copy_from_user( &request, (drm_scatter_gather_t __user *)arg, sizeof(request) ) ) return -EFAULT; entry = dev->sg; dev->sg = NULL; if ( !entry || entry->handle != request.handle ) return -EINVAL; DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); DRM(sg_cleanup)( entry ); return 0; }