mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-03 04:40:15 +01:00
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
This commit is contained in:
commit
8d2da20233
23 changed files with 440 additions and 312 deletions
|
|
@ -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" );
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -558,6 +558,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 */
|
||||
/*@{*/
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Frank C. Earl <fearl@airmail.net>
|
||||
* Leif Delgass <ldelgass@retinalburn.net>
|
||||
* Jos<EFBFBD>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)
|
||||
{
|
||||
|
|
@ -749,61 +689,13 @@ 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__ */
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Leif Delgass <ldelgass@retinalburn.net>
|
||||
* Jos<EFBFBD>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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue