Fixed reclaim Oops

main
Jeff Hartmann 2000-04-05 18:48:23 +00:00
parent ba1b1ae380
commit 1dcfddf915
8 changed files with 170 additions and 50 deletions

View File

@ -714,17 +714,17 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
if (!dma) return; if (!dma) return;
if(dev->dev_private == NULL) return; if(dev->dev_private == NULL) return;
if(dma->buflist == NULL) return;
i810_flush_queue(dev); i810_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) { for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[ i ]; drm_buf_t *buf = dma->buflist[ i ];
drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_buf_priv_t *buf_priv = buf->dev_private;
if (buf->pid == pid) { /* Only buffers that need to get reclaimed ever
/* Only buffers that need to get reclaimed ever * get set to free
* get set to free */ */
if(buf_priv == NULL) return; if (buf->pid == pid && buf_priv) {
cmpxchg(buf_priv->in_use, cmpxchg(buf_priv->in_use,
I810_BUF_USED, I810_BUF_FREE); I810_BUF_USED, I810_BUF_FREE);
} }

View File

@ -499,7 +499,7 @@ int i810_release(struct inode *inode, struct file *filp)
DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
current->pid, dev->device, dev->open_count); current->pid, dev->device, dev->open_count);
if (_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
&& dev->lock.pid == current->pid) { && dev->lock.pid == current->pid) {
i810_reclaim_buffers(dev, priv->pid); i810_reclaim_buffers(dev, priv->pid);
DRM_ERROR("Process %d dead, freeing lock for context %d\n", DRM_ERROR("Process %d dead, freeing lock for context %d\n",
@ -513,7 +513,7 @@ int i810_release(struct inode *inode, struct file *filp)
hardware at this point, possibly hardware at this point, possibly
processed via a callback to the X processed via a callback to the X
server. */ server. */
} else { } else if (dev->lock.hw_lock) {
/* The lock is required to reclaim buffers */ /* The lock is required to reclaim buffers */
DECLARE_WAITQUEUE(entry, current); DECLARE_WAITQUEUE(entry, current);
add_wait_queue(&dev->lock.lock_queue, &entry); add_wait_queue(&dev->lock.lock_queue, &entry);

View File

@ -510,27 +510,86 @@ int mga_release(struct inode *inode, struct file *filp)
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
int retcode = 0; int retcode = 0;
DRM_DEBUG("open_count = %d\n", dev->open_count); DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
if (!(retcode = drm_release(inode, filp))) { current->pid, dev->device, dev->open_count);
MOD_DEC_USE_COUNT;
atomic_inc(&dev->total_close); if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
spin_lock(&dev->count_lock); && dev->lock.pid == current->pid) {
if (!--dev->open_count) { mga_reclaim_buffers(dev, priv->pid);
if (atomic_read(&dev->ioctl_count) || dev->blocked) { DRM_ERROR("Process %d dead, freeing lock for context %d\n",
DRM_ERROR("Device busy: %d %d\n", current->pid,
atomic_read(&dev->ioctl_count), _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
dev->blocked); drm_lock_free(dev,
spin_unlock(&dev->count_lock); &dev->lock.hw_lock->lock,
return -EBUSY; _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 if (dev->lock.hw_lock) {
/* 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 mga_takedown(dev);
} }
spin_unlock(&dev->count_lock); current->state = TASK_RUNNING;
remove_wait_queue(&dev->lock.lock_queue, &entry);
if(!retcode) {
mga_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 mga_takedown(dev);
}
spin_unlock(&dev->count_lock);
return retcode; return retcode;
} }
/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */ /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */
int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,

View File

@ -714,17 +714,17 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
if (!dma) return; if (!dma) return;
if(dev->dev_private == NULL) return; if(dev->dev_private == NULL) return;
if(dma->buflist == NULL) return;
i810_flush_queue(dev); i810_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) { for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[ i ]; drm_buf_t *buf = dma->buflist[ i ];
drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_buf_priv_t *buf_priv = buf->dev_private;
if (buf->pid == pid) { /* Only buffers that need to get reclaimed ever
/* Only buffers that need to get reclaimed ever * get set to free
* get set to free */ */
if(buf_priv == NULL) return; if (buf->pid == pid && buf_priv) {
cmpxchg(buf_priv->in_use, cmpxchg(buf_priv->in_use,
I810_BUF_USED, I810_BUF_FREE); I810_BUF_USED, I810_BUF_FREE);
} }

View File

@ -499,7 +499,7 @@ int i810_release(struct inode *inode, struct file *filp)
DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
current->pid, dev->device, dev->open_count); current->pid, dev->device, dev->open_count);
if (_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
&& dev->lock.pid == current->pid) { && dev->lock.pid == current->pid) {
i810_reclaim_buffers(dev, priv->pid); i810_reclaim_buffers(dev, priv->pid);
DRM_ERROR("Process %d dead, freeing lock for context %d\n", DRM_ERROR("Process %d dead, freeing lock for context %d\n",
@ -513,7 +513,7 @@ int i810_release(struct inode *inode, struct file *filp)
hardware at this point, possibly hardware at this point, possibly
processed via a callback to the X processed via a callback to the X
server. */ server. */
} else { } else if (dev->lock.hw_lock) {
/* The lock is required to reclaim buffers */ /* The lock is required to reclaim buffers */
DECLARE_WAITQUEUE(entry, current); DECLARE_WAITQUEUE(entry, current);
add_wait_queue(&dev->lock.lock_queue, &entry); add_wait_queue(&dev->lock.lock_queue, &entry);

View File

@ -1016,6 +1016,7 @@ void mga_reclaim_buffers(drm_device_t *dev, pid_t pid)
if (!dma) return; if (!dma) return;
if(dev->dev_private == NULL) return; if(dev->dev_private == NULL) return;
if(dma->buflist == NULL) return;
mga_flush_queue(dev); mga_flush_queue(dev);
@ -1023,10 +1024,10 @@ void mga_reclaim_buffers(drm_device_t *dev, pid_t pid)
drm_buf_t *buf = dma->buflist[ i ]; drm_buf_t *buf = dma->buflist[ i ];
drm_mga_buf_priv_t *buf_priv = buf->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private;
if (buf->pid == pid) { /* Only buffers that need to get reclaimed ever
if(buf_priv == NULL) return; * 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; buf_priv->my_freelist->age = MGA_BUF_FREE;
} }

View File

@ -510,27 +510,86 @@ int mga_release(struct inode *inode, struct file *filp)
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
int retcode = 0; int retcode = 0;
DRM_DEBUG("open_count = %d\n", dev->open_count); DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
if (!(retcode = drm_release(inode, filp))) { current->pid, dev->device, dev->open_count);
MOD_DEC_USE_COUNT;
atomic_inc(&dev->total_close); if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
spin_lock(&dev->count_lock); && dev->lock.pid == current->pid) {
if (!--dev->open_count) { mga_reclaim_buffers(dev, priv->pid);
if (atomic_read(&dev->ioctl_count) || dev->blocked) { DRM_ERROR("Process %d dead, freeing lock for context %d\n",
DRM_ERROR("Device busy: %d %d\n", current->pid,
atomic_read(&dev->ioctl_count), _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
dev->blocked); drm_lock_free(dev,
spin_unlock(&dev->count_lock); &dev->lock.hw_lock->lock,
return -EBUSY; _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 if (dev->lock.hw_lock) {
/* 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 mga_takedown(dev);
} }
spin_unlock(&dev->count_lock); current->state = TASK_RUNNING;
remove_wait_queue(&dev->lock.lock_queue, &entry);
if(!retcode) {
mga_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 mga_takedown(dev);
}
spin_unlock(&dev->count_lock);
return retcode; return retcode;
} }
/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */ /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */
int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,

View File

@ -131,6 +131,7 @@ extern unsigned int mga_create_sync_tag(drm_device_t *dev);
extern drm_buf_t *mga_freelist_get(drm_device_t *dev); extern drm_buf_t *mga_freelist_get(drm_device_t *dev);
extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf); extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf);
extern int mga_advance_primary(drm_device_t *dev); extern int mga_advance_primary(drm_device_t *dev);
extern void mga_reclaim_buffers(drm_device_t *dev, pid_t pid);
/* mga_bufs.c */ /* mga_bufs.c */