Fixed reclaim Oops
parent
ba1b1ae380
commit
1dcfddf915
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue