summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2007-12-11 16:58:00 +1000
committerDave Airlie <airlied@linux.ie>2007-12-11 16:58:00 +1000
commit8d2da202337300e821f4867cb2654b41ff6053b6 (patch)
treec7b0c4644c99180081eaa3f2e4bf0d1b4f8bbd63
parentf99dea7db00dd46aa96eaed3a61dff9c956fd86f (diff)
parentcfa21b22b43c7113107b5eb086b5f4d4ec36dc0a (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.c4
-rw-r--r--bsd-core/drmP.h12
-rw-r--r--bsd-core/drm_drv.c30
-rw-r--r--bsd-core/drm_irq.c46
-rw-r--r--bsd-core/drm_lock.c2
-rw-r--r--bsd-core/i915_drv.c4
-rw-r--r--bsd-core/radeon_drv.c2
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_agpsupport.c2
-rw-r--r--linux-core/drm_drv.c13
-rw-r--r--linux-core/drm_ioctl.c16
-rw-r--r--linux-core/drm_sysfs.c7
-rw-r--r--linux-core/i915_buffer.c2
-rw-r--r--linux-core/i915_compat.c3
-rw-r--r--shared-core/drm.h2
-rw-r--r--shared-core/i915_dma.c40
-rw-r--r--shared-core/i915_drm.h3
-rw-r--r--shared-core/i915_irq.c19
-rw-r--r--shared-core/mach64_dma.c255
-rw-r--r--shared-core/mach64_drv.h255
-rw-r--r--shared-core/mach64_state.c16
-rw-r--r--shared-core/nouveau_state.c15
-rw-r--r--shared-core/radeon_cp.c2
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);