diff options
author | Dave Airlie <airlied@linux.ie> | 2007-12-11 16:58:00 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-12-11 16:58:00 +1000 |
commit | 8d2da202337300e821f4867cb2654b41ff6053b6 (patch) | |
tree | c7b0c4644c99180081eaa3f2e4bf0d1b4f8bbd63 | |
parent | f99dea7db00dd46aa96eaed3a61dff9c956fd86f (diff) | |
parent | cfa21b22b43c7113107b5eb086b5f4d4ec36dc0a (diff) |
Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/drm into modesetting-101
Conflicts:
linux-core/drm_drv.c
shared-core/drm.h
shared-core/i915_dma.c
-rw-r--r-- | bsd-core/ati_pcigart.c | 4 | ||||
-rw-r--r-- | bsd-core/drmP.h | 12 | ||||
-rw-r--r-- | bsd-core/drm_drv.c | 30 | ||||
-rw-r--r-- | bsd-core/drm_irq.c | 46 | ||||
-rw-r--r-- | bsd-core/drm_lock.c | 2 | ||||
-rw-r--r-- | bsd-core/i915_drv.c | 4 | ||||
-rw-r--r-- | bsd-core/radeon_drv.c | 2 | ||||
-rw-r--r-- | linux-core/drmP.h | 2 | ||||
-rw-r--r-- | linux-core/drm_agpsupport.c | 2 | ||||
-rw-r--r-- | linux-core/drm_drv.c | 13 | ||||
-rw-r--r-- | linux-core/drm_ioctl.c | 16 | ||||
-rw-r--r-- | linux-core/drm_sysfs.c | 7 | ||||
-rw-r--r-- | linux-core/i915_buffer.c | 2 | ||||
-rw-r--r-- | linux-core/i915_compat.c | 3 | ||||
-rw-r--r-- | shared-core/drm.h | 2 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 40 | ||||
-rw-r--r-- | shared-core/i915_drm.h | 3 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 19 | ||||
-rw-r--r-- | shared-core/mach64_dma.c | 255 | ||||
-rw-r--r-- | shared-core/mach64_drv.h | 255 | ||||
-rw-r--r-- | shared-core/mach64_state.c | 16 | ||||
-rw-r--r-- | shared-core/nouveau_state.c | 15 | ||||
-rw-r--r-- | shared-core/radeon_cp.c | 2 |
23 files changed, 440 insertions, 312 deletions
diff --git a/bsd-core/ati_pcigart.c b/bsd-core/ati_pcigart.c index db19a75d..bb0c46e2 100644 --- a/bsd-core/ati_pcigart.c +++ b/bsd-core/ati_pcigart.c @@ -35,7 +35,7 @@ #define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */ -int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) +int drm_ati_pcigart_init(drm_device_t *dev, struct drm_ati_pcigart_info *gart_info) { unsigned long pages; u32 *pci_gart = NULL, page_base; @@ -94,7 +94,7 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) return 1; } -int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) +int drm_ati_pcigart_cleanup(drm_device_t *dev, struct drm_ati_pcigart_info *gart_info) { if (dev->sg == NULL) { DRM_ERROR( "no scatter/gather memory!\n" ); diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 1dd27282..99457bf8 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -388,7 +388,7 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \ DRM_UNLOCK(); \ mtx_lock(&dev->irq_lock); \ if (!(condition)) \ - ret = -msleep(&(queue), &dev->irq_lock, \ + ret = -mtx_sleep(&(queue), &dev->irq_lock, \ PZERO | PCATCH, "drmwtq", (timeout)); \ mtx_unlock(&dev->irq_lock); \ DRM_LOCK(); \ @@ -614,14 +614,14 @@ typedef struct drm_vbl_sig { #define DRM_ATI_GART_PCIE 2 #define DRM_ATI_GART_IGP 3 -typedef struct ati_pcigart_info { +struct drm_ati_pcigart_info { int gart_table_location; int gart_reg_if; void *addr; dma_addr_t bus_addr; drm_local_map_t mapping; int table_size; -} drm_ati_pcigart_info; +}; struct drm_driver_info { int (*load)(struct drm_device *, unsigned long flags); @@ -650,6 +650,7 @@ struct drm_driver_info { void (*irq_uninstall)(drm_device_t *dev); void (*irq_handler)(DRM_IRQ_ARGS); int (*vblank_wait)(drm_device_t *dev, unsigned int *sequence); + int (*vblank_wait2)(drm_device_t *dev, unsigned int *sequence); drm_pci_id_list_t *id_entry; /* PCI ID, name, and chipset private */ @@ -686,6 +687,7 @@ struct drm_driver_info { unsigned use_dma_queue :1; unsigned use_irq :1; unsigned use_vbl_irq :1; + unsigned use_vbl_irq2 :1; unsigned use_mtrr :1; }; @@ -925,9 +927,9 @@ extern int drm_sysctl_cleanup(drm_device_t *dev); /* ATI PCIGART support (ati_pcigart.c) */ int drm_ati_pcigart_init(drm_device_t *dev, - drm_ati_pcigart_info *gart_info); + struct drm_ati_pcigart_info *gart_info); int drm_ati_pcigart_cleanup(drm_device_t *dev, - drm_ati_pcigart_info *gart_info); + struct drm_ati_pcigart_info *gart_info); /* Locking IOCTL support (drm_drv.c) */ int drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv); diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index d6868b9c..8466ce33 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -403,17 +403,6 @@ static int drm_firstopen(drm_device_t *dev) return i; } - dev->counters = 6; - dev->types[0] = _DRM_STAT_LOCK; - dev->types[1] = _DRM_STAT_OPENS; - dev->types[2] = _DRM_STAT_CLOSES; - dev->types[3] = _DRM_STAT_IOCTLS; - dev->types[4] = _DRM_STAT_LOCKS; - dev->types[5] = _DRM_STAT_UNLOCKS; - - for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ ) - atomic_set( &dev->counts[i], 0 ); - for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) { dev->magiclist[i].head = NULL; dev->magiclist[i].tail = NULL; @@ -495,10 +484,10 @@ static int drm_lastclose(drm_device_t *dev) } TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) { - drm_rmmap(dev, map); + if (!(map->flags & _DRM_DRIVER)) + drm_rmmap(dev, map); } - drm_dma_takedown(dev); if ( dev->lock.hw_lock ) { dev->lock.hw_lock = NULL; /* SHM removed */ @@ -511,7 +500,7 @@ static int drm_lastclose(drm_device_t *dev) static int drm_load(drm_device_t *dev) { - int retcode; + int i, retcode; DRM_DEBUG( "\n" ); @@ -536,6 +525,17 @@ static int drm_load(drm_device_t *dev) #endif TAILQ_INIT(&dev->files); + dev->counters = 6; + dev->types[0] = _DRM_STAT_LOCK; + dev->types[1] = _DRM_STAT_OPENS; + dev->types[2] = _DRM_STAT_CLOSES; + dev->types[3] = _DRM_STAT_IOCTLS; + dev->types[4] = _DRM_STAT_LOCKS; + dev->types[5] = _DRM_STAT_UNLOCKS; + + for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ ) + atomic_set( &dev->counts[i], 0 ); + if (dev->driver.load != NULL) { DRM_LOCK(); /* Shared code returns -errno. */ @@ -772,7 +772,7 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p) } /* Contention */ #if defined(__FreeBSD__) && __FreeBSD_version > 500000 - retcode = msleep((void *)&dev->lock.lock_queue, + retcode = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0); #else retcode = tsleep((void *)&dev->lock.lock_queue, diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c index 0772445a..40d0b71f 100644 --- a/bsd-core/drm_irq.c +++ b/bsd-core/drm_irq.c @@ -211,17 +211,43 @@ int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv) { drm_wait_vblank_t *vblwait = data; struct timeval now; - int ret, flags; + int ret = 0; + int flags, seq; if (!dev->irq_enabled) return EINVAL; - if (vblwait->request.type & _DRM_VBLANK_RELATIVE) { - vblwait->request.sequence += atomic_read(&dev->vbl_received); - vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; + if (vblwait->request.type & + ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { + DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", + vblwait->request.type, + (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); + return EINVAL; } flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; + + if ((flags & _DRM_VBLANK_SECONDARY) && !dev->driver.use_vbl_irq2) + return EINVAL; + + seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? + &dev->vbl_received2 : &dev->vbl_received); + + switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { + case _DRM_VBLANK_RELATIVE: + vblwait->request.sequence += seq; + vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; + case _DRM_VBLANK_ABSOLUTE: + break; + default: + return EINVAL; + } + + if ((flags & _DRM_VBLANK_NEXTONMISS) && + (seq - vblwait->request.sequence) <= (1<<23)) { + vblwait->request.sequence = seq + 1; + } + if (flags & _DRM_VBLANK_SIGNAL) { #if 0 /* disabled */ drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM, @@ -244,8 +270,14 @@ int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv) } else { DRM_LOCK(); /* shared code returns -errno */ - ret = -dev->driver.vblank_wait(dev, - &vblwait->request.sequence); + if (flags & _DRM_VBLANK_SECONDARY) { + if (dev->driver.vblank_wait2) + ret = -dev->driver.vblank_wait2(dev, + &vblwait->request.sequence); + } else if (dev->driver.vblank_wait) + ret = -dev->driver.vblank_wait(dev, + &vblwait->request.sequence); + DRM_UNLOCK(); microtime(&now); @@ -303,7 +335,7 @@ static void drm_locked_task(void *context, int pending __unused) /* Contention */ #if defined(__FreeBSD__) && __FreeBSD_version > 500000 - ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock, + ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0); #else ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH, diff --git a/bsd-core/drm_lock.c b/bsd-core/drm_lock.c index fb86fc68..9731ff92 100644 --- a/bsd-core/drm_lock.c +++ b/bsd-core/drm_lock.c @@ -140,7 +140,7 @@ int drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv) /* Contention */ #if defined(__FreeBSD__) && __FreeBSD_version > 500000 - ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock, + ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0); #else ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH, diff --git a/bsd-core/i915_drv.c b/bsd-core/i915_drv.c index d42b2076..e8897fbe 100644 --- a/bsd-core/i915_drv.c +++ b/bsd-core/i915_drv.c @@ -46,8 +46,9 @@ static void i915_configure(drm_device_t *dev) dev->driver.load = i915_driver_load; dev->driver.preclose = i915_driver_preclose; dev->driver.lastclose = i915_driver_lastclose; - dev->driver.device_is_agp = i915_driver_device_is_agp, + dev->driver.device_is_agp = i915_driver_device_is_agp; dev->driver.vblank_wait = i915_driver_vblank_wait; + dev->driver.vblank_wait2 = i915_driver_vblank_wait2; dev->driver.irq_preinstall = i915_driver_irq_preinstall; dev->driver.irq_postinstall = i915_driver_irq_postinstall; dev->driver.irq_uninstall = i915_driver_irq_uninstall; @@ -68,6 +69,7 @@ static void i915_configure(drm_device_t *dev) dev->driver.use_mtrr = 1; dev->driver.use_irq = 1; dev->driver.use_vbl_irq = 1; + dev->driver.use_vbl_irq2 = 1; } #ifdef __FreeBSD__ diff --git a/bsd-core/radeon_drv.c b/bsd-core/radeon_drv.c index f66bc795..93f875c5 100644 --- a/bsd-core/radeon_drv.c +++ b/bsd-core/radeon_drv.c @@ -53,6 +53,7 @@ static void radeon_configure(drm_device_t *dev) dev->driver.postclose = radeon_driver_postclose; dev->driver.lastclose = radeon_driver_lastclose; dev->driver.vblank_wait = radeon_driver_vblank_wait; + dev->driver.vblank_wait2 = radeon_driver_vblank_wait2; dev->driver.irq_preinstall = radeon_driver_irq_preinstall; dev->driver.irq_postinstall = radeon_driver_irq_postinstall; dev->driver.irq_uninstall = radeon_driver_irq_uninstall; @@ -76,6 +77,7 @@ static void radeon_configure(drm_device_t *dev) dev->driver.use_dma = 1; dev->driver.use_irq = 1; dev->driver.use_vbl_irq = 1; + dev->driver.use_vbl_irq2 = 1; } #ifdef __FreeBSD__ diff --git a/linux-core/drmP.h b/linux-core/drmP.h index afdf6798..4a0cabc3 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -66,8 +66,8 @@ #ifdef CONFIG_MTRR #include <asm/mtrr.h> #endif -#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) #include <asm/agp.h> +#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) #include <linux/types.h> #include <linux/agp_backend.h> #endif diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index cb665009..e8bfaea4 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -652,7 +652,7 @@ struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev) EXPORT_SYMBOL(drm_agp_init_ttm); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) -void drm_agp_flush_chipset(struct drm_device *dev) +void drm_agp_chipset_flush(struct drm_device *dev) { agp_flush_chipset(dev->agp->bridge); } diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 98fb9ac8..0b9ce30a 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -395,14 +395,6 @@ static void drm_cleanup(struct drm_device * dev) drm_lastclose(dev); drm_fence_manager_takedown(dev); - drm_mm_takedown(&dev->offset_manager); - drm_ht_remove(&dev->object_hash); - - if (!drm_fb_loaded) - pci_disable_device(dev->pdev); - - drm_ctxbitmap_cleanup(dev); - if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp && dev->agp->agp_mtrr >= 0) { int retval; @@ -424,6 +416,11 @@ static void drm_cleanup(struct drm_device * dev) if (!drm_fb_loaded) pci_disable_device(dev->pdev); + drm_ctxbitmap_cleanup(dev); + drm_ht_remove(&dev->map_hash); + drm_mm_takedown(&dev->offset_manager); + drm_ht_remove(&dev->object_hash); + drm_put_head(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c index 395f7b4e..3df163db 100644 --- a/linux-core/drm_ioctl.c +++ b/linux-core/drm_ioctl.c @@ -98,12 +98,14 @@ int drm_setunique(struct drm_device *dev, void *data, dev->unique[dev->unique_len] = '\0'; - dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + strlen(dev->unique) + 2, - DRM_MEM_DRIVER); + dev->devname = + drm_alloc(strlen(dev->driver->pci_driver.name) + + strlen(dev->unique) + 2, DRM_MEM_DRIVER); if (!dev->devname) return -ENOMEM; - sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique); + sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, + dev->unique); /* Return error if the busid submitted doesn't match the device's actual * busid. @@ -142,12 +144,14 @@ static int drm_set_busid(struct drm_device * dev) if (len > dev->unique_len) DRM_ERROR("buffer overflow"); - dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + 2, - DRM_MEM_DRIVER); + dev->devname = + drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + + 2, DRM_MEM_DRIVER); if (dev->devname == NULL) return -ENOMEM; - sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique); + sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, + dev->unique); return 0; } diff --git a/linux-core/drm_sysfs.c b/linux-core/drm_sysfs.c index caec120a..3aaac11b 100644 --- a/linux-core/drm_sysfs.c +++ b/linux-core/drm_sysfs.c @@ -162,12 +162,7 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) dev->dev.parent = &dev->pdev->dev; dev->dev.class = drm_class; dev->dev.release = drm_sysfs_device_release; - /* - * This will actually add the major:minor file so that udev - * will create the device node. We don't want to do that just - * yet... - */ - /* dev->dev.devt = head->device; */ + dev->dev.devt = head->device; snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor); err = device_register(&dev->dev); diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index 4577a942..c455a515 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -280,7 +280,7 @@ void i915_flush_ttm(struct drm_ttm *ttm) return; DRM_MEMORYBARRIER(); - for (i = ttm->num_pages-1; i >= 0; i--) + for (i = ttm->num_pages - 1; i >= 0; i--) drm_cache_flush_page(drm_ttm_get_page(ttm, i)); DRM_MEMORYBARRIER(); } diff --git a/linux-core/i915_compat.c b/linux-core/i915_compat.c index e119a992..58fb8418 100644 --- a/linux-core/i915_compat.c +++ b/linux-core/i915_compat.c @@ -84,7 +84,8 @@ static void intel_i965_g33_setup_chipset_flush(struct pci_dev *pdev) intel_alloc_chipset_flush_resource(pdev); - pci_write_config_dword(pdev, I965_IFPADDR + 4, (i9xx_private.ifp_resource.start >> 32)); + pci_write_config_dword(pdev, I965_IFPADDR + 4, + upper_32_bits(i9xx_private.ifp_resource.start)); pci_write_config_dword(pdev, I965_IFPADDR, (i9xx_private.ifp_resource.start & 0xffffffff) | 0x1); } else { u64 l64; diff --git a/shared-core/drm.h b/shared-core/drm.h index f13e36c9..9186b64b 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -250,7 +250,7 @@ enum drm_map_flags { _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ _DRM_REMOVABLE = 0x40, /**< Removable mapping */ - _DRM_DRIVER = 0x80 /**< Driver will take care of it */ + _DRM_DRIVER = 0x80 /**< Managed by driver */ }; struct drm_ctx_priv_map { diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3632a091..a6684ce0 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -51,8 +51,6 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) if (ring->space >= n) return 0; - dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; - if (ring->head != last_head) i = 0; @@ -73,9 +71,6 @@ void i915_kernel_lost_context(struct drm_device * dev) ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; - - if (ring->head == ring->tail) - dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; } int i915_dma_cleanup(struct drm_device * dev) @@ -144,6 +139,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) * private backbuffer/depthbuffer usage. */ dev_priv->use_mi_batchbuffer_start = 0; + if (IS_I965G(dev)) /* 965 doesn't support older method */ + dev_priv->use_mi_batchbuffer_start = 1; /* Allow hardware batchbuffers unless told otherwise. */ @@ -181,7 +178,7 @@ static int i915_dma_resume(struct drm_device * dev) { struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); if (!dev_priv->sarea) { DRM_ERROR("can not find sarea!\n"); @@ -315,7 +312,7 @@ static int validate_cmd(int cmd) return ret; } -static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, +static int i915_emit_cmds(struct drm_device *dev, int __user *buffer, int dwords) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -471,7 +468,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, return ret; } - i915_emit_breadcrumb( dev ); + i915_emit_breadcrumb(dev); #ifdef I915_HAVE_FENCE drm_fence_flush_old(dev, 0, dev_priv->counter); #endif @@ -525,7 +522,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, } } - i915_emit_breadcrumb( dev ); + i915_emit_breadcrumb(dev); #ifdef I915_HAVE_FENCE drm_fence_flush_old(dev, 0, dev_priv->counter); #endif @@ -589,8 +586,7 @@ void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) struct drm_i915_private *dev_priv = dev->dev_private; int i; - DRM_DEBUG("%s: planes=0x%x pfCurrentPage=%d\n", - __FUNCTION__, + DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n", planes, dev_priv->sarea_priv->pf_current_page); i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH); @@ -606,7 +602,7 @@ void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) #endif } -static int i915_quiescent(struct drm_device * dev) +static int i915_quiescent(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -895,7 +891,7 @@ int i915_validate_buffer_list(struct drm_file *file_priv, buffers[buf_count] = NULL; - if (copy_from_user(&arg, (void __user *)(unsigned)data, sizeof(arg))) { + if (copy_from_user(&arg, (void __user *)(unsigned long)data, sizeof(arg))) { ret = -EFAULT; goto out_err; } @@ -946,7 +942,7 @@ int i915_validate_buffer_list(struct drm_file *file_priv, arg.handled = 1; arg.d.rep = rep; - if (copy_to_user((void __user *)(unsigned)data, &arg, sizeof(arg))) + if (copy_to_user((void __user *)(unsigned long)data, &arg, sizeof(arg))) return -EFAULT; data = next; @@ -1011,10 +1007,10 @@ static int i915_execbuffer(struct drm_device *dev, void *data, buffers = drm_calloc(num_buffers, sizeof(struct drm_buffer_object *), DRM_MEM_DRIVER); if (!buffers) { - drm_bo_read_unlock(&dev->bm.bm_lock); + drm_bo_read_unlock(&dev->bm.bm_lock); mutex_unlock(&dev_priv->cmdbuf_mutex); return -ENOMEM; - } + } /* validate buffer list + fixup relocations */ ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, @@ -1074,15 +1070,13 @@ int i915_do_cleanup_pageflip(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int i, planes, num_pages; - DRM_DEBUG("%s\n", __FUNCTION__); - if (!dev_priv->sarea_priv) - return 0; + DRM_DEBUG("\n"); num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; for (i = 0, planes = 0; i < 2; i++) { if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) { dev_priv->sarea_priv->pf_current_page = (dev_priv->sarea_priv->pf_current_page & - ~(0x3 << (2 * i))) | (num_pages - 1) << (2 * i); + ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i)); planes |= 1 << i; } @@ -1098,7 +1092,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data, struct drm_file *f { struct drm_i915_flip *param = data; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -1226,9 +1220,9 @@ static int i915_mmio(struct drm_device *dev, void *data, case I915_MMIO_WRITE: if (!(e->flag & I915_MMIO_MAY_WRITE)) return -EINVAL; - if(DRM_COPY_FROM_USER(buf, mmio->data, e->size)) { + if (DRM_COPY_FROM_USER(buf, mmio->data, e->size)) { DRM_ERROR("DRM_COPY_TO_USER failed\n"); - return -EFAULT; + return -EFAULT; } for (i = 0; i < e->size / 4; i++) I915_WRITE(e->offset + i * 4, buf[i]); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 65bc9e89..c5819953 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -178,6 +178,7 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +#define DRM_IOCTL_I915_MMIO DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_MMIO, drm_i915_mmio) #define DRM_IOCTL_I915_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer) /* Asynchronous page flipping: @@ -274,7 +275,7 @@ typedef struct drm_i915_mem_init_heap { * rotate): */ typedef struct drm_i915_mem_destroy_heap { - int region; + int region; } drm_i915_mem_destroy_heap_t; /* Allow X server to configure which pipes to monitor for vblank signals diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index bd576078..4312eae2 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -418,8 +418,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) if (READ_BREADCRUMB(dev_priv) >= irq_nr) return 0; - dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; - i915_user_irq_on(dev_priv); DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); @@ -472,12 +470,25 @@ void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe) int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) { - return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); + atomic_t *counter; + + if (i915_get_pipe(dev, 0) == 0) + counter = &dev->vbl_received; + else + counter = &dev->vbl_received2; + return i915_driver_vblank_do_wait(dev, sequence, counter); } int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) { - return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2); + atomic_t *counter; + + if (i915_get_pipe(dev, 1) == 0) + counter = &dev->vbl_received; + else + counter = &dev->vbl_received2; + + return i915_driver_vblank_do_wait(dev, sequence, counter); } /* Needs the lock as it touches the ring. diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 13fa0446..411b98d5 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -6,7 +6,7 @@ * \author Gareth Hughes <gareth@valinux.com> * \author Frank C. Earl <fearl@airmail.net> * \author Leif Delgass <ldelgass@retinalburn.net> - * \author Jose Fonseca <j_r_fonseca@yahoo.co.uk> + * \author José Fonseca <j_r_fonseca@yahoo.co.uk> */ /* @@ -559,6 +559,259 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv) /*******************************************************************/ +/** \name DMA descriptor ring macros */ +/*@{*/ + +/** + * Add the end mark to the ring's new tail position. + * + * The bus master engine will keep processing the DMA buffers listed in the ring + * until it finds this mark, making it stop. + * + * \sa mach64_clear_dma_eol + */ +static __inline__ void mach64_set_dma_eol(volatile u32 * addr) +{ +#if defined(__i386__) + int nr = 31; + + /* Taken from include/asm-i386/bitops.h linux header */ + __asm__ __volatile__("lock;" "btsl %1,%0":"=m"(*addr) + :"Ir"(nr)); +#elif defined(__powerpc__) + u32 old; + u32 mask = cpu_to_le32(MACH64_DMA_EOL); + + /* Taken from the include/asm-ppc/bitops.h linux header */ + __asm__ __volatile__("\n\ +1: lwarx %0,0,%3 \n\ + or %0,%0,%2 \n\ + stwcx. %0,0,%3 \n\ + bne- 1b":"=&r"(old), "=m"(*addr) + :"r"(mask), "r"(addr), "m"(*addr) + :"cc"); +#elif defined(__alpha__) + u32 temp; + u32 mask = MACH64_DMA_EOL; + + /* Taken from the include/asm-alpha/bitops.h linux header */ + __asm__ __volatile__("1: ldl_l %0,%3\n" + " bis %0,%2,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous":"=&r"(temp), "=m"(*addr) + :"Ir"(mask), "m"(*addr)); +#else + u32 mask = cpu_to_le32(MACH64_DMA_EOL); + + *addr |= mask; +#endif +} + +/** + * Remove the end mark from the ring's old tail position. + * + * It should be called after calling mach64_set_dma_eol to mark the ring's new + * tail position. + * + * We update the end marks while the bus master engine is in operation. Since + * the bus master engine may potentially be reading from the same position + * that we write, we must change atomically to avoid having intermediary bad + * data. + */ +static __inline__ void mach64_clear_dma_eol(volatile u32 * addr) +{ +#if defined(__i386__) + int nr = 31; + + /* Taken from include/asm-i386/bitops.h linux header */ + __asm__ __volatile__("lock;" "btrl %1,%0":"=m"(*addr) + :"Ir"(nr)); +#elif defined(__powerpc__) + u32 old; + u32 mask = cpu_to_le32(MACH64_DMA_EOL); + + /* Taken from the include/asm-ppc/bitops.h linux header */ + __asm__ __volatile__("\n\ +1: lwarx %0,0,%3 \n\ + andc %0,%0,%2 \n\ + stwcx. %0,0,%3 \n\ + bne- 1b":"=&r"(old), "=m"(*addr) + :"r"(mask), "r"(addr), "m"(*addr) + :"cc"); +#elif defined(__alpha__) + u32 temp; + u32 mask = ~MACH64_DMA_EOL; + + /* Taken from the include/asm-alpha/bitops.h linux header */ + __asm__ __volatile__("1: ldl_l %0,%3\n" + " and %0,%2,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous":"=&r"(temp), "=m"(*addr) + :"Ir"(mask), "m"(*addr)); +#else + u32 mask = cpu_to_le32(~MACH64_DMA_EOL); + + *addr &= mask; +#endif +} + +#define RING_LOCALS \ + int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring + +#define RING_WRITE_OFS _ring_write + +#define BEGIN_RING( n ) \ +do { \ + if ( MACH64_VERBOSE ) { \ + DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ + (n), __FUNCTION__ ); \ + } \ + if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ + int ret; \ + if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \ + DRM_ERROR( "wait_ring failed, resetting engine\n"); \ + mach64_dump_engine_info( dev_priv ); \ + mach64_do_engine_reset( dev_priv ); \ + return ret; \ + } \ + } \ + dev_priv->ring.space -= (n) * sizeof(u32); \ + _ring = (u32 *) dev_priv->ring.start; \ + _ring_tail = _ring_write = dev_priv->ring.tail; \ + _ring_mask = dev_priv->ring.tail_mask; \ +} while (0) + +#define OUT_RING( x ) \ +do { \ + if ( MACH64_VERBOSE ) { \ + DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ + (unsigned int)(x), _ring_write ); \ + } \ + _ring[_ring_write++] = cpu_to_le32( x ); \ + _ring_write &= _ring_mask; \ +} while (0) + +#define ADVANCE_RING() \ +do { \ + if ( MACH64_VERBOSE ) { \ + DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ + _ring_write, _ring_tail ); \ + } \ + DRM_MEMORYBARRIER(); \ + mach64_clear_dma_eol( &_ring[(_ring_tail - 2) & _ring_mask] ); \ + DRM_MEMORYBARRIER(); \ + dev_priv->ring.tail = _ring_write; \ + mach64_ring_tick( dev_priv, &(dev_priv)->ring ); \ +} while (0) + +/** + * Queue a DMA buffer of registers writes into the ring buffer. + */ +int mach64_add_buf_to_ring(drm_mach64_private_t *dev_priv, + drm_mach64_freelist_t *entry) +{ + int bytes, pages, remainder; + u32 address, page; + int i; + struct drm_buf *buf = entry->buf; + RING_LOCALS; + + bytes = buf->used; + address = GETBUFADDR( buf ); + pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; + + BEGIN_RING( pages * 4 ); + + for ( i = 0 ; i < pages-1 ; i++ ) { + page = address + i * MACH64_DMA_CHUNKSIZE; + OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); + OUT_RING( page ); + OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); + OUT_RING( 0 ); + } + + /* generate the final descriptor for any remaining commands in this buffer */ + page = address + i * MACH64_DMA_CHUNKSIZE; + remainder = bytes - i * MACH64_DMA_CHUNKSIZE; + + /* Save dword offset of last descriptor for this buffer. + * This is needed to check for completion of the buffer in freelist_get + */ + entry->ring_ofs = RING_WRITE_OFS; + + OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); + OUT_RING( page ); + OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); + OUT_RING( 0 ); + + ADVANCE_RING(); + + return 0; +} + +/** + * Queue DMA buffer controlling host data tranfers (e.g., blit). + * + * Almost identical to mach64_add_buf_to_ring. + */ +int mach64_add_hostdata_buf_to_ring(drm_mach64_private_t *dev_priv, + drm_mach64_freelist_t *entry) +{ + int bytes, pages, remainder; + u32 address, page; + int i; + struct drm_buf *buf = entry->buf; + RING_LOCALS; + + bytes = buf->used - MACH64_HOSTDATA_BLIT_OFFSET; + pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; + address = GETBUFADDR( buf ); + + BEGIN_RING( 4 + pages * 4 ); + + OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); + OUT_RING( address ); + OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | MACH64_DMA_HOLD_OFFSET ); + OUT_RING( 0 ); + address += MACH64_HOSTDATA_BLIT_OFFSET; + + for ( i = 0 ; i < pages-1 ; i++ ) { + page = address + i * MACH64_DMA_CHUNKSIZE; + OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); + OUT_RING( page ); + OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); + OUT_RING( 0 ); + } + + /* generate the final descriptor for any remaining commands in this buffer */ + page = address + i * MACH64_DMA_CHUNKSIZE; + remainder = bytes - i * MACH64_DMA_CHUNKSIZE; + + /* Save dword offset of last descriptor for this buffer. + * This is needed to check for completion of the buffer in freelist_get + */ + entry->ring_ofs = RING_WRITE_OFS; + + OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); + OUT_RING( page ); + OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); + OUT_RING( 0 ); + + ADVANCE_RING(); + + return 0; +} + +/*@}*/ + + +/*******************************************************************/ /** \name DMA test and initialization */ /*@{*/ diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h index 79c2c61d..1768a2a4 100644 --- a/shared-core/mach64_drv.h +++ b/shared-core/mach64_drv.h @@ -29,7 +29,7 @@ * Gareth Hughes <gareth@valinux.com> * Frank C. Earl <fearl@airmail.net> * Leif Delgass <ldelgass@retinalburn.net> - * Jos�Fonseca <j_r_fonseca@yahoo.co.uk> + * José Fonseca <j_r_fonseca@yahoo.co.uk> */ #ifndef __MACH64_DRV_H__ @@ -140,6 +140,11 @@ extern void mach64_dump_engine_info(drm_mach64_private_t * dev_priv); extern void mach64_dump_ring_info(drm_mach64_private_t * dev_priv); extern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv); +extern int mach64_add_buf_to_ring(drm_mach64_private_t *dev_priv, + drm_mach64_freelist_t *_entry); +extern int mach64_add_hostdata_buf_to_ring(drm_mach64_private_t *dev_priv, + drm_mach64_freelist_t *_entry); + extern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv); extern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv); extern int mach64_do_cleanup_dma(struct drm_device * dev); @@ -521,89 +526,12 @@ extern void mach64_driver_irq_uninstall(struct drm_device * dev); #define MACH64_APERTURE_OFFSET 0x7ff800 /* frame-buffer offset for gui-masters */ /* ================================================================ - * Misc helper macros + * Ring operations + * + * Since the Mach64 bus master engine requires polling, these functions end + * up being called frequently, hence being inline. */ -static __inline__ void mach64_set_dma_eol(volatile u32 * addr) -{ -#if defined(__i386__) - int nr = 31; - - /* Taken from include/asm-i386/bitops.h linux header */ - __asm__ __volatile__("lock;" "btsl %1,%0":"=m"(*addr) - :"Ir"(nr)); -#elif defined(__powerpc__) - u32 old; - u32 mask = cpu_to_le32(MACH64_DMA_EOL); - - /* Taken from the include/asm-ppc/bitops.h linux header */ - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - or %0,%0,%2 \n\ - stwcx. %0,0,%3 \n\ - bne- 1b":"=&r"(old), "=m"(*addr) - :"r"(mask), "r"(addr), "m"(*addr) - :"cc"); -#elif defined(__alpha__) - u32 temp; - u32 mask = MACH64_DMA_EOL; - - /* Taken from the include/asm-alpha/bitops.h linux header */ - __asm__ __volatile__("1: ldl_l %0,%3\n" - " bis %0,%2,%0\n" - " stl_c %0,%1\n" - " beq %0,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous":"=&r"(temp), "=m"(*addr) - :"Ir"(mask), "m"(*addr)); -#else - u32 mask = cpu_to_le32(MACH64_DMA_EOL); - - *addr |= mask; -#endif -} - -static __inline__ void mach64_clear_dma_eol(volatile u32 * addr) -{ -#if defined(__i386__) - int nr = 31; - - /* Taken from include/asm-i386/bitops.h linux header */ - __asm__ __volatile__("lock;" "btrl %1,%0":"=m"(*addr) - :"Ir"(nr)); -#elif defined(__powerpc__) - u32 old; - u32 mask = cpu_to_le32(MACH64_DMA_EOL); - - /* Taken from the include/asm-ppc/bitops.h linux header */ - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - andc %0,%0,%2 \n\ - stwcx. %0,0,%3 \n\ - bne- 1b":"=&r"(old), "=m"(*addr) - :"r"(mask), "r"(addr), "m"(*addr) - :"cc"); -#elif defined(__alpha__) - u32 temp; - u32 mask = ~MACH64_DMA_EOL; - - /* Taken from the include/asm-alpha/bitops.h linux header */ - __asm__ __volatile__("1: ldl_l %0,%3\n" - " and %0,%2,%0\n" - " stl_c %0,%1\n" - " beq %0,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous":"=&r"(temp), "=m"(*addr) - :"Ir"(mask), "m"(*addr)); -#else - u32 mask = cpu_to_le32(~MACH64_DMA_EOL); - - *addr &= mask; -#endif -} - static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; @@ -666,6 +594,18 @@ static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv, } } +/** + * Poll the ring head and make sure the bus master is alive. + * + * Mach64's bus master engine will stop if there are no more entries to process. + * This function polls the engine for the last processed entry and calls + * mach64_ring_resume if there is an unprocessed entry. + * + * Note also that, since we update the ring tail while the bus master engine is + * in operation, it is possible that the last tail update was too late to be + * processed, and the bus master engine stops at the previous tail position. + * Therefore it is important to call this function frequently. + */ static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv, drm_mach64_descriptor_ring_t * ring) { @@ -750,60 +690,12 @@ mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv) } /* ================================================================ - * DMA descriptor ring macros - */ - -#define RING_LOCALS \ - int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring - -#define RING_WRITE_OFS _ring_write - -#define BEGIN_RING( n ) \ -do { \ - if ( MACH64_VERBOSE ) { \ - DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ - (n), __FUNCTION__ ); \ - } \ - if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ - int ret; \ - if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \ - DRM_ERROR( "wait_ring failed, resetting engine\n"); \ - mach64_dump_engine_info( dev_priv ); \ - mach64_do_engine_reset( dev_priv ); \ - return ret; \ - } \ - } \ - dev_priv->ring.space -= (n) * sizeof(u32); \ - _ring = (u32 *) dev_priv->ring.start; \ - _ring_tail = _ring_write = dev_priv->ring.tail; \ - _ring_mask = dev_priv->ring.tail_mask; \ -} while (0) - -#define OUT_RING( x ) \ -do { \ - if ( MACH64_VERBOSE ) { \ - DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ - (unsigned int)(x), _ring_write ); \ - } \ - _ring[_ring_write++] = cpu_to_le32( x ); \ - _ring_write &= _ring_mask; \ -} while (0) - -#define ADVANCE_RING() \ -do { \ - if ( MACH64_VERBOSE ) { \ - DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ - _ring_write, _ring_tail ); \ - } \ - DRM_MEMORYBARRIER(); \ - mach64_clear_dma_eol( &_ring[(_ring_tail - 2) & _ring_mask] ); \ - DRM_MEMORYBARRIER(); \ - dev_priv->ring.tail = _ring_write; \ - mach64_ring_tick( dev_priv, &(dev_priv)->ring ); \ -} while (0) - -/* ================================================================ * DMA macros + * + * Mach64's ring buffer doesn't take register writes directly. These + * have to be written indirectly in DMA buffers. These macros simplify + * the task of setting up a buffer, writing commands to it, and + * queuing the buffer in the ring. */ #define DMALOCALS \ @@ -889,7 +781,7 @@ do { \ #define DMAADVANCE( dev_priv, _discard ) \ do { \ struct list_head *ptr; \ - RING_LOCALS; \ + int ret; \ \ if ( MACH64_VERBOSE ) { \ DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ ); \ @@ -902,7 +794,6 @@ do { \ } \ if (_buf->pending) { \ /* This is a resued buffer, so we need to find it in the pending list */ \ - int ret; \ if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \ DRM_ERROR( "DMAADVANCE() in %s: couldn't find pending buf %d\n", \ __FUNCTION__, _buf->idx ); \ @@ -927,7 +818,8 @@ do { \ list_add_tail(ptr, &dev_priv->pending); \ } \ _entry->discard = (_discard); \ - ADD_BUF_TO_RING( dev_priv ); \ + if ( (ret = mach64_add_buf_to_ring( dev_priv, _entry )) ) \ + return ret; \ } while (0) #define DMADISCARDBUF() \ @@ -943,48 +835,10 @@ do { \ _entry->discard = 1; \ } while(0) -#define ADD_BUF_TO_RING( dev_priv ) \ -do { \ - int bytes, pages, remainder; \ - u32 address, page; \ - int i; \ - \ - bytes = _buf->used; \ - address = GETBUFADDR( _buf ); \ - \ - pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \ - \ - BEGIN_RING( pages * 4 ); \ - \ - for ( i = 0 ; i < pages-1 ; i++ ) { \ - page = address + i * MACH64_DMA_CHUNKSIZE; \ - OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ - OUT_RING( page ); \ - OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \ - OUT_RING( 0 ); \ - } \ - \ - /* generate the final descriptor for any remaining commands in this buffer */ \ - page = address + i * MACH64_DMA_CHUNKSIZE; \ - remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \ - \ - /* Save dword offset of last descriptor for this buffer. \ - * This is needed to check for completion of the buffer in freelist_get \ - */ \ - _entry->ring_ofs = RING_WRITE_OFS; \ - \ - OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ - OUT_RING( page ); \ - OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \ - OUT_RING( 0 ); \ - \ - ADVANCE_RING(); \ -} while(0) - #define DMAADVANCEHOSTDATA( dev_priv ) \ do { \ struct list_head *ptr; \ - RING_LOCALS; \ + int ret; \ \ if ( MACH64_VERBOSE ) { \ DRM_INFO( "DMAADVANCEHOSTDATA() in %s\n", __FUNCTION__ ); \ @@ -1008,51 +862,8 @@ do { \ _entry->buf->pending = 1; \ list_add_tail(ptr, &dev_priv->pending); \ _entry->discard = 1; \ - ADD_HOSTDATA_BUF_TO_RING( dev_priv ); \ + if ( (ret = mach64_add_hostdata_buf_to_ring( dev_priv, _entry )) ) \ + return ret; \ } while (0) -#define ADD_HOSTDATA_BUF_TO_RING( dev_priv ) \ -do { \ - int bytes, pages, remainder; \ - u32 address, page; \ - int i; \ - \ - bytes = _buf->used - MACH64_HOSTDATA_BLIT_OFFSET; \ - pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \ - address = GETBUFADDR( _buf ); \ - \ - BEGIN_RING( 4 + pages * 4 ); \ - \ - OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ - OUT_RING( address ); \ - OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | MACH64_DMA_HOLD_OFFSET ); \ - OUT_RING( 0 ); \ - \ - address += MACH64_HOSTDATA_BLIT_OFFSET; \ - \ - for ( i = 0 ; i < pages-1 ; i++ ) { \ - page = address + i * MACH64_DMA_CHUNKSIZE; \ - OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ - OUT_RING( page ); \ - OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \ - OUT_RING( 0 ); \ - } \ - \ - /* generate the final descriptor for any remaining commands in this buffer */ \ - page = address + i * MACH64_DMA_CHUNKSIZE; \ - remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \ - \ - /* Save dword offset of last descriptor for this buffer. \ - * This is needed to check for completion of the buffer in freelist_get \ - */ \ - _entry->ring_ofs = RING_WRITE_OFS; \ - \ - OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ - OUT_RING( page ); \ - OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \ - OUT_RING( 0 ); \ - \ - ADVANCE_RING(); \ -} while(0) - #endif /* __MACH64_DRV_H__ */ diff --git a/shared-core/mach64_state.c b/shared-core/mach64_state.c index 89b6c6ce..88ff4843 100644 --- a/shared-core/mach64_state.c +++ b/shared-core/mach64_state.c @@ -27,7 +27,7 @@ * Authors: * Gareth Hughes <gareth@valinux.com> * Leif Delgass <ldelgass@retinalburn.net> - * Jos�Fonseca <j_r_fonseca@yahoo.co.uk> + * José Fonseca <j_r_fonseca@yahoo.co.uk> */ #include "drmP.h" @@ -575,6 +575,10 @@ static int mach64_dma_dispatch_vertex(struct drm_device * dev, return -EAGAIN; } + /* Mach64's vertex data is actually register writes. To avoid security + * compromises these register writes have to be verified and copied from + * user space into a private DMA buffer. + */ verify_ret = copy_from_user_vertex(GETBUFPTR(copy_buf), buf, used); if (verify_ret != 0) { @@ -698,6 +702,16 @@ static int mach64_dma_dispatch_blit(struct drm_device * dev, return -EAGAIN; } + /* Copy the blit data from userspace. + * + * XXX: This is overkill. The most efficient solution would be having + * two sets of buffers (one set private for vertex data, the other set + * client-writable for blits). However that would bring more complexity + * and would break backward compatability. The solution currently + * implemented is keeping all buffers private, allowing to secure the + * driver, without increasing complexity at the expense of some speed + * transfering data. + */ verify_ret = copy_from_user_blit(GETBUFPTR(copy_buf), blit->buf, used); if (verify_ret != 0) { diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 7c9503e8..16c86494 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -454,6 +454,9 @@ int nouveau_firstopen(struct drm_device *dev) return 0; } +#define NV40_CHIPSET_MASK 0x00000baf +#define NV44_CHIPSET_MASK 0x00005450 + int nouveau_load(struct drm_device *dev, unsigned long flags) { struct drm_nouveau_private *dev_priv; @@ -497,10 +500,16 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) if (architecture >= 0x50) { dev_priv->card_type = NV_50; - } else if (architecture >= 0x44) { - dev_priv->card_type = NV_44; } else if (architecture >= 0x40) { - dev_priv->card_type = NV_40; + uint8_t subarch = architecture & 0xf; + /* Selection criteria borrowed from NV40EXA */ + if (NV40_CHIPSET_MASK & (1 << subarch)) { + dev_priv->card_type = NV_40; + } else if (NV44_CHIPSET_MASK & (1 << subarch)) { + dev_priv->card_type = NV_44; + } else { + dev_priv->card_type = NV_UNKNOWN; + } } else if (architecture >= 0x30) { dev_priv->card_type = NV_30; } else if (architecture >= 0x20) { diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 76232e48..c2863346 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1974,7 +1974,7 @@ void radeon_do_release(struct drm_device * dev) schedule(); #else #if defined(__FreeBSD__) && __FreeBSD_version > 500000 - msleep(&ret, &dev->dev_lock, PZERO, "rdnrel", + mtx_sleep(&ret, &dev->dev_lock, PZERO, "rdnrel", 1); #else tsleep(&ret, PZERO, "rdnrel", 1); |