patch-2.4.0-test9 linux/drivers/char/drm/mga_dma.c
Next file: linux/drivers/char/drm/mga_drm.h
Previous file: linux/drivers/char/drm/mga_context.c
Back to the patch index
Back to the overall index
- Lines: 993
- Date:
Sun Oct 1 20:00:00 2000
- Orig file:
v2.4.0-test8/linux/drivers/char/drm/mga_dma.c
- Orig date:
Tue Aug 29 21:09:10 2000
diff -u --recursive --new-file v2.4.0-test8/linux/drivers/char/drm/mga_dma.c linux/drivers/char/drm/mga_dma.c
@@ -11,11 +11,11 @@
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -51,53 +51,30 @@
static unsigned long mga_alloc_page(drm_device_t *dev)
{
unsigned long address;
-
- DRM_DEBUG("%s\n", __FUNCTION__);
+
address = __get_free_page(GFP_KERNEL);
if(address == 0UL) {
return 0;
}
atomic_inc(&virt_to_page(address)->count);
- set_bit(PG_locked, &virt_to_page(address)->flags);
-
+ set_bit(PG_reserved, &virt_to_page(address)->flags);
+
return address;
}
static void mga_free_page(drm_device_t *dev, unsigned long page)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
-
- if(page == 0UL) {
- return;
- }
+ if(!page) return;
atomic_dec(&virt_to_page(page)->count);
- clear_bit(PG_locked, &virt_to_page(page)->flags);
- wake_up(&virt_to_page(page)->wait);
+ clear_bit(PG_reserved, &virt_to_page(page)->flags);
free_page(page);
return;
}
static void mga_delay(void)
{
- return;
-}
-
-#ifdef __i386__
-void mga_flush_write_combine(void)
-{
- int xchangeDummy;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
- __asm__ volatile(" push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy));
- __asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;"
- " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;"
- " pop %%eax" : /* no outputs */ : /* no inputs */ );
-}
-#else
-void mga_flush_write_combine(void)
-{
+ return;
}
-#endif
/* These are two age tags that will never be sent to
* the hardware */
@@ -113,13 +90,11 @@
drm_mga_freelist_t *item;
int i;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
if(dev_priv->head == NULL) return -ENOMEM;
memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
dev_priv->head->age = MGA_BUF_USED;
-
+
for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[ i ];
buf_priv = buf->dev_private;
@@ -139,7 +114,7 @@
buf_priv->dispatched = 0;
dev_priv->head->next = item;
}
-
+
return 0;
}
@@ -149,15 +124,13 @@
drm_mga_freelist_t *item;
drm_mga_freelist_t *prev;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
item = dev_priv->head;
while(item) {
prev = item;
item = item->next;
drm_free(prev, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
}
-
+
dev_priv->head = dev_priv->tail = NULL;
}
@@ -170,19 +143,21 @@
unsigned long end;
int i;
- DRM_DEBUG("%s\n", __FUNCTION__);
+ DRM_DEBUG("dispatch_status = 0x%02x\n", dev_priv->dispatch_status);
end = jiffies + (HZ*3);
while(1) {
- if(!test_and_set_bit(MGA_IN_DISPATCH,
+ if(!test_and_set_bit(MGA_IN_DISPATCH,
&dev_priv->dispatch_status)) {
break;
}
if((signed)(end - jiffies) <= 0) {
- DRM_ERROR("irqs: %d wanted %d\n",
- atomic_read(&dev->total_irq),
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup\n");
- goto out_nolock;
+ DRM_ERROR("lockup: dispatch_status = 0x%02x,"
+ " jiffies = %lu, end = %lu\n",
+ dev_priv->dispatch_status, jiffies, end);
+ return;
}
for (i = 0 ; i < 2000 ; i++) mga_delay();
}
@@ -190,19 +165,20 @@
DRM_DEBUG("quiescent status : %x\n", MGA_READ(MGAREG_STATUS));
while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) {
if((signed)(end - jiffies) <= 0) {
- DRM_ERROR("irqs: %d wanted %d\n",
- atomic_read(&dev->total_irq),
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup\n");
- goto out_status;
+ DRM_ERROR("lockup\n");
+ clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
+ return;
}
- for (i = 0 ; i < 2000 ; i++) mga_delay();
+ for (i = 0 ; i < 2000 ; i++) mga_delay();
}
sarea_priv->dirty |= MGA_DMA_FLUSH;
-out_status:
clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
-out_nolock:
+ DRM_DEBUG("exit, dispatch_status = 0x%02x\n",
+ dev_priv->dispatch_status);
}
static void mga_reset_freelist(drm_device_t *dev)
@@ -220,44 +196,44 @@
}
/* Least recently used :
- * These operations are not atomic b/c they are protected by the
+ * These operations are not atomic b/c they are protected by the
* hardware lock */
drm_buf_t *mga_freelist_get(drm_device_t *dev)
{
DECLARE_WAITQUEUE(entry, current);
- drm_mga_private_t *dev_priv =
+ drm_mga_private_t *dev_priv =
(drm_mga_private_t *) dev->dev_private;
drm_mga_freelist_t *prev;
drm_mga_freelist_t *next;
static int failed = 0;
+ int return_null = 0;
- DRM_DEBUG("%s : tail->age : %d last_prim_age : %d\n", __FUNCTION__,
- dev_priv->tail->age, dev_priv->last_prim_age);
-
if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) {
- DRM_DEBUG("I'm waiting on the freelist!!! %d\n",
- dev_priv->last_prim_age);
- set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
- current->state = TASK_INTERRUPTIBLE;
+ DRM_DEBUG("Waiting on freelist,"
+ " tail->age = %d, last_prim_age= %d\n",
+ dev_priv->tail->age,
+ dev_priv->last_prim_age);
add_wait_queue(&dev_priv->buf_queue, &entry);
+ set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
mga_dma_schedule(dev, 0);
- if(!test_bit(MGA_IN_GETBUF,
- &dev_priv->dispatch_status))
+ if(dev_priv->tail->age < dev_priv->last_prim_age)
break;
atomic_inc(&dev->total_sleeps);
schedule();
if (signal_pending(current)) {
- clear_bit(MGA_IN_GETBUF,
- &dev_priv->dispatch_status);
- goto failed_getbuf;
+ ++return_null;
+ break;
}
}
- current->state = TASK_RUNNING;
+ clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
+ current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->buf_queue, &entry);
+ if (return_null) return NULL;
}
-
+
if(dev_priv->tail->age < dev_priv->last_prim_age) {
prev = dev_priv->tail->prev;
next = dev_priv->tail;
@@ -269,22 +245,19 @@
return next->buf;
}
-failed_getbuf:
failed++;
return NULL;
}
int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf)
{
- drm_mga_private_t *dev_priv =
+ drm_mga_private_t *dev_priv =
(drm_mga_private_t *) dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
drm_mga_freelist_t *prev;
drm_mga_freelist_t *head;
drm_mga_freelist_t *next;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if(buf_priv->my_freelist->age == MGA_BUF_USED) {
/* Discarded buffer, put it on the tail */
next = buf_priv->my_freelist;
@@ -294,7 +267,6 @@
next->prev = prev;
next->next = NULL;
dev_priv->tail = next;
- DRM_DEBUG("Discarded\n");
} else {
/* Normally aged buffer, put it on the head + 1,
* as the real head is a sentinal element
@@ -307,7 +279,7 @@
next->prev = head;
next->next = prev;
}
-
+
return 0;
}
@@ -318,42 +290,41 @@
int i, temp, size_of_buf;
int offset = init->reserved_map_agpstart;
- DRM_DEBUG("%s\n", __FUNCTION__);
- dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
+ dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
PAGE_SIZE) * PAGE_SIZE;
size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS;
dev_priv->warp_ucode_size = init->warp_ucode_size;
- dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) *
- (MGA_NUM_PRIM_BUFS + 1),
+ dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) *
+ (MGA_NUM_PRIM_BUFS + 1),
DRM_MEM_DRIVER);
if(dev_priv->prim_bufs == NULL) {
DRM_ERROR("Unable to allocate memory for prim_buf\n");
return -ENOMEM;
}
- memset(dev_priv->prim_bufs,
+ memset(dev_priv->prim_bufs,
0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1));
-
+
temp = init->warp_ucode_size + dev_priv->primary_size;
temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
-
- dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
+
+ dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
temp);
if(dev_priv->ioremap == NULL) {
- DRM_DEBUG("Ioremap failed\n");
+ DRM_ERROR("Ioremap failed\n");
return -ENOMEM;
}
init_waitqueue_head(&dev_priv->wait_queue);
-
+
for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
- prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t),
+ prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t),
DRM_MEM_DRIVER);
if(prim_buffer == NULL) return -ENOMEM;
memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t));
prim_buffer->phys_head = offset + dev->agp->base;
- prim_buffer->current_dma_ptr =
- prim_buffer->head =
- (u32 *) (dev_priv->ioremap +
- offset -
+ prim_buffer->current_dma_ptr =
+ prim_buffer->head =
+ (u32 *) (dev_priv->ioremap +
+ offset -
init->reserved_map_agpstart);
prim_buffer->num_dwords = 0;
prim_buffer->max_dwords = size_of_buf / sizeof(u32);
@@ -365,11 +336,11 @@
dev_priv->prim_bufs[i] = prim_buffer;
}
dev_priv->current_prim_idx = 0;
- dev_priv->next_prim =
- dev_priv->last_prim =
+ dev_priv->next_prim =
+ dev_priv->last_prim =
dev_priv->current_prim =
dev_priv->prim_bufs[0];
- dev_priv->next_prim_age = 2;
+ dev_priv->next_prim_age = 2;
dev_priv->last_prim_age = 1;
set_bit(MGA_BUF_IN_USE, &dev_priv->current_prim->buffer_status);
return 0;
@@ -386,13 +357,12 @@
int next_idx;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
dev_priv->last_prim = prim;
-
+
/* We never check for overflow, b/c there is always room */
PRIMPTR(prim);
if(num_dwords <= 0) {
- DRM_DEBUG("num_dwords == 0 when dispatched\n");
+ DRM_ERROR("num_dwords == 0 when dispatched\n");
goto out_prim_wait;
}
PRIMOUTREG( MGAREG_DMAPAD, 0);
@@ -403,32 +373,28 @@
end = jiffies + (HZ*3);
if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) {
if((signed)(end - jiffies) <= 0) {
- DRM_ERROR("irqs: %d wanted %d\n",
- atomic_read(&dev->total_irq),
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup in fire primary "
- "(Dma Top Flush)\n");
+ DRM_ERROR("lockup (flush)\n");
goto out_prim_wait;
}
-
+
for (i = 0 ; i < 4096 ; i++) mga_delay();
}
sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
} else {
- DRM_DEBUG("Status wait\n");
while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) {
if((signed)(end - jiffies) <= 0) {
- DRM_ERROR("irqs: %d wanted %d\n",
- atomic_read(&dev->total_irq),
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup in fire primary "
- "(Status Wait)\n");
+ DRM_ERROR("lockup (wait)\n");
goto out_prim_wait;
}
-
+
for (i = 0 ; i < 4096 ; i++) mga_delay();
}
}
@@ -439,9 +405,9 @@
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
prim->num_dwords = 0;
sarea_priv->last_enqueue = prim->prim_age;
-
+
next_idx = prim->idx + 1;
- if(next_idx >= MGA_NUM_PRIM_BUFS)
+ if(next_idx >= MGA_NUM_PRIM_BUFS)
next_idx = 0;
dev_priv->next_prim = dev_priv->prim_bufs[next_idx];
@@ -464,28 +430,26 @@
drm_device_dma_t *dma = dev->dma;
int next_prim_idx;
int ret = 0;
-
+
/* This needs to reset the primary buffer if available,
* we should collect stats on how many times it bites
* it's tail */
- DRM_DEBUG("%s\n", __FUNCTION__);
-
+
next_prim_idx = dev_priv->current_prim_idx + 1;
if(next_prim_idx >= MGA_NUM_PRIM_BUFS)
next_prim_idx = 0;
prim_buffer = dev_priv->prim_bufs[next_prim_idx];
set_bit(MGA_IN_WAIT, &dev_priv->dispatch_status);
-
+
/* In use is cleared in interrupt handler */
-
+
if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) {
add_wait_queue(&dev_priv->wait_queue, &entry);
- current->state = TASK_INTERRUPTIBLE;
-
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
mga_dma_schedule(dev, 0);
- if(!test_and_set_bit(MGA_BUF_IN_USE,
- &prim_buffer->buffer_status))
+ if(!test_and_set_bit(MGA_BUF_IN_USE,
+ &prim_buffer->buffer_status))
break;
atomic_inc(&dev->total_sleeps);
atomic_inc(&dma->total_missed_sched);
@@ -495,7 +459,7 @@
break;
}
}
- current->state = TASK_RUNNING;
+ current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->wait_queue, &entry);
if(ret) return ret;
}
@@ -507,10 +471,10 @@
prim_buffer->sec_used = 0;
prim_buffer->prim_age = dev_priv->next_prim_age++;
if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) {
- mga_flush_queue(dev);
- mga_dma_quiescent(dev);
- mga_reset_freelist(dev);
- prim_buffer->prim_age = (dev_priv->next_prim_age += 2);
+ mga_flush_queue(dev);
+ mga_dma_quiescent(dev);
+ mga_reset_freelist(dev);
+ prim_buffer->prim_age = (dev_priv->next_prim_age += 2);
}
/* Reset all buffer status stuff */
@@ -527,88 +491,72 @@
static inline int mga_decide_to_fire(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
-
- DRM_DEBUG("%s\n", __FUNCTION__);
if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) {
- atomic_inc(&dma->total_prio);
return 1;
}
if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
dev_priv->next_prim->num_dwords) {
- atomic_inc(&dma->total_prio);
return 1;
}
if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
dev_priv->next_prim->num_dwords) {
- atomic_inc(&dma->total_prio);
return 1;
}
-
+
if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS - 1) {
- if(test_bit(MGA_BUF_SWAP_PENDING,
+ if(test_bit(MGA_BUF_SWAP_PENDING,
&dev_priv->next_prim->buffer_status)) {
- atomic_inc(&dma->total_dmas);
return 1;
}
}
if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS / 2) {
if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 8) {
- atomic_inc(&dma->total_hit);
return 1;
}
}
if(atomic_read(&dev_priv->pending_bufs) >= MGA_NUM_PRIM_BUFS / 2) {
if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 4) {
- atomic_inc(&dma->total_missed_free);
return 1;
}
}
- atomic_inc(&dma->total_tried);
return 0;
}
int mga_dma_schedule(drm_device_t *dev, int locked)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- int retval = 0;
+ int retval = 0;
- if (test_and_set_bit(0, &dev->dma_flag)) {
- atomic_inc(&dma->total_missed_dma);
+ if (!dev_priv) return -EBUSY;
+
+ if (test_and_set_bit(0, &dev->dma_flag)) {
retval = -EBUSY;
goto sch_out_wakeup;
}
-
- DRM_DEBUG("%s\n", __FUNCTION__);
- if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) ||
+ if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) ||
test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) ||
test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
locked = 1;
}
-
- if (!locked &&
+
+ if (!locked &&
!drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
- atomic_inc(&dma->total_missed_lock);
clear_bit(0, &dev->dma_flag);
- DRM_DEBUG("Not locked\n");
retval = -EBUSY;
goto sch_out_wakeup;
}
- DRM_DEBUG("I'm locked\n");
if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) {
/* Fire dma buffer */
if(mga_decide_to_fire(dev)) {
- DRM_DEBUG("idx :%d\n", dev_priv->next_prim->idx);
- clear_bit(MGA_BUF_FORCE_FIRE,
+ clear_bit(MGA_BUF_FORCE_FIRE,
&dev_priv->next_prim->buffer_status);
if(dev_priv->current_prim == dev_priv->next_prim) {
/* Schedule overflow for a later time */
@@ -619,10 +567,8 @@
} else {
clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
}
- } else {
- DRM_DEBUG("I can't get the dispatch lock\n");
}
-
+
if (!locked) {
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT)) {
@@ -630,6 +576,8 @@
}
}
+ clear_bit(0, &dev->dma_flag);
+
sch_out_wakeup:
if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
atomic_read(&dev_priv->pending_bufs) == 0) {
@@ -638,18 +586,10 @@
wake_up_interruptible(&dev_priv->flush_queue);
}
- if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
- dev_priv->tail->age < dev_priv->last_prim_age) {
- clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
- DRM_DEBUG("Waking up buf queue\n");
+ if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)
+ && dev_priv->tail->age < dev_priv->last_prim_age)
wake_up_interruptible(&dev_priv->buf_queue);
- } else if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
- DRM_DEBUG("Not waking buf_queue on %d %d\n",
- atomic_read(&dev->total_irq),
- dev_priv->last_prim_age);
- }
- clear_bit(0, &dev->dma_flag);
return retval;
}
@@ -659,41 +599,40 @@
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
drm_mga_prim_buf_t *last_prim_buffer;
- DRM_DEBUG("%s\n", __FUNCTION__);
atomic_inc(&dev->total_irq);
if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return;
MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
last_prim_buffer = dev_priv->last_prim;
last_prim_buffer->num_dwords = 0;
last_prim_buffer->sec_used = 0;
- dev_priv->sarea_priv->last_dispatch =
+ dev_priv->sarea_priv->last_dispatch =
dev_priv->last_prim_age = last_prim_buffer->prim_age;
clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status);
- wake_up_interruptible(&dev_priv->wait_queue);
clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status);
clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
atomic_dec(&dev_priv->pending_bufs);
queue_task(&dev->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
+ wake_up_interruptible(&dev_priv->wait_queue);
}
static void mga_dma_task_queue(void *device)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
mga_dma_schedule((drm_device_t *)device, 0);
}
int mga_dma_cleanup(drm_device_t *dev)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if(dev->dev_private) {
- drm_mga_private_t *dev_priv =
+ drm_mga_private_t *dev_priv =
(drm_mga_private_t *) dev->dev_private;
-
+
+ if (dev->irq) mga_flush_queue(dev);
+ mga_dma_quiescent(dev);
+
if(dev_priv->ioremap) {
- int temp = (dev_priv->warp_ucode_size +
- dev_priv->primary_size +
+ int temp = (dev_priv->warp_ucode_size +
+ dev_priv->primary_size +
PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
drm_ioremapfree((void *) dev_priv->ioremap, temp);
@@ -714,7 +653,7 @@
}
}
drm_free(dev_priv->prim_bufs, sizeof(void *) *
- (MGA_NUM_PRIM_BUFS + 1),
+ (MGA_NUM_PRIM_BUFS + 1),
DRM_MEM_DRIVER);
}
if(dev_priv->head != NULL) {
@@ -722,7 +661,7 @@
}
- drm_free(dev->dev_private, sizeof(drm_mga_private_t),
+ drm_free(dev->dev_private, sizeof(drm_mga_private_t),
DRM_MEM_DRIVER);
dev->dev_private = NULL;
}
@@ -733,9 +672,6 @@
static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
drm_mga_private_t *dev_priv;
drm_map_t *sarea_map = NULL;
- int i;
-
- DRM_DEBUG("%s\n", __FUNCTION__);
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
if(dev_priv == NULL) return -ENOMEM;
@@ -746,15 +682,14 @@
if((init->reserved_map_idx >= dev->map_count) ||
(init->buffer_map_idx >= dev->map_count)) {
mga_dma_cleanup(dev);
- DRM_DEBUG("reserved_map or buffer_map are invalid\n");
return -EINVAL;
}
-
+
dev_priv->reserved_map_idx = init->reserved_map_idx;
dev_priv->buffer_map_idx = init->buffer_map_idx;
sarea_map = dev->maplist[0];
- dev_priv->sarea_priv = (drm_mga_sarea_t *)
- ((u8 *)sarea_map->handle +
+ dev_priv->sarea_priv = (drm_mga_sarea_t *)
+ ((u8 *)sarea_map->handle +
init->sarea_priv_offset);
/* Scale primary size to the next page */
@@ -772,23 +707,17 @@
init_waitqueue_head(&dev_priv->flush_queue);
init_waitqueue_head(&dev_priv->buf_queue);
dev_priv->WarpPipe = 0xff000000;
+ dev_priv->vertexsize = 0;
- DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n",
- dev_priv->chipset, dev_priv->warp_ucode_size,
+ DRM_DEBUG("chipset=%d ucode_size=%d backOffset=%x depthOffset=%x\n",
+ dev_priv->chipset, dev_priv->warp_ucode_size,
dev_priv->backOffset, dev_priv->depthOffset);
DRM_DEBUG("cpp: %d sgram: %d stride: %d maccess: %x\n",
- dev_priv->cpp, dev_priv->sgram, dev_priv->stride,
+ dev_priv->cpp, dev_priv->sgram, dev_priv->stride,
dev_priv->mAccess);
-
- memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
- sizeof(drm_mga_warp_index_t) * MGA_MAX_WARP_PIPES);
- for (i = 0 ; i < MGA_MAX_WARP_PIPES ; i++)
- DRM_DEBUG("warp pipe %d: installed: %d phys: %lx size: %x\n",
- i,
- dev_priv->WarpIndex[i].installed,
- dev_priv->WarpIndex[i].phys_addr,
- dev_priv->WarpIndex[i].size);
+ memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
+ sizeof(drm_mga_warp_index_t) * MGA_MAX_WARP_PIPES);
if(mga_init_primary_bufs(dev, init) != 0) {
DRM_ERROR("Can not initialize primary buffers\n");
@@ -802,7 +731,7 @@
return -ENOMEM;
}
- dev_priv->status_page =
+ dev_priv->status_page =
ioremap_nocache(virt_to_bus((void *)dev_priv->real_status_page),
PAGE_SIZE);
@@ -813,15 +742,15 @@
}
/* Write status page when secend or softrap occurs */
- MGA_WRITE(MGAREG_PRIMPTR,
+ MGA_WRITE(MGAREG_PRIMPTR,
virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003);
-
+
/* Private is now filled in, initialize the hardware */
{
PRIMLOCALS;
PRIMGETPTR( dev_priv );
-
+
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DWGSYNC, 0x0100);
@@ -829,13 +758,13 @@
/* Poll for the first buffer to insure that
* the status register will be correct
*/
-
+
mga_flush_write_combine();
MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) |
+ MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) |
PDEA_pagpxfer_enable));
-
+
while(MGA_READ(MGAREG_DWGSYNC) != 0x0100) ;
}
@@ -853,12 +782,10 @@
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_mga_init_t init;
-
- DRM_DEBUG("%s\n", __FUNCTION__);
if (copy_from_user(&init, (drm_mga_init_t *)arg, sizeof(init)))
return -EFAULT;
-
+
switch(init.func) {
case MGA_INIT_DMA:
return mga_dma_initialize(dev, &init);
@@ -874,7 +801,7 @@
int retcode;
if (!irq) return -EINVAL;
-
+
down(&dev->struct_sem);
if (dev->irq) {
up(&dev->struct_sem);
@@ -882,7 +809,7 @@
}
dev->irq = irq;
up(&dev->struct_sem);
-
+
DRM_DEBUG("install irq handler %d\n", irq);
dev->context_flag = 0;
@@ -923,7 +850,7 @@
irq = dev->irq;
dev->irq = 0;
up(&dev->struct_sem);
-
+
if (!irq) return -EINVAL;
DRM_DEBUG("remove irq handler %d\n", irq);
MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
@@ -938,12 +865,10 @@
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_control_t ctl;
-
+
if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
return -EFAULT;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
switch (ctl.func) {
case DRM_INST_HANDLER:
return mga_irq_install(dev, ctl.irq);
@@ -960,31 +885,29 @@
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
int ret = 0;
- DRM_DEBUG("%s\n", __FUNCTION__);
+ if(!dev_priv) return 0;
- if(dev_priv == NULL) {
- return 0;
- }
-
if(dev_priv->next_prim->num_dwords != 0) {
- current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&dev_priv->flush_queue, &entry);
+ if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status))
+ DRM_ERROR("Incorrect mga_flush_queue logic\n");
set_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
mga_dma_schedule(dev, 0);
for (;;) {
- if (!test_bit(MGA_IN_FLUSH,
- &dev_priv->dispatch_status))
+ current->state = TASK_INTERRUPTIBLE;
+ if (!test_bit(MGA_IN_FLUSH,
+ &dev_priv->dispatch_status))
break;
atomic_inc(&dev->total_sleeps);
schedule();
if (signal_pending(current)) {
ret = -EINTR; /* Can't restart */
- clear_bit(MGA_IN_FLUSH,
+ clear_bit(MGA_IN_FLUSH,
&dev_priv->dispatch_status);
break;
}
}
- current->state = TASK_RUNNING;
+ current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->flush_queue, &entry);
}
return ret;
@@ -1000,18 +923,19 @@
if(dev->dev_private == NULL) return;
if(dma->buflist == NULL) return;
- DRM_DEBUG("%s\n", __FUNCTION__);
+ DRM_DEBUG("buf_count=%d\n", dma->buf_count);
+
mga_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[ i ];
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
- /* Only buffers that need to get reclaimed ever
- * get set to free
+ /* Only buffers that need to get reclaimed ever
+ * get set to free
*/
if (buf->pid == pid && buf_priv) {
- if(buf_priv->my_freelist->age == MGA_BUF_USED)
+ if(buf_priv->my_freelist->age == MGA_BUF_USED)
buf_priv->my_freelist->age = MGA_BUF_FREE;
}
}
@@ -1026,7 +950,6 @@
int ret = 0;
drm_lock_t lock;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
return -EFAULT;
@@ -1035,21 +958,16 @@
current->pid, lock.context);
return -EINVAL;
}
-
- DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
- lock.context, current->pid, dev->lock.hw_lock->lock,
- lock.flags);
- if (lock.context < 0) {
- return -EINVAL;
- }
-
+ if (lock.context < 0) return -EINVAL;
+
/* Only one queue:
*/
if (!ret) {
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
@@ -1062,10 +980,9 @@
atomic_inc(&dev->total_locks);
break; /* Got lock */
}
-
+
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
@@ -1075,7 +992,7 @@
current->state = TASK_RUNNING;
remove_wait_queue(&dev->lock.lock_queue, &entry);
}
-
+
if (!ret) {
sigemptyset(&dev->sigmask);
sigaddset(&dev->sigmask, SIGSTOP);
@@ -1092,12 +1009,13 @@
mga_dma_quiescent(dev);
}
}
-
- DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+
+ if (ret) DRM_DEBUG("%d %s\n", lock.context,
+ ret ? "interrupted" : "has lock");
return ret;
}
-
-int mga_flush_ioctl(struct inode *inode, struct file *filp,
+
+int mga_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
@@ -1105,12 +1023,11 @@
drm_lock_t lock;
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
- DRM_ERROR("mga_flush_ioctl called without lock held\n");
+ DRM_ERROR("lock not held\n");
return -EINVAL;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)