diff options
author | Jeff Hartmann <jhartmann@valinux.com> | 2000-02-17 21:26:49 +0000 |
---|---|---|
committer | Jeff Hartmann <jhartmann@valinux.com> | 2000-02-17 21:26:49 +0000 |
commit | e1f5452b77d087aa84482e015c42f9eda9cd0f7b (patch) | |
tree | 55a77ebcafab331179fedcc19bc023be628390a7 | |
parent | 71f5f1de26acc17c736ee90247504818792bdf97 (diff) |
Multiple outstanding dma requests and no queueing for the i810
-rw-r--r-- | linux-core/i810_dma.c | 851 | ||||
-rw-r--r-- | linux-core/i810_drv.c | 91 | ||||
-rw-r--r-- | linux-core/i810_drv.h | 8 | ||||
-rw-r--r-- | linux/Makefile.linux | 333 | ||||
-rw-r--r-- | linux/i810_clear.c | 217 | ||||
-rw-r--r-- | linux/i810_context.c | 44 | ||||
-rw-r--r-- | linux/i810_dma.c | 851 | ||||
-rw-r--r-- | linux/i810_dma.h | 6 | ||||
-rw-r--r-- | linux/i810_drm_public.h | 16 | ||||
-rw-r--r-- | linux/i810_drv.c | 91 | ||||
-rw-r--r-- | linux/i810_drv.h | 8 | ||||
-rw-r--r-- | linux/mga_dma.c | 1 |
12 files changed, 964 insertions, 1553 deletions
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c index 7b0e4475..56b99850 100644 --- a/linux-core/i810_dma.c +++ b/linux-core/i810_dma.c @@ -40,6 +40,9 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/time.h> /* For do_gettimeofday */ +#define I810_BUF_FREE 1 +#define I810_BUF_USED 0 + #define I810_REG(reg) 2 #define I810_BASE(reg) ((unsigned long) \ dev->maplist[I810_REG(reg)]->handle) @@ -53,10 +56,9 @@ #define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; - #define BEGIN_LP_RING(n) do { \ if (I810_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ + printk("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ if (dev_priv->ring.space < n*4) i810_wait_ring(dev, n*4, 0); \ dev_priv->ring.space -= n*4; \ outring = dev_priv->ring.tail; \ @@ -65,18 +67,115 @@ } while (0) #define ADVANCE_LP_RING() do { \ - if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + if (I810_VERBOSE) printk("ADVANCE_LP_RING\n"); \ dev_priv->ring.tail = outring; \ I810_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) #define OUT_RING(n) do { \ - if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + if (I810_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \ *(volatile unsigned int *)(virt + outring) = n; \ outring += 4; \ outring &= ringmask; \ } while (0); +static inline void i810_print_status_page(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + drm_i810_private_t *dev_priv = dev->dev_private; + u32 *temp = (u32 *)dev_priv->hw_status_page; + int i; + + printk( "hw_status: Interrupt Status : %x\n", temp[0]); + printk( "hw_status: LpRing Head ptr : %x\n", temp[1]); + printk( "hw_status: IRing Head ptr : %x\n", temp[2]); + printk( "hw_status: Reserved : %x\n", temp[3]); + printk( "hw_status: Driver Counter : %d\n", temp[5]); + for(i = 6; i < dma->buf_count + 6; i++) { + printk( "buffer status idx : %d used: %d\n", i - 6, temp[i]); + } +} + +static drm_buf_t *i810_freelist_get(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i; + int used; + + /* Linear search might not be the best solution */ + +#if 0 + i810_print_status_page(dev); +#endif + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + /* In use is already a pointer */ +#if 0 + printk("idx : %d in_use : %d\n", i, *buf_priv->in_use); +#endif + used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, + I810_BUF_USED); +#if 0 + printk("used : %d\n", used); +#endif + if(used == I810_BUF_FREE) { +#if 0 + printk("Got buffer\n"); +#endif + return buf; + } + } +#if 0 + printk("Didn't get buffer\n"); +#endif + return NULL; +} + +/* This should only be called if the buffer is not sent to the hardware + * yet, the hardware updates in use for us once its on the ring buffer. + */ + +static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf) +{ + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + int used; + + /* In use is already a pointer */ +#if 0 + i810_print_status_page(dev); +#endif + used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE); + if(used != I810_BUF_USED) { + DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx); + return -EINVAL; + } + + return 0; +} + +static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) +{ + int i; + drm_buf_t *buf; + + for (i = d->granted_count; i < d->request_count; i++) { + buf = i810_freelist_get(dev); + if (!buf) break; + buf->pid = current->pid; + copy_to_user_ret(&d->request_indices[i], + &buf->idx, + sizeof(buf->idx), + -EFAULT); + copy_to_user_ret(&d->request_sizes[i], + &buf->total, + sizeof(buf->total), + -EFAULT); + ++d->granted_count; + } + return 0; +} + static unsigned long i810_alloc_page(drm_device_t *dev) { unsigned long address; @@ -103,68 +202,8 @@ static void i810_free_page(drm_device_t *dev, unsigned long page) return; } -static int i810_alloc_kernel_queue(drm_device_t *dev) -{ - drm_queue_t *queue = NULL; - /* Allocate a new queue */ - down(&dev->struct_sem); - - if(dev->queue_count != 0) { - /* Reseting the kernel context here is not - * a race, since it can only happen when that - * queue is empty. - */ - queue = dev->queuelist[DRM_KERNEL_CONTEXT]; - DRM_DEBUG("Kernel queue already allocated\n"); - } else { - queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES); - if(!queue) { - up(&dev->struct_sem); - DRM_DEBUG("out of memory\n"); - return -ENOMEM; - } - ++dev->queue_count; - dev->queuelist = drm_alloc(sizeof(*dev->queuelist), - DRM_MEM_QUEUES); - if(!dev->queuelist) { - up(&dev->struct_sem); - drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES); - DRM_DEBUG("out of memory\n"); - return -ENOMEM; - } - } - - memset(queue, 0, sizeof(*queue)); - atomic_set(&queue->use_count, 1); - atomic_set(&queue->finalization, 0); - atomic_set(&queue->block_count, 0); - atomic_set(&queue->block_read, 0); - atomic_set(&queue->block_write, 0); - atomic_set(&queue->total_queued, 0); - atomic_set(&queue->total_flushed, 0); - atomic_set(&queue->total_locks, 0); - - init_waitqueue_head(&queue->write_queue); - init_waitqueue_head(&queue->read_queue); - init_waitqueue_head(&queue->flush_queue); - - queue->flags = 0; - - drm_waitlist_create(&queue->waitlist, dev->dma->buf_count); - - dev->queue_slots = 1; - dev->queuelist[DRM_KERNEL_CONTEXT] = queue; - dev->queue_count--; - - up(&dev->struct_sem); - if (I810_VERBOSE) DRM_DEBUG("%d (new)\n", dev->queue_count - 1); - return DRM_KERNEL_CONTEXT; -} - static int i810_dma_cleanup(drm_device_t *dev) { - if (I810_VERBOSE) DRM_DEBUG("i810_dma_cleanup\n"); - if(dev->dev_private) { drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; @@ -201,9 +240,7 @@ static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis) int curTime = 0; if (timeout_millis == 0) timeout_millis = 3000; - - if (I810_VERBOSE) DRM_DEBUG( "i810_wait_ring %d\n", n); - + while (ring->space < n) { int i; @@ -233,49 +270,40 @@ static void i810_kernel_lost_context(drm_device_t *dev) { drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_ring_buffer_t *ring = &(dev_priv->ring); - - if (0) DRM_DEBUG("i810_kernel_lost_context, old ring (%x,%x)\n", - ring->head, ring->tail); - + ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->tail = I810_READ(LP_RING + RING_TAIL); ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; - - if (0) DRM_DEBUG("new ring (%x,%x)\n", ring->head, ring->tail); } -static inline void i810_ring_write_status(drm_device_t *dev) +static int i810_freelist_init(drm_device_t *dev) { - drm_i810_private_t *dev_priv = dev->dev_private; - RING_LOCALS; + drm_device_dma_t *dma = dev->dma; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u8 *hw_status = (u8 *)dev_priv->hw_status_page; + int i; + int my_idx = 24; - i810_kernel_lost_context(dev); - dev_priv->counter++; - - BEGIN_LP_RING(6); - OUT_RING(CMD_REPORT_HEAD); - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(5 * sizeof(unsigned long)); - OUT_RING(dev_priv->counter); - OUT_RING(GFX_OP_BREAKPOINT_INTERRUPT); - OUT_RING(0); - ADVANCE_LP_RING(); - - /* Wait for ring to complete */ - i810_wait_ring(dev, dev_priv->ring.Size - 8, 0); -} - -static inline void i810_print_status_page(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - u32 *temp = (u32 *)dev_priv->hw_status_page; + if(dma->buf_count > 1019) { + /* Not enough space in the status page for the freelist */ + return -EINVAL; + } - DRM_DEBUG( "hw_status: Interrupt Status : %x\n", temp[0]); - DRM_DEBUG( "hw_status: LpRing Head ptr : %x\n", temp[1]); - DRM_DEBUG( "hw_status: IRing Head ptr : %x\n", temp[2]); - DRM_DEBUG( "hw_status: Reserved : %x\n", temp[3]); - DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]); + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + + buf_priv->in_use = hw_status + my_idx; + printk("buf_priv->in_use : %p\n", buf_priv->in_use); + *buf_priv->in_use = I810_BUF_FREE; + buf_priv->my_use_idx = my_idx; + my_idx += 4; + } +#if 0 + i810_print_status_page(dev); +#endif + return 0; } static int i810_dma_initialize(drm_device_t *dev, @@ -284,7 +312,6 @@ static int i810_dma_initialize(drm_device_t *dev, { drm_map_t *sarea_map; - DRM_DEBUG( "i810_dma_init\n"); dev->dev_private = (void *) dev_priv; memset(dev_priv, 0, sizeof(drm_i810_private_t)); @@ -295,12 +322,6 @@ static int i810_dma_initialize(drm_device_t *dev, return -EINVAL; } - if (i810_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) { - i810_dma_cleanup(dev); - DRM_ERROR("Kernel context queue not present\n"); - return -ENOMEM; - } - dev_priv->ring_map_idx = init->ring_map_idx; dev_priv->buffer_map_idx = init->buffer_map_idx; sarea_map = dev->maplist[0]; @@ -308,9 +329,8 @@ static int i810_dma_initialize(drm_device_t *dev, ((u8 *)sarea_map->handle + init->sarea_priv_offset); - atomic_set(&dev_priv->pending_bufs, 0); - atomic_set(&dev_priv->dispatch_lock, 0); - atomic_set(&dev_priv->in_flush, 0); + atomic_set(&dev_priv->flush_done, 0); + init_waitqueue_head(&dev_priv->flush_queue); dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; @@ -339,13 +359,14 @@ static int i810_dma_initialize(drm_device_t *dev, I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); DRM_DEBUG("Enabled hardware status page\n"); -#if 0 - DRM_DEBUG("Doing first ring buffer write\n"); - i810_ring_write_status(dev); - DRM_DEBUG("First ring write succeeded\n"); - i810_print_status_page(dev); - DRM_DEBUG("Status page dump succeeded\n"); -#endif + + /* Now we need to init our freelist */ + if(i810_freelist_init(dev) != 0) { + i810_dma_cleanup(dev); + DRM_ERROR("Not enough space in the status page for" + " the freelist\n"); + return -ENOMEM; + } return 0; } @@ -379,18 +400,16 @@ int i810_dma_init(struct inode *inode, struct file *filp, return retcode; } -static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf) +static inline void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf) { - drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; unsigned long address = (unsigned long)buf->bus_address; unsigned long start = address - dev->agp->base; int length = buf->used; RING_LOCALS; - sarea_priv->last_dispatch = buf_priv->age; - dev_priv->counter++; + dev_priv->counter++; DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); DRM_DEBUG( "i810_dma_dispatch\n"); DRM_DEBUG( "start : 0x%lx\n", start); @@ -398,44 +417,41 @@ static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf) DRM_DEBUG( "start + length - 4 : 0x%lx\n", start + length - 4); i810_kernel_lost_context(dev); - - BEGIN_LP_RING(8); + BEGIN_LP_RING(10); OUT_RING( CMD_OP_BATCH_BUFFER ); OUT_RING( start | BB1_PROTECTED ); OUT_RING( start + length - 4 ); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( 20 ); OUT_RING( dev_priv->counter ); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( buf_priv->my_use_idx ); + OUT_RING( I810_BUF_FREE ); OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT ); - ADVANCE_LP_RING(); - -/* i810_print_status_page(dev); */ + ADVANCE_LP_RING(); } - - - - -static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) +static inline void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) { drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_buf_t *real_buf = dev->dma->buflist[ buf_priv->vertex_real_idx ]; + drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + xf86drmClipRectRec *box = sarea_priv->boxes; + int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)real_buf->bus_address; unsigned long start = address - dev->agp->base; - xf86drmClipRectRec *box = buf_priv->boxes; int length = buf->used; int i = 0; RING_LOCALS; - - if (0) - printk("dispatch vertex %d addr 0x%lx, length 0x%x nbox %d\n", - buf->idx, address, length, buf_priv->nbox); - sarea_priv->last_dispatch = buf_priv->age; - dev_priv->counter++; + + if(nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; + + DRM_DEBUG("dispatch vertex addr 0x%lx, length 0x%x nbox %d\n", + address, length, buf_priv->nbox); + + dev_priv->counter++; DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); DRM_DEBUG( "i810_dma_dispatch\n"); DRM_DEBUG( "start : %lx\n", start); @@ -445,7 +461,7 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) if (!buf_priv->vertex_discard) { do { - if (i < buf_priv->nbox) { + if (i < nbox) { BEGIN_LP_RING(4); OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | SC_ENABLE ); @@ -462,321 +478,54 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) OUT_RING( 0 ); ADVANCE_LP_RING(); - } while (++i < buf_priv->nbox); + } while (++i < nbox); } - BEGIN_LP_RING( 6 ); + BEGIN_LP_RING(8); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( 20 ); OUT_RING( dev_priv->counter ); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( buf_priv->my_use_idx ); + OUT_RING( I810_BUF_FREE ); OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT ); OUT_RING( 0 ); ADVANCE_LP_RING(); } - - - - static inline void i810_dma_quiescent(drm_device_t *dev) { +#if 0 + /* Not written yet */ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - - -/* DRM_DEBUG( "i810_dma_quiescent\n"); */ - while(1) { - atomic_inc(&dev_priv->dispatch_lock); - if(atomic_read(&dev_priv->dispatch_lock) == 1) { - break; - } else { - atomic_dec(&dev_priv->dispatch_lock); - } - } - atomic_dec(&dev_priv->dispatch_lock); -} - -static inline void i810_dma_ready(drm_device_t *dev) -{ - i810_dma_quiescent(dev); -/* DRM_DEBUG( "i810_dma_ready\n"); */ -} - -static inline int i810_dma_is_ready(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; -/* DRM_DEBUG( "i810_dma_is_ready\n"); */ - atomic_inc(&dev_priv->dispatch_lock); - if(atomic_read(&dev_priv->dispatch_lock) == 1) { - /* We got the lock */ - return 1; - } else { - atomic_dec(&dev_priv->dispatch_lock); - return 0; - } -} - -static inline int i810_dma_is_ready_no_hold(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - atomic_inc(&dev_priv->dispatch_lock); - if(atomic_read(&dev_priv->dispatch_lock) == 1) { - /* We got the lock, but free it */ - atomic_dec(&dev_priv->dispatch_lock); - return 1; - } else { - atomic_dec(&dev_priv->dispatch_lock); - return 0; - } +#endif } +/* Interrupts are only for flushing */ static void i810_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; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u16 temp; atomic_inc(&dev->total_irq); -/* DRM_DEBUG("Interrupt Handler\n"); */ -/* i810_print_status_page(dev); */ temp = I810_READ16(I810REG_INT_IDENTITY_R); temp = temp & ~(0x6000); if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, temp); /* Clear all interrupts */ - atomic_dec(&dev_priv->dispatch_lock); - - /* Free previous buffer */ - if (test_and_set_bit(0, &dev->dma_flag)) { - atomic_inc(&dma->total_missed_free); - return; - } - if (dma->this_buffer) { - drm_free_buffer(dev, dma->this_buffer); - dma->this_buffer = NULL; - } - clear_bit(0, &dev->dma_flag); - /* Dispatch new buffer */ queue_task(&dev->tq, &tq_immediate); mark_bh(IMMEDIATE_BH); } -/* Only called by i810_dma_schedule. */ -static int i810_do_dma(drm_device_t *dev, int locked) +static void i810_dma_task_queue(void *device) { - drm_buf_t *buf; - int retcode = 0; - drm_device_dma_t *dma = dev->dma; + drm_device_t *dev = (drm_device_t *) device; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - drm_i810_buf_priv_t *buf_priv; - - - DRM_DEBUG("i810_do_dma\n"); - if (test_and_set_bit(0, &dev->dma_flag)) { - atomic_inc(&dma->total_missed_dma); - return -EBUSY; - } - - if (!dma->next_buffer) { - DRM_ERROR("No next_buffer\n"); - clear_bit(0, &dev->dma_flag); - return -EINVAL; - } - - buf = dma->next_buffer; - - DRM_DEBUG("context %d, buffer %d\n", buf->context, buf->idx); - - if (buf->list == DRM_LIST_RECLAIM) { - drm_clear_next_buffer(dev); - drm_free_buffer(dev, buf); - atomic_dec(&dev_priv->pending_bufs); - DRM_DEBUG("i810_do_dma: pending %d\n",atomic_read( &dev_priv->pending_bufs )); - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - clear_bit(0, &dev->dma_flag); - DRM_DEBUG("RECLIAM\n"); - - return -EINVAL; - } - - if (!buf->used) { - DRM_ERROR("0 length buffer\n"); - drm_clear_next_buffer(dev); - drm_free_buffer(dev, buf); - clear_bit(0, &dev->dma_flag); - DRM_DEBUG("NOT USED\n"); - return 0; - } - - if (i810_dma_is_ready(dev) == 0) { - clear_bit(0, &dev->dma_flag); - DRM_DEBUG("NOT READY\n"); - return -EBUSY; - } - - - DRM_DEBUG("--inflush: %d\n", atomic_read(&dev_priv->in_flush)); - - if ( !locked && - !atomic_read(&dev_priv->in_flush) && - !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) - { - atomic_inc(&dma->total_missed_lock); - clear_bit(0, &dev->dma_flag); - atomic_dec(&dev_priv->dispatch_lock); - DRM_DEBUG("NOT LOCKED\n"); - return -EBUSY; - } - - dma->next_queue = dev->queuelist[DRM_KERNEL_CONTEXT]; - drm_clear_next_buffer(dev); - buf->pending = 1; - buf->waiting = 0; - buf->list = DRM_LIST_PEND; - - buf_priv = buf->dev_private; - - - - - - DRM_DEBUG("i810_do_dma - type %d\n", buf_priv->dma_type); - - switch (buf_priv->dma_type) { - case I810_DMA_GENERAL: - i810_dma_dispatch_general( dev, buf ); - break; - case I810_DMA_VERTEX: - i810_dma_dispatch_vertex( dev, buf ); - break; - default: - DRM_DEBUG("bad buffer type %x in dispatch\n", buf_priv->dma_type); - break; - } - - DRM_DEBUG("DONE\n"); - - atomic_dec(&dev_priv->pending_bufs); - - if(dma->this_buffer) { - drm_free_buffer(dev, dma->this_buffer); - } - - dma->this_buffer = buf; - - atomic_add(buf->used, &dma->total_bytes); - atomic_inc(&dma->total_dmas); - - DRM_DEBUG("inflush: %d\n", atomic_read(&dev_priv->in_flush)); - if (!locked && - !atomic_read(&dev_priv->in_flush)) { - if (drm_lock_free(dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT)) { - DRM_ERROR("\n"); - } - } - - clear_bit(0, &dev->dma_flag); - - DRM_DEBUG("i810_do_dma2: pending %d\n",atomic_read( &dev_priv->pending_bufs )); - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - - /* We hold the dispatch lock until the interrupt handler - * frees it - */ - return retcode; -} - -static void i810_dma_schedule_tq_wrapper(void *dev) -{ - drm_i810_private_t *dev_priv = ((drm_device_t *)dev)->dev_private; - i810_dma_schedule(dev, atomic_read(&dev_priv->in_flush)); -} - -int i810_dma_schedule(drm_device_t *dev, int locked) -{ - drm_queue_t *q; - drm_buf_t *buf; - int retcode = 0; - int processed = 0; - int missed; - int expire = 20; - drm_device_dma_t *dma = dev->dma; - drm_i810_private_t *dev_priv = dev->dev_private; - - - DRM_DEBUG("i810_dma_schedule\n"); - - if (test_and_set_bit(0, &dev->interrupt_flag)) { - /* Not reentrant */ - atomic_inc(&dma->total_missed_sched); - return -EBUSY; - } - missed = atomic_read(&dma->total_missed_sched); - -again: - /* There is only one queue: - */ - if (!dma->next_buffer && DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) { - q = dev->queuelist[DRM_KERNEL_CONTEXT]; - buf = drm_waitlist_get(&q->waitlist); - dma->next_buffer = buf; - dma->next_queue = q; - if (buf && buf->list == DRM_LIST_RECLAIM) { - DRM_DEBUG("reclaiming in i810_dma_schedule\n"); - drm_clear_next_buffer(dev); - drm_free_buffer(dev, buf); - atomic_dec(&dev_priv->pending_bufs); - DRM_DEBUG("fred pending bufs : %d\n", - atomic_read(&dev_priv->pending_bufs)); - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - dma->next_buffer = NULL; - goto again; - } - } - - if (dma->next_buffer) { - if (!(retcode = i810_do_dma(dev, locked))) - ++processed; - } - DRM_DEBUG("ixxx810_do_dma: pending %d\n",atomic_read( &dev_priv->pending_bufs )); - - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - - - /* Try again if we succesfully dispatched a buffer, or if someone - * tried to schedule while we were working. - */ - if (--expire) { - if (missed != atomic_read(&dma->total_missed_sched)) { - atomic_inc(&dma->total_lost); - if (i810_dma_is_ready_no_hold(dev)) - goto again; - } - - if (processed && i810_dma_is_ready_no_hold(dev)) { - atomic_inc(&dma->total_lost); - processed = 0; - goto again; - } - } - - clear_bit(0, &dev->interrupt_flag); - - return retcode; + atomic_set(&dev_priv->flush_done, 1); + wake_up_interruptible(&dev_priv->flush_queue); } - int i810_irq_install(drm_device_t *dev, int irq) { int retcode; @@ -793,6 +542,7 @@ int i810_irq_install(drm_device_t *dev, int irq) up(&dev->struct_sem); DRM_DEBUG( "Interrupt Install : %d\n", irq); + DRM_DEBUG("%d\n", irq); dev->context_flag = 0; dev->interrupt_flag = 0; @@ -804,7 +554,7 @@ int i810_irq_install(drm_device_t *dev, int irq) dev->tq.next = NULL; dev->tq.sync = 0; - dev->tq.routine = i810_dma_schedule_tq_wrapper; + dev->tq.routine = i810_dma_task_queue; dev->tq.data = dev; /* Before installing handler */ @@ -832,9 +582,9 @@ int i810_irq_install(drm_device_t *dev, int irq) } temp = I810_READ16(I810REG_INT_ENABLE_R); temp = temp & 0x6000; - temp = temp | 0x0001; + temp = temp | 0x0003; I810_WRITE16(I810REG_INT_ENABLE_R, - 0x0001); /* Enable bp interrupts */ + temp); /* Enable bp & user interrupts */ return 0; } @@ -851,6 +601,9 @@ int i810_irq_uninstall(drm_device_t *dev) if (!irq) return -EINVAL; DRM_DEBUG( "Interrupt UnInstall: %d\n", irq); + + + DRM_DEBUG("%d\n", irq); temp = I810_READ16(I810REG_INT_IDENTITY_R); temp = temp & ~(0x6000); @@ -875,7 +628,7 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_control_t ctl; int retcode; -/* DRM_DEBUG( "i810_control\n"); */ + DRM_DEBUG( "i810_control\n"); copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); @@ -894,44 +647,85 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int i810_flush_queue(drm_device_t *dev) +static inline void i810_dma_emit_flush(drm_device_t *dev) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + i810_kernel_lost_context(dev); + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); +#if 1 + OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT ); +#else + OUT_RING( GFX_OP_USER_INTERRUPT ); +#endif + ADVANCE_LP_RING(); +} + +static int i810_flush_queue(drm_device_t *dev) { DECLARE_WAITQUEUE(entry, current); - drm_queue_t *q = dev->queuelist[DRM_KERNEL_CONTEXT]; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; int ret = 0; - - DRM_DEBUG("i810_flush_queue\n"); - DRM_DEBUG("pending_bufs : %d\n", atomic_read(&dev_priv->pending_bufs)); - if(atomic_read(&dev_priv->pending_bufs) != 0) { - DRM_DEBUG("got to flush\n"); - current->state = TASK_INTERRUPTIBLE; - add_wait_queue(&q->flush_queue, &entry); - for (;;) { - if (!atomic_read(&dev_priv->pending_bufs)) break; - DRM_DEBUG("Calling schedule from flush_queue : %d\n", - atomic_read(&dev_priv->pending_bufs)); - i810_dma_schedule(dev, 0); + +#if 0 + printk("i810_flush_queue\n"); +#endif + if(dev_priv == NULL) { + return 0; + } + atomic_set(&dev_priv->flush_done, 0); +#if 0 + printk("got to flush\n"); +#endif + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&dev_priv->flush_queue, &entry); + for (;;) { + i810_dma_emit_flush(dev); + if (atomic_read(&dev_priv->flush_done) == 1) break; schedule_timeout(DRM_LOCK_SLICE); if (signal_pending(current)) { ret = -EINTR; /* Can't restart */ break; } } - DRM_DEBUG("Exited out of schedule from flush_queue\n"); - current->state = TASK_RUNNING; - remove_wait_queue(&q->flush_queue, &entry); - } + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->flush_queue, &entry); return ret; } +/* Must be called with the lock held */ +void i810_reclaim_buffers(drm_device_t *dev, pid_t pid) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + if (!dma) return; + if(dev->dev_private == NULL) return; + + i810_flush_queue(dev); + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + + if (buf->pid == pid) { + /* Only buffers that need to get reclaimed ever + * get set to free */ + if(buf_priv == NULL) return; + cmpxchg(buf_priv->in_use, + I810_BUF_USED, I810_BUF_FREE); + } + } +} + int i810_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; - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; DECLARE_WAITQUEUE(entry, current); int ret = 0; @@ -952,11 +746,21 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, if (lock.context < 0) { return -EINVAL; } - /* Only one queue: */ 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 (;;) { if (!dev->lock.hw_lock) { @@ -975,7 +779,9 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); current->state = TASK_INTERRUPTIBLE; +#if 0 current->policy |= SCHED_YIELD; +#endif DRM_DEBUG("Calling lock schedule\n"); schedule(); if (signal_pending(current)) { @@ -990,10 +796,8 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, if (!ret) { if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); - atomic_set(&dev_priv->in_flush, 1); i810_flush_queue(dev); i810_dma_quiescent(dev); - atomic_set(&dev_priv->in_flush, 0); } } DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); @@ -1005,12 +809,153 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; DRM_DEBUG("i810_flush_ioctl\n"); - atomic_set(&dev_priv->in_flush, 1); i810_flush_queue(dev); i810_dma_quiescent(dev); - atomic_set(&dev_priv->in_flush, 0); return 0; } + +static int i810DmaGeneral(drm_device_t *dev, drm_i810_general_t *args) +{ + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf = dma->buflist[ args->idx ]; + + buf->used = args->used; + + DRM_DEBUG("i810DmaGeneral idx %d used %d\n", args->idx, buf->used); + + if (!buf->used) { + DRM_ERROR("0 length buffer\n"); + i810_freelist_put(dev, buf); + return 0; + } + + i810_dma_dispatch_general( dev, buf ); + atomic_add(buf->used, &dma->total_bytes); + atomic_inc(&dma->total_dmas); + + return 0; +} + +static int i810DmaVertex(drm_device_t *dev, drm_i810_vertex_t *args) +{ + drm_device_dma_t *dma = dev->dma; + drm_i810_buf_priv_t *buf_priv; + drm_buf_t *buf; + + + buf = dma->buflist[ args->idx ]; + buf->used = args->real_used; + + DRM_DEBUG("i810DmaVertex idx %d used %d\n", args->idx, buf->used); + + buf_priv = buf->dev_private; + buf_priv->vertex_real_idx = args->real_idx; + buf_priv->vertex_discard = args->discard; + + i810_dma_dispatch_vertex( dev, buf); + atomic_add(buf->used, &dma->total_bytes); + atomic_inc(&dma->total_dmas); + return 0; +} + +int i810_dma_general(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_i810_general_t general; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + + int retcode = 0; + + copy_from_user_ret(&general, (drm_i810_general_t *)arg, sizeof(general), + -EFAULT); + + DRM_DEBUG("i810 dma general idx %d used %d\n", + general.idx, general.used); + + retcode = i810DmaGeneral(dev, &general); + sarea_priv->last_dispatch = (int) hw_status[5]; + + return retcode; +} + +int i810_dma_vertex(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + drm_i810_vertex_t vertex; + int retcode = 0; + + copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex), + -EFAULT); + + DRM_DEBUG("i810 dma vertex, idx %d used %d real_idx %d discard %d\n", + vertex.idx, vertex.real_used, vertex.real_idx, + vertex.discard); + + retcode = i810DmaVertex(dev, &vertex); + sarea_priv->last_dispatch = (int) hw_status[5]; + + return retcode; + +} + +int i810_dma(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_device_dma_t *dma = dev->dma; + int retcode = 0; + drm_dma_t d; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + + + copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); + DRM_DEBUG("%d %d: %d send, %d req\n", + current->pid, d.context, d.send_count, d.request_count); + + /* Please don't send us buffers. + */ + if (d.send_count != 0) { + DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", + current->pid, d.send_count); + return -EINVAL; + } + + /* We'll send you buffers. + */ + 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); + return -EINVAL; + } + + d.granted_count = 0; + + if (!retcode && d.request_count) { + retcode = i810_dma_get_buffers(dev, &d); + } + + DRM_DEBUG("i810_dma: %d returning, granted = %d\n", + current->pid, d.granted_count); + + copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); + sarea_priv->last_dispatch = (int) hw_status[5]; + + return retcode; +} diff --git a/linux-core/i810_drv.c b/linux-core/i810_drv.c index 49a3c995..85a5b05e 100644 --- a/linux-core/i810_drv.c +++ b/linux-core/i810_drv.c @@ -585,24 +585,82 @@ int i810_release(struct inode *inode, struct file *filp) drm_device_t *dev = priv->dev; int retcode = 0; - DRM_DEBUG("open_count = %d\n", dev->open_count); - if (!(retcode = drm_release(inode, filp))) { - MOD_DEC_USE_COUNT; - atomic_inc(&dev->total_close); - 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); - spin_unlock(&dev->count_lock); - return -EBUSY; + DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", + current->pid, dev->device, dev->open_count); + + if (_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) + && dev->lock.pid == current->pid) { + i810_reclaim_buffers(dev, priv->pid); + DRM_ERROR("Process %d dead, freeing lock for context %d\n", + current->pid, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + drm_lock_free(dev, + &dev->lock.hw_lock->lock, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + + /* FIXME: may require heavy-handed reset of + hardware at this point, possibly + processed via a callback to the X + server. */ + } else { + /* The lock is required to reclaim buffers */ + DECLARE_WAITQUEUE(entry, current); + add_wait_queue(&dev->lock.lock_queue, &entry); + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + retcode = -EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + dev->lock.pid = priv->pid; + dev->lock.lock_time = jiffies; + atomic_inc(&dev->total_locks); + break; /* Got lock */ + } + /* Contention */ + atomic_inc(&dev->total_sleeps); + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (signal_pending(current)) { + retcode = -ERESTARTSYS; + break; } - spin_unlock(&dev->count_lock); - return i810_takedown(dev); } - spin_unlock(&dev->count_lock); + current->state = TASK_RUNNING; + remove_wait_queue(&dev->lock.lock_queue, &entry); + if(!retcode) { + i810_reclaim_buffers(dev, priv->pid); + drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT); + } + } + drm_fasync(-1, filp, 0); + + down(&dev->struct_sem); + if (priv->prev) priv->prev->next = priv->next; + else dev->file_first = priv->next; + if (priv->next) priv->next->prev = priv->prev; + else dev->file_last = priv->prev; + up(&dev->struct_sem); + + drm_free(priv, sizeof(*priv), DRM_MEM_FILES); + MOD_DEC_USE_COUNT; + atomic_inc(&dev->total_close); + 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); + spin_unlock(&dev->count_lock); + return -EBUSY; + } + spin_unlock(&dev->count_lock); + return i810_takedown(dev); } + spin_unlock(&dev->count_lock); return retcode; } @@ -667,8 +725,7 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, atomic_inc(&dev->total_unlocks); if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) atomic_inc(&dev->total_contends); - drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); - i810_dma_schedule(dev, 1); + drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); if (!dev->context_flag) { if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { diff --git a/linux-core/i810_drv.h b/linux-core/i810_drv.h index 2cbcc061..36d477a4 100644 --- a/linux-core/i810_drv.h +++ b/linux-core/i810_drv.h @@ -54,10 +54,8 @@ typedef struct drm_i810_private { unsigned long hw_status_page; unsigned long counter; - atomic_t dispatch_lock; - atomic_t pending_bufs; - atomic_t in_flush; - + atomic_t flush_done; + wait_queue_head_t flush_queue; /* Processes waiting until flush */ } drm_i810_private_t; /* i810_drv.c */ @@ -86,6 +84,8 @@ extern int i810_dma_init(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_flush_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid); + /* i810_bufs.c */ extern int i810_addbufs(struct inode *inode, struct file *filp, diff --git a/linux/Makefile.linux b/linux/Makefile.linux index 85931ec5..41f7a7db 100644 --- a/linux/Makefile.linux +++ b/linux/Makefile.linux @@ -78,9 +78,8 @@ MGAHEADERS= mga_drv.h mga_drm_public.h $(DRMHEADERS) R128OBJS= r128_drv.o r128_context.o R128HEADERS= r128_drv.h $(DRMHEADERS) -I810OBJS= i810_drv.o i810_dma.o i810_bufs.o i810_context.o \ - i810_clear.o -I810HEADERS= i810_drv.h $(DRMHEADERS) +I810OBJS= i810_drv.o i810_dma.o i810_bufs.o i810_context.o +I810HEADERS= i810_drv.h i810_drm_public.h $(DRMHEADERS) PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po PROGHEADERS= xf86drm.h $(DRMHEADERS) @@ -157,331 +156,3 @@ $(PROGOBJS): $(PROGHEADERS) clean: rm -f *.o *.a *.po *~ core $(PROGS) -# DO NOT DELETE - -agpsupport.o: drmP.h -auth.o: drmP.h -bufs.o: drmP.h /usr/include/linux/un.h -context.o: drmP.h -ctxbitmap.o: drmP.h -dma.o: drmP.h /usr/include/linux/interrupt.h /usr/include/linux/kernel.h -dma.o: /usr/include/asm/bitops.h /usr/include/asm/atomic.h -dma.o: /usr/include/asm/hardirq.h /usr/include/linux/threads.h -dma.o: /usr/include/asm/softirq.h -drawable.o: drmP.h -drm.o: /usr/include/asm/ioctl.h -drmstat.o: /usr/include/stdio.h /usr/include/features.h -drmstat.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h -drmstat.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h -drmstat.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h -drmstat.o: /usr/include/bits/types.h /usr/include/libio.h -drmstat.o: /usr/include/_G_config.h /usr/include/bits/stdio_lim.h -drmstat.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h -drmstat.o: /usr/include/endian.h /usr/include/bits/endian.h -drmstat.o: /usr/include/sys/select.h /usr/include/bits/select.h -drmstat.o: /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h -drmstat.o: /usr/include/alloca.h /usr/include/unistd.h -drmstat.o: /usr/include/bits/posix_opt.h /usr/include/bits/confname.h -drmstat.o: /usr/include/getopt.h /usr/include/sys/time.h -drmstat.o: /usr/include/bits/time.h /usr/include/sys/mman.h -drmstat.o: /usr/include/bits/mman.h /usr/include/strings.h -drmstat.o: /usr/include/errno.h /usr/include/bits/errno.h -drmstat.o: /usr/include/linux/errno.h /usr/include/asm/errno.h -drmstat.o: /usr/include/signal.h /usr/include/bits/signum.h -drmstat.o: /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h -drmstat.o: /usr/include/bits/sigcontext.h /usr/include/asm/sigcontext.h -drmstat.o: /usr/include/bits/sigstack.h /usr/include/fcntl.h -drmstat.o: /usr/include/bits/fcntl.h xf86drm.h -fops.o: drmP.h /usr/include/linux/poll.h /usr/include/asm/poll.h -gamma_dma.o: drmP.h gamma_drv.h /usr/include/linux/interrupt.h -gamma_dma.o: /usr/include/linux/kernel.h /usr/include/asm/bitops.h -gamma_dma.o: /usr/include/asm/atomic.h /usr/include/asm/hardirq.h -gamma_dma.o: /usr/include/linux/threads.h /usr/include/asm/softirq.h -gamma_drv.o: drmP.h gamma_drv.h -i810_bufs.o: drmP.h i810_drv.h i810_drm_public.h i810_dma.h -i810_bufs.o: /usr/include/linux/un.h -i810_clear.o: drmP.h i810_drv.h i810_drm_public.h i810_dma.h -i810_context.o: /usr/include/linux/sched.h /usr/include/asm/param.h -i810_context.o: /usr/include/linux/binfmts.h /usr/include/linux/ptrace.h -i810_context.o: /usr/include/asm/ptrace.h /usr/include/linux/capability.h -i810_context.o: /usr/include/linux/types.h /usr/include/linux/config.h -i810_context.o: /usr/include/linux/autoconf.h -i810_context.o: /usr/include/linux/posix_types.h /usr/include/linux/stddef.h -i810_context.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h -i810_context.o: /usr/include/linux/fs.h /usr/include/linux/linkage.h -i810_context.o: /usr/include/linux/limits.h /usr/include/linux/wait.h -i810_context.o: /usr/include/linux/vfs.h /usr/include/asm/statfs.h -i810_context.o: /usr/include/linux/net.h /usr/include/linux/socket.h -i810_context.o: /usr/include/asm/socket.h /usr/include/asm/sockios.h -i810_context.o: /usr/include/linux/sockios.h /usr/include/linux/uio.h -i810_context.o: /usr/include/linux/kdev_t.h /usr/include/linux/ioctl.h -i810_context.o: /usr/include/asm/ioctl.h /usr/include/linux/list.h -i810_context.o: /usr/include/linux/dcache.h /usr/include/linux/stat.h -i810_context.o: /usr/include/linux/cache.h /usr/include/asm/cache.h -i810_context.o: /usr/include/asm/atomic.h /usr/include/asm/bitops.h -i810_context.o: /usr/include/linux/personality.h /usr/include/linux/threads.h -i810_context.o: /usr/include/linux/kernel.h /usr/include/linux/times.h -i810_context.o: /usr/include/linux/timex.h /usr/include/asm/timex.h -i810_context.o: /usr/include/asm/msr.h /usr/include/asm/system.h -i810_context.o: /usr/include/asm/segment.h /usr/include/linux/bitops.h -i810_context.o: /usr/include/asm/semaphore.h /usr/include/asm/rwlock.h -i810_context.o: /usr/include/asm/page.h /usr/include/linux/smp.h -i810_context.o: /usr/include/linux/tty.h /usr/include/linux/sem.h -i810_context.o: /usr/include/linux/ipc.h /usr/include/asm/ipcbuf.h -i810_context.o: /usr/include/asm/sembuf.h /usr/include/linux/signal.h -i810_context.o: /usr/include/asm/signal.h /usr/include/asm/siginfo.h -i810_context.o: /usr/include/linux/securebits.h /usr/include/linux/time.h -i810_context.o: /usr/include/linux/param.h /usr/include/linux/resource.h -i810_context.o: /usr/include/asm/resource.h /usr/include/linux/timer.h -i810_context.o: /usr/include/asm/processor.h /usr/include/asm/vm86.h -i810_context.o: /usr/include/asm/math_emu.h /usr/include/asm/sigcontext.h -i810_context.o: drmP.h i810_drv.h i810_drm_public.h -i810_dma.o: drmP.h i810_drm_public.h i810_drv.h i810_dma.h -i810_dma.o: /usr/include/linux/interrupt.h /usr/include/linux/kernel.h -i810_dma.o: /usr/include/asm/bitops.h /usr/include/asm/atomic.h -i810_dma.o: /usr/include/asm/hardirq.h /usr/include/linux/threads.h -i810_dma.o: /usr/include/asm/softirq.h /usr/include/linux/time.h -i810_dma.o: /usr/include/asm/param.h /usr/include/linux/types.h -i810_dma.o: /usr/include/linux/config.h /usr/include/linux/autoconf.h -i810_dma.o: /usr/include/linux/posix_types.h /usr/include/linux/stddef.h -i810_dma.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h -i810_dma.o: i810_drm_public.h -i810_dma_jeff.o: drmP.h i810_drm_public.h i810_drv.h -i810_dma_jeff.o: /usr/include/linux/interrupt.h /usr/include/linux/kernel.h -i810_dma_jeff.o: /usr/include/asm/bitops.h /usr/include/asm/atomic.h -i810_dma_jeff.o: /usr/include/asm/hardirq.h /usr/include/linux/threads.h -i810_dma_jeff.o: /usr/include/asm/softirq.h /usr/include/linux/time.h -i810_dma_jeff.o: /usr/include/asm/param.h /usr/include/linux/types.h -i810_dma_jeff.o: /usr/include/linux/config.h /usr/include/linux/autoconf.h -i810_dma_jeff.o: /usr/include/linux/posix_types.h /usr/include/linux/stddef.h -i810_dma_jeff.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h -i810_dmamine.o: drmP.h i810_drm_public.h i810_drv.h i810_dma.h -i810_dmamine.o: /usr/include/linux/interrupt.h /usr/include/linux/kernel.h -i810_dmamine.o: /usr/include/asm/bitops.h /usr/include/asm/atomic.h -i810_dmamine.o: /usr/include/asm/hardirq.h /usr/include/linux/threads.h -i810_dmamine.o: /usr/include/asm/softirq.h /usr/include/linux/time.h -i810_dmamine.o: /usr/include/asm/param.h /usr/include/linux/types.h -i810_dmamine.o: /usr/include/linux/config.h /usr/include/linux/autoconf.h -i810_dmamine.o: /usr/include/linux/posix_types.h /usr/include/linux/stddef.h -i810_dmamine.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h -i810_drv.o: drmP.h i810_drv.h i810_drm_public.h i810_dma.h -i810_drv.o: i810_drm_public.h -init.o: drmP.h -ioctl.o: drmP.h -lists.o: drmP.h -lock.o: drmP.h -memory.o: drmP.h -mga_bufs.o: drmP.h mga_drv.h mga_drm_public.h mga_dma.h -mga_bufs.o: /usr/include/linux/un.h -mga_clear.o: drmP.h mga_drv.h mga_drm_public.h mgareg_flags.h mga_dma.h -mga_clear.o: mga_state.h -mga_context.o: /usr/include/linux/sched.h /usr/include/asm/param.h -mga_context.o: /usr/include/linux/binfmts.h /usr/include/linux/ptrace.h -mga_context.o: /usr/include/asm/ptrace.h /usr/include/linux/capability.h -mga_context.o: /usr/include/linux/types.h /usr/include/linux/config.h -mga_context.o: /usr/include/linux/autoconf.h /usr/include/linux/posix_types.h -mga_context.o: /usr/include/linux/stddef.h /usr/include/asm/posix_types.h -mga_context.o: /usr/include/asm/types.h /usr/include/linux/fs.h -mga_context.o: /usr/include/linux/linkage.h /usr/include/linux/limits.h -mga_context.o: /usr/include/linux/wait.h /usr/include/linux/vfs.h -mga_context.o: /usr/include/asm/statfs.h /usr/include/linux/net.h -mga_context.o: /usr/include/linux/socket.h /usr/include/asm/socket.h -mga_context.o: /usr/include/asm/sockios.h /usr/include/linux/sockios.h -mga_context.o: /usr/include/linux/uio.h /usr/include/linux/kdev_t.h -mga_context.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h -mga_context.o: /usr/include/linux/list.h /usr/include/linux/dcache.h -mga_context.o: /usr/include/linux/stat.h /usr/include/linux/cache.h -mga_context.o: /usr/include/asm/cache.h /usr/include/asm/atomic.h -mga_context.o: /usr/include/asm/bitops.h /usr/include/linux/personality.h -mga_context.o: /usr/include/linux/threads.h /usr/include/linux/kernel.h -mga_context.o: /usr/include/linux/times.h /usr/include/linux/timex.h -mga_context.o: /usr/include/asm/timex.h /usr/include/asm/msr.h -mga_context.o: /usr/include/asm/system.h /usr/include/asm/segment.h -mga_context.o: /usr/include/linux/bitops.h /usr/include/asm/semaphore.h -mga_context.o: /usr/include/asm/rwlock.h /usr/include/asm/page.h -mga_context.o: /usr/include/linux/smp.h /usr/include/linux/tty.h -mga_context.o: /usr/include/linux/sem.h /usr/include/linux/ipc.h -mga_context.o: /usr/include/asm/ipcbuf.h /usr/include/asm/sembuf.h -mga_context.o: /usr/include/linux/signal.h /usr/include/asm/signal.h -mga_context.o: /usr/include/asm/siginfo.h /usr/include/linux/securebits.h -mga_context.o: /usr/include/linux/time.h /usr/include/linux/param.h -mga_context.o: /usr/include/linux/resource.h /usr/include/asm/resource.h -mga_context.o: /usr/include/linux/timer.h /usr/include/asm/processor.h -mga_context.o: /usr/include/asm/vm86.h /usr/include/asm/math_emu.h -mga_context.o: /usr/include/asm/sigcontext.h drmP.h mga_drv.h -mga_context.o: mga_drm_public.h -mga_dma.o: drmP.h mga_drv.h mga_drm_public.h mgareg_flags.h mga_dma.h -mga_dma.o: mga_state.h /usr/include/linux/interrupt.h -mga_dma.o: /usr/include/linux/kernel.h /usr/include/asm/bitops.h -mga_dma.o: /usr/include/asm/atomic.h /usr/include/asm/hardirq.h -mga_dma.o: /usr/include/linux/threads.h /usr/include/asm/softirq.h -mga_dma.o: mga_drm_public.h -mga_dma_mine.o: drmP.h mga_drv.h mga_drm_public.h mgareg_flags.h mga_dma.h -mga_dma_mine.o: mga_state.h /usr/include/linux/interrupt.h -mga_dma_mine.o: /usr/include/linux/kernel.h /usr/include/asm/bitops.h -mga_dma_mine.o: /usr/include/asm/atomic.h /usr/include/asm/hardirq.h -mga_dma_mine.o: /usr/include/linux/threads.h /usr/include/asm/softirq.h -mga_dmapoll.o: drmP.h mga_drv.h mga_drm_public.h mgareg_flags.h mga_dma.h -mga_dmapoll.o: mga_state.h /usr/include/linux/interrupt.h -mga_dmapoll.o: /usr/include/linux/kernel.h /usr/include/asm/bitops.h -mga_dmapoll.o: /usr/include/asm/atomic.h /usr/include/asm/hardirq.h -mga_dmapoll.o: /usr/include/linux/threads.h /usr/include/asm/softirq.h -mga_drv.o: drmP.h mga_drv.h mga_drm_public.h -mga_drv.o: mga_drm_public.h -mga_state.o: drmP.h mga_drv.h mga_drm_public.h mgareg_flags.h mga_dma.h -mga_state.o: mga_state.h drm.h /usr/include/asm/ioctl.h -mga_state.o: mga_drv.h mga_drm_public.h -proc.o: drmP.h -r128_context.o: /usr/include/linux/sched.h /usr/include/asm/param.h -r128_context.o: /usr/include/linux/binfmts.h /usr/include/linux/ptrace.h -r128_context.o: /usr/include/asm/ptrace.h /usr/include/linux/capability.h -r128_context.o: /usr/include/linux/types.h /usr/include/linux/config.h -r128_context.o: /usr/include/linux/autoconf.h -r128_context.o: /usr/include/linux/posix_types.h /usr/include/linux/stddef.h -r128_context.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h -r128_context.o: /usr/include/linux/fs.h /usr/include/linux/linkage.h -r128_context.o: /usr/include/linux/limits.h /usr/include/linux/wait.h -r128_context.o: /usr/include/linux/vfs.h /usr/include/asm/statfs.h -r128_context.o: /usr/include/linux/net.h /usr/include/linux/socket.h -r128_context.o: /usr/include/asm/socket.h /usr/include/asm/sockios.h -r128_context.o: /usr/include/linux/sockios.h /usr/include/linux/uio.h -r128_context.o: /usr/include/linux/kdev_t.h /usr/include/linux/ioctl.h -r128_context.o: /usr/include/asm/ioctl.h /usr/include/linux/list.h -r128_context.o: /usr/include/linux/dcache.h /usr/include/linux/stat.h -r128_context.o: /usr/include/linux/cache.h /usr/include/asm/cache.h -r128_context.o: /usr/include/asm/atomic.h /usr/include/asm/bitops.h -r128_context.o: /usr/include/linux/personality.h /usr/include/linux/threads.h -r128_context.o: /usr/include/linux/kernel.h /usr/include/linux/times.h -r128_context.o: /usr/include/linux/timex.h /usr/include/asm/timex.h -r128_context.o: /usr/include/asm/msr.h /usr/include/asm/system.h -r128_context.o: /usr/include/asm/segment.h /usr/include/linux/bitops.h -r128_context.o: /usr/include/asm/semaphore.h /usr/include/asm/rwlock.h -r128_context.o: /usr/include/asm/page.h /usr/include/linux/smp.h -r128_context.o: /usr/include/linux/tty.h /usr/include/linux/sem.h -r128_context.o: /usr/include/linux/ipc.h /usr/include/asm/ipcbuf.h -r128_context.o: /usr/include/asm/sembuf.h /usr/include/linux/signal.h -r128_context.o: /usr/include/asm/signal.h /usr/include/asm/siginfo.h -r128_context.o: /usr/include/linux/securebits.h /usr/include/linux/time.h -r128_context.o: /usr/include/linux/param.h /usr/include/linux/resource.h -r128_context.o: /usr/include/asm/resource.h /usr/include/linux/timer.h -r128_context.o: /usr/include/asm/processor.h /usr/include/asm/vm86.h -r128_context.o: /usr/include/asm/math_emu.h /usr/include/asm/sigcontext.h -r128_context.o: drmP.h r128_drv.h -r128_drv.o: drmP.h r128_drv.h -sigio.o: /usr/include/unistd.h /usr/include/features.h -sigio.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h -sigio.o: /usr/include/bits/posix_opt.h /usr/include/bits/types.h -sigio.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h -sigio.o: /usr/include/bits/confname.h /usr/include/getopt.h -sigio.o: /usr/include/signal.h /usr/include/bits/sigset.h -sigio.o: /usr/include/bits/signum.h /usr/include/time.h -sigio.o: /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h -sigio.o: /usr/include/bits/sigcontext.h /usr/include/asm/sigcontext.h -sigio.o: /usr/include/bits/sigstack.h /usr/include/fcntl.h -sigio.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h -sigio.o: /usr/include/endian.h /usr/include/bits/endian.h -sigio.o: /usr/include/sys/select.h /usr/include/bits/select.h -sigio.o: /usr/include/sys/sysmacros.h /usr/include/sys/time.h -sigio.o: /usr/include/bits/time.h /usr/include/errno.h -sigio.o: /usr/include/bits/errno.h /usr/include/linux/errno.h -sigio.o: /usr/include/asm/errno.h /usr/include/stdio.h -sigio.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h -sigio.o: /usr/include/libio.h /usr/include/_G_config.h -sigio.o: /usr/include/bits/stdio_lim.h /usr/include/string.h -tdfx_context.o: /usr/include/linux/sched.h /usr/include/asm/param.h -tdfx_context.o: /usr/include/linux/binfmts.h /usr/include/linux/ptrace.h -tdfx_context.o: /usr/include/asm/ptrace.h /usr/include/linux/capability.h -tdfx_context.o: /usr/include/linux/types.h /usr/include/linux/config.h -tdfx_context.o: /usr/include/linux/autoconf.h -tdfx_context.o: /usr/include/linux/posix_types.h /usr/include/linux/stddef.h -tdfx_context.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h -tdfx_context.o: /usr/include/linux/fs.h /usr/include/linux/linkage.h -tdfx_context.o: /usr/include/linux/limits.h /usr/include/linux/wait.h -tdfx_context.o: /usr/include/linux/vfs.h /usr/include/asm/statfs.h -tdfx_context.o: /usr/include/linux/net.h /usr/include/linux/socket.h -tdfx_context.o: /usr/include/asm/socket.h /usr/include/asm/sockios.h -tdfx_context.o: /usr/include/linux/sockios.h /usr/include/linux/uio.h -tdfx_context.o: /usr/include/linux/kdev_t.h /usr/include/linux/ioctl.h -tdfx_context.o: /usr/include/asm/ioctl.h /usr/include/linux/list.h -tdfx_context.o: /usr/include/linux/dcache.h /usr/include/linux/stat.h -tdfx_context.o: /usr/include/linux/cache.h /usr/include/asm/cache.h -tdfx_context.o: /usr/include/asm/atomic.h /usr/include/asm/bitops.h -tdfx_context.o: /usr/include/linux/personality.h /usr/include/linux/threads.h -tdfx_context.o: /usr/include/linux/kernel.h /usr/include/linux/times.h -tdfx_context.o: /usr/include/linux/timex.h /usr/include/asm/timex.h -tdfx_context.o: /usr/include/asm/msr.h /usr/include/asm/system.h -tdfx_context.o: /usr/include/asm/segment.h /usr/include/linux/bitops.h -tdfx_context.o: /usr/include/asm/semaphore.h /usr/include/asm/rwlock.h -tdfx_context.o: /usr/include/asm/page.h /usr/include/linux/smp.h -tdfx_context.o: /usr/include/linux/tty.h /usr/include/linux/sem.h -tdfx_context.o: /usr/include/linux/ipc.h /usr/include/asm/ipcbuf.h -tdfx_context.o: /usr/include/asm/sembuf.h /usr/include/linux/signal.h -tdfx_context.o: /usr/include/asm/signal.h /usr/include/asm/siginfo.h -tdfx_context.o: /usr/include/linux/securebits.h /usr/include/linux/time.h -tdfx_context.o: /usr/include/linux/param.h /usr/include/linux/resource.h -tdfx_context.o: /usr/include/asm/resource.h /usr/include/linux/timer.h -tdfx_context.o: /usr/include/asm/processor.h /usr/include/asm/vm86.h -tdfx_context.o: /usr/include/asm/math_emu.h /usr/include/asm/sigcontext.h -tdfx_context.o: drmP.h tdfx_drv.h -tdfx_drv.o: drmP.h tdfx_drv.h -vm.o: drmP.h -xf86_OSproc.o: /usr/include/X11/Xfuncproto.h -xf86drm.o: /usr/include/stdio.h /usr/include/features.h -xf86drm.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h -xf86drm.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h -xf86drm.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h -xf86drm.o: /usr/include/bits/types.h /usr/include/libio.h -xf86drm.o: /usr/include/_G_config.h /usr/include/bits/stdio_lim.h -xf86drm.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h -xf86drm.o: /usr/include/endian.h /usr/include/bits/endian.h -xf86drm.o: /usr/include/sys/select.h /usr/include/bits/select.h -xf86drm.o: /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h -xf86drm.o: /usr/include/alloca.h /usr/include/unistd.h -xf86drm.o: /usr/include/bits/posix_opt.h /usr/include/bits/confname.h -xf86drm.o: /usr/include/getopt.h /usr/include/string.h /usr/include/ctype.h -xf86drm.o: /usr/include/fcntl.h /usr/include/bits/fcntl.h -xf86drm.o: /usr/include/errno.h /usr/include/bits/errno.h -xf86drm.o: /usr/include/linux/errno.h /usr/include/asm/errno.h -xf86drm.o: /usr/include/signal.h /usr/include/bits/signum.h -xf86drm.o: /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h -xf86drm.o: /usr/include/bits/sigcontext.h /usr/include/asm/sigcontext.h -xf86drm.o: /usr/include/bits/sigstack.h /usr/include/sys/stat.h -xf86drm.o: /usr/include/bits/stat.h /usr/include/sys/ioctl.h -xf86drm.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h -xf86drm.o: /usr/include/asm/ioctl.h /usr/include/bits/ioctl-types.h -xf86drm.o: /usr/include/sys/ttydefaults.h /usr/include/sys/mman.h -xf86drm.o: /usr/include/bits/mman.h /usr/include/sys/time.h -xf86drm.o: /usr/include/bits/time.h xf86drm.h drm.h -xf86drmHash.o: xf86drm.h /usr/include/stdio.h /usr/include/features.h -xf86drmHash.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h -xf86drmHash.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h -xf86drmHash.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h -xf86drmHash.o: /usr/include/bits/types.h /usr/include/libio.h -xf86drmHash.o: /usr/include/_G_config.h /usr/include/bits/stdio_lim.h -xf86drmHash.o: /usr/include/stdlib.h /usr/include/sys/types.h -xf86drmHash.o: /usr/include/time.h /usr/include/endian.h -xf86drmHash.o: /usr/include/bits/endian.h /usr/include/sys/select.h -xf86drmHash.o: /usr/include/bits/select.h /usr/include/bits/sigset.h -xf86drmHash.o: /usr/include/sys/sysmacros.h /usr/include/alloca.h -xf86drmRandom.o: xf86drm.h /usr/include/stdio.h /usr/include/features.h -xf86drmRandom.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h -xf86drmRandom.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h -xf86drmRandom.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h -xf86drmRandom.o: /usr/include/bits/types.h /usr/include/libio.h -xf86drmRandom.o: /usr/include/_G_config.h /usr/include/bits/stdio_lim.h -xf86drmRandom.o: /usr/include/stdlib.h /usr/include/sys/types.h -xf86drmRandom.o: /usr/include/time.h /usr/include/endian.h -xf86drmRandom.o: /usr/include/bits/endian.h /usr/include/sys/select.h -xf86drmRandom.o: /usr/include/bits/select.h /usr/include/bits/sigset.h -xf86drmRandom.o: /usr/include/sys/sysmacros.h /usr/include/alloca.h -xf86drmSL.o: xf86drm.h /usr/include/stdio.h /usr/include/features.h -xf86drmSL.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h -xf86drmSL.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h -xf86drmSL.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h -xf86drmSL.o: /usr/include/bits/types.h /usr/include/libio.h -xf86drmSL.o: /usr/include/_G_config.h /usr/include/bits/stdio_lim.h -xf86drmSL.o: /usr/include/stdlib.h /usr/include/sys/types.h -xf86drmSL.o: /usr/include/time.h /usr/include/endian.h -xf86drmSL.o: /usr/include/bits/endian.h /usr/include/sys/select.h -xf86drmSL.o: /usr/include/bits/select.h /usr/include/bits/sigset.h -xf86drmSL.o: /usr/include/sys/sysmacros.h /usr/include/alloca.h diff --git a/linux/i810_clear.c b/linux/i810_clear.c deleted file mode 100644 index ca25e596..00000000 --- a/linux/i810_clear.c +++ /dev/null @@ -1,217 +0,0 @@ -/* i810_state.c -- State support for i810 g200/g400 -*- linux-c -*- - * - * Created: February 2000 by keithw@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * 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 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * 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: - * Keith Whitwell <keithw@precisioninsight.com> - * - */ - -#define __NO_VERSION__ -#include "drmP.h" -#include "i810_drv.h" -#include "i810_dma.h" -#include "i810_drm_public.h" - - - -static int i810DmaGeneral(drm_device_t *dev, drm_i810_general_t *args) -{ - drm_device_dma_t *dma = dev->dma; - drm_buf_t *buf = dma->buflist[ args->idx ]; - drm_i810_buf_priv_t *buf_priv = (drm_i810_buf_priv_t *)buf->dev_private; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - drm_dma_t d; - - buf_priv->dma_type = I810_DMA_GENERAL; - buf_priv->age = args->age; - buf->used = args->used; - - if (I810_VERBOSE) - printk("i810DmaGeneral idx %d used %d\n", args->idx, buf->used); - - d.context = DRM_KERNEL_CONTEXT; - d.send_count = 1; - d.send_indices = &buf->idx; - d.send_sizes = &buf->used; - d.flags = 0; - d.request_count = 0; - d.request_size = 0; - d.request_indices = NULL; - d.request_sizes = NULL; - d.granted_count = 0; - - atomic_inc(&dev_priv->pending_bufs); - if((drm_dma_enqueue(dev, &d)) != 0) - atomic_dec(&dev_priv->pending_bufs); - i810_dma_schedule(dev, 1); - - return 0; -} - - -static int i810DmaVertex(drm_device_t *dev, drm_i810_vertex_t *args) -{ - drm_device_dma_t *dma = dev->dma; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_i810_buf_priv_t *buf_priv; - drm_buf_t *buf; - drm_dma_t d; - - - buf = dma->buflist[ args->idx ]; - buf->used = args->real_used; - - if (I810_VERBOSE) - printk("i810DmaVertex idx %d used %d\n", args->idx, buf->used); - - buf_priv = buf->dev_private; - buf_priv->dma_type = I810_DMA_VERTEX; - buf_priv->vertex_real_idx = args->real_idx; - buf_priv->vertex_discard = args->discard; - buf_priv->nbox = sarea_priv->nbox; - buf_priv->age = args->age; - - if (buf_priv->nbox >= I810_NR_SAREA_CLIPRECTS) - buf_priv->nbox = I810_NR_SAREA_CLIPRECTS; - - if (buf_priv->nbox) - memcpy( buf_priv->boxes, - sarea_priv->boxes, - buf_priv->nbox * sizeof(xf86drmClipRectRec)); - - d.context = DRM_KERNEL_CONTEXT; - d.send_count = 1; - d.send_indices = &buf->idx; - d.send_sizes = &buf->used; - d.flags = 0; - d.request_count = 0; - d.request_size = 0; - d.request_indices = NULL; - d.request_sizes = NULL; - d.granted_count = 0; - - atomic_inc(&dev_priv->pending_bufs); - if((drm_dma_enqueue(dev, &d)) != 0) - atomic_dec(&dev_priv->pending_bufs); - i810_dma_schedule(dev, 1); - return 0; -} - - - - -int i810_dma_general(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_i810_general_t general; - int retcode = 0; - - copy_from_user_ret(&general, (drm_i810_general_t *)arg, sizeof(general), - -EFAULT); - - if (I810_VERBOSE) - printk("i810 dma general idx %d used %d\n", - general.idx, general.used); - - retcode = i810DmaGeneral(dev, &general); - - return retcode; -} - -int i810_dma_vertex(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_i810_vertex_t vertex; - int retcode = 0; - - copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex), - -EFAULT); - - if (I810_VERBOSE) - printk("i810 dma vertex, idx %d used %d" - " real_idx %d discard %d\n", - vertex.idx, vertex.real_used, vertex.real_idx, - vertex.discard); - - retcode = i810DmaVertex(dev, &vertex); - - return retcode; - -} - - -int i810_dma(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_device_dma_t *dma = dev->dma; - int retcode = 0; - drm_dma_t d; - - copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); - DRM_DEBUG("%d %d: %d send, %d req\n", - current->pid, d.context, d.send_count, d.request_count); - - /* Per-context queues are unworkable if you are trying to do - * state management from the client. - */ - d.context = DRM_KERNEL_CONTEXT; - d.flags &= ~_DRM_DMA_WHILE_LOCKED; - - /* Please don't send us buffers. - */ - if (d.send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - current->pid, d.send_count); - return -EINVAL; - } - - /* We'll send you buffers. - */ - 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); - return -EINVAL; - } - - d.granted_count = 0; - - if (!retcode && d.request_count) { - retcode = drm_dma_get_buffers(dev, &d); - } - - copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); - - return retcode; -} - - diff --git a/linux/i810_context.c b/linux/i810_context.c index fca7b29a..6176b774 100644 --- a/linux/i810_context.c +++ b/linux/i810_context.c @@ -194,51 +194,11 @@ int i810_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_ctx_t ctx; - drm_queue_t *q; - drm_buf_t *buf; copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); printk("%d\n", ctx.handle); - if(ctx.handle == DRM_KERNEL_CONTEXT) { - q = dev->queuelist[ctx.handle]; - atomic_inc(&q->use_count); - if (atomic_read(&q->use_count) == 1) { - /* No longer in use */ - atomic_dec(&q->use_count); - return -EINVAL; - } - atomic_inc(&q->finalization); /* Mark queue in finalization state */ - atomic_sub(2, &q->use_count); - /* Mark queue as unused (pending finalization) */ - - while (test_and_set_bit(0, &dev->interrupt_flag)) { - printk("Calling schedule from rmctx\n"); - schedule(); - if (signal_pending(current)) { - clear_bit(0, &dev->interrupt_flag); - return -EINTR; - } - } - - /* Remove queued buffers */ - while ((buf = drm_waitlist_get(&q->waitlist))) { - drm_free_buffer(dev, buf); - } - clear_bit(0, &dev->interrupt_flag); - - /* Wakeup blocked processes */ - wake_up_interruptible(&q->read_queue); - wake_up_interruptible(&q->write_queue); - wake_up_interruptible(&q->flush_queue); - - /* Finalization over. Queue is made - available when both use_count and - finalization become 0, which won't - happen until all the waiting processes - stop waiting. */ - atomic_dec(&q->finalization); - } else { - drm_ctxbitmap_free(dev, ctx.handle); + if(ctx.handle != DRM_KERNEL_CONTEXT) { + drm_ctxbitmap_free(dev, ctx.handle); } return 0; diff --git a/linux/i810_dma.c b/linux/i810_dma.c index 7b0e4475..56b99850 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -40,6 +40,9 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/time.h> /* For do_gettimeofday */ +#define I810_BUF_FREE 1 +#define I810_BUF_USED 0 + #define I810_REG(reg) 2 #define I810_BASE(reg) ((unsigned long) \ dev->maplist[I810_REG(reg)]->handle) @@ -53,10 +56,9 @@ #define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; - #define BEGIN_LP_RING(n) do { \ if (I810_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ + printk("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ if (dev_priv->ring.space < n*4) i810_wait_ring(dev, n*4, 0); \ dev_priv->ring.space -= n*4; \ outring = dev_priv->ring.tail; \ @@ -65,18 +67,115 @@ } while (0) #define ADVANCE_LP_RING() do { \ - if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + if (I810_VERBOSE) printk("ADVANCE_LP_RING\n"); \ dev_priv->ring.tail = outring; \ I810_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) #define OUT_RING(n) do { \ - if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + if (I810_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \ *(volatile unsigned int *)(virt + outring) = n; \ outring += 4; \ outring &= ringmask; \ } while (0); +static inline void i810_print_status_page(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + drm_i810_private_t *dev_priv = dev->dev_private; + u32 *temp = (u32 *)dev_priv->hw_status_page; + int i; + + printk( "hw_status: Interrupt Status : %x\n", temp[0]); + printk( "hw_status: LpRing Head ptr : %x\n", temp[1]); + printk( "hw_status: IRing Head ptr : %x\n", temp[2]); + printk( "hw_status: Reserved : %x\n", temp[3]); + printk( "hw_status: Driver Counter : %d\n", temp[5]); + for(i = 6; i < dma->buf_count + 6; i++) { + printk( "buffer status idx : %d used: %d\n", i - 6, temp[i]); + } +} + +static drm_buf_t *i810_freelist_get(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i; + int used; + + /* Linear search might not be the best solution */ + +#if 0 + i810_print_status_page(dev); +#endif + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + /* In use is already a pointer */ +#if 0 + printk("idx : %d in_use : %d\n", i, *buf_priv->in_use); +#endif + used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, + I810_BUF_USED); +#if 0 + printk("used : %d\n", used); +#endif + if(used == I810_BUF_FREE) { +#if 0 + printk("Got buffer\n"); +#endif + return buf; + } + } +#if 0 + printk("Didn't get buffer\n"); +#endif + return NULL; +} + +/* This should only be called if the buffer is not sent to the hardware + * yet, the hardware updates in use for us once its on the ring buffer. + */ + +static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf) +{ + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + int used; + + /* In use is already a pointer */ +#if 0 + i810_print_status_page(dev); +#endif + used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE); + if(used != I810_BUF_USED) { + DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx); + return -EINVAL; + } + + return 0; +} + +static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) +{ + int i; + drm_buf_t *buf; + + for (i = d->granted_count; i < d->request_count; i++) { + buf = i810_freelist_get(dev); + if (!buf) break; + buf->pid = current->pid; + copy_to_user_ret(&d->request_indices[i], + &buf->idx, + sizeof(buf->idx), + -EFAULT); + copy_to_user_ret(&d->request_sizes[i], + &buf->total, + sizeof(buf->total), + -EFAULT); + ++d->granted_count; + } + return 0; +} + static unsigned long i810_alloc_page(drm_device_t *dev) { unsigned long address; @@ -103,68 +202,8 @@ static void i810_free_page(drm_device_t *dev, unsigned long page) return; } -static int i810_alloc_kernel_queue(drm_device_t *dev) -{ - drm_queue_t *queue = NULL; - /* Allocate a new queue */ - down(&dev->struct_sem); - - if(dev->queue_count != 0) { - /* Reseting the kernel context here is not - * a race, since it can only happen when that - * queue is empty. - */ - queue = dev->queuelist[DRM_KERNEL_CONTEXT]; - DRM_DEBUG("Kernel queue already allocated\n"); - } else { - queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES); - if(!queue) { - up(&dev->struct_sem); - DRM_DEBUG("out of memory\n"); - return -ENOMEM; - } - ++dev->queue_count; - dev->queuelist = drm_alloc(sizeof(*dev->queuelist), - DRM_MEM_QUEUES); - if(!dev->queuelist) { - up(&dev->struct_sem); - drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES); - DRM_DEBUG("out of memory\n"); - return -ENOMEM; - } - } - - memset(queue, 0, sizeof(*queue)); - atomic_set(&queue->use_count, 1); - atomic_set(&queue->finalization, 0); - atomic_set(&queue->block_count, 0); - atomic_set(&queue->block_read, 0); - atomic_set(&queue->block_write, 0); - atomic_set(&queue->total_queued, 0); - atomic_set(&queue->total_flushed, 0); - atomic_set(&queue->total_locks, 0); - - init_waitqueue_head(&queue->write_queue); - init_waitqueue_head(&queue->read_queue); - init_waitqueue_head(&queue->flush_queue); - - queue->flags = 0; - - drm_waitlist_create(&queue->waitlist, dev->dma->buf_count); - - dev->queue_slots = 1; - dev->queuelist[DRM_KERNEL_CONTEXT] = queue; - dev->queue_count--; - - up(&dev->struct_sem); - if (I810_VERBOSE) DRM_DEBUG("%d (new)\n", dev->queue_count - 1); - return DRM_KERNEL_CONTEXT; -} - static int i810_dma_cleanup(drm_device_t *dev) { - if (I810_VERBOSE) DRM_DEBUG("i810_dma_cleanup\n"); - if(dev->dev_private) { drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; @@ -201,9 +240,7 @@ static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis) int curTime = 0; if (timeout_millis == 0) timeout_millis = 3000; - - if (I810_VERBOSE) DRM_DEBUG( "i810_wait_ring %d\n", n); - + while (ring->space < n) { int i; @@ -233,49 +270,40 @@ static void i810_kernel_lost_context(drm_device_t *dev) { drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_ring_buffer_t *ring = &(dev_priv->ring); - - if (0) DRM_DEBUG("i810_kernel_lost_context, old ring (%x,%x)\n", - ring->head, ring->tail); - + ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->tail = I810_READ(LP_RING + RING_TAIL); ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; - - if (0) DRM_DEBUG("new ring (%x,%x)\n", ring->head, ring->tail); } -static inline void i810_ring_write_status(drm_device_t *dev) +static int i810_freelist_init(drm_device_t *dev) { - drm_i810_private_t *dev_priv = dev->dev_private; - RING_LOCALS; + drm_device_dma_t *dma = dev->dma; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u8 *hw_status = (u8 *)dev_priv->hw_status_page; + int i; + int my_idx = 24; - i810_kernel_lost_context(dev); - dev_priv->counter++; - - BEGIN_LP_RING(6); - OUT_RING(CMD_REPORT_HEAD); - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(5 * sizeof(unsigned long)); - OUT_RING(dev_priv->counter); - OUT_RING(GFX_OP_BREAKPOINT_INTERRUPT); - OUT_RING(0); - ADVANCE_LP_RING(); - - /* Wait for ring to complete */ - i810_wait_ring(dev, dev_priv->ring.Size - 8, 0); -} - -static inline void i810_print_status_page(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - u32 *temp = (u32 *)dev_priv->hw_status_page; + if(dma->buf_count > 1019) { + /* Not enough space in the status page for the freelist */ + return -EINVAL; + } - DRM_DEBUG( "hw_status: Interrupt Status : %x\n", temp[0]); - DRM_DEBUG( "hw_status: LpRing Head ptr : %x\n", temp[1]); - DRM_DEBUG( "hw_status: IRing Head ptr : %x\n", temp[2]); - DRM_DEBUG( "hw_status: Reserved : %x\n", temp[3]); - DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]); + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + + buf_priv->in_use = hw_status + my_idx; + printk("buf_priv->in_use : %p\n", buf_priv->in_use); + *buf_priv->in_use = I810_BUF_FREE; + buf_priv->my_use_idx = my_idx; + my_idx += 4; + } +#if 0 + i810_print_status_page(dev); +#endif + return 0; } static int i810_dma_initialize(drm_device_t *dev, @@ -284,7 +312,6 @@ static int i810_dma_initialize(drm_device_t *dev, { drm_map_t *sarea_map; - DRM_DEBUG( "i810_dma_init\n"); dev->dev_private = (void *) dev_priv; memset(dev_priv, 0, sizeof(drm_i810_private_t)); @@ -295,12 +322,6 @@ static int i810_dma_initialize(drm_device_t *dev, return -EINVAL; } - if (i810_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) { - i810_dma_cleanup(dev); - DRM_ERROR("Kernel context queue not present\n"); - return -ENOMEM; - } - dev_priv->ring_map_idx = init->ring_map_idx; dev_priv->buffer_map_idx = init->buffer_map_idx; sarea_map = dev->maplist[0]; @@ -308,9 +329,8 @@ static int i810_dma_initialize(drm_device_t *dev, ((u8 *)sarea_map->handle + init->sarea_priv_offset); - atomic_set(&dev_priv->pending_bufs, 0); - atomic_set(&dev_priv->dispatch_lock, 0); - atomic_set(&dev_priv->in_flush, 0); + atomic_set(&dev_priv->flush_done, 0); + init_waitqueue_head(&dev_priv->flush_queue); dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; @@ -339,13 +359,14 @@ static int i810_dma_initialize(drm_device_t *dev, I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); DRM_DEBUG("Enabled hardware status page\n"); -#if 0 - DRM_DEBUG("Doing first ring buffer write\n"); - i810_ring_write_status(dev); - DRM_DEBUG("First ring write succeeded\n"); - i810_print_status_page(dev); - DRM_DEBUG("Status page dump succeeded\n"); -#endif + + /* Now we need to init our freelist */ + if(i810_freelist_init(dev) != 0) { + i810_dma_cleanup(dev); + DRM_ERROR("Not enough space in the status page for" + " the freelist\n"); + return -ENOMEM; + } return 0; } @@ -379,18 +400,16 @@ int i810_dma_init(struct inode *inode, struct file *filp, return retcode; } -static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf) +static inline void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf) { - drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; unsigned long address = (unsigned long)buf->bus_address; unsigned long start = address - dev->agp->base; int length = buf->used; RING_LOCALS; - sarea_priv->last_dispatch = buf_priv->age; - dev_priv->counter++; + dev_priv->counter++; DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); DRM_DEBUG( "i810_dma_dispatch\n"); DRM_DEBUG( "start : 0x%lx\n", start); @@ -398,44 +417,41 @@ static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf) DRM_DEBUG( "start + length - 4 : 0x%lx\n", start + length - 4); i810_kernel_lost_context(dev); - - BEGIN_LP_RING(8); + BEGIN_LP_RING(10); OUT_RING( CMD_OP_BATCH_BUFFER ); OUT_RING( start | BB1_PROTECTED ); OUT_RING( start + length - 4 ); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( 20 ); OUT_RING( dev_priv->counter ); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( buf_priv->my_use_idx ); + OUT_RING( I810_BUF_FREE ); OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT ); - ADVANCE_LP_RING(); - -/* i810_print_status_page(dev); */ + ADVANCE_LP_RING(); } - - - - -static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) +static inline void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) { drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_buf_t *real_buf = dev->dma->buflist[ buf_priv->vertex_real_idx ]; + drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + xf86drmClipRectRec *box = sarea_priv->boxes; + int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)real_buf->bus_address; unsigned long start = address - dev->agp->base; - xf86drmClipRectRec *box = buf_priv->boxes; int length = buf->used; int i = 0; RING_LOCALS; - - if (0) - printk("dispatch vertex %d addr 0x%lx, length 0x%x nbox %d\n", - buf->idx, address, length, buf_priv->nbox); - sarea_priv->last_dispatch = buf_priv->age; - dev_priv->counter++; + + if(nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; + + DRM_DEBUG("dispatch vertex addr 0x%lx, length 0x%x nbox %d\n", + address, length, buf_priv->nbox); + + dev_priv->counter++; DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); DRM_DEBUG( "i810_dma_dispatch\n"); DRM_DEBUG( "start : %lx\n", start); @@ -445,7 +461,7 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) if (!buf_priv->vertex_discard) { do { - if (i < buf_priv->nbox) { + if (i < nbox) { BEGIN_LP_RING(4); OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | SC_ENABLE ); @@ -462,321 +478,54 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) OUT_RING( 0 ); ADVANCE_LP_RING(); - } while (++i < buf_priv->nbox); + } while (++i < nbox); } - BEGIN_LP_RING( 6 ); + BEGIN_LP_RING(8); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( 20 ); OUT_RING( dev_priv->counter ); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( buf_priv->my_use_idx ); + OUT_RING( I810_BUF_FREE ); OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT ); OUT_RING( 0 ); ADVANCE_LP_RING(); } - - - - static inline void i810_dma_quiescent(drm_device_t *dev) { +#if 0 + /* Not written yet */ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - - -/* DRM_DEBUG( "i810_dma_quiescent\n"); */ - while(1) { - atomic_inc(&dev_priv->dispatch_lock); - if(atomic_read(&dev_priv->dispatch_lock) == 1) { - break; - } else { - atomic_dec(&dev_priv->dispatch_lock); - } - } - atomic_dec(&dev_priv->dispatch_lock); -} - -static inline void i810_dma_ready(drm_device_t *dev) -{ - i810_dma_quiescent(dev); -/* DRM_DEBUG( "i810_dma_ready\n"); */ -} - -static inline int i810_dma_is_ready(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; -/* DRM_DEBUG( "i810_dma_is_ready\n"); */ - atomic_inc(&dev_priv->dispatch_lock); - if(atomic_read(&dev_priv->dispatch_lock) == 1) { - /* We got the lock */ - return 1; - } else { - atomic_dec(&dev_priv->dispatch_lock); - return 0; - } -} - -static inline int i810_dma_is_ready_no_hold(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - atomic_inc(&dev_priv->dispatch_lock); - if(atomic_read(&dev_priv->dispatch_lock) == 1) { - /* We got the lock, but free it */ - atomic_dec(&dev_priv->dispatch_lock); - return 1; - } else { - atomic_dec(&dev_priv->dispatch_lock); - return 0; - } +#endif } +/* Interrupts are only for flushing */ static void i810_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; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u16 temp; atomic_inc(&dev->total_irq); -/* DRM_DEBUG("Interrupt Handler\n"); */ -/* i810_print_status_page(dev); */ temp = I810_READ16(I810REG_INT_IDENTITY_R); temp = temp & ~(0x6000); if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, temp); /* Clear all interrupts */ - atomic_dec(&dev_priv->dispatch_lock); - - /* Free previous buffer */ - if (test_and_set_bit(0, &dev->dma_flag)) { - atomic_inc(&dma->total_missed_free); - return; - } - if (dma->this_buffer) { - drm_free_buffer(dev, dma->this_buffer); - dma->this_buffer = NULL; - } - clear_bit(0, &dev->dma_flag); - /* Dispatch new buffer */ queue_task(&dev->tq, &tq_immediate); mark_bh(IMMEDIATE_BH); } -/* Only called by i810_dma_schedule. */ -static int i810_do_dma(drm_device_t *dev, int locked) +static void i810_dma_task_queue(void *device) { - drm_buf_t *buf; - int retcode = 0; - drm_device_dma_t *dma = dev->dma; + drm_device_t *dev = (drm_device_t *) device; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - drm_i810_buf_priv_t *buf_priv; - - - DRM_DEBUG("i810_do_dma\n"); - if (test_and_set_bit(0, &dev->dma_flag)) { - atomic_inc(&dma->total_missed_dma); - return -EBUSY; - } - - if (!dma->next_buffer) { - DRM_ERROR("No next_buffer\n"); - clear_bit(0, &dev->dma_flag); - return -EINVAL; - } - - buf = dma->next_buffer; - - DRM_DEBUG("context %d, buffer %d\n", buf->context, buf->idx); - - if (buf->list == DRM_LIST_RECLAIM) { - drm_clear_next_buffer(dev); - drm_free_buffer(dev, buf); - atomic_dec(&dev_priv->pending_bufs); - DRM_DEBUG("i810_do_dma: pending %d\n",atomic_read( &dev_priv->pending_bufs )); - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - clear_bit(0, &dev->dma_flag); - DRM_DEBUG("RECLIAM\n"); - - return -EINVAL; - } - - if (!buf->used) { - DRM_ERROR("0 length buffer\n"); - drm_clear_next_buffer(dev); - drm_free_buffer(dev, buf); - clear_bit(0, &dev->dma_flag); - DRM_DEBUG("NOT USED\n"); - return 0; - } - - if (i810_dma_is_ready(dev) == 0) { - clear_bit(0, &dev->dma_flag); - DRM_DEBUG("NOT READY\n"); - return -EBUSY; - } - - - DRM_DEBUG("--inflush: %d\n", atomic_read(&dev_priv->in_flush)); - - if ( !locked && - !atomic_read(&dev_priv->in_flush) && - !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) - { - atomic_inc(&dma->total_missed_lock); - clear_bit(0, &dev->dma_flag); - atomic_dec(&dev_priv->dispatch_lock); - DRM_DEBUG("NOT LOCKED\n"); - return -EBUSY; - } - - dma->next_queue = dev->queuelist[DRM_KERNEL_CONTEXT]; - drm_clear_next_buffer(dev); - buf->pending = 1; - buf->waiting = 0; - buf->list = DRM_LIST_PEND; - - buf_priv = buf->dev_private; - - - - - - DRM_DEBUG("i810_do_dma - type %d\n", buf_priv->dma_type); - - switch (buf_priv->dma_type) { - case I810_DMA_GENERAL: - i810_dma_dispatch_general( dev, buf ); - break; - case I810_DMA_VERTEX: - i810_dma_dispatch_vertex( dev, buf ); - break; - default: - DRM_DEBUG("bad buffer type %x in dispatch\n", buf_priv->dma_type); - break; - } - - DRM_DEBUG("DONE\n"); - - atomic_dec(&dev_priv->pending_bufs); - - if(dma->this_buffer) { - drm_free_buffer(dev, dma->this_buffer); - } - - dma->this_buffer = buf; - - atomic_add(buf->used, &dma->total_bytes); - atomic_inc(&dma->total_dmas); - - DRM_DEBUG("inflush: %d\n", atomic_read(&dev_priv->in_flush)); - if (!locked && - !atomic_read(&dev_priv->in_flush)) { - if (drm_lock_free(dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT)) { - DRM_ERROR("\n"); - } - } - - clear_bit(0, &dev->dma_flag); - - DRM_DEBUG("i810_do_dma2: pending %d\n",atomic_read( &dev_priv->pending_bufs )); - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - - /* We hold the dispatch lock until the interrupt handler - * frees it - */ - return retcode; -} - -static void i810_dma_schedule_tq_wrapper(void *dev) -{ - drm_i810_private_t *dev_priv = ((drm_device_t *)dev)->dev_private; - i810_dma_schedule(dev, atomic_read(&dev_priv->in_flush)); -} - -int i810_dma_schedule(drm_device_t *dev, int locked) -{ - drm_queue_t *q; - drm_buf_t *buf; - int retcode = 0; - int processed = 0; - int missed; - int expire = 20; - drm_device_dma_t *dma = dev->dma; - drm_i810_private_t *dev_priv = dev->dev_private; - - - DRM_DEBUG("i810_dma_schedule\n"); - - if (test_and_set_bit(0, &dev->interrupt_flag)) { - /* Not reentrant */ - atomic_inc(&dma->total_missed_sched); - return -EBUSY; - } - missed = atomic_read(&dma->total_missed_sched); - -again: - /* There is only one queue: - */ - if (!dma->next_buffer && DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) { - q = dev->queuelist[DRM_KERNEL_CONTEXT]; - buf = drm_waitlist_get(&q->waitlist); - dma->next_buffer = buf; - dma->next_queue = q; - if (buf && buf->list == DRM_LIST_RECLAIM) { - DRM_DEBUG("reclaiming in i810_dma_schedule\n"); - drm_clear_next_buffer(dev); - drm_free_buffer(dev, buf); - atomic_dec(&dev_priv->pending_bufs); - DRM_DEBUG("fred pending bufs : %d\n", - atomic_read(&dev_priv->pending_bufs)); - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - dma->next_buffer = NULL; - goto again; - } - } - - if (dma->next_buffer) { - if (!(retcode = i810_do_dma(dev, locked))) - ++processed; - } - DRM_DEBUG("ixxx810_do_dma: pending %d\n",atomic_read( &dev_priv->pending_bufs )); - - if(!(atomic_read(&dev_priv->pending_bufs))) { - wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue); - } - - - /* Try again if we succesfully dispatched a buffer, or if someone - * tried to schedule while we were working. - */ - if (--expire) { - if (missed != atomic_read(&dma->total_missed_sched)) { - atomic_inc(&dma->total_lost); - if (i810_dma_is_ready_no_hold(dev)) - goto again; - } - - if (processed && i810_dma_is_ready_no_hold(dev)) { - atomic_inc(&dma->total_lost); - processed = 0; - goto again; - } - } - - clear_bit(0, &dev->interrupt_flag); - - return retcode; + atomic_set(&dev_priv->flush_done, 1); + wake_up_interruptible(&dev_priv->flush_queue); } - int i810_irq_install(drm_device_t *dev, int irq) { int retcode; @@ -793,6 +542,7 @@ int i810_irq_install(drm_device_t *dev, int irq) up(&dev->struct_sem); DRM_DEBUG( "Interrupt Install : %d\n", irq); + DRM_DEBUG("%d\n", irq); dev->context_flag = 0; dev->interrupt_flag = 0; @@ -804,7 +554,7 @@ int i810_irq_install(drm_device_t *dev, int irq) dev->tq.next = NULL; dev->tq.sync = 0; - dev->tq.routine = i810_dma_schedule_tq_wrapper; + dev->tq.routine = i810_dma_task_queue; dev->tq.data = dev; /* Before installing handler */ @@ -832,9 +582,9 @@ int i810_irq_install(drm_device_t *dev, int irq) } temp = I810_READ16(I810REG_INT_ENABLE_R); temp = temp & 0x6000; - temp = temp | 0x0001; + temp = temp | 0x0003; I810_WRITE16(I810REG_INT_ENABLE_R, - 0x0001); /* Enable bp interrupts */ + temp); /* Enable bp & user interrupts */ return 0; } @@ -851,6 +601,9 @@ int i810_irq_uninstall(drm_device_t *dev) if (!irq) return -EINVAL; DRM_DEBUG( "Interrupt UnInstall: %d\n", irq); + + + DRM_DEBUG("%d\n", irq); temp = I810_READ16(I810REG_INT_IDENTITY_R); temp = temp & ~(0x6000); @@ -875,7 +628,7 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_control_t ctl; int retcode; -/* DRM_DEBUG( "i810_control\n"); */ + DRM_DEBUG( "i810_control\n"); copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); @@ -894,44 +647,85 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int i810_flush_queue(drm_device_t *dev) +static inline void i810_dma_emit_flush(drm_device_t *dev) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + i810_kernel_lost_context(dev); + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); +#if 1 + OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT ); +#else + OUT_RING( GFX_OP_USER_INTERRUPT ); +#endif + ADVANCE_LP_RING(); +} + +static int i810_flush_queue(drm_device_t *dev) { DECLARE_WAITQUEUE(entry, current); - drm_queue_t *q = dev->queuelist[DRM_KERNEL_CONTEXT]; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; int ret = 0; - - DRM_DEBUG("i810_flush_queue\n"); - DRM_DEBUG("pending_bufs : %d\n", atomic_read(&dev_priv->pending_bufs)); - if(atomic_read(&dev_priv->pending_bufs) != 0) { - DRM_DEBUG("got to flush\n"); - current->state = TASK_INTERRUPTIBLE; - add_wait_queue(&q->flush_queue, &entry); - for (;;) { - if (!atomic_read(&dev_priv->pending_bufs)) break; - DRM_DEBUG("Calling schedule from flush_queue : %d\n", - atomic_read(&dev_priv->pending_bufs)); - i810_dma_schedule(dev, 0); + +#if 0 + printk("i810_flush_queue\n"); +#endif + if(dev_priv == NULL) { + return 0; + } + atomic_set(&dev_priv->flush_done, 0); +#if 0 + printk("got to flush\n"); +#endif + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&dev_priv->flush_queue, &entry); + for (;;) { + i810_dma_emit_flush(dev); + if (atomic_read(&dev_priv->flush_done) == 1) break; schedule_timeout(DRM_LOCK_SLICE); if (signal_pending(current)) { ret = -EINTR; /* Can't restart */ break; } } - DRM_DEBUG("Exited out of schedule from flush_queue\n"); - current->state = TASK_RUNNING; - remove_wait_queue(&q->flush_queue, &entry); - } + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->flush_queue, &entry); return ret; } +/* Must be called with the lock held */ +void i810_reclaim_buffers(drm_device_t *dev, pid_t pid) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + if (!dma) return; + if(dev->dev_private == NULL) return; + + i810_flush_queue(dev); + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + + if (buf->pid == pid) { + /* Only buffers that need to get reclaimed ever + * get set to free */ + if(buf_priv == NULL) return; + cmpxchg(buf_priv->in_use, + I810_BUF_USED, I810_BUF_FREE); + } + } +} + int i810_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; - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; DECLARE_WAITQUEUE(entry, current); int ret = 0; @@ -952,11 +746,21 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, if (lock.context < 0) { return -EINVAL; } - /* Only one queue: */ 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 (;;) { if (!dev->lock.hw_lock) { @@ -975,7 +779,9 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); current->state = TASK_INTERRUPTIBLE; +#if 0 current->policy |= SCHED_YIELD; +#endif DRM_DEBUG("Calling lock schedule\n"); schedule(); if (signal_pending(current)) { @@ -990,10 +796,8 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, if (!ret) { if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); - atomic_set(&dev_priv->in_flush, 1); i810_flush_queue(dev); i810_dma_quiescent(dev); - atomic_set(&dev_priv->in_flush, 0); } } DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); @@ -1005,12 +809,153 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; DRM_DEBUG("i810_flush_ioctl\n"); - atomic_set(&dev_priv->in_flush, 1); i810_flush_queue(dev); i810_dma_quiescent(dev); - atomic_set(&dev_priv->in_flush, 0); return 0; } + +static int i810DmaGeneral(drm_device_t *dev, drm_i810_general_t *args) +{ + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf = dma->buflist[ args->idx ]; + + buf->used = args->used; + + DRM_DEBUG("i810DmaGeneral idx %d used %d\n", args->idx, buf->used); + + if (!buf->used) { + DRM_ERROR("0 length buffer\n"); + i810_freelist_put(dev, buf); + return 0; + } + + i810_dma_dispatch_general( dev, buf ); + atomic_add(buf->used, &dma->total_bytes); + atomic_inc(&dma->total_dmas); + + return 0; +} + +static int i810DmaVertex(drm_device_t *dev, drm_i810_vertex_t *args) +{ + drm_device_dma_t *dma = dev->dma; + drm_i810_buf_priv_t *buf_priv; + drm_buf_t *buf; + + + buf = dma->buflist[ args->idx ]; + buf->used = args->real_used; + + DRM_DEBUG("i810DmaVertex idx %d used %d\n", args->idx, buf->used); + + buf_priv = buf->dev_private; + buf_priv->vertex_real_idx = args->real_idx; + buf_priv->vertex_discard = args->discard; + + i810_dma_dispatch_vertex( dev, buf); + atomic_add(buf->used, &dma->total_bytes); + atomic_inc(&dma->total_dmas); + return 0; +} + +int i810_dma_general(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_i810_general_t general; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + + int retcode = 0; + + copy_from_user_ret(&general, (drm_i810_general_t *)arg, sizeof(general), + -EFAULT); + + DRM_DEBUG("i810 dma general idx %d used %d\n", + general.idx, general.used); + + retcode = i810DmaGeneral(dev, &general); + sarea_priv->last_dispatch = (int) hw_status[5]; + + return retcode; +} + +int i810_dma_vertex(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + drm_i810_vertex_t vertex; + int retcode = 0; + + copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex), + -EFAULT); + + DRM_DEBUG("i810 dma vertex, idx %d used %d real_idx %d discard %d\n", + vertex.idx, vertex.real_used, vertex.real_idx, + vertex.discard); + + retcode = i810DmaVertex(dev, &vertex); + sarea_priv->last_dispatch = (int) hw_status[5]; + + return retcode; + +} + +int i810_dma(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_device_dma_t *dma = dev->dma; + int retcode = 0; + drm_dma_t d; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + + + copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); + DRM_DEBUG("%d %d: %d send, %d req\n", + current->pid, d.context, d.send_count, d.request_count); + + /* Please don't send us buffers. + */ + if (d.send_count != 0) { + DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", + current->pid, d.send_count); + return -EINVAL; + } + + /* We'll send you buffers. + */ + 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); + return -EINVAL; + } + + d.granted_count = 0; + + if (!retcode && d.request_count) { + retcode = i810_dma_get_buffers(dev, &d); + } + + DRM_DEBUG("i810_dma: %d returning, granted = %d\n", + current->pid, d.granted_count); + + copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); + sarea_priv->last_dispatch = (int) hw_status[5]; + + return retcode; +} diff --git a/linux/i810_dma.h b/linux/i810_dma.h index 11c2e28c..ecc0ffdf 100644 --- a/linux/i810_dma.h +++ b/linux/i810_dma.h @@ -40,10 +40,10 @@ * 'vertex_dma' ioctl. */ typedef struct { - int dma_type; - int age; int vertex_real_idx; int vertex_discard; + u32 *in_use; + int my_use_idx; unsigned int nbox; xf86drmClipRectRec boxes[I810_NR_SAREA_CLIPRECTS]; } drm_i810_buf_priv_t; @@ -53,8 +53,6 @@ typedef struct { #define I810_DMA_VERTEX 1 #define I810_DMA_DISCARD 2 /* not used */ - - #define I810_VERBOSE 0 diff --git a/linux/i810_drm_public.h b/linux/i810_drm_public.h index 68714ae9..9ed8bef6 100644 --- a/linux/i810_drm_public.h +++ b/linux/i810_drm_public.h @@ -53,27 +53,22 @@ typedef struct _xf86drmClipRectRec { unsigned short y2; } xf86drmClipRectRec; - /* Might one day want to support the client-side ringbuffer code again. */ + #define I810_USE_BATCH 1 -/* 32 16k dma buffers -- 512k - */ #define I810_DMA_BUF_ORDER 14 #define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER) #define I810_DMA_BUF_NR 32 #define I810_NR_SAREA_CLIPRECTS 2 - /* Each region is a minimum of 64k, and there are at most 128 of them. */ #define I810_NR_TEX_REGIONS 128 #define I810_LOG_MIN_TEX_REGION_SIZE 16 - - typedef struct { unsigned char next, prev; /* indices to form a circular LRU */ unsigned char in_use; /* owned by a client, or free? */ @@ -99,22 +94,21 @@ typedef struct { * else's - simply eject them all in LRU order. */ i810TexRegion texList[I810_NR_TEX_REGIONS+1]; /* Last elt is sentinal */ + int texAge; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ int last_dispatch; /* age of the most recently dispatched buffer */ int last_quiescent; /* */ - int ctxOwner; /* last 3d context to hold lock */ - - + int ctxOwner; /* last context to upload state */ } drm_i810_sarea_t; typedef struct { int idx; int used; - int age; + int age; } drm_i810_general_t; @@ -139,5 +133,5 @@ typedef struct { #define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) #define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) #define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t) -#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43 ) +#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) #endif /* _I810_DRM_H_ */ diff --git a/linux/i810_drv.c b/linux/i810_drv.c index 49a3c995..85a5b05e 100644 --- a/linux/i810_drv.c +++ b/linux/i810_drv.c @@ -585,24 +585,82 @@ int i810_release(struct inode *inode, struct file *filp) drm_device_t *dev = priv->dev; int retcode = 0; - DRM_DEBUG("open_count = %d\n", dev->open_count); - if (!(retcode = drm_release(inode, filp))) { - MOD_DEC_USE_COUNT; - atomic_inc(&dev->total_close); - 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); - spin_unlock(&dev->count_lock); - return -EBUSY; + DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", + current->pid, dev->device, dev->open_count); + + if (_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) + && dev->lock.pid == current->pid) { + i810_reclaim_buffers(dev, priv->pid); + DRM_ERROR("Process %d dead, freeing lock for context %d\n", + current->pid, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + drm_lock_free(dev, + &dev->lock.hw_lock->lock, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + + /* FIXME: may require heavy-handed reset of + hardware at this point, possibly + processed via a callback to the X + server. */ + } else { + /* The lock is required to reclaim buffers */ + DECLARE_WAITQUEUE(entry, current); + add_wait_queue(&dev->lock.lock_queue, &entry); + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + retcode = -EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + dev->lock.pid = priv->pid; + dev->lock.lock_time = jiffies; + atomic_inc(&dev->total_locks); + break; /* Got lock */ + } + /* Contention */ + atomic_inc(&dev->total_sleeps); + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (signal_pending(current)) { + retcode = -ERESTARTSYS; + break; } - spin_unlock(&dev->count_lock); - return i810_takedown(dev); } - spin_unlock(&dev->count_lock); + current->state = TASK_RUNNING; + remove_wait_queue(&dev->lock.lock_queue, &entry); + if(!retcode) { + i810_reclaim_buffers(dev, priv->pid); + drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT); + } + } + drm_fasync(-1, filp, 0); + + down(&dev->struct_sem); + if (priv->prev) priv->prev->next = priv->next; + else dev->file_first = priv->next; + if (priv->next) priv->next->prev = priv->prev; + else dev->file_last = priv->prev; + up(&dev->struct_sem); + + drm_free(priv, sizeof(*priv), DRM_MEM_FILES); + MOD_DEC_USE_COUNT; + atomic_inc(&dev->total_close); + 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); + spin_unlock(&dev->count_lock); + return -EBUSY; + } + spin_unlock(&dev->count_lock); + return i810_takedown(dev); } + spin_unlock(&dev->count_lock); return retcode; } @@ -667,8 +725,7 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, atomic_inc(&dev->total_unlocks); if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) atomic_inc(&dev->total_contends); - drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); - i810_dma_schedule(dev, 1); + drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); if (!dev->context_flag) { if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { diff --git a/linux/i810_drv.h b/linux/i810_drv.h index 2cbcc061..36d477a4 100644 --- a/linux/i810_drv.h +++ b/linux/i810_drv.h @@ -54,10 +54,8 @@ typedef struct drm_i810_private { unsigned long hw_status_page; unsigned long counter; - atomic_t dispatch_lock; - atomic_t pending_bufs; - atomic_t in_flush; - + atomic_t flush_done; + wait_queue_head_t flush_queue; /* Processes waiting until flush */ } drm_i810_private_t; /* i810_drv.c */ @@ -86,6 +84,8 @@ extern int i810_dma_init(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_flush_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid); + /* i810_bufs.c */ extern int i810_addbufs(struct inode *inode, struct file *filp, diff --git a/linux/mga_dma.c b/linux/mga_dma.c index 683260d1..a424e2f6 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -1419,6 +1419,7 @@ int mga_flush_queue(drm_device_t *dev) atomic_read(&dev_priv->pending_bufs)); mga_dma_schedule(dev, 0); schedule_timeout((HZ/60)); + atomic_inc(&dev->total_sleeps); if (signal_pending(current)) { ret = -EINTR; /* Can't restart */ break; |