patch-2.4.8 linux/drivers/char/drm/gamma_dma.c

Next file: linux/drivers/char/drm/gamma_drv.c
Previous file: linux/drivers/char/drm/gamma.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.7/linux/drivers/char/drm/gamma_dma.c linux/drivers/char/drm/gamma_dma.c
@@ -11,11 +11,11 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the next
  * paragraph) shall be included in all copies or substantial portions of the
  * Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
@@ -23,73 +23,38 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- * 
+ *
  * Authors:
  *    Rickard E. (Rik) Faith <faith@valinux.com>
  *
  */
 
 #define __NO_VERSION__
+#include "gamma.h"
 #include "drmP.h"
 #include "gamma_drv.h"
 
 #include <linux/interrupt.h>	/* For task queue support */
+#include <linux/delay.h>
 
 
-/* WARNING!!! MAGIC NUMBER!!!  The number of regions already added to the
-   kernel must be specified here.  Currently, the number is 2.	This must
-   match the order the X server uses for instantiating register regions ,
-   or must be passed in a new ioctl. */
-#define GAMMA_REG(reg)						   \
-	(2							   \
-	 + ((reg < 0x1000)					   \
-	    ? 0							   \
-	    : ((reg < 0x10000) ? 1 : ((reg < 0x11000) ? 2 : 3))))
-
-#define GAMMA_OFF(reg)						   \
-	((reg < 0x1000)						   \
-	 ? reg							   \
-	 : ((reg < 0x10000)					   \
-	    ? (reg - 0x1000)					   \
-	    : ((reg < 0x11000)					   \
-	       ? (reg - 0x10000)				   \
-	       : (reg - 0x11000))))
-
-#define GAMMA_BASE(reg)	 ((unsigned long)dev->maplist[GAMMA_REG(reg)]->handle)
-#define GAMMA_ADDR(reg)	 (GAMMA_BASE(reg) + GAMMA_OFF(reg))
-#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
-#define GAMMA_READ(reg)	 GAMMA_DEREF(reg)
-#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
-
-#define GAMMA_BROADCASTMASK    0x9378
-#define GAMMA_COMMANDINTENABLE 0x0c48
-#define GAMMA_DMAADDRESS       0x0028
-#define GAMMA_DMACOUNT	       0x0030
-#define GAMMA_FILTERMODE       0x8c00
-#define GAMMA_GCOMMANDINTFLAGS 0x0c50
-#define GAMMA_GCOMMANDMODE     0x0c40
-#define GAMMA_GCOMMANDSTATUS   0x0c60
-#define GAMMA_GDELAYTIMER      0x0c38
-#define GAMMA_GDMACONTROL      0x0060
-#define GAMMA_GINTENABLE       0x0808
-#define GAMMA_GINTFLAGS	       0x0810
-#define GAMMA_INFIFOSPACE      0x0018
-#define GAMMA_OUTFIFOWORDS     0x0020
-#define GAMMA_OUTPUTFIFO       0x2000
-#define GAMMA_SYNC	       0x8c40
-#define GAMMA_SYNC_TAG	       0x0188
-
 static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
 				      unsigned long length)
 {
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
 	GAMMA_WRITE(GAMMA_DMAADDRESS, virt_to_phys((void *)address));
 	while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
 		;
 	GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
 }
 
-static inline void gamma_dma_quiescent_single(drm_device_t *dev)
+void gamma_dma_quiescent_single(drm_device_t *dev)
 {
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
 	while (GAMMA_READ(GAMMA_DMACOUNT))
 		;
 	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
@@ -97,15 +62,18 @@
 
 	GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
 	GAMMA_WRITE(GAMMA_SYNC, 0);
-	
+
 	do {
 		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
 			;
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
 }
 
-static inline void gamma_dma_quiescent_dual(drm_device_t *dev)
+void gamma_dma_quiescent_dual(drm_device_t *dev)
 {
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
 	while (GAMMA_READ(GAMMA_DMACOUNT))
 		;
 	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
@@ -115,13 +83,13 @@
 
 	GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
 	GAMMA_WRITE(GAMMA_SYNC, 0);
-	
+
 				/* Read from first MX */
 	do {
 		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
 			;
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-	
+
 				/* Read from second MX */
 	do {
 		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
@@ -129,34 +97,39 @@
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
 }
 
-static inline void gamma_dma_ready(drm_device_t *dev)
+void gamma_dma_ready(drm_device_t *dev)
 {
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
 	while (GAMMA_READ(GAMMA_DMACOUNT))
 		;
 }
 
 static inline int gamma_dma_is_ready(drm_device_t *dev)
 {
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
 	return !GAMMA_READ(GAMMA_DMACOUNT);
 }
 
-static void gamma_dma_service(int irq, void *device, struct pt_regs *regs)
+void gamma_dma_service(int irq, void *device, struct pt_regs *regs)
 {
-	drm_device_t	 *dev = (drm_device_t *)device;
-	drm_device_dma_t *dma = dev->dma;
-	
-	atomic_inc(&dev->total_irq);
+	drm_device_t	    *dev      = (drm_device_t *)device;
+	drm_device_dma_t    *dma      = dev->dma;
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
+	atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
 	GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
 	GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
 	GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
 	if (gamma_dma_is_ready(dev)) {
 				/* Free previous buffer */
-		if (test_and_set_bit(0, &dev->dma_flag)) {
-			atomic_inc(&dma->total_missed_free);
-			return;
-		}
+		if (test_and_set_bit(0, &dev->dma_flag)) return;
 		if (dma->this_buffer) {
-			drm_free_buffer(dev, dma->this_buffer);
+			gamma_free_buffer(dev, dma->this_buffer);
 			dma->this_buffer = NULL;
 		}
 		clear_bit(0, &dev->dma_flag);
@@ -179,11 +152,8 @@
 	cycles_t	 dma_start, dma_stop;
 #endif
 
-	if (test_and_set_bit(0, &dev->dma_flag)) {
-		atomic_inc(&dma->total_missed_dma);
-		return -EBUSY;
-	}
-	
+	if (test_and_set_bit(0, &dev->dma_flag)) return -EBUSY;
+
 #if DRM_DMA_HISTOGRAM
 	dma_start = get_cycles();
 #endif
@@ -202,20 +172,20 @@
 		  buf->context, buf->idx, length);
 
 	if (buf->list == DRM_LIST_RECLAIM) {
-		drm_clear_next_buffer(dev);
-		drm_free_buffer(dev, buf);
+		gamma_clear_next_buffer(dev);
+		gamma_free_buffer(dev, buf);
 		clear_bit(0, &dev->dma_flag);
 		return -EINVAL;
 	}
 
 	if (!length) {
 		DRM_ERROR("0 length buffer\n");
-		drm_clear_next_buffer(dev);
-		drm_free_buffer(dev, buf);
+		gamma_clear_next_buffer(dev);
+		gamma_free_buffer(dev, buf);
 		clear_bit(0, &dev->dma_flag);
 		return 0;
 	}
-	
+
 	if (!gamma_dma_is_ready(dev)) {
 		clear_bit(0, &dev->dma_flag);
 		return -EBUSY;
@@ -228,9 +198,8 @@
 				  buf->idx, buf->pid);
 		}
 	} else {
-		if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock,
+		if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
 					      DRM_KERNEL_CONTEXT)) {
-			atomic_inc(&dma->total_missed_lock);
 			clear_bit(0, &dev->dma_flag);
 			return -EBUSY;
 		}
@@ -240,13 +209,14 @@
 	    && !(dev->queuelist[buf->context]->flags
 		 & _DRM_CONTEXT_PRESERVED)) {
 				/* PRE: dev->last_context != buf->context */
-		if (drm_context_switch(dev, dev->last_context, buf->context)) {
-			drm_clear_next_buffer(dev);
-			drm_free_buffer(dev, buf);
+		if (DRM(context_switch)(dev, dev->last_context,
+					buf->context)) {
+			DRM(clear_next_buffer)(dev);
+			DRM(free_buffer)(dev, buf);
 		}
 		retcode = -EBUSY;
 		goto cleanup;
-			
+
 				/* POST: we will wait for the context
 				   switch and will dispatch on a later call
 				   when dev->last_context == buf->context.
@@ -254,7 +224,7 @@
 				   TIME! */
 	}
 
-	drm_clear_next_buffer(dev);
+	gamma_clear_next_buffer(dev);
 	buf->pending	 = 1;
 	buf->waiting	 = 0;
 	buf->list	 = DRM_LIST_PEND;
@@ -263,14 +233,14 @@
 #endif
 
 	gamma_dma_dispatch(dev, address, length);
-	drm_free_buffer(dev, dma->this_buffer);
+	gamma_free_buffer(dev, dma->this_buffer);
 	dma->this_buffer = buf;
 
-	atomic_add(length, &dma->total_bytes);
-	atomic_inc(&dma->total_dmas);
+	atomic_inc(&dev->counts[7]); /* _DRM_STAT_DMA */
+	atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
 
 	if (!buf->while_locked && !dev->context_flag && !locked) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+		if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
 				  DRM_KERNEL_CONTEXT)) {
 			DRM_ERROR("\n");
 		}
@@ -281,18 +251,18 @@
 
 #if DRM_DMA_HISTOGRAM
 	dma_stop = get_cycles();
-	atomic_inc(&dev->histo.dma[drm_histogram_slot(dma_stop - dma_start)]);
+	atomic_inc(&dev->histo.dma[gamma_histogram_slot(dma_stop - dma_start)]);
 #endif
 
 	return retcode;
 }
 
-static void gamma_dma_schedule_timer_wrapper(unsigned long dev)
+static void gamma_dma_timer_bh(unsigned long dev)
 {
 	gamma_dma_schedule((drm_device_t *)dev, 0);
 }
 
-static void gamma_dma_schedule_tq_wrapper(void *dev)
+void gamma_dma_immediate_bh(void *dev)
 {
 	gamma_dma_schedule(dev, 0);
 }
@@ -313,10 +283,10 @@
 
 	if (test_and_set_bit(0, &dev->interrupt_flag)) {
 				/* Not reentrant */
-		atomic_inc(&dma->total_missed_sched);
+		atomic_inc(&dev->counts[10]); /* _DRM_STAT_MISSED */
 		return -EBUSY;
 	}
-	missed = atomic_read(&dma->total_missed_sched);
+	missed = atomic_read(&dev->counts[10]);
 
 #if DRM_DMA_HISTOGRAM
 	schedule_start = get_cycles();
@@ -333,23 +303,18 @@
 				   because the lock could not be obtained
 				   or the DMA engine wasn't ready.  Try
 				   again. */
-		atomic_inc(&dma->total_tried);
-		if (!(retcode = gamma_do_dma(dev, locked))) {
-			atomic_inc(&dma->total_hit);
-			++processed;
-		}
+		if (!(retcode = gamma_do_dma(dev, locked))) ++processed;
 	} else {
 		do {
-			next = drm_select_queue(dev,
-					     gamma_dma_schedule_timer_wrapper);
+			next = gamma_select_queue(dev, gamma_dma_timer_bh);
 			if (next >= 0) {
 				q   = dev->queuelist[next];
-				buf = drm_waitlist_get(&q->waitlist);
+				buf = gamma_waitlist_get(&q->waitlist);
 				dma->next_buffer = buf;
 				dma->next_queue	 = q;
 				if (buf && buf->list == DRM_LIST_RECLAIM) {
-					drm_clear_next_buffer(dev);
-					drm_free_buffer(dev, buf);
+					gamma_clear_next_buffer(dev);
+					gamma_free_buffer(dev, buf);
 				}
 			}
 		} while (next >= 0 && !dma->next_buffer);
@@ -361,21 +326,19 @@
 	}
 
 	if (--expire) {
-		if (missed != atomic_read(&dma->total_missed_sched)) {
-			atomic_inc(&dma->total_lost);
+		if (missed != atomic_read(&dev->counts[10])) {
 			if (gamma_dma_is_ready(dev)) goto again;
 		}
 		if (processed && gamma_dma_is_ready(dev)) {
-			atomic_inc(&dma->total_lost);
 			processed = 0;
 			goto again;
 		}
 	}
-	
+
 	clear_bit(0, &dev->interrupt_flag);
-	
+
 #if DRM_DMA_HISTOGRAM
-	atomic_inc(&dev->histo.schedule[drm_histogram_slot(get_cycles()
+	atomic_inc(&dev->histo.schedule[gamma_histogram_slot(get_cycles()
 							   - schedule_start)]);
 #endif
 	return retcode;
@@ -400,7 +363,7 @@
 		if (signal_pending(current)) return -EINTR;
 	}
 	if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
-		while (!drm_lock_take(&dev->lock.hw_lock->lock,
+		while (!gamma_lock_take(&dev->lock.hw_lock->lock,
 				      DRM_KERNEL_CONTEXT)) {
 			schedule();
 			if (signal_pending(current)) {
@@ -410,7 +373,6 @@
 		}
 		++must_free;
 	}
-	atomic_inc(&dma->total_prio);
 
 	for (i = 0; i < d->send_count; i++) {
 		idx = d->send_indices[i];
@@ -461,15 +423,15 @@
 			goto cleanup;
 		}
 		buf->pending = 1;
-		
+
 		if (dev->last_context != buf->context
 		    && !(dev->queuelist[buf->context]->flags
 			 & _DRM_CONTEXT_PRESERVED)) {
 			add_wait_queue(&dev->context_wait, &entry);
 			current->state = TASK_INTERRUPTIBLE;
 				/* PRE: dev->last_context != buf->context */
-			drm_context_switch(dev, dev->last_context,
-					   buf->context);
+			DRM(context_switch)(dev, dev->last_context,
+					    buf->context);
 				/* POST: we will wait for the context
 				   switch and will dispatch on a later call
 				   when dev->last_context == buf->context.
@@ -494,11 +456,11 @@
 		buf->time_dispatched = buf->time_queued;
 #endif
 		gamma_dma_dispatch(dev, address, length);
-		atomic_add(length, &dma->total_bytes);
-		atomic_inc(&dma->total_dmas);
-		
+		atomic_inc(&dev->counts[9]); /* _DRM_STAT_SPECIAL */
+		atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
+
 		if (last_buf) {
-			drm_free_buffer(dev, last_buf);
+			gamma_free_buffer(dev, last_buf);
 		}
 		last_buf = buf;
 	}
@@ -507,11 +469,11 @@
 cleanup:
 	if (last_buf) {
 		gamma_dma_ready(dev);
-		drm_free_buffer(dev, last_buf);
+		gamma_free_buffer(dev, last_buf);
 	}
-	
+
 	if (must_free && !dev->context_flag) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+		if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
 				  DRM_KERNEL_CONTEXT)) {
 			DRM_ERROR("\n");
 		}
@@ -531,15 +493,15 @@
 		last_buf = dma->buflist[d->send_indices[d->send_count-1]];
 		add_wait_queue(&last_buf->dma_wait, &entry);
 	}
-	
-	if ((retcode = drm_dma_enqueue(dev, d))) {
+
+	if ((retcode = gamma_dma_enqueue(dev, d))) {
 		if (d->flags & _DRM_DMA_BLOCK)
 			remove_wait_queue(&last_buf->dma_wait, &entry);
 		return retcode;
 	}
-	
+
 	gamma_dma_schedule(dev, 0);
-	
+
 	if (d->flags & _DRM_DMA_BLOCK) {
 		DRM_DEBUG("%d waiting\n", current->pid);
 		for (;;) {
@@ -558,7 +520,7 @@
 		if (!retcode
 		    || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
 			if (!waitqueue_active(&last_buf->dma_wait)) {
-				drm_free_buffer(dev, last_buf);
+				gamma_free_buffer(dev, last_buf);
 			}
 		}
 		if (retcode) {
@@ -587,19 +549,13 @@
 
 	if (copy_from_user(&d, (drm_dma_t *)arg, sizeof(d)))
 		return -EFAULT;
-	DRM_DEBUG("%d %d: %d send, %d req\n",
-		  current->pid, d.context, d.send_count, d.request_count);
 
-	if (d.context == DRM_KERNEL_CONTEXT || d.context >= dev->queue_slots) {
-		DRM_ERROR("Process %d using context %d\n",
-			  current->pid, d.context);
-		return -EINVAL;
-	}
 	if (d.send_count < 0 || d.send_count > dma->buf_count) {
 		DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
 			  current->pid, d.send_count, dma->buf_count);
 		return -EINVAL;
 	}
+
 	if (d.request_count < 0 || d.request_count > dma->buf_count) {
 		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
 			  current->pid, d.request_count, dma->buf_count);
@@ -609,14 +565,14 @@
 	if (d.send_count) {
 		if (d.flags & _DRM_DMA_PRIORITY)
 			retcode = gamma_dma_priority(dev, &d);
-		else 
+		else
 			retcode = gamma_dma_send_buffers(dev, &d);
 	}
 
 	d.granted_count = 0;
 
 	if (!retcode && d.request_count) {
-		retcode = drm_dma_get_buffers(dev, &d);
+		retcode = gamma_dma_get_buffers(dev, &d);
 	}
 
 	DRM_DEBUG("%d returning, granted = %d\n",
@@ -625,212 +581,4 @@
 		return -EFAULT;
 
 	return retcode;
-}
-
-int gamma_irq_install(drm_device_t *dev, int irq)
-{
-	int retcode;
-
-	if (!irq)     return -EINVAL;
-	
-	down(&dev->struct_sem);
-	if (dev->irq) {
-		up(&dev->struct_sem);
-		return -EBUSY;
-	}
-	dev->irq = irq;
-	up(&dev->struct_sem);
-	
-	DRM_DEBUG("%d\n", irq);
-
-	dev->context_flag     = 0;
-	dev->interrupt_flag   = 0;
-	dev->dma_flag	      = 0;
-	
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue  = NULL;
-	dev->dma->this_buffer = NULL;
-
-	INIT_LIST_HEAD(&dev->tq.list);
-	dev->tq.sync	      = 0;
-	dev->tq.routine	      = gamma_dma_schedule_tq_wrapper;
-	dev->tq.data	      = dev;
-
-
-				/* Before installing handler */
-	GAMMA_WRITE(GAMMA_GCOMMANDMODE, 0);
-	GAMMA_WRITE(GAMMA_GDMACONTROL, 0);
-	
-				/* Install handler */
-	if ((retcode = request_irq(dev->irq,
-				   gamma_dma_service,
-				   0,
-				   dev->devname,
-				   dev))) {
-		down(&dev->struct_sem);
-		dev->irq = 0;
-		up(&dev->struct_sem);
-		return retcode;
-	}
-
-				/* After installing handler */
-	GAMMA_WRITE(GAMMA_GINTENABLE,	    0x2001);
-	GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0x0008);
-	GAMMA_WRITE(GAMMA_GDELAYTIMER,	   0x39090);
-	
-	return 0;
-}
-
-int gamma_irq_uninstall(drm_device_t *dev)
-{
-	int irq;
-
-	down(&dev->struct_sem);
-	irq	 = dev->irq;
-	dev->irq = 0;
-	up(&dev->struct_sem);
-	
-	if (!irq) return -EINVAL;
-	
-	DRM_DEBUG("%d\n", irq);
-	
-	GAMMA_WRITE(GAMMA_GDELAYTIMER,	    0);
-	GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0);
-	GAMMA_WRITE(GAMMA_GINTENABLE,	    0);
-	free_irq(irq, dev);
-
-	return 0;
-}
-
-
-int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_file_t	*priv	= filp->private_data;
-	drm_device_t	*dev	= priv->dev;
-	drm_control_t	ctl;
-	int		retcode;
-	
-	if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
-		return -EFAULT;
-	
-	switch (ctl.func) {
-	case DRM_INST_HANDLER:
-		if ((retcode = gamma_irq_install(dev, ctl.irq)))
-			return retcode;
-		break;
-	case DRM_UNINST_HANDLER:
-		if ((retcode = gamma_irq_uninstall(dev)))
-			return retcode;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
-{
-	drm_file_t	  *priv	  = filp->private_data;
-	drm_device_t	  *dev	  = priv->dev;
-	DECLARE_WAITQUEUE(entry, current);
-	int		  ret	= 0;
-	drm_lock_t	  lock;
-	drm_queue_t	  *q;
-#if DRM_DMA_HISTOGRAM
-	cycles_t	  start;
-
-	dev->lck_start = start = get_cycles();
-#endif
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-		  lock.context, current->pid, dev->lock.hw_lock->lock,
-		  lock.flags);
-
-	if (lock.context < 0 || lock.context >= dev->queue_count)
-		return -EINVAL;
-	q = dev->queuelist[lock.context];
-	
-	ret = drm_flush_block_and_flush(dev, lock.context, lock.flags);
-
-	if (!ret) {
-		if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
-		    != lock.context) {
-			long j = jiffies - dev->lock.lock_time;
-
-			if (j > 0 && j <= DRM_LOCK_SLICE) {
-				/* Can't take lock if we just had it and
-				   there is contention. */
-				current->state = TASK_INTERRUPTIBLE;
-				schedule_timeout(j);
-			}
-		}
-		add_wait_queue(&dev->lock.lock_queue, &entry);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!dev->lock.hw_lock) {
-				/* Device has been unregistered */
-				ret = -EINTR;
-				break;
-			}
-			if (drm_lock_take(&dev->lock.hw_lock->lock,
-					  lock.context)) {
-				dev->lock.pid	    = current->pid;
-				dev->lock.lock_time = jiffies;
-				atomic_inc(&dev->total_locks);
-				atomic_inc(&q->total_locks);
-				break;	/* Got lock */
-			}
-			
-				/* Contention */
-			atomic_inc(&dev->total_sleeps);
-			schedule();
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&dev->lock.lock_queue, &entry);
-	}
-
-	drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */
-	
-	if (!ret) {
-		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;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-
-		if (lock.flags & _DRM_LOCK_READY)
-			gamma_dma_ready(dev);
-		if (lock.flags & _DRM_LOCK_QUIESCENT) {
-			if (gamma_found() == 1) {
-				gamma_dma_quiescent_single(dev);
-			} else {
-				gamma_dma_quiescent_dual(dev);
-			}
-		}
-	}
-	DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-
-#if DRM_DMA_HISTOGRAM
-	atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
-#endif
-	
-	return ret;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)