mirror of
https://github.com/torvalds/linux
synced 2024-09-21 19:47:35 +00:00
drm/qxl: properly free qxl releases
Reorganize qxl_device_fini() a bit. Add missing unpin() calls. Count releases. Add wait queue for releases. That way qxl_device_fini() can easily wait until everything is ready for proper shutdown. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Link: http://patchwork.freedesktop.org/patch/msgid/20210204145712.1531203-9-kraxel@redhat.com
This commit is contained in:
parent
a7709b9b89
commit
5f6c871fe9
|
@ -254,6 +254,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
|
|||
}
|
||||
}
|
||||
|
||||
wake_up_all(&qdev->release_event);
|
||||
DRM_DEBUG_DRIVER("%d\n", i);
|
||||
|
||||
return i;
|
||||
|
|
|
@ -214,6 +214,8 @@ struct qxl_device {
|
|||
spinlock_t release_lock;
|
||||
struct idr release_idr;
|
||||
uint32_t release_seqno;
|
||||
atomic_t release_count;
|
||||
wait_queue_head_t release_event;
|
||||
spinlock_t release_idr_lock;
|
||||
struct mutex async_io_mutex;
|
||||
unsigned int last_sent_io_cmd;
|
||||
|
|
|
@ -87,6 +87,7 @@ int qxl_irq_init(struct qxl_device *qdev)
|
|||
init_waitqueue_head(&qdev->display_event);
|
||||
init_waitqueue_head(&qdev->cursor_event);
|
||||
init_waitqueue_head(&qdev->io_cmd_event);
|
||||
init_waitqueue_head(&qdev->release_event);
|
||||
INIT_WORK(&qdev->client_monitors_config_work,
|
||||
qxl_client_monitors_config_work_func);
|
||||
atomic_set(&qdev->irq_received, 0);
|
||||
|
|
|
@ -286,11 +286,31 @@ int qxl_device_init(struct qxl_device *qdev,
|
|||
|
||||
void qxl_device_fini(struct qxl_device *qdev)
|
||||
{
|
||||
qxl_bo_unref(&qdev->current_release_bo[0]);
|
||||
qxl_bo_unref(&qdev->current_release_bo[1]);
|
||||
int cur_idx;
|
||||
|
||||
for (cur_idx = 0; cur_idx < 3; cur_idx++) {
|
||||
if (!qdev->current_release_bo[cur_idx])
|
||||
continue;
|
||||
qxl_bo_unpin(qdev->current_release_bo[cur_idx]);
|
||||
qxl_bo_unref(&qdev->current_release_bo[cur_idx]);
|
||||
qdev->current_release_bo_offset[cur_idx] = 0;
|
||||
qdev->current_release_bo[cur_idx] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask host to release resources (+fill release ring),
|
||||
* then wait for the release actually happening.
|
||||
*/
|
||||
qxl_io_notify_oom(qdev);
|
||||
wait_event_timeout(qdev->release_event,
|
||||
atomic_read(&qdev->release_count) == 0,
|
||||
HZ);
|
||||
flush_work(&qdev->gc_work);
|
||||
qxl_surf_evict(qdev);
|
||||
qxl_vram_evict(qdev);
|
||||
|
||||
qxl_gem_fini(qdev);
|
||||
qxl_bo_fini(qdev);
|
||||
flush_work(&qdev->gc_work);
|
||||
qxl_ring_free(qdev->command_ring);
|
||||
qxl_ring_free(qdev->cursor_ring);
|
||||
qxl_ring_free(qdev->release_ring);
|
||||
|
|
|
@ -196,6 +196,7 @@ qxl_release_free(struct qxl_device *qdev,
|
|||
qxl_release_free_list(release);
|
||||
kfree(release);
|
||||
}
|
||||
atomic_dec(&qdev->release_count);
|
||||
}
|
||||
|
||||
static int qxl_release_bo_alloc(struct qxl_device *qdev,
|
||||
|
@ -344,6 +345,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
|
|||
*rbo = NULL;
|
||||
return idr_ret;
|
||||
}
|
||||
atomic_inc(&qdev->release_count);
|
||||
|
||||
mutex_lock(&qdev->release_mutex);
|
||||
if (qdev->current_release_bo_offset[cur_idx] + 1 >= releases_per_bo[cur_idx]) {
|
||||
|
|
Loading…
Reference in a new issue