quake3-smp is OK
drmCommandWrite: -22
drmRadeonCmdBuffer: -22 (exiting)
Seems to be fixed.
Latest DRI and DRM CVS.
Yesterday's DRI CVS was fine (textures).
DRM reset works.
See attached patch.
More to come, I'm in hurry.
-Dieter
diff -ru drm.orig/linux/drm_drv.h drm/linux/drm_drv.h
--- drm.orig/linux/drm_drv.h 2004-09-23 17:56:18.000000000 +0200
+++ drm/linux/drm_drv.h 2004-09-23 17:58:09.562593427 +0200
@@ -158,6 +158,8 @@
#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( DRM(ioctls) )
+static void drm_lock_watchdog( unsigned long __data );
+
static int DRM(setup)( drm_device_t *dev )
{
int i;
@@ -261,6 +263,7 @@
down( &dev->struct_sem );
del_timer( &dev->timer );
+ del_timer_sync( &dev->lock.watchdog );
if ( dev->devname ) {
DRM(free)( dev->devname, strlen( dev->devname ) + 1,
@@ -371,6 +374,7 @@
if ( dev->lock.hw_lock ) {
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
dev->lock.filp = NULL;
+ dev->lock.dontbreak = 1;
wake_up_interruptible( &dev->lock.lock_queue );
}
up( &dev->struct_sem );
@@ -463,6 +467,10 @@
goto error_out_unreg;
}
+ init_timer( &dev->lock.watchdog );
+ dev->lock.watchdog.data = (unsigned long) dev;
+ dev->lock.watchdog.function = drm_lock_watchdog;
+
dev->device = MKDEV(DRM_MAJOR, dev->minor );
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
@@ -810,6 +818,11 @@
if (dev->fn_tbl.release)
dev->fn_tbl.release(dev, filp);
+ /* Avoid potential race where the watchdog callback is still
+ * running when filp is freed.
+ */
+ del_timer_sync( &dev->lock.watchdog );
+
DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
@@ -832,6 +845,7 @@
}
if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT ) ) {
+ dev->lock.dontbreak = 1;
dev->lock.filp = filp;
dev->lock.lock_time = jiffies;
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
@@ -983,6 +997,40 @@
return retcode;
}
+
+/**
+ * Lock watchdog callback function.
+ *
+ * Whenever a privileged client must sleep on the lock waitqueue
+ * in the LOCK ioctl, the watchdog timer is started.
+ * When the UNLOCK ioctl is called, the timer is stopped.
+ *
+ * When the watchdog timer expires, the process holding the lock
+ * is killed. Privileged clients set lock.dontbreak and are exempt
+ * from this rule.
+ */
+static void drm_lock_watchdog( unsigned long __data )
+{
+ drm_device_t *dev = (drm_device_t *)__data;
+ drm_file_t *priv;
+
+ if ( !dev->lock.filp ) {
+ DRM_DEBUG( "held by kernel\n" );
+ return;
+ }
+
+ if ( dev->lock.dontbreak ) {
+ DRM_DEBUG( "privileged lock\n" );
+ return;
+ }
+
+ priv = dev->lock.filp->private_data;
+ DRM_DEBUG( "Kill pid=%d\n", priv->pid );
+
+ kill_proc( priv->pid, SIGKILL, 1 );
+}
+
+
/**
* Lock ioctl.
*
@@ -1002,6 +1050,7 @@
DECLARE_WAITQUEUE( entry, current );
drm_lock_t lock;
int ret = 0;
+ int privileged = capable( CAP_SYS_ADMIN );
++priv->lock_count;
@@ -1032,6 +1081,7 @@
}
if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
lock.context ) ) {
+ dev->lock.dontbreak = privileged;
dev->lock.filp = filp;
dev->lock.lock_time = jiffies;
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
@@ -1039,6 +1089,14 @@
}
/* Contention */
+
+ if ( privileged ) {
+ if ( !timer_pending( &dev->lock.watchdog ) ) {
+ DRM_DEBUG( "Starting lock watchdog\n" );
+ mod_timer( &dev->lock.watchdog, jiffies + 5 * HZ );
+ }
+ }
+
schedule();
if ( signal_pending( current ) ) {
ret = -ERESTARTSYS;
@@ -1103,8 +1161,12 @@
return -EINVAL;
}
+ DRM_DEBUG( "\n" );
+
atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
+ del_timer_sync( &dev->lock.watchdog );
+
if (dev->fn_tbl.kernel_context_switch_unlock)
dev->fn_tbl.kernel_context_switch_unlock(dev);
else
diff -ru drm.orig/linux/drmP.h drm/linux/drmP.h
--- drm.orig/linux/drmP.h 2004-09-23 17:56:18.000000000 +0200
+++ drm/linux/drmP.h 2004-09-23 17:58:09.565592833 +0200
@@ -406,6 +406,8 @@
struct file *filp; /**< File descr of lock holder (0=kernel) */
wait_queue_head_t lock_queue; /**< Queue of blocked processes */
unsigned long lock_time; /**< Time of last lock in jiffies */
+ struct timer_list watchdog; /**< Watchdog timer to kill runaway processes */
+ int dontbreak; /**< Even watchdog honours the current lock */
} drm_lock_data_t;
/**