summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-08-06 15:49:21 +1000
committerDave Airlie <airlied@redhat.com>2013-09-03 15:11:29 +1000
commit77fccfe7b9c313b159f27b0fd6bba575aa0e117a (patch)
treeb7c420a5e9b1521be5dfb0e0925ad13a9a6a503e
parent8f6206598f2304911bf27e922841a25b796ab967 (diff)
virgl: unreference buffers aand free outside spinlock
when we remove buffers add them to a list, then free them outside the lock
-rw-r--r--drivers/gpu/drm/virgl/virgl_3d.c15
-rw-r--r--drivers/gpu/drm/virgl/virgl_drv.h1
2 files changed, 13 insertions, 3 deletions
diff --git a/drivers/gpu/drm/virgl/virgl_3d.c b/drivers/gpu/drm/virgl/virgl_3d.c
index 342c2f4c2274..5c7923a5a8ee 100644
--- a/drivers/gpu/drm/virgl/virgl_3d.c
+++ b/drivers/gpu/drm/virgl/virgl_3d.c
@@ -334,13 +334,13 @@ struct virgl_command *virgl_alloc_cmd_buf(struct virgl_device *qdev,
return (struct virgl_command *)vbuf->buf;
}
-static int reclaim_vbufs(struct virtqueue *vq)
+static int reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list)
{
struct virgl_vbuffer *vbuf;
unsigned int len;
int freed = 0;
while ((vbuf = virtqueue_get_buf(vq, &len))) {
- free_vbuf(vbuf);
+ list_add(&vbuf->destroy_list, reclaim_list);
freed++;
}
return freed;
@@ -351,15 +351,24 @@ void virgl_dequeue_work_func(struct work_struct *work)
struct virgl_device *qdev = container_of(work, struct virgl_device,
dequeue_work);
int ret;
+ struct list_head reclaim_list;
+ struct virgl_vbuffer *entry, *tmp;
+
+ INIT_LIST_HEAD(&reclaim_list);
spin_lock(&qdev->cmdq_lock);
do {
virtqueue_disable_cb(qdev->cmdq);
- ret = reclaim_vbufs(qdev->cmdq);
+ ret = reclaim_vbufs(qdev->cmdq, &reclaim_list);
if (ret == 0)
printk("cleaned 0 buffers wierd\n");
qdev->num_freed += ret;
} while (!virtqueue_enable_cb(qdev->cmdq));
spin_unlock(&qdev->cmdq_lock);
+
+ list_for_each_entry_safe(entry, tmp, &reclaim_list, destroy_list) {
+ list_del(&entry->destroy_list);
+ free_vbuf(entry);
+ }
wake_up(&qdev->cmd_ack_queue);
}
diff --git a/drivers/gpu/drm/virgl/virgl_drv.h b/drivers/gpu/drm/virgl/virgl_drv.h
index 90e0fa82c481..1e96c4373f13 100644
--- a/drivers/gpu/drm/virgl/virgl_drv.h
+++ b/drivers/gpu/drm/virgl/virgl_drv.h
@@ -127,6 +127,7 @@ struct virgl_vbuffer {
char *buf;
size_t size;
+ struct list_head destroy_list;
size_t bo_max_len;
size_t bo_start_offset;
size_t bo_user_offset;