Code to help in debugging of the mga drm modules locking policy

This commit is contained in:
Jeff Hartmann 2000-09-07 22:33:36 +00:00
parent 5f2cfc5bd8
commit 4f2c60bb65
11 changed files with 323 additions and 98 deletions

View file

@ -27,6 +27,7 @@ export-objs := $(patsubst %.o,%_drv.o,$(module-list))
#
lib-objs := init.o memory.o proc.o auth.o context.o drawable.o bufs.o
lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
lib-objs += drm_heavy_kern_lock.o
ifeq ($(CONFIG_AGP),y)
lib-objs += agpsupport.o

View file

@ -300,6 +300,7 @@ typedef struct drm_ioctl_desc {
drm_ioctl_t *func;
int auth_needed;
int root_only;
int needs_hvy_lock;
} drm_ioctl_desc_t;
typedef struct drm_devstate {
@ -430,9 +431,10 @@ typedef struct drm_file {
struct drm_file *next;
struct drm_file *prev;
struct drm_device *dev;
volatile int lock_depth;
unsigned long irq_flags;
} drm_file_t;
typedef struct drm_queue {
atomic_t use_count; /* Outstanding uses (+1) */
atomic_t finalization; /* Finalization in progress */
@ -615,6 +617,12 @@ typedef struct drm_device {
void *dev_private;
drm_sigdata_t sigdata; /* For block_all_signals */
sigset_t sigmask;
spinlock_t big_fscking_lock;
volatile int irq_lock_depth;
unsigned long irq_flags;
volatile int bh_lock_depth;
unsigned long bh_flags;
} drm_device_t;
@ -817,6 +825,16 @@ extern void drm_ctxbitmap_cleanup(drm_device_t *dev);
extern int drm_ctxbitmap_next(drm_device_t *dev);
extern void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle);
/* BIG Fscking lock (drm_heavy_kern_lock.c) */
extern void drm_schedule(drm_device_t *dev);
extern void drm_schedule_timeout(drm_device_t *dev, unsigned long timeout);
extern void drm_big_fscking_lock(drm_device_t *dev);
extern void drm_big_fscking_unlock(drm_device_t *dev);
extern void __inline drm_big_fscking_lock_filp(drm_device_t *dev,
drm_file_t *filp);
extern void __inline drm_big_fscking_unlock_filp(drm_device_t *dev,
drm_file_t *filp);
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
/* AGP/GART support (agpsupport.c) */
extern drm_agp_head_t *drm_agp_init(void);

View file

@ -66,54 +66,55 @@ static struct miscdevice mga_misc = {
};
static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { mga_version, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { mga_version, 0, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { mga_control, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { mga_addbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { mga_markbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { mga_infobufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { mga_mapbufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { mga_freebufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { mga_control, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { mga_addbufs, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { mga_markbufs, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { mga_infobufs, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { mga_mapbufs, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { mga_freebufs, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { mga_addctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { mga_rmctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { mga_modctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { mga_getctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { mga_switchctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { mga_newctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { mga_resctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { mga_addctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { mga_rmctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { mga_modctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { mga_getctx, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { mga_switchctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { mga_newctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { mga_resctx, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { mga_lock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { mga_unlock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { mga_lock, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { mga_unlock, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_flush_ioctl, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_flush_ioctl, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices, 1, 0, 1 },
};
#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
@ -182,6 +183,9 @@ static int mga_setup(drm_device_t *dev)
dev->last_context = 0;
dev->last_switch = 0;
dev->last_checked = 0;
dev->irq_lock_depth = -1;
dev->bh_lock_depth = -1;
init_timer(&dev->timer);
init_waitqueue_head(&dev->context_wait);
@ -192,6 +196,7 @@ static int mga_setup(drm_device_t *dev)
dev->buf_wp = dev->buf;
dev->buf_end = dev->buf + DRM_BSZ;
dev->buf_async = NULL;
init_waitqueue_head(&dev->buf_readers);
init_waitqueue_head(&dev->buf_writers);
@ -539,7 +544,7 @@ int mga_release(struct inode *inode, struct file *filp)
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
schedule();
drm_schedule(dev);
if (signal_pending(current)) {
retcode = -ERESTARTSYS;
break;
@ -619,7 +624,11 @@ int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|| (ioctl->auth_needed && !priv->authenticated)) {
retcode = -EACCES;
} else {
if(ioctl->needs_hvy_lock == 1)
drm_big_fscking_lock_filp(dev, priv);
retcode = (func)(inode, filp, cmd, arg);
if(ioctl->needs_hvy_lock == 1)
drm_big_fscking_unlock_filp(dev, priv);
}
}

View file

@ -27,6 +27,7 @@ export-objs := $(patsubst %.o,%_drv.o,$(module-list))
#
lib-objs := init.o memory.o proc.o auth.o context.o drawable.o bufs.o
lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
lib-objs += drm_heavy_kern_lock.o
ifeq ($(CONFIG_AGP),y)
lib-objs += agpsupport.o

View file

@ -53,7 +53,8 @@ LIBS= libdrm.a
PROGS= drmstat
DRMOBJS= init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o \
drm_heavy_kern_lock.o
DRMHEADERS= drm.h drmP.h compat-pre24.h
GAMMAOBJS= gamma_drv.o gamma_dma.o

View file

@ -300,6 +300,7 @@ typedef struct drm_ioctl_desc {
drm_ioctl_t *func;
int auth_needed;
int root_only;
int needs_hvy_lock;
} drm_ioctl_desc_t;
typedef struct drm_devstate {
@ -430,9 +431,10 @@ typedef struct drm_file {
struct drm_file *next;
struct drm_file *prev;
struct drm_device *dev;
volatile int lock_depth;
unsigned long irq_flags;
} drm_file_t;
typedef struct drm_queue {
atomic_t use_count; /* Outstanding uses (+1) */
atomic_t finalization; /* Finalization in progress */
@ -615,6 +617,12 @@ typedef struct drm_device {
void *dev_private;
drm_sigdata_t sigdata; /* For block_all_signals */
sigset_t sigmask;
spinlock_t big_fscking_lock;
volatile int irq_lock_depth;
unsigned long irq_flags;
volatile int bh_lock_depth;
unsigned long bh_flags;
} drm_device_t;
@ -817,6 +825,16 @@ extern void drm_ctxbitmap_cleanup(drm_device_t *dev);
extern int drm_ctxbitmap_next(drm_device_t *dev);
extern void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle);
/* BIG Fscking lock (drm_heavy_kern_lock.c) */
extern void drm_schedule(drm_device_t *dev);
extern void drm_schedule_timeout(drm_device_t *dev, unsigned long timeout);
extern void drm_big_fscking_lock(drm_device_t *dev);
extern void drm_big_fscking_unlock(drm_device_t *dev);
extern void __inline drm_big_fscking_lock_filp(drm_device_t *dev,
drm_file_t *filp);
extern void __inline drm_big_fscking_unlock_filp(drm_device_t *dev,
drm_file_t *filp);
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
/* AGP/GART support (agpsupport.c) */
extern drm_agp_head_t *drm_agp_init(void);

150
linux/drm_heavy_kern_lock.c Normal file
View file

@ -0,0 +1,150 @@
/* This has to be used VERY carefully, since you never want to sleep with the
* lock. It would be very bad if you slept w/ irq's disabled.
*/
/* Big fscking lock implementation */
#define __NO_VERSION__
#include "drmP.h"
#include <asm/softirq.h>
/* This is not smp safe! */
static __inline__ drm_file_t *drm_find_filp_by_current_pid(drm_device_t *dev)
{
drm_file_t *first;
/* down(&dev->struct_sem); */
first = dev->file_first;
while(first != NULL) {
if(first->pid == current->pid) {
break;
}
first = first->next;
}
/* up(&dev->struct_sem); */
return first;
}
static __inline__ void drm_release_big_fscking_lock(drm_device_t *dev, drm_file_t *filp)
{
if(filp->lock_depth >= 0)
spin_unlock_irqrestore(&dev->big_fscking_lock,
filp->irq_flags);
}
static __inline__ void drm_reacquire_big_fscking_lock(drm_device_t *dev, drm_file_t *filp)
{
unsigned long flags;
if(filp->lock_depth >= 0) {
barrier();
spin_lock_irqsave(&dev->big_fscking_lock, flags);
filp->irq_flags = flags;
}
}
/* This can NEVER be called from an interrupt */
void drm_schedule(drm_device_t *dev)
{
drm_file_t *filp;
if(in_interrupt()) {
BUG();
}
filp = drm_find_filp_by_current_pid(dev);
if(filp == NULL) BUG();
drm_release_big_fscking_lock(dev, filp);
schedule();
drm_reacquire_big_fscking_lock(dev, filp);
}
void drm_schedule_timeout(drm_device_t *dev, unsigned long timeout)
{
drm_file_t *filp;
if(in_interrupt()) {
BUG();
}
filp = drm_find_filp_by_current_pid(dev);
if(filp == NULL) BUG();
drm_release_big_fscking_lock(dev, filp);
schedule_timeout(timeout);
drm_reacquire_big_fscking_lock(dev, filp);
}
void drm_big_fscking_lock(drm_device_t *dev)
{
drm_file_t *filp;
unsigned long flags;
if(in_irq()) {
barrier();
if(!++dev->irq_lock_depth) {
spin_lock_irqsave(&dev->big_fscking_lock,
flags);
dev->irq_flags = flags;
}
} else if (in_softirq()) {
barrier();
if(!++dev->bh_lock_depth) {
spin_lock_irqsave(&dev->big_fscking_lock,
flags);
dev->bh_flags = flags;
}
} else {
filp = drm_find_filp_by_current_pid(dev);
if(filp == NULL) BUG();
barrier();
if(!++filp->lock_depth) {
spin_lock_irqsave(&dev->big_fscking_lock,
flags);
dev->irq_flags = flags;
}
}
}
void drm_big_fscking_unlock(drm_device_t *dev)
{
drm_file_t *filp;
if(in_irq()) {
barrier();
if(--dev->irq_lock_depth < 0)
spin_unlock_irqrestore(&dev->big_fscking_lock,
dev->irq_flags);
} else if (in_softirq()) {
barrier();
if(--dev->bh_lock_depth < 0)
spin_unlock_irqrestore(&dev->big_fscking_lock,
dev->bh_flags);
} else {
filp = drm_find_filp_by_current_pid(dev);
if(filp == NULL) BUG();
barrier();
if(--filp->lock_depth < 0)
spin_unlock_irqrestore(&dev->big_fscking_lock,
filp->irq_flags);
}
}
void __inline drm_big_fscking_lock_filp(drm_device_t *dev, drm_file_t *filp)
{
unsigned long flags;
barrier();
if(!++filp->lock_depth) {
spin_lock_irqsave(&dev->big_fscking_lock,
flags);
dev->irq_flags = flags;
}
}
void __inline drm_big_fscking_unlock_filp(drm_device_t *dev, drm_file_t *filp)
{
barrier();
if(--filp->lock_depth < 0)
spin_unlock_irqrestore(&dev->big_fscking_lock,
filp->irq_flags);
}

View file

@ -55,6 +55,7 @@ int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
priv->dev = dev;
priv->ioctl_count = 0;
priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_depth = -1;
down(&dev->struct_sem);
if (!dev->file_last) {

View file

@ -230,7 +230,7 @@ drm_buf_t *mga_freelist_get(drm_device_t *dev)
&dev_priv->dispatch_status))
break;
atomic_inc(&dev->total_sleeps);
schedule();
drm_schedule(dev);
if (signal_pending(current)) {
clear_bit(MGA_IN_GETBUF,
&dev_priv->dispatch_status);
@ -417,6 +417,7 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
}
mga_flush_write_combine();
atomic_inc(&dev_priv->pending_bufs);
MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
@ -472,7 +473,7 @@ int mga_advance_primary(drm_device_t *dev)
break;
atomic_inc(&dev->total_sleeps);
atomic_inc(&dma->total_missed_sched);
schedule();
drm_schedule(dev);
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
@ -563,6 +564,8 @@ int mga_dma_schedule(drm_device_t *dev, int locked)
drm_device_dma_t *dma = dev->dma;
int retval = 0;
drm_big_fscking_lock(dev);
if (test_and_set_bit(0, &dev->dma_flag)) {
atomic_inc(&dma->total_missed_dma);
retval = -EBUSY;
@ -633,6 +636,7 @@ sch_out_wakeup:
}
clear_bit(0, &dev->dma_flag);
drm_big_fscking_unlock(dev);
return retval;
}
@ -645,6 +649,7 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
DRM_DEBUG("%s\n", __FUNCTION__);
atomic_inc(&dev->total_irq);
if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return;
drm_big_fscking_lock(dev);
MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
last_prim_buffer = dev_priv->last_prim;
last_prim_buffer->num_dwords = 0;
@ -658,6 +663,7 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
atomic_dec(&dev_priv->pending_bufs);
queue_task(&dev->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
drm_big_fscking_unlock(dev);
}
static void mga_dma_task_queue(void *device)
@ -813,8 +819,9 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
/* Poll for the first buffer to insure that
* the status register will be correct
*/
mga_flush_write_combine();
MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) |
@ -960,7 +967,7 @@ static int mga_flush_queue(drm_device_t *dev)
&dev_priv->dispatch_status))
break;
atomic_inc(&dev->total_sleeps);
schedule();
drm_schedule(dev);
if (signal_pending(current)) {
ret = -EINTR; /* Can't restart */
clear_bit(MGA_IN_FLUSH,
@ -1050,7 +1057,7 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
schedule();
drm_schedule(dev);
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;

View file

@ -66,54 +66,55 @@ static struct miscdevice mga_misc = {
};
static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { mga_version, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { mga_version, 0, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { mga_control, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { mga_addbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { mga_markbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { mga_infobufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { mga_mapbufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { mga_freebufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { mga_control, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { mga_addbufs, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { mga_markbufs, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { mga_infobufs, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { mga_mapbufs, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { mga_freebufs, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { mga_addctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { mga_rmctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { mga_modctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { mga_getctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { mga_switchctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { mga_newctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { mga_resctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { mga_addctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { mga_rmctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { mga_modctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { mga_getctx, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { mga_switchctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { mga_newctx, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { mga_resctx, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { mga_lock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { mga_unlock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { mga_lock, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { mga_unlock, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_flush_ioctl, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_flush_ioctl, 1, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices, 1, 0, 1 },
};
#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
@ -182,6 +183,9 @@ static int mga_setup(drm_device_t *dev)
dev->last_context = 0;
dev->last_switch = 0;
dev->last_checked = 0;
dev->irq_lock_depth = -1;
dev->bh_lock_depth = -1;
init_timer(&dev->timer);
init_waitqueue_head(&dev->context_wait);
@ -192,6 +196,7 @@ static int mga_setup(drm_device_t *dev)
dev->buf_wp = dev->buf;
dev->buf_end = dev->buf + DRM_BSZ;
dev->buf_async = NULL;
init_waitqueue_head(&dev->buf_readers);
init_waitqueue_head(&dev->buf_writers);
@ -539,7 +544,7 @@ int mga_release(struct inode *inode, struct file *filp)
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
schedule();
drm_schedule(dev);
if (signal_pending(current)) {
retcode = -ERESTARTSYS;
break;
@ -619,7 +624,11 @@ int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|| (ioctl->auth_needed && !priv->authenticated)) {
retcode = -EACCES;
} else {
if(ioctl->needs_hvy_lock == 1)
drm_big_fscking_lock_filp(dev, priv);
retcode = (func)(inode, filp, cmd, arg);
if(ioctl->needs_hvy_lock == 1)
drm_big_fscking_unlock_filp(dev, priv);
}
}

View file

@ -218,8 +218,8 @@ static void mgaG400EmitTex1(drm_mga_private_t * dev_priv, int source )
/* This takes 25 dwords */
PRIMOUTREG(MGAREG_TEXCTL2,
regs[MGA_TEXREG_CTL2] | TMC_map1_enable | 0x00008000);
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable |
0x00008000);
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
@ -873,7 +873,9 @@ int mga_clear_bufs(struct inode *inode, struct file *filp,
clear.clear_color_mask,
clear.clear_depth_mask);
PRIMUPDATE(dev_priv);
mga_flush_write_combine();
mga_dma_schedule(dev, 1);
return 0;
}
@ -903,7 +905,9 @@ int mga_swap_bufs(struct inode *inode, struct file *filp,
PRIMUPDATE(dev_priv);
set_bit(MGA_BUF_SWAP_PENDING,
&dev_priv->current_prim->buffer_status);
mga_flush_write_combine();
mga_dma_schedule(dev, 1);
return 0;
}
@ -951,7 +955,9 @@ int mga_iload(struct inode *inode, struct file *filp,
AGEBUF(dev_priv, buf_priv);
buf_priv->discard = 1;
mga_freelist_put(dev, buf);
mga_flush_write_combine();
mga_dma_schedule(dev, 1);
return 0;
}
@ -999,7 +1005,9 @@ int mga_vertex(struct inode *inode, struct file *filp,
mga_dma_dispatch_vertex(dev, buf);
PRIMUPDATE(dev_priv);
mga_flush_write_combine();
mga_dma_schedule(dev, 1);
return 0;
}
@ -1046,7 +1054,9 @@ int mga_indices(struct inode *inode, struct file *filp,
mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
PRIMUPDATE(dev_priv);
mga_flush_write_combine();
mga_dma_schedule(dev, 1);
return 0;
}