drm: move to kref per-master structures.
This is step one towards having multiple masters sharing a drm device in order to get fast-user-switching to work. It splits out the information associated with the drm master into a separate kref counted structure, and allocates this when a master opens the device node. It also allows the current master to abdicate (say while VT switched), and a new master to take over the hardware. It moves the Intel and radeon drivers to using the sarea from within the new master structures. Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Родитель
e7f7ab45eb
Коммит
7c1c2871a6
|
@ -45,14 +45,15 @@
|
|||
* the one with matching magic number, while holding the drm_device::struct_mutex
|
||||
* lock.
|
||||
*/
|
||||
static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
|
||||
static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)
|
||||
{
|
||||
struct drm_file *retval = NULL;
|
||||
struct drm_magic_entry *pt;
|
||||
struct drm_hash_item *hash;
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
|
||||
if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
|
||||
pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
|
||||
retval = pt->priv;
|
||||
}
|
||||
|
@ -71,11 +72,11 @@ static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic
|
|||
* associated the magic number hash key in drm_device::magiclist, while holding
|
||||
* the drm_device::struct_mutex lock.
|
||||
*/
|
||||
static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
|
||||
static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
|
||||
drm_magic_t magic)
|
||||
{
|
||||
struct drm_magic_entry *entry;
|
||||
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
|
||||
|
@ -83,11 +84,10 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
|
|||
return -ENOMEM;
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
entry->priv = priv;
|
||||
|
||||
entry->hash_item.key = (unsigned long)magic;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
|
||||
list_add_tail(&entry->head, &dev->magicfree);
|
||||
drm_ht_insert_item(&master->magiclist, &entry->hash_item);
|
||||
list_add_tail(&entry->head, &master->magicfree);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -102,20 +102,21 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
|
|||
* Searches and unlinks the entry in drm_device::magiclist with the magic
|
||||
* number hash key, while holding the drm_device::struct_mutex lock.
|
||||
*/
|
||||
static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
|
||||
static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
|
||||
{
|
||||
struct drm_magic_entry *pt;
|
||||
struct drm_hash_item *hash;
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
|
||||
if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
|
||||
drm_ht_remove_item(&dev->magiclist, hash);
|
||||
drm_ht_remove_item(&master->magiclist, hash);
|
||||
list_del(&pt->head);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
|
@ -153,9 +154,9 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
++sequence; /* reserve 0 */
|
||||
auth->magic = sequence++;
|
||||
spin_unlock(&lock);
|
||||
} while (drm_find_file(dev, auth->magic));
|
||||
} while (drm_find_file(file_priv->master, auth->magic));
|
||||
file_priv->magic = auth->magic;
|
||||
drm_add_magic(dev, file_priv, auth->magic);
|
||||
drm_add_magic(file_priv->master, file_priv, auth->magic);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%u\n", auth->magic);
|
||||
|
@ -181,9 +182,9 @@ int drm_authmagic(struct drm_device *dev, void *data,
|
|||
struct drm_file *file;
|
||||
|
||||
DRM_DEBUG("%u\n", auth->magic);
|
||||
if ((file = drm_find_file(dev, auth->magic))) {
|
||||
if ((file = drm_find_file(file_priv->master, auth->magic))) {
|
||||
file->authenticated = 1;
|
||||
drm_remove_magic(dev, auth->magic);
|
||||
drm_remove_magic(file_priv->master, auth->magic);
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
|
|
|
@ -54,9 +54,9 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
|
|||
{
|
||||
struct drm_map_list *entry;
|
||||
list_for_each_entry(entry, &dev->maplist, head) {
|
||||
if (entry->map && map->type == entry->map->type &&
|
||||
if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) &&
|
||||
((entry->map->offset == map->offset) ||
|
||||
(map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
|
||||
((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
@ -210,12 +210,12 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
|
|||
map->offset = (unsigned long)map->handle;
|
||||
if (map->flags & _DRM_CONTAINS_LOCK) {
|
||||
/* Prevent a 2nd X Server from creating a 2nd lock */
|
||||
if (dev->lock.hw_lock != NULL) {
|
||||
if (dev->primary->master->lock.hw_lock != NULL) {
|
||||
vfree(map->handle);
|
||||
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||
return -EBUSY;
|
||||
}
|
||||
dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */
|
||||
dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle; /* Pointer to lock */
|
||||
}
|
||||
break;
|
||||
case _DRM_AGP: {
|
||||
|
@ -319,6 +319,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
|
|||
list->user_token = list->hash.key << PAGE_SHIFT;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
list->master = dev->primary->master;
|
||||
*maplist = list;
|
||||
return 0;
|
||||
}
|
||||
|
@ -345,7 +346,7 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,
|
|||
struct drm_map_list *maplist;
|
||||
int err;
|
||||
|
||||
if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP))
|
||||
if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM))
|
||||
return -EPERM;
|
||||
|
||||
err = drm_addmap_core(dev, map->offset, map->size, map->type,
|
||||
|
@ -380,10 +381,12 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
|
|||
struct drm_map_list *r_list = NULL, *list_t;
|
||||
drm_dma_handle_t dmah;
|
||||
int found = 0;
|
||||
struct drm_master *master;
|
||||
|
||||
/* Find the list entry for the map and remove it */
|
||||
list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
|
||||
if (r_list->map == map) {
|
||||
master = r_list->master;
|
||||
list_del(&r_list->head);
|
||||
drm_ht_remove_key(&dev->map_hash,
|
||||
r_list->user_token >> PAGE_SHIFT);
|
||||
|
@ -409,6 +412,13 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
|
|||
break;
|
||||
case _DRM_SHM:
|
||||
vfree(map->handle);
|
||||
if (master) {
|
||||
if (dev->sigdata.lock == master->lock.hw_lock)
|
||||
dev->sigdata.lock = NULL;
|
||||
master->lock.hw_lock = NULL; /* SHM removed */
|
||||
master->lock.file_priv = NULL;
|
||||
wake_up_interruptible(&master->lock.lock_queue);
|
||||
}
|
||||
break;
|
||||
case _DRM_AGP:
|
||||
case _DRM_SCATTER_GATHER:
|
||||
|
|
|
@ -256,12 +256,13 @@ static int drm_context_switch(struct drm_device * dev, int old, int new)
|
|||
* hardware lock is held, clears the drm_device::context_flag and wakes up
|
||||
* drm_device::context_wait.
|
||||
*/
|
||||
static int drm_context_switch_complete(struct drm_device * dev, int new)
|
||||
static int drm_context_switch_complete(struct drm_device *dev,
|
||||
struct drm_file *file_priv, int new)
|
||||
{
|
||||
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
|
||||
dev->last_switch = jiffies;
|
||||
|
||||
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
|
||||
if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {
|
||||
DRM_ERROR("Lock isn't held after context switch\n");
|
||||
}
|
||||
|
||||
|
@ -420,7 +421,7 @@ int drm_newctx(struct drm_device *dev, void *data,
|
|||
struct drm_ctx *ctx = data;
|
||||
|
||||
DRM_DEBUG("%d\n", ctx->handle);
|
||||
drm_context_switch_complete(dev, ctx->handle);
|
||||
drm_context_switch_complete(dev, file_priv, ctx->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -442,9 +443,6 @@ int drm_rmctx(struct drm_device *dev, void *data,
|
|||
struct drm_ctx *ctx = data;
|
||||
|
||||
DRM_DEBUG("%d\n", ctx->handle);
|
||||
if (ctx->handle == DRM_KERNEL_CONTEXT + 1) {
|
||||
file_priv->remove_auth_on_close = 1;
|
||||
}
|
||||
if (ctx->handle != DRM_KERNEL_CONTEXT) {
|
||||
if (dev->driver->context_dtor)
|
||||
dev->driver->context_dtor(dev, ctx->handle);
|
||||
|
|
|
@ -74,6 +74,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {
|
|||
DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
@ -138,8 +141,6 @@ static struct drm_ioctl_desc drm_ioctls[] = {
|
|||
*/
|
||||
int drm_lastclose(struct drm_device * dev)
|
||||
{
|
||||
struct drm_magic_entry *pt, *next;
|
||||
struct drm_map_list *r_list, *list_t;
|
||||
struct drm_vma_entry *vma, *vma_temp;
|
||||
int i;
|
||||
|
||||
|
@ -149,12 +150,6 @@ int drm_lastclose(struct drm_device * dev)
|
|||
dev->driver->lastclose(dev);
|
||||
DRM_DEBUG("driver lastclose completed\n");
|
||||
|
||||
if (dev->unique) {
|
||||
drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
|
||||
dev->unique = NULL;
|
||||
dev->unique_len = 0;
|
||||
}
|
||||
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
|
@ -164,16 +159,6 @@ int drm_lastclose(struct drm_device * dev)
|
|||
drm_drawable_free_all(dev);
|
||||
del_timer(&dev->timer);
|
||||
|
||||
/* Clear pid list */
|
||||
if (dev->magicfree.next) {
|
||||
list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
|
||||
list_del(&pt->head);
|
||||
drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
|
||||
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||
}
|
||||
drm_ht_remove(&dev->magiclist);
|
||||
}
|
||||
|
||||
/* Clear AGP information */
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
struct drm_agp_mem *entry, *tempe;
|
||||
|
@ -205,13 +190,6 @@ int drm_lastclose(struct drm_device * dev)
|
|||
drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
|
||||
if (!(r_list->map->flags & _DRM_DRIVER)) {
|
||||
drm_rmmap_locked(dev, r_list->map);
|
||||
r_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
|
||||
for (i = 0; i < dev->queue_count; i++) {
|
||||
if (dev->queuelist[i]) {
|
||||
|
@ -231,11 +209,6 @@ int drm_lastclose(struct drm_device * dev)
|
|||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
|
||||
drm_dma_takedown(dev);
|
||||
|
||||
if (dev->lock.hw_lock) {
|
||||
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
|
||||
dev->lock.file_priv = NULL;
|
||||
wake_up_interruptible(&dev->lock.lock_queue);
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG("lastclose completed\n");
|
||||
|
|
|
@ -44,10 +44,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
|||
|
||||
static int drm_setup(struct drm_device * dev)
|
||||
{
|
||||
drm_local_map_t *map;
|
||||
int i;
|
||||
int ret;
|
||||
u32 sareapage;
|
||||
|
||||
if (dev->driver->firstopen) {
|
||||
ret = dev->driver->firstopen(dev);
|
||||
|
@ -55,14 +53,6 @@ static int drm_setup(struct drm_device * dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
dev->magicfree.next = NULL;
|
||||
|
||||
/* prebuild the SAREA */
|
||||
sareapage = max_t(unsigned, SAREA_MAX, PAGE_SIZE);
|
||||
i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
|
||||
if (i != 0)
|
||||
return i;
|
||||
|
||||
atomic_set(&dev->ioctl_count, 0);
|
||||
atomic_set(&dev->vma_count, 0);
|
||||
dev->buf_use = 0;
|
||||
|
@ -77,16 +67,12 @@ static int drm_setup(struct drm_device * dev)
|
|||
for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
|
||||
atomic_set(&dev->counts[i], 0);
|
||||
|
||||
drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
|
||||
INIT_LIST_HEAD(&dev->magicfree);
|
||||
|
||||
dev->sigdata.lock = NULL;
|
||||
init_waitqueue_head(&dev->lock.lock_queue);
|
||||
|
||||
dev->queue_count = 0;
|
||||
dev->queue_reserved = 0;
|
||||
dev->queue_slots = 0;
|
||||
dev->queuelist = NULL;
|
||||
dev->irq_enabled = 0;
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
dev->dma_flag = 0;
|
||||
|
@ -265,10 +251,42 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (list_empty(&dev->filelist))
|
||||
priv->master = 1;
|
||||
|
||||
/* if there is no current master make this fd it */
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (!priv->minor->master) {
|
||||
/* create a new master */
|
||||
priv->minor->master = drm_master_create(priv->minor);
|
||||
if (!priv->minor->master) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
priv->is_master = 1;
|
||||
/* take another reference for the copy in the local file priv */
|
||||
priv->master = drm_master_get(priv->minor->master);
|
||||
|
||||
priv->authenticated = 1;
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (dev->driver->master_create) {
|
||||
ret = dev->driver->master_create(dev, priv->master);
|
||||
if (ret) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
/* drop both references if this fails */
|
||||
drm_master_put(&priv->minor->master);
|
||||
drm_master_put(&priv->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* get a reference to the master */
|
||||
priv->master = drm_master_get(priv->minor->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
list_add(&priv->lhead, &dev->filelist);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
|
@ -314,6 +332,74 @@ int drm_fasync(int fd, struct file *filp, int on)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_fasync);
|
||||
|
||||
/*
|
||||
* Reclaim locked buffers; note that this may be a bad idea if the current
|
||||
* context doesn't have the hw lock...
|
||||
*/
|
||||
static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f)
|
||||
{
|
||||
struct drm_file *file_priv = f->private_data;
|
||||
|
||||
if (drm_i_have_hw_lock(dev, file_priv)) {
|
||||
dev->driver->reclaim_buffers_locked(dev, file_priv);
|
||||
} else {
|
||||
unsigned long _end = jiffies + 3 * DRM_HZ;
|
||||
int locked = 0;
|
||||
|
||||
drm_idlelock_take(&file_priv->master->lock);
|
||||
|
||||
/*
|
||||
* Wait for a while.
|
||||
*/
|
||||
do {
|
||||
spin_lock_bh(&file_priv->master->lock.spinlock);
|
||||
locked = file_priv->master->lock.idle_has_lock;
|
||||
spin_unlock_bh(&file_priv->master->lock.spinlock);
|
||||
if (locked)
|
||||
break;
|
||||
schedule();
|
||||
} while (!time_after_eq(jiffies, _end));
|
||||
|
||||
if (!locked) {
|
||||
DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
|
||||
"\tdriver to use reclaim_buffers_idlelocked() instead.\n"
|
||||
"\tI will go on reclaiming the buffers anyway.\n");
|
||||
}
|
||||
|
||||
dev->driver->reclaim_buffers_locked(dev, file_priv);
|
||||
drm_idlelock_release(&file_priv->master->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_master_release(struct drm_device *dev, struct file *filp)
|
||||
{
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
|
||||
if (dev->driver->reclaim_buffers_locked &&
|
||||
file_priv->master->lock.hw_lock)
|
||||
drm_reclaim_locked_buffers(dev, filp);
|
||||
|
||||
if (dev->driver->reclaim_buffers_idlelocked &&
|
||||
file_priv->master->lock.hw_lock) {
|
||||
drm_idlelock_take(&file_priv->master->lock);
|
||||
dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
|
||||
drm_idlelock_release(&file_priv->master->lock);
|
||||
}
|
||||
|
||||
|
||||
if (drm_i_have_hw_lock(dev, file_priv)) {
|
||||
DRM_DEBUG("File %p released, freeing lock for context %d\n",
|
||||
filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
|
||||
drm_lock_free(&file_priv->master->lock,
|
||||
_DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
|
||||
!dev->driver->reclaim_buffers_locked) {
|
||||
dev->driver->reclaim_buffers(dev, file_priv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release file.
|
||||
*
|
||||
|
@ -348,60 +434,9 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
(long)old_encode_dev(file_priv->minor->device),
|
||||
dev->open_count);
|
||||
|
||||
if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
|
||||
if (drm_i_have_hw_lock(dev, file_priv)) {
|
||||
dev->driver->reclaim_buffers_locked(dev, file_priv);
|
||||
} else {
|
||||
unsigned long endtime = jiffies + 3 * DRM_HZ;
|
||||
int locked = 0;
|
||||
|
||||
drm_idlelock_take(&dev->lock);
|
||||
|
||||
/*
|
||||
* Wait for a while.
|
||||
*/
|
||||
|
||||
do{
|
||||
spin_lock_bh(&dev->lock.spinlock);
|
||||
locked = dev->lock.idle_has_lock;
|
||||
spin_unlock_bh(&dev->lock.spinlock);
|
||||
if (locked)
|
||||
break;
|
||||
schedule();
|
||||
} while (!time_after_eq(jiffies, endtime));
|
||||
|
||||
if (!locked) {
|
||||
DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
|
||||
"\tdriver to use reclaim_buffers_idlelocked() instead.\n"
|
||||
"\tI will go on reclaiming the buffers anyway.\n");
|
||||
}
|
||||
|
||||
dev->driver->reclaim_buffers_locked(dev, file_priv);
|
||||
drm_idlelock_release(&dev->lock);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) {
|
||||
|
||||
drm_idlelock_take(&dev->lock);
|
||||
dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
|
||||
drm_idlelock_release(&dev->lock);
|
||||
|
||||
}
|
||||
|
||||
if (drm_i_have_hw_lock(dev, file_priv)) {
|
||||
DRM_DEBUG("File %p released, freeing lock for context %d\n",
|
||||
filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||
|
||||
drm_lock_free(&dev->lock,
|
||||
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||
}
|
||||
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
|
||||
!dev->driver->reclaim_buffers_locked) {
|
||||
dev->driver->reclaim_buffers(dev, file_priv);
|
||||
}
|
||||
/* if the master has gone away we can't do anything with the lock */
|
||||
if (file_priv->minor->master)
|
||||
drm_master_release(dev, filp);
|
||||
|
||||
if (dev->driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_release(dev, file_priv);
|
||||
|
@ -428,12 +463,24 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
mutex_unlock(&dev->ctxlist_mutex);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (file_priv->remove_auth_on_close == 1) {
|
||||
struct drm_file *temp;
|
||||
|
||||
list_for_each_entry(temp, &dev->filelist, lhead)
|
||||
temp->authenticated = 0;
|
||||
if (file_priv->is_master) {
|
||||
struct drm_file *temp;
|
||||
list_for_each_entry(temp, &dev->filelist, lhead) {
|
||||
if ((temp->master == file_priv->master) &&
|
||||
(temp != file_priv))
|
||||
temp->authenticated = 0;
|
||||
}
|
||||
|
||||
if (file_priv->minor->master == file_priv->master) {
|
||||
/* drop the reference held my the minor */
|
||||
drm_master_put(&file_priv->minor->master);
|
||||
}
|
||||
}
|
||||
|
||||
/* drop the reference held my the file priv */
|
||||
drm_master_put(&file_priv->master);
|
||||
file_priv->is_master = 0;
|
||||
list_del(&file_priv->lhead);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
|
@ -448,9 +495,9 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
|
||||
spin_lock(&dev->count_lock);
|
||||
if (!--dev->open_count) {
|
||||
if (atomic_read(&dev->ioctl_count) || dev->blocked) {
|
||||
DRM_ERROR("Device busy: %d %d\n",
|
||||
atomic_read(&dev->ioctl_count), dev->blocked);
|
||||
if (atomic_read(&dev->ioctl_count)) {
|
||||
DRM_ERROR("Device busy: %d\n",
|
||||
atomic_read(&dev->ioctl_count));
|
||||
spin_unlock(&dev->count_lock);
|
||||
unlock_kernel();
|
||||
return -EBUSY;
|
||||
|
|
|
@ -53,12 +53,13 @@ int drm_getunique(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_unique *u = data;
|
||||
struct drm_master *master = file_priv->master;
|
||||
|
||||
if (u->unique_len >= dev->unique_len) {
|
||||
if (copy_to_user(u->unique, dev->unique, dev->unique_len))
|
||||
if (u->unique_len >= master->unique_len) {
|
||||
if (copy_to_user(u->unique, master->unique, master->unique_len))
|
||||
return -EFAULT;
|
||||
}
|
||||
u->unique_len = dev->unique_len;
|
||||
u->unique_len = master->unique_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -81,36 +82,37 @@ int drm_setunique(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_unique *u = data;
|
||||
struct drm_master *master = file_priv->master;
|
||||
int domain, bus, slot, func, ret;
|
||||
|
||||
if (dev->unique_len || dev->unique)
|
||||
if (master->unique_len || master->unique)
|
||||
return -EBUSY;
|
||||
|
||||
if (!u->unique_len || u->unique_len > 1024)
|
||||
return -EINVAL;
|
||||
|
||||
dev->unique_len = u->unique_len;
|
||||
dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER);
|
||||
if (!dev->unique)
|
||||
master->unique_len = u->unique_len;
|
||||
master->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER);
|
||||
if (!master->unique)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(dev->unique, u->unique, dev->unique_len))
|
||||
if (copy_from_user(master->unique, u->unique, master->unique_len))
|
||||
return -EFAULT;
|
||||
|
||||
dev->unique[dev->unique_len] = '\0';
|
||||
master->unique[master->unique_len] = '\0';
|
||||
|
||||
dev->devname =
|
||||
drm_alloc(strlen(dev->driver->pci_driver.name) +
|
||||
strlen(dev->unique) + 2, DRM_MEM_DRIVER);
|
||||
strlen(master->unique) + 2, DRM_MEM_DRIVER);
|
||||
if (!dev->devname)
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
|
||||
dev->unique);
|
||||
master->unique);
|
||||
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
*/
|
||||
ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
if (ret != 3)
|
||||
return -EINVAL;
|
||||
domain = bus >> 8;
|
||||
|
@ -125,34 +127,35 @@ int drm_setunique(struct drm_device *dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int drm_set_busid(struct drm_device * dev)
|
||||
static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_master *master = file_priv->master;
|
||||
int len;
|
||||
|
||||
if (dev->unique != NULL)
|
||||
return 0;
|
||||
if (master->unique != NULL)
|
||||
return -EBUSY;
|
||||
|
||||
dev->unique_len = 40;
|
||||
dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
|
||||
if (dev->unique == NULL)
|
||||
master->unique_len = 40;
|
||||
master->unique = drm_alloc(master->unique_len + 1, DRM_MEM_DRIVER);
|
||||
if (master->unique == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
|
||||
drm_get_pci_domain(dev), dev->pdev->bus->number,
|
||||
len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d",
|
||||
drm_get_pci_domain(dev),
|
||||
dev->pdev->bus->number,
|
||||
PCI_SLOT(dev->pdev->devfn),
|
||||
PCI_FUNC(dev->pdev->devfn));
|
||||
|
||||
if (len > dev->unique_len)
|
||||
DRM_ERROR("Unique buffer overflowed\n");
|
||||
if (len > master->unique_len)
|
||||
DRM_ERROR("buffer overflow");
|
||||
|
||||
dev->devname =
|
||||
drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
|
||||
drm_alloc(strlen(dev->driver->pci_driver.name) + master->unique_len +
|
||||
2, DRM_MEM_DRIVER);
|
||||
if (dev->devname == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
|
||||
dev->unique);
|
||||
master->unique);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -276,7 +279,7 @@ int drm_getstats(struct drm_device *dev, void *data,
|
|||
for (i = 0; i < dev->counters; i++) {
|
||||
if (dev->types[i] == _DRM_STAT_LOCK)
|
||||
stats->data[i].value =
|
||||
(dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
|
||||
(file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0);
|
||||
else
|
||||
stats->data[i].value = atomic_read(&dev->counts[i]);
|
||||
stats->data[i].type = dev->types[i];
|
||||
|
@ -318,7 +321,7 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri
|
|||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
*/
|
||||
drm_set_busid(dev);
|
||||
drm_set_busid(dev, file_priv);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
{
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
struct drm_lock *lock = data;
|
||||
struct drm_master *master = file_priv->master;
|
||||
int ret = 0;
|
||||
|
||||
++file_priv->lock_count;
|
||||
|
@ -64,26 +65,27 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
|
||||
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||
lock->context, task_pid_nr(current),
|
||||
dev->lock.hw_lock->lock, lock->flags);
|
||||
master->lock.hw_lock->lock, lock->flags);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
|
||||
if (lock->context < 0)
|
||||
return -EINVAL;
|
||||
|
||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
spin_lock_bh(&dev->lock.spinlock);
|
||||
dev->lock.user_waiters++;
|
||||
spin_unlock_bh(&dev->lock.spinlock);
|
||||
add_wait_queue(&master->lock.lock_queue, &entry);
|
||||
spin_lock_bh(&master->lock.spinlock);
|
||||
master->lock.user_waiters++;
|
||||
spin_unlock_bh(&master->lock.spinlock);
|
||||
|
||||
for (;;) {
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (!dev->lock.hw_lock) {
|
||||
if (!master->lock.hw_lock) {
|
||||
/* Device has been unregistered */
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
if (drm_lock_take(&dev->lock, lock->context)) {
|
||||
dev->lock.file_priv = file_priv;
|
||||
dev->lock.lock_time = jiffies;
|
||||
if (drm_lock_take(&master->lock, lock->context)) {
|
||||
master->lock.file_priv = file_priv;
|
||||
master->lock.lock_time = jiffies;
|
||||
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
||||
break; /* Got lock */
|
||||
}
|
||||
|
@ -95,11 +97,11 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
break;
|
||||
}
|
||||
}
|
||||
spin_lock_bh(&dev->lock.spinlock);
|
||||
dev->lock.user_waiters--;
|
||||
spin_unlock_bh(&dev->lock.spinlock);
|
||||
spin_lock_bh(&master->lock.spinlock);
|
||||
master->lock.user_waiters--;
|
||||
spin_unlock_bh(&master->lock.spinlock);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
remove_wait_queue(&master->lock.lock_queue, &entry);
|
||||
|
||||
DRM_DEBUG("%d %s\n", lock->context,
|
||||
ret ? "interrupted" : "has lock");
|
||||
|
@ -108,14 +110,14 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
/* don't set the block all signals on the master process for now
|
||||
* really probably not the correct answer but lets us debug xkb
|
||||
* xserver for now */
|
||||
if (!file_priv->master) {
|
||||
if (!file_priv->is_master) {
|
||||
sigemptyset(&dev->sigmask);
|
||||
sigaddset(&dev->sigmask, SIGSTOP);
|
||||
sigaddset(&dev->sigmask, SIGTSTP);
|
||||
sigaddset(&dev->sigmask, SIGTTIN);
|
||||
sigaddset(&dev->sigmask, SIGTTOU);
|
||||
dev->sigdata.context = lock->context;
|
||||
dev->sigdata.lock = dev->lock.hw_lock;
|
||||
dev->sigdata.lock = master->lock.hw_lock;
|
||||
block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
|
||||
}
|
||||
|
||||
|
@ -154,6 +156,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_lock *lock = data;
|
||||
struct drm_master *master = file_priv->master;
|
||||
|
||||
if (lock->context == DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Process %d using kernel context %d\n",
|
||||
|
@ -169,7 +172,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
if (dev->driver->kernel_context_switch_unlock)
|
||||
dev->driver->kernel_context_switch_unlock(dev);
|
||||
else {
|
||||
if (drm_lock_free(&dev->lock,lock->context)) {
|
||||
if (drm_lock_free(&master->lock, lock->context)) {
|
||||
/* FIXME: Should really bail out here. */
|
||||
}
|
||||
}
|
||||
|
@ -379,9 +382,10 @@ EXPORT_SYMBOL(drm_idlelock_release);
|
|||
|
||||
int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
return (file_priv->lock_count && dev->lock.hw_lock &&
|
||||
_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
|
||||
dev->lock.file_priv == file_priv);
|
||||
struct drm_master *master = file_priv->master;
|
||||
return (file_priv->lock_count && master->lock.hw_lock &&
|
||||
_DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) &&
|
||||
master->lock.file_priv == file_priv);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_i_have_hw_lock);
|
||||
|
|
|
@ -195,6 +195,7 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
|
|||
int *eof, void *data)
|
||||
{
|
||||
struct drm_minor *minor = (struct drm_minor *) data;
|
||||
struct drm_master *master = minor->master;
|
||||
struct drm_device *dev = minor->dev;
|
||||
int len = 0;
|
||||
|
||||
|
@ -203,13 +204,16 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!master)
|
||||
return 0;
|
||||
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
|
||||
if (dev->unique) {
|
||||
if (master->unique) {
|
||||
DRM_PROC_PRINT("%s %s %s\n",
|
||||
dev->driver->pci_driver.name,
|
||||
pci_name(dev->pdev), dev->unique);
|
||||
pci_name(dev->pdev), master->unique);
|
||||
} else {
|
||||
DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
|
||||
pci_name(dev->pdev));
|
||||
|
|
|
@ -79,6 +79,104 @@ again:
|
|||
return new_id;
|
||||
}
|
||||
|
||||
struct drm_master *drm_master_create(struct drm_minor *minor)
|
||||
{
|
||||
struct drm_master *master;
|
||||
|
||||
master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER);
|
||||
if (!master)
|
||||
return NULL;
|
||||
|
||||
kref_init(&master->refcount);
|
||||
spin_lock_init(&master->lock.spinlock);
|
||||
init_waitqueue_head(&master->lock.lock_queue);
|
||||
drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
|
||||
INIT_LIST_HEAD(&master->magicfree);
|
||||
master->minor = minor;
|
||||
|
||||
list_add_tail(&master->head, &minor->master_list);
|
||||
|
||||
return master;
|
||||
}
|
||||
|
||||
struct drm_master *drm_master_get(struct drm_master *master)
|
||||
{
|
||||
kref_get(&master->refcount);
|
||||
return master;
|
||||
}
|
||||
|
||||
static void drm_master_destroy(struct kref *kref)
|
||||
{
|
||||
struct drm_master *master = container_of(kref, struct drm_master, refcount);
|
||||
struct drm_magic_entry *pt, *next;
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
|
||||
list_del(&master->head);
|
||||
|
||||
if (dev->driver->master_destroy)
|
||||
dev->driver->master_destroy(dev, master);
|
||||
|
||||
if (master->unique) {
|
||||
drm_free(master->unique, strlen(master->unique) + 1, DRM_MEM_DRIVER);
|
||||
master->unique = NULL;
|
||||
master->unique_len = 0;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(pt, next, &master->magicfree, head) {
|
||||
list_del(&pt->head);
|
||||
drm_ht_remove_item(&master->magiclist, &pt->hash_item);
|
||||
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||
}
|
||||
|
||||
drm_ht_remove(&master->magiclist);
|
||||
|
||||
if (master->lock.hw_lock) {
|
||||
if (dev->sigdata.lock == master->lock.hw_lock)
|
||||
dev->sigdata.lock = NULL;
|
||||
master->lock.hw_lock = NULL;
|
||||
master->lock.file_priv = NULL;
|
||||
wake_up_interruptible(&master->lock.lock_queue);
|
||||
}
|
||||
|
||||
drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
|
||||
}
|
||||
|
||||
void drm_master_put(struct drm_master **master)
|
||||
{
|
||||
kref_put(&(*master)->refcount, drm_master_destroy);
|
||||
*master = NULL;
|
||||
}
|
||||
|
||||
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
|
||||
return -EINVAL;
|
||||
|
||||
if (!file_priv->master)
|
||||
return -EINVAL;
|
||||
|
||||
if (!file_priv->minor->master &&
|
||||
file_priv->minor->master != file_priv->master) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
file_priv->minor->master = drm_master_get(file_priv->master);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
if (!file_priv->master)
|
||||
return -EINVAL;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_master_put(&file_priv->minor->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
|
@ -92,7 +190,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
|||
|
||||
spin_lock_init(&dev->count_lock);
|
||||
spin_lock_init(&dev->drw_lock);
|
||||
spin_lock_init(&dev->lock.spinlock);
|
||||
init_timer(&dev->timer);
|
||||
mutex_init(&dev->struct_mutex);
|
||||
mutex_init(&dev->ctxlist_mutex);
|
||||
|
@ -200,6 +297,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
|
|||
new_minor->device = MKDEV(DRM_MAJOR, minor_id);
|
||||
new_minor->dev = dev;
|
||||
new_minor->index = minor_id;
|
||||
INIT_LIST_HEAD(&new_minor->master_list);
|
||||
|
||||
idr_replace(&drm_minors_idr, new_minor, minor_id);
|
||||
|
||||
|
@ -299,11 +397,6 @@ int drm_put_dev(struct drm_device * dev)
|
|||
{
|
||||
DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
|
||||
|
||||
if (dev->unique) {
|
||||
drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
|
||||
dev->unique = NULL;
|
||||
dev->unique_len = 0;
|
||||
}
|
||||
if (dev->devname) {
|
||||
drm_free(dev->devname, strlen(dev->devname) + 1,
|
||||
DRM_MEM_DRIVER);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
|
||||
u32 last_acthd = I915_READ(acthd_reg);
|
||||
|
@ -55,8 +56,8 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
|
|||
if (ring->space >= n)
|
||||
return 0;
|
||||
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
|
||||
if (ring->head != last_head)
|
||||
i = 0;
|
||||
|
@ -121,6 +122,7 @@ static void i915_free_hws(struct drm_device *dev)
|
|||
void i915_kernel_lost_context(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv;
|
||||
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
|
||||
ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
|
||||
|
@ -129,8 +131,12 @@ void i915_kernel_lost_context(struct drm_device * dev)
|
|||
if (ring->space < 0)
|
||||
ring->space += ring->Size;
|
||||
|
||||
if (ring->head == ring->tail && dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
|
||||
if (!dev->primary->master)
|
||||
return;
|
||||
|
||||
master_priv = dev->primary->master->driver_priv;
|
||||
if (ring->head == ring->tail && master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
|
||||
}
|
||||
|
||||
static int i915_dma_cleanup(struct drm_device * dev)
|
||||
|
@ -154,25 +160,13 @@ static int i915_dma_cleanup(struct drm_device * dev)
|
|||
if (I915_NEED_GFX_HWS(dev))
|
||||
i915_free_hws(dev);
|
||||
|
||||
dev_priv->sarea = NULL;
|
||||
dev_priv->sarea_priv = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->sarea = drm_getsarea(dev);
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("can not find sarea!\n");
|
||||
i915_dma_cleanup(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_priv->sarea_priv = (drm_i915_sarea_t *)
|
||||
((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
|
||||
if (init->ring_size != 0) {
|
||||
if (dev_priv->ring.ring_obj != NULL) {
|
||||
|
@ -207,7 +201,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
|
|||
dev_priv->back_offset = init->back_offset;
|
||||
dev_priv->front_offset = init->front_offset;
|
||||
dev_priv->current_page = 0;
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->pf_current_page = 0;
|
||||
|
||||
/* Allow hardware batchbuffers unless told otherwise.
|
||||
*/
|
||||
|
@ -222,11 +217,6 @@ static int i915_dma_resume(struct drm_device * dev)
|
|||
|
||||
DRM_DEBUG("%s\n", __func__);
|
||||
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("can not find sarea!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" ring buffer\n");
|
||||
|
@ -435,13 +425,14 @@ i915_emit_box(struct drm_device *dev,
|
|||
static void i915_emit_breadcrumb(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
RING_LOCALS;
|
||||
|
||||
dev_priv->counter++;
|
||||
if (dev_priv->counter > 0x7FFFFFFFUL)
|
||||
dev_priv->counter = 0;
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->last_enqueue = dev_priv->counter;
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_STORE_DWORD_INDEX);
|
||||
|
@ -537,15 +528,17 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
|
|||
static int i915_dispatch_flip(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv =
|
||||
dev->primary->master->driver_priv;
|
||||
RING_LOCALS;
|
||||
|
||||
if (!dev_priv->sarea_priv)
|
||||
if (!master_priv->sarea_priv)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
|
||||
__func__,
|
||||
dev_priv->current_page,
|
||||
dev_priv->sarea_priv->pf_current_page);
|
||||
master_priv->sarea_priv->pf_current_page);
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
|
@ -572,7 +565,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
|
|||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
|
||||
master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_STORE_DWORD_INDEX);
|
||||
|
@ -581,7 +574,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
|
|||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -611,8 +604,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
master_priv->sarea_priv;
|
||||
drm_i915_batchbuffer_t *batch = data;
|
||||
int ret;
|
||||
|
||||
|
@ -644,8 +638,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
master_priv->sarea_priv;
|
||||
drm_i915_cmdbuffer_t *cmdbuf = data;
|
||||
int ret;
|
||||
|
||||
|
@ -802,6 +797,30 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int i915_master_create(struct drm_device *dev, struct drm_master *master)
|
||||
{
|
||||
struct drm_i915_master_private *master_priv;
|
||||
|
||||
master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
|
||||
if (!master_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
master->driver_priv = master_priv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
|
||||
{
|
||||
struct drm_i915_master_private *master_priv = master->driver_priv;
|
||||
|
||||
if (!master_priv)
|
||||
return;
|
||||
|
||||
drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
|
||||
|
||||
master->driver_priv = NULL;
|
||||
}
|
||||
|
||||
int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
|
|
@ -107,6 +107,8 @@ static struct drm_driver driver = {
|
|||
.reclaim_buffers = drm_core_reclaim_buffers,
|
||||
.get_map_ofs = drm_core_get_map_ofs,
|
||||
.get_reg_ofs = drm_core_get_reg_ofs,
|
||||
.master_create = i915_master_create,
|
||||
.master_destroy = i915_master_destroy,
|
||||
.proc_init = i915_gem_proc_init,
|
||||
.proc_cleanup = i915_gem_proc_cleanup,
|
||||
.gem_init_object = i915_gem_init_object,
|
||||
|
|
|
@ -103,15 +103,18 @@ struct intel_opregion {
|
|||
int enabled;
|
||||
};
|
||||
|
||||
struct drm_i915_master_private {
|
||||
drm_local_map_t *sarea;
|
||||
struct _drm_i915_sarea *sarea_priv;
|
||||
};
|
||||
|
||||
typedef struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
|
||||
int has_gem;
|
||||
|
||||
void __iomem *regs;
|
||||
drm_local_map_t *sarea;
|
||||
|
||||
drm_i915_sarea_t *sarea_priv;
|
||||
drm_i915_ring_buffer_t ring;
|
||||
|
||||
drm_dma_handle_t *status_page_dmah;
|
||||
|
@ -417,6 +420,9 @@ struct drm_i915_file_private {
|
|||
extern struct drm_ioctl_desc i915_ioctls[];
|
||||
extern int i915_max_ioctl;
|
||||
|
||||
extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
|
||||
extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
|
||||
|
||||
/* i915_dma.c */
|
||||
extern void i915_kernel_lost_context(struct drm_device * dev);
|
||||
extern int i915_driver_load(struct drm_device *, unsigned long flags);
|
||||
|
|
|
@ -168,6 +168,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv;
|
||||
u32 iir, new_iir;
|
||||
u32 pipea_stats, pipeb_stats;
|
||||
u32 vblank_status;
|
||||
|
@ -222,9 +223,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
I915_WRITE(IIR, iir);
|
||||
new_iir = I915_READ(IIR); /* Flush posted writes */
|
||||
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->last_dispatch =
|
||||
READ_BREADCRUMB(dev_priv);
|
||||
if (dev->primary->master) {
|
||||
master_priv = dev->primary->master->driver_priv;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->last_dispatch =
|
||||
READ_BREADCRUMB(dev_priv);
|
||||
}
|
||||
|
||||
if (iir & I915_USER_INTERRUPT) {
|
||||
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
|
||||
|
@ -269,6 +273,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
static int i915_emit_irq(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
RING_LOCALS;
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
@ -278,8 +283,8 @@ static int i915_emit_irq(struct drm_device * dev)
|
|||
dev_priv->counter++;
|
||||
if (dev_priv->counter > 0x7FFFFFFFUL)
|
||||
dev_priv->counter = 1;
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->last_enqueue = dev_priv->counter;
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_STORE_DWORD_INDEX);
|
||||
|
@ -317,21 +322,20 @@ void i915_user_irq_put(struct drm_device *dev)
|
|||
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
|
||||
READ_BREADCRUMB(dev_priv));
|
||||
|
||||
if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
|
||||
if (dev_priv->sarea_priv) {
|
||||
dev_priv->sarea_priv->last_dispatch =
|
||||
READ_BREADCRUMB(dev_priv);
|
||||
}
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
|
||||
i915_user_irq_get(dev);
|
||||
DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
|
||||
|
@ -343,10 +347,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
|
|||
READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
|
||||
}
|
||||
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->last_dispatch =
|
||||
READ_BREADCRUMB(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,8 @@
|
|||
static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
struct drm_tex_region *list;
|
||||
unsigned shift, nr;
|
||||
unsigned start;
|
||||
|
|
|
@ -860,12 +860,12 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
|
|||
* The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
|
||||
* be careful about how this function is called.
|
||||
*/
|
||||
static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
|
||||
static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
|
||||
buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
|
||||
buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
|
||||
buf->pending = 1;
|
||||
buf->used = 0;
|
||||
}
|
||||
|
@ -1027,6 +1027,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
struct drm_buf *buf = NULL;
|
||||
int emit_dispatch_age = 0;
|
||||
|
@ -1134,7 +1135,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
}
|
||||
|
||||
emit_dispatch_age = 1;
|
||||
r300_discard_buffer(dev, buf);
|
||||
r300_discard_buffer(dev, file_priv->master, buf);
|
||||
break;
|
||||
|
||||
case R300_CMD_WAIT:
|
||||
|
@ -1189,7 +1190,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
|
||||
/* Emit the vertex buffer age */
|
||||
BEGIN_RING(2);
|
||||
RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
|
||||
RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_sarea.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
#include "r300_reg.h"
|
||||
|
@ -667,15 +668,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
|
|||
RADEON_WRITE(RADEON_BUS_CNTL, tmp);
|
||||
} /* PCIE cards appears to not need this */
|
||||
|
||||
dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
|
||||
RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
|
||||
dev_priv->scratch[0] = 0;
|
||||
RADEON_WRITE(RADEON_LAST_FRAME_REG, 0);
|
||||
|
||||
dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
|
||||
RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
|
||||
dev_priv->sarea_priv->last_dispatch);
|
||||
dev_priv->scratch[1] = 0;
|
||||
RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0);
|
||||
|
||||
dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
|
||||
RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
|
||||
dev_priv->scratch[2] = 0;
|
||||
RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
|
||||
|
||||
radeon_do_wait_for_idle(dev_priv);
|
||||
|
||||
|
@ -871,9 +871,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
|
|||
}
|
||||
}
|
||||
|
||||
static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
|
||||
static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
|
@ -998,8 +1000,8 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
|
|||
dev_priv->buffers_offset = init->buffers_offset;
|
||||
dev_priv->gart_textures_offset = init->gart_textures_offset;
|
||||
|
||||
dev_priv->sarea = drm_getsarea(dev);
|
||||
if (!dev_priv->sarea) {
|
||||
master_priv->sarea = drm_getsarea(dev);
|
||||
if (!master_priv->sarea) {
|
||||
DRM_ERROR("could not find sarea!\n");
|
||||
radeon_do_cleanup_cp(dev);
|
||||
return -EINVAL;
|
||||
|
@ -1035,10 +1037,6 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
|
|||
}
|
||||
}
|
||||
|
||||
dev_priv->sarea_priv =
|
||||
(drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
|
||||
init->sarea_priv_offset);
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
if (dev_priv->flags & RADEON_IS_AGP) {
|
||||
drm_core_ioremap(dev_priv->cp_ring, dev);
|
||||
|
@ -1329,7 +1327,7 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri
|
|||
case RADEON_INIT_CP:
|
||||
case RADEON_INIT_R200_CP:
|
||||
case RADEON_INIT_R300_CP:
|
||||
return radeon_do_init_cp(dev, init);
|
||||
return radeon_do_init_cp(dev, init, file_priv);
|
||||
case RADEON_CLEANUP_CP:
|
||||
return radeon_do_cleanup_cp(dev);
|
||||
}
|
||||
|
@ -1768,6 +1766,51 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int radeon_master_create(struct drm_device *dev, struct drm_master *master)
|
||||
{
|
||||
struct drm_radeon_master_private *master_priv;
|
||||
unsigned long sareapage;
|
||||
int ret;
|
||||
|
||||
master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
|
||||
if (!master_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
/* prebuild the SAREA */
|
||||
sareapage = max(SAREA_MAX, PAGE_SIZE);
|
||||
ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
|
||||
&master_priv->sarea);
|
||||
if (ret) {
|
||||
DRM_ERROR("SAREA setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
|
||||
master_priv->sarea_priv->pfCurrentPage = 0;
|
||||
|
||||
master->driver_priv = master_priv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_master_destroy(struct drm_device *dev, struct drm_master *master)
|
||||
{
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
|
||||
if (!master_priv)
|
||||
return;
|
||||
|
||||
if (master_priv->sarea_priv &&
|
||||
master_priv->sarea_priv->pfCurrentPage != 0)
|
||||
radeon_cp_dispatch_flip(dev, master);
|
||||
|
||||
master_priv->sarea_priv = NULL;
|
||||
if (master_priv->sarea)
|
||||
drm_rmmap(dev, master_priv->sarea);
|
||||
|
||||
drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
|
||||
|
||||
master->driver_priv = NULL;
|
||||
}
|
||||
|
||||
/* Create mappings for registers and framebuffer so userland doesn't necessarily
|
||||
* have to find them.
|
||||
*/
|
||||
|
|
|
@ -226,9 +226,13 @@ struct radeon_virt_surface {
|
|||
#define RADEON_FLUSH_EMITED (1 < 0)
|
||||
#define RADEON_PURGE_EMITED (1 < 1)
|
||||
|
||||
struct drm_radeon_master_private {
|
||||
drm_local_map_t *sarea;
|
||||
drm_radeon_sarea_t *sarea_priv;
|
||||
};
|
||||
|
||||
typedef struct drm_radeon_private {
|
||||
drm_radeon_ring_buffer_t ring;
|
||||
drm_radeon_sarea_t *sarea_priv;
|
||||
|
||||
u32 fb_location;
|
||||
u32 fb_size;
|
||||
|
@ -409,6 +413,9 @@ extern int radeon_driver_open(struct drm_device *dev,
|
|||
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
extern int radeon_master_create(struct drm_device *dev, struct drm_master *master);
|
||||
extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master);
|
||||
extern void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master);
|
||||
/* r300_cmdbuf.c */
|
||||
extern void r300_init_reg_flags(struct drm_device *dev);
|
||||
|
||||
|
@ -1335,8 +1342,9 @@ do { \
|
|||
} while (0)
|
||||
|
||||
#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
|
||||
do { \
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
|
||||
do { \
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; \
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \
|
||||
if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
|
||||
int __ret = radeon_do_cp_idle( dev_priv ); \
|
||||
if ( __ret ) return __ret; \
|
||||
|
|
|
@ -742,13 +742,14 @@ static struct {
|
|||
*/
|
||||
|
||||
static void radeon_clear_box(drm_radeon_private_t * dev_priv,
|
||||
struct drm_radeon_master_private *master_priv,
|
||||
int x, int y, int w, int h, int r, int g, int b)
|
||||
{
|
||||
u32 color;
|
||||
RING_LOCALS;
|
||||
|
||||
x += dev_priv->sarea_priv->boxes[0].x1;
|
||||
y += dev_priv->sarea_priv->boxes[0].y1;
|
||||
x += master_priv->sarea_priv->boxes[0].x1;
|
||||
y += master_priv->sarea_priv->boxes[0].y1;
|
||||
|
||||
switch (dev_priv->color_fmt) {
|
||||
case RADEON_COLOR_FORMAT_RGB565:
|
||||
|
@ -776,7 +777,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
|
|||
RADEON_GMC_SRC_DATATYPE_COLOR |
|
||||
RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
|
||||
|
||||
if (dev_priv->sarea_priv->pfCurrentPage == 1) {
|
||||
if (master_priv->sarea_priv->pfCurrentPage == 1) {
|
||||
OUT_RING(dev_priv->front_pitch_offset);
|
||||
} else {
|
||||
OUT_RING(dev_priv->back_pitch_offset);
|
||||
|
@ -790,7 +791,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
|
|||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
|
||||
static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv, struct drm_radeon_master_private *master_priv)
|
||||
{
|
||||
/* Collapse various things into a wait flag -- trying to
|
||||
* guess if userspase slept -- better just to have them tell us.
|
||||
|
@ -807,12 +808,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
|
|||
/* Purple box for page flipping
|
||||
*/
|
||||
if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
|
||||
radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
|
||||
radeon_clear_box(dev_priv, master_priv, 4, 4, 8, 8, 255, 0, 255);
|
||||
|
||||
/* Red box if we have to wait for idle at any point
|
||||
*/
|
||||
if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
|
||||
radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
|
||||
radeon_clear_box(dev_priv, master_priv, 16, 4, 8, 8, 255, 0, 0);
|
||||
|
||||
/* Blue box: lost context?
|
||||
*/
|
||||
|
@ -820,12 +821,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
|
|||
/* Yellow box for texture swaps
|
||||
*/
|
||||
if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
|
||||
radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
|
||||
radeon_clear_box(dev_priv, master_priv, 40, 4, 8, 8, 255, 255, 0);
|
||||
|
||||
/* Green box if hardware never idles (as far as we can tell)
|
||||
*/
|
||||
if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
|
||||
radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
|
||||
radeon_clear_box(dev_priv, master_priv, 64, 4, 8, 8, 0, 255, 0);
|
||||
|
||||
/* Draw bars indicating number of buffers allocated
|
||||
* (not a great measure, easily confused)
|
||||
|
@ -834,7 +835,7 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
|
|||
if (dev_priv->stats.requested_bufs > 100)
|
||||
dev_priv->stats.requested_bufs = 100;
|
||||
|
||||
radeon_clear_box(dev_priv, 4, 16,
|
||||
radeon_clear_box(dev_priv, master_priv, 4, 16,
|
||||
dev_priv->stats.requested_bufs, 4,
|
||||
196, 128, 128);
|
||||
}
|
||||
|
@ -848,11 +849,13 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
|
|||
*/
|
||||
|
||||
static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
||||
struct drm_master *master,
|
||||
drm_radeon_clear_t * clear,
|
||||
drm_radeon_clear_rect_t * depth_boxes)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
|
||||
int nbox = sarea_priv->nbox;
|
||||
struct drm_clip_rect *pbox = sarea_priv->boxes;
|
||||
|
@ -864,7 +867,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
|||
|
||||
dev_priv->stats.clears++;
|
||||
|
||||
if (dev_priv->sarea_priv->pfCurrentPage == 1) {
|
||||
if (sarea_priv->pfCurrentPage == 1) {
|
||||
unsigned int tmp = flags;
|
||||
|
||||
flags &= ~(RADEON_FRONT | RADEON_BACK);
|
||||
|
@ -890,7 +893,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
|||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
dev_priv->sarea_priv->ctx_owner = 0;
|
||||
sarea_priv->ctx_owner = 0;
|
||||
|
||||
for (i = 0; i < nbox; i++) {
|
||||
int x = pbox[i].x1;
|
||||
|
@ -967,7 +970,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
|||
/* Make sure we restore the 3D state next time.
|
||||
* we haven't touched any "normal" state - still need this?
|
||||
*/
|
||||
dev_priv->sarea_priv->ctx_owner = 0;
|
||||
sarea_priv->ctx_owner = 0;
|
||||
|
||||
if ((dev_priv->flags & RADEON_HAS_HIERZ)
|
||||
&& (flags & RADEON_USE_HIERZ)) {
|
||||
|
@ -1214,7 +1217,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
|||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
dev_priv->sarea_priv->ctx_owner = 0;
|
||||
sarea_priv->ctx_owner = 0;
|
||||
|
||||
for (i = 0; i < nbox; i++) {
|
||||
|
||||
|
@ -1285,7 +1288,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
|||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
dev_priv->sarea_priv->ctx_owner = 0;
|
||||
sarea_priv->ctx_owner = 0;
|
||||
|
||||
for (i = 0; i < nbox; i++) {
|
||||
|
||||
|
@ -1328,20 +1331,21 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
|||
* wait on this value before performing the clear ioctl. We
|
||||
* need this because the card's so damned fast...
|
||||
*/
|
||||
dev_priv->sarea_priv->last_clear++;
|
||||
sarea_priv->last_clear++;
|
||||
|
||||
BEGIN_RING(4);
|
||||
|
||||
RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
|
||||
RADEON_CLEAR_AGE(sarea_priv->last_clear);
|
||||
RADEON_WAIT_UNTIL_IDLE();
|
||||
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
static void radeon_cp_dispatch_swap(struct drm_device * dev)
|
||||
static void radeon_cp_dispatch_swap(struct drm_device *dev, struct drm_master *master)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
int nbox = sarea_priv->nbox;
|
||||
struct drm_clip_rect *pbox = sarea_priv->boxes;
|
||||
int i;
|
||||
|
@ -1351,7 +1355,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)
|
|||
/* Do some trivial performance monitoring...
|
||||
*/
|
||||
if (dev_priv->do_boxes)
|
||||
radeon_cp_performance_boxes(dev_priv);
|
||||
radeon_cp_performance_boxes(dev_priv, master_priv);
|
||||
|
||||
/* Wait for the 3D stream to idle before dispatching the bitblt.
|
||||
* This will prevent data corruption between the two streams.
|
||||
|
@ -1385,7 +1389,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)
|
|||
/* Make this work even if front & back are flipped:
|
||||
*/
|
||||
OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
|
||||
if (dev_priv->sarea_priv->pfCurrentPage == 0) {
|
||||
if (sarea_priv->pfCurrentPage == 0) {
|
||||
OUT_RING(dev_priv->back_pitch_offset);
|
||||
OUT_RING(dev_priv->front_pitch_offset);
|
||||
} else {
|
||||
|
@ -1405,31 +1409,32 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)
|
|||
* throttle the framerate by waiting for this value before
|
||||
* performing the swapbuffer ioctl.
|
||||
*/
|
||||
dev_priv->sarea_priv->last_frame++;
|
||||
sarea_priv->last_frame++;
|
||||
|
||||
BEGIN_RING(4);
|
||||
|
||||
RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
|
||||
RADEON_FRAME_AGE(sarea_priv->last_frame);
|
||||
RADEON_WAIT_UNTIL_2D_IDLE();
|
||||
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
static void radeon_cp_dispatch_flip(struct drm_device * dev)
|
||||
void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
|
||||
int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->handle;
|
||||
int offset = (master_priv->sarea_priv->pfCurrentPage == 1)
|
||||
? dev_priv->front_offset : dev_priv->back_offset;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("pfCurrentPage=%d\n",
|
||||
dev_priv->sarea_priv->pfCurrentPage);
|
||||
master_priv->sarea_priv->pfCurrentPage);
|
||||
|
||||
/* Do some trivial performance monitoring...
|
||||
*/
|
||||
if (dev_priv->do_boxes) {
|
||||
dev_priv->stats.boxes |= RADEON_BOX_FLIP;
|
||||
radeon_cp_performance_boxes(dev_priv);
|
||||
radeon_cp_performance_boxes(dev_priv, master_priv);
|
||||
}
|
||||
|
||||
/* Update the frame offsets for both CRTCs
|
||||
|
@ -1441,7 +1446,7 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev)
|
|||
((sarea->frame.y * dev_priv->front_pitch +
|
||||
sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
|
||||
+ offset);
|
||||
OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
|
||||
OUT_RING_REG(RADEON_CRTC2_OFFSET, master_priv->sarea_priv->crtc2_base
|
||||
+ offset);
|
||||
|
||||
ADVANCE_RING();
|
||||
|
@ -1450,13 +1455,13 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev)
|
|||
* throttle the framerate by waiting for this value before
|
||||
* performing the swapbuffer ioctl.
|
||||
*/
|
||||
dev_priv->sarea_priv->last_frame++;
|
||||
dev_priv->sarea_priv->pfCurrentPage =
|
||||
1 - dev_priv->sarea_priv->pfCurrentPage;
|
||||
master_priv->sarea_priv->last_frame++;
|
||||
master_priv->sarea_priv->pfCurrentPage =
|
||||
1 - master_priv->sarea_priv->pfCurrentPage;
|
||||
|
||||
BEGIN_RING(2);
|
||||
|
||||
RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
|
||||
RADEON_FRAME_AGE(master_priv->sarea_priv->last_frame);
|
||||
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
@ -1494,11 +1499,13 @@ typedef struct {
|
|||
} drm_radeon_tcl_prim_t;
|
||||
|
||||
static void radeon_cp_dispatch_vertex(struct drm_device * dev,
|
||||
struct drm_file *file_priv,
|
||||
struct drm_buf * buf,
|
||||
drm_radeon_tcl_prim_t * prim)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
|
||||
int numverts = (int)prim->numverts;
|
||||
int nbox = sarea_priv->nbox;
|
||||
|
@ -1539,13 +1546,14 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev,
|
|||
} while (i < nbox);
|
||||
}
|
||||
|
||||
static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
|
||||
static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
|
||||
buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
|
||||
|
||||
/* Emit the vertex buffer age */
|
||||
BEGIN_RING(2);
|
||||
|
@ -1590,12 +1598,14 @@ static void radeon_cp_dispatch_indirect(struct drm_device * dev,
|
|||
}
|
||||
}
|
||||
|
||||
static void radeon_cp_dispatch_indices(struct drm_device * dev,
|
||||
static void radeon_cp_dispatch_indices(struct drm_device *dev,
|
||||
struct drm_master *master,
|
||||
struct drm_buf * elt_buf,
|
||||
drm_radeon_tcl_prim_t * prim)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
int offset = dev_priv->gart_buffers_offset + prim->offset;
|
||||
u32 *data;
|
||||
int dwords;
|
||||
|
@ -1870,7 +1880,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
|
|||
ADVANCE_RING();
|
||||
COMMIT_RING();
|
||||
|
||||
radeon_cp_discard_buffer(dev, buf);
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
|
||||
/* Update the input parameters for next time */
|
||||
image->y += height;
|
||||
|
@ -2110,7 +2120,8 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi
|
|||
static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
drm_radeon_clear_t *clear = data;
|
||||
drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
|
||||
DRM_DEBUG("\n");
|
||||
|
@ -2126,7 +2137,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
|
|||
sarea_priv->nbox * sizeof(depth_boxes[0])))
|
||||
return -EFAULT;
|
||||
|
||||
radeon_cp_dispatch_clear(dev, clear, depth_boxes);
|
||||
radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes);
|
||||
|
||||
COMMIT_RING();
|
||||
return 0;
|
||||
|
@ -2134,9 +2145,10 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
|
|||
|
||||
/* Not sure why this isn't set all the time:
|
||||
*/
|
||||
static int radeon_do_init_pageflip(struct drm_device * dev)
|
||||
static int radeon_do_init_pageflip(struct drm_device *dev, struct drm_master *master)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
RING_LOCALS;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
@ -2153,8 +2165,8 @@ static int radeon_do_init_pageflip(struct drm_device * dev)
|
|||
|
||||
dev_priv->page_flipping = 1;
|
||||
|
||||
if (dev_priv->sarea_priv->pfCurrentPage != 1)
|
||||
dev_priv->sarea_priv->pfCurrentPage = 0;
|
||||
if (master_priv->sarea_priv->pfCurrentPage != 1)
|
||||
master_priv->sarea_priv->pfCurrentPage = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2172,9 +2184,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
|
|||
RING_SPACE_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
if (!dev_priv->page_flipping)
|
||||
radeon_do_init_pageflip(dev);
|
||||
radeon_do_init_pageflip(dev, file_priv->master);
|
||||
|
||||
radeon_cp_dispatch_flip(dev);
|
||||
radeon_cp_dispatch_flip(dev, file_priv->master);
|
||||
|
||||
COMMIT_RING();
|
||||
return 0;
|
||||
|
@ -2183,7 +2195,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
|
|||
static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
@ -2193,8 +2207,8 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
|
|||
if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
|
||||
|
||||
radeon_cp_dispatch_swap(dev);
|
||||
dev_priv->sarea_priv->ctx_owner = 0;
|
||||
radeon_cp_dispatch_swap(dev, file_priv->master);
|
||||
sarea_priv->ctx_owner = 0;
|
||||
|
||||
COMMIT_RING();
|
||||
return 0;
|
||||
|
@ -2203,7 +2217,8 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
|
|||
static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv;
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
struct drm_buf *buf;
|
||||
drm_radeon_vertex_t *vertex = data;
|
||||
|
@ -2211,6 +2226,8 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
sarea_priv = master_priv->sarea_priv;
|
||||
|
||||
DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
|
||||
DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
|
||||
|
||||
|
@ -2263,13 +2280,13 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
|
|||
prim.finish = vertex->count; /* unused */
|
||||
prim.prim = vertex->prim;
|
||||
prim.numverts = vertex->count;
|
||||
prim.vc_format = dev_priv->sarea_priv->vc_format;
|
||||
prim.vc_format = sarea_priv->vc_format;
|
||||
|
||||
radeon_cp_dispatch_vertex(dev, buf, &prim);
|
||||
radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim);
|
||||
}
|
||||
|
||||
if (vertex->discard) {
|
||||
radeon_cp_discard_buffer(dev, buf);
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
}
|
||||
|
||||
COMMIT_RING();
|
||||
|
@ -2279,7 +2296,8 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
|
|||
static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv;
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
struct drm_buf *buf;
|
||||
drm_radeon_indices_t *elts = data;
|
||||
|
@ -2288,6 +2306,8 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
sarea_priv = master_priv->sarea_priv;
|
||||
|
||||
DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
|
||||
DRM_CURRENTPID, elts->idx, elts->start, elts->end,
|
||||
elts->discard);
|
||||
|
@ -2353,11 +2373,11 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file
|
|||
prim.prim = elts->prim;
|
||||
prim.offset = 0; /* offset from start of dma buffers */
|
||||
prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
|
||||
prim.vc_format = dev_priv->sarea_priv->vc_format;
|
||||
prim.vc_format = sarea_priv->vc_format;
|
||||
|
||||
radeon_cp_dispatch_indices(dev, buf, &prim);
|
||||
radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim);
|
||||
if (elts->discard) {
|
||||
radeon_cp_discard_buffer(dev, buf);
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
}
|
||||
|
||||
COMMIT_RING();
|
||||
|
@ -2468,7 +2488,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
|
|||
*/
|
||||
radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
|
||||
if (indirect->discard) {
|
||||
radeon_cp_discard_buffer(dev, buf);
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
}
|
||||
|
||||
COMMIT_RING();
|
||||
|
@ -2478,7 +2498,8 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
|
|||
static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv;
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
struct drm_buf *buf;
|
||||
drm_radeon_vertex2_t *vertex = data;
|
||||
|
@ -2487,6 +2508,8 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
sarea_priv = master_priv->sarea_priv;
|
||||
|
||||
DRM_DEBUG("pid=%d index=%d discard=%d\n",
|
||||
DRM_CURRENTPID, vertex->idx, vertex->discard);
|
||||
|
||||
|
@ -2547,12 +2570,12 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
|
|||
tclprim.offset = prim.numverts * 64;
|
||||
tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
|
||||
|
||||
radeon_cp_dispatch_indices(dev, buf, &tclprim);
|
||||
radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim);
|
||||
} else {
|
||||
tclprim.numverts = prim.numverts;
|
||||
tclprim.offset = 0; /* not used */
|
||||
|
||||
radeon_cp_dispatch_vertex(dev, buf, &tclprim);
|
||||
radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim);
|
||||
}
|
||||
|
||||
if (sarea_priv->nbox == 1)
|
||||
|
@ -2560,7 +2583,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
|
|||
}
|
||||
|
||||
if (vertex->discard) {
|
||||
radeon_cp_discard_buffer(dev, buf);
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
}
|
||||
|
||||
COMMIT_RING();
|
||||
|
@ -2909,7 +2932,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
goto err;
|
||||
}
|
||||
|
||||
radeon_cp_discard_buffer(dev, buf);
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
break;
|
||||
|
||||
case RADEON_CMD_PACKET3:
|
||||
|
@ -3020,7 +3043,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
|
|||
*/
|
||||
case RADEON_PARAM_SAREA_HANDLE:
|
||||
/* The lock is the first dword in the sarea. */
|
||||
value = (long)dev->lock.hw_lock;
|
||||
/* no users of this parameter */
|
||||
break;
|
||||
#endif
|
||||
case RADEON_PARAM_GART_TEX_HANDLE:
|
||||
|
@ -3064,6 +3087,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
|
|||
static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
|
||||
drm_radeon_setparam_t *sp = data;
|
||||
struct drm_radeon_driver_file_fields *radeon_priv;
|
||||
|
||||
|
@ -3078,12 +3102,14 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil
|
|||
DRM_DEBUG("color tiling disabled\n");
|
||||
dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
|
||||
dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
|
||||
dev_priv->sarea_priv->tiling_enabled = 0;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->tiling_enabled = 0;
|
||||
} else if (sp->value == 1) {
|
||||
DRM_DEBUG("color tiling enabled\n");
|
||||
dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
|
||||
dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
|
||||
dev_priv->sarea_priv->tiling_enabled = 1;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->tiling_enabled = 1;
|
||||
}
|
||||
break;
|
||||
case RADEON_SETPARAM_PCIGART_LOCATION:
|
||||
|
@ -3129,14 +3155,6 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
|
|||
|
||||
void radeon_driver_lastclose(struct drm_device *dev)
|
||||
{
|
||||
if (dev->dev_private) {
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->sarea_priv &&
|
||||
dev_priv->sarea_priv->pfCurrentPage != 0)
|
||||
radeon_cp_dispatch_flip(dev);
|
||||
}
|
||||
|
||||
radeon_do_release(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -634,6 +634,9 @@ struct drm_gem_open {
|
|||
#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
|
||||
#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
|
||||
|
||||
#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
|
||||
#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
|
||||
|
||||
#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx)
|
||||
#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx)
|
||||
#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx)
|
||||
|
|
|
@ -238,11 +238,11 @@ struct drm_device;
|
|||
*/
|
||||
#define LOCK_TEST_WITH_RETURN( dev, file_priv ) \
|
||||
do { \
|
||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
|
||||
dev->lock.file_priv != file_priv ) { \
|
||||
if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock) || \
|
||||
file_priv->master->lock.file_priv != file_priv) { \
|
||||
DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\
|
||||
__func__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
|
||||
dev->lock.file_priv, file_priv ); \
|
||||
__func__, _DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock),\
|
||||
file_priv->master->lock.file_priv, file_priv); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -379,21 +379,25 @@ struct drm_buf_entry {
|
|||
/** File private data */
|
||||
struct drm_file {
|
||||
int authenticated;
|
||||
int master;
|
||||
pid_t pid;
|
||||
uid_t uid;
|
||||
drm_magic_t magic;
|
||||
unsigned long ioctl_count;
|
||||
struct list_head lhead;
|
||||
struct drm_minor *minor;
|
||||
int remove_auth_on_close;
|
||||
unsigned long lock_count;
|
||||
|
||||
/** Mapping of mm object handles to object pointers. */
|
||||
struct idr object_idr;
|
||||
/** Lock for synchronization of access to object_idr. */
|
||||
spinlock_t table_lock;
|
||||
|
||||
struct file *filp;
|
||||
void *driver_priv;
|
||||
|
||||
int is_master; /* this file private is a master for a minor */
|
||||
struct drm_master *master; /* master this node is currently associated with
|
||||
N.B. not always minor->master */
|
||||
};
|
||||
|
||||
/** Wait queue */
|
||||
|
@ -523,6 +527,7 @@ struct drm_map_list {
|
|||
struct drm_hash_item hash;
|
||||
struct drm_map *map; /**< mapping */
|
||||
uint64_t user_token;
|
||||
struct drm_master *master;
|
||||
};
|
||||
|
||||
typedef struct drm_map drm_local_map_t;
|
||||
|
@ -612,6 +617,30 @@ struct drm_gem_object {
|
|||
void *driver_private;
|
||||
};
|
||||
|
||||
/* per-master structure */
|
||||
struct drm_master {
|
||||
|
||||
struct kref refcount; /* refcount for this master */
|
||||
|
||||
struct list_head head; /**< each minor contains a list of masters */
|
||||
struct drm_minor *minor; /**< link back to minor we are a master for */
|
||||
|
||||
char *unique; /**< Unique identifier: e.g., busid */
|
||||
int unique_len; /**< Length of unique field */
|
||||
|
||||
int blocked; /**< Blocked due to VC switch? */
|
||||
|
||||
/** \name Authentication */
|
||||
/*@{ */
|
||||
struct drm_open_hash magiclist;
|
||||
struct list_head magicfree;
|
||||
/*@} */
|
||||
|
||||
struct drm_lock_data lock; /**< Information on hardware lock */
|
||||
|
||||
void *driver_priv; /**< Private structure for driver to use */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM driver structure. This structure represent the common code for
|
||||
* a family of cards. There will one drm_device for each card present
|
||||
|
@ -712,6 +741,10 @@ struct drm_driver {
|
|||
void (*set_version) (struct drm_device *dev,
|
||||
struct drm_set_version *sv);
|
||||
|
||||
/* Master routines */
|
||||
int (*master_create)(struct drm_device *dev, struct drm_master *master);
|
||||
void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
|
||||
|
||||
int (*proc_init)(struct drm_minor *minor);
|
||||
void (*proc_cleanup)(struct drm_minor *minor);
|
||||
|
||||
|
@ -754,6 +787,8 @@ struct drm_minor {
|
|||
struct device kdev; /**< Linux device */
|
||||
struct drm_device *dev;
|
||||
struct proc_dir_entry *dev_root; /**< proc directory entry */
|
||||
struct drm_master *master; /* currently active master for this node */
|
||||
struct list_head master_list;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -762,13 +797,9 @@ struct drm_minor {
|
|||
*/
|
||||
struct drm_device {
|
||||
struct list_head driver_item; /**< list of devices per driver */
|
||||
char *unique; /**< Unique identifier: e.g., busid */
|
||||
int unique_len; /**< Length of unique field */
|
||||
char *devname; /**< For /proc/interrupts */
|
||||
int if_version; /**< Highest interface version set */
|
||||
|
||||
int blocked; /**< Blocked due to VC switch? */
|
||||
|
||||
/** \name Locks */
|
||||
/*@{ */
|
||||
spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
|
||||
|
@ -791,12 +822,7 @@ struct drm_device {
|
|||
atomic_t counts[15];
|
||||
/*@} */
|
||||
|
||||
/** \name Authentication */
|
||||
/*@{ */
|
||||
struct list_head filelist;
|
||||
struct drm_open_hash magiclist; /**< magic hash table */
|
||||
struct list_head magicfree;
|
||||
/*@} */
|
||||
|
||||
/** \name Memory management */
|
||||
/*@{ */
|
||||
|
@ -813,7 +839,6 @@ struct drm_device {
|
|||
struct idr ctx_idr;
|
||||
|
||||
struct list_head vmalist; /**< List of vmas (for debugging) */
|
||||
struct drm_lock_data lock; /**< Information on hardware lock */
|
||||
/*@} */
|
||||
|
||||
/** \name DMA queues (contexts) */
|
||||
|
@ -1192,6 +1217,13 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
|
|||
extern void drm_agp_chipset_flush(struct drm_device *dev);
|
||||
|
||||
/* Stub support (drm_stub.h) */
|
||||
extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
struct drm_master *drm_master_create(struct drm_minor *minor);
|
||||
extern struct drm_master *drm_master_get(struct drm_master *master);
|
||||
extern void drm_master_put(struct drm_master **master);
|
||||
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
struct drm_driver *driver);
|
||||
extern int drm_put_dev(struct drm_device *dev);
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
|
||||
/* SAREA area needs to be at least a page */
|
||||
#if defined(__alpha__)
|
||||
#define SAREA_MAX 0x2000
|
||||
#define SAREA_MAX 0x2000U
|
||||
#elif defined(__ia64__)
|
||||
#define SAREA_MAX 0x10000 /* 64kB */
|
||||
#define SAREA_MAX 0x10000U /* 64kB */
|
||||
#else
|
||||
/* Intel 830M driver needs at least 8k SAREA */
|
||||
#define SAREA_MAX 0x2000
|
||||
#define SAREA_MAX 0x2000U
|
||||
#endif
|
||||
|
||||
/** Maximum number of drawables in the SAREA */
|
||||
|
|
Загрузка…
Ссылка в новой задаче