diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_cmd.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_display.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_draw.c | 185 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.h | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_fb.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_image.c | 103 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_object.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_release.c | 53 |
8 files changed, 348 insertions, 70 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 6efcf140bda1..1ada5d72e7c4 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -254,7 +254,25 @@ int qxl_garbage_collect(struct qxl_device *qdev) return i; } -int qxl_alloc_bo_reserved(struct qxl_device *qdev, unsigned long size, +int qxl_alloc_bo(struct qxl_device *qdev, + unsigned long size, + struct qxl_bo **_bo) +{ + int ret; + struct qxl_bo *bo; + ret = qxl_bo_create(qdev, size, false /* not kernel - device */, + QXL_GEM_DOMAIN_VRAM, NULL, &bo); + if (ret) { + DRM_ERROR("failed to allocate VRAM BO\n"); + return ret; + } + *_bo = bo; + return 0; +} + +int qxl_alloc_bo_reserved(struct qxl_device *qdev, + struct qxl_release *release, + unsigned long size, struct qxl_bo **_bo) { struct qxl_bo *bo; @@ -266,7 +284,7 @@ int qxl_alloc_bo_reserved(struct qxl_device *qdev, unsigned long size, DRM_ERROR("failed to allocate VRAM BO\n"); return ret; } - ret = qxl_bo_reserve(bo, false); + ret = qxl_bo_ticket_reserve(release, bo, false); if (unlikely(ret != 0)) goto out_unref; diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 6b7934bddbea..e592fe09bc4d 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -246,7 +246,7 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc, &release, NULL); if (ret) goto out_kunmap; - ret = qxl_alloc_bo_reserved(qdev, sizeof(struct qxl_cursor) + size, + ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_cursor) + size, &cursor_bo); if (ret) goto out_free_release; diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index a6a6c99301f1..129e09887b66 100644 --- a/drivers/gpu/drm/qxl/qxl_draw.c +++ b/drivers/gpu/drm/qxl/qxl_draw.c @@ -23,25 +23,42 @@ #include "qxl_drv.h" #include "qxl_object.h" +static int attempt_reserveations(struct qxl_release *release, + struct qxl_drm_image *image, + struct qxl_bo *clips_bo, + struct qxl_bo *palette_bo) +{ + ww_acquire_init(&release->ticket, &reservation_ww_class); + + +} + +static int alloc_clips(struct qxl_device *qdev, + unsigned num_clips, + struct qxl_bo **clips_bo) +{ + int ret; + int size = sizeof(struct qxl_clip_rects) + sizeof(struct qxl_rect) * num_clips; + ret = qxl_alloc_bo(qdev, size, clips_bo); + if (ret) + return ret; + + return 0; +} + /* returns a pointer to the already allocated qxl_rect array inside * the qxl_clip_rects. This is *not* the same as the memory allocated * on the device, it is offset to qxl_clip_rects.chunk.data */ static struct qxl_rect *drawable_set_clipping(struct qxl_device *qdev, struct qxl_drawable *drawable, unsigned num_clips, - struct qxl_bo **clips_bo, - struct qxl_release *release) + struct qxl_bo *clips_bo) { struct qxl_clip_rects *dev_clips; int ret; - int size = sizeof(*dev_clips) + sizeof(struct qxl_rect) * num_clips; - ret = qxl_alloc_bo_reserved(qdev, size, clips_bo); - if (ret) - return NULL; - ret = qxl_bo_kmap(*clips_bo, (void **)&dev_clips); + ret = qxl_bo_kmap(clips_bo, (void **)&dev_clips); if (ret) { - qxl_bo_unref(clips_bo); return NULL; } dev_clips->num_rects = num_clips; @@ -52,20 +69,34 @@ static struct qxl_rect *drawable_set_clipping(struct qxl_device *qdev, } static int +alloc_drawable(struct qxl_device *qdev, struct qxl_release **release) +{ + int ret; + ret = qxl_alloc_release_reserved(qdev, sizeof(struct qxl_drawable), + QXL_RELEASE_DRAWABLE, release, + NULL); + return ret; +} + +static void +free_drawable(struct qxl_device *qdev, struct qxl_release *release) +{ + qxl_release_free(qdev, release); +} + +/* release needs to be reserved at this point */ +static int make_drawable(struct qxl_device *qdev, int surface, uint8_t type, const struct qxl_rect *rect, - struct qxl_release **release) + struct qxl_release *release) { struct qxl_drawable *drawable; - int i, ret; + int i; - ret = qxl_alloc_release_reserved(qdev, sizeof(*drawable), - QXL_RELEASE_DRAWABLE, release, - NULL); - if (ret) - return ret; + drawable = (struct qxl_drawable *)qxl_release_map(qdev, release); + if (!drawable) + return -ENOMEM; - drawable = (struct qxl_drawable *)qxl_release_map(qdev, *release); drawable->type = type; drawable->surface_id = surface; /* Only primary for now */ @@ -91,14 +122,25 @@ make_drawable(struct qxl_device *qdev, int surface, uint8_t type, drawable->bbox = *rect; drawable->mm_time = qdev->rom->mm_clock; - qxl_release_unmap(qdev, *release, &drawable->release_info); + qxl_release_unmap(qdev, release, &drawable->release_info); return 0; } -static int qxl_palette_create_1bit(struct qxl_bo **palette_bo, +static int alloc_palette_object(struct qxl_device *qdev, + struct qxl_bo **palette_bo) +{ + int ret; + + ret = qxl_alloc_bo(qdev, + sizeof(struct qxl_palette) + sizeof(uint32_t) * 2, + palette_bo); + return ret; +} + +static int qxl_palette_create_1bit(struct qxl_bo *palette_bo, + struct qxl_release *release, const struct qxl_fb_image *qxl_fb_image) { - struct qxl_device *qdev = qxl_fb_image->qdev; const struct fb_image *fb_image = &qxl_fb_image->fb_image; uint32_t visual = qxl_fb_image->visual; const uint32_t *pseudo_palette = qxl_fb_image->pseudo_palette; @@ -108,12 +150,7 @@ static int qxl_palette_create_1bit(struct qxl_bo **palette_bo, static uint64_t unique; /* we make no attempt to actually set this * correctly globaly, since that would require * tracking all of our palettes. */ - - ret = qxl_alloc_bo_reserved(qdev, - sizeof(struct qxl_palette) + sizeof(uint32_t) * 2, - palette_bo); - - ret = qxl_bo_kmap(*palette_bo, (void **)&pal); + ret = qxl_bo_kmap(palette_bo, (void **)&pal); pal->num_ents = 2; pal->unique = unique++; if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) { @@ -126,7 +163,7 @@ static int qxl_palette_create_1bit(struct qxl_bo **palette_bo, } pal->ents[0] = bgcolor; pal->ents[1] = fgcolor; - qxl_bo_kunmap(*palette_bo); + qxl_bo_kunmap(palette_bo); return 0; } @@ -147,22 +184,41 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image, struct qxl_bo *image_bo; struct qxl_image *image; int ret; - + struct qxl_drm_image *dimage; + struct qxl_bo *palette_bo = NULL; if (stride == 0) stride = depth * width / 8; + ret = alloc_drawable(qdev, &release); + if (ret) + return; + + ret = qxl_image_alloc_objects(qdev, &dimage, + height, stride); + if (ret) + goto out_free_drawable; + + if (depth == 1) { + ret = alloc_palette_object(qdev, &palette_bo); + if (ret) + goto out_free_image; + } + + /* do a reservation run over all the objects we just allocated */ + rect.left = x; rect.right = x + width; rect.top = y; rect.bottom = y + height; - ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &rect, &release); + + ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &rect, release); if (ret) - return; + goto out_free_palette; - ret = qxl_image_create(qdev, release, &image_bo, - (const uint8_t *)src, 0, 0, - width, height, depth, stride); + ret = qxl_image_init(qdev, release, dimage, + (const uint8_t *)src, 0, 0, + width, height, depth, stride); if (ret) { qxl_release_unreserve(qdev, release); qxl_release_free(qdev, release); @@ -170,9 +226,8 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image, } if (depth == 1) { - struct qxl_bo *palette_bo; void *ptr; - ret = qxl_palette_create_1bit(&palette_bo, qxl_fb_image); + ret = qxl_palette_create_1bit(palette_bo, release, qxl_fb_image); qxl_release_list_add(release, palette_bo); @@ -206,10 +261,18 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image, qxl_release_list_add(release, image_bo); qxl_bo_unreserve(image_bo); qxl_bo_unref(&image_bo); - + qxl_fence_releaseable(qdev, release); qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); qxl_release_unreserve(qdev, release); + +out_free_palette: + if (palette_bo) + qxl_bo_unref(&palette_bo); +out_free_image: + qxl_image_free_objects(qdev, dimage); +out_free_drawable: + free_drawable(qdev, release); } /* push a draw command using the given clipping rectangles as @@ -246,8 +309,13 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, struct qxl_release *release; struct qxl_bo *image_bo; struct qxl_bo *clips_bo; + struct qxl_drm_image *dimage; int ret; + ret = alloc_drawable(qdev, &release); + if (ret) + return; + left = clips->x1; right = clips->x2; top = clips->y1; @@ -264,26 +332,40 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, width = right - left; height = bottom - top; + + ret = alloc_clips(qdev, num_clips, &clips_bo); + if (ret) + goto out_free_drawable; + + ret = qxl_image_alloc_objects(qdev, &dimage, + height, stride); + if (ret) + goto out_free_clips; + + /* do a reservation run over all the objects we just allocated */ + drawable_rect.left = left; drawable_rect.right = right; drawable_rect.top = top; drawable_rect.bottom = bottom; + ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &drawable_rect, - &release); + release); if (ret) - return; + goto out_free_image; + ret = qxl_bo_kmap(bo, (void **)&surface_base); if (ret) goto out_unref; - ret = qxl_image_create(qdev, release, &image_bo, surface_base, - left, top, width, height, depth, stride); + ret = qxl_image_init(qdev, release, dimage, surface_base, + left, top, width, height, depth, stride); qxl_bo_kunmap(bo); if (ret) goto out_unref; - rects = drawable_set_clipping(qdev, drawable, num_clips, &clips_bo, release); + rects = drawable_set_clipping(qdev, drawable, num_clips, clips_bo); if (!rects) { qxl_bo_unref(&image_bo); goto out_unref; @@ -332,6 +414,13 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, out_unref: qxl_release_unreserve(qdev, release); qxl_release_free(qdev, release); +out_free_image: + qxl_image_free_objects(qdev, dimage); +out_free_clips: + qxl_bo_unref(&clips_bo); +out_free_drawable: + free_drawable(qdev, release); + } void qxl_draw_copyarea(struct qxl_device *qdev, @@ -344,11 +433,17 @@ void qxl_draw_copyarea(struct qxl_device *qdev, struct qxl_release *release; int ret; + ret = alloc_drawable(qdev, &release); + if (ret) + return; + + /* do a reservation run over all the objects we just allocated */ + rect.left = dx; rect.top = dy; rect.right = dx + width; rect.bottom = dy + height; - ret = make_drawable(qdev, 0, QXL_COPY_BITS, &rect, &release); + ret = make_drawable(qdev, 0, QXL_COPY_BITS, &rect, release); if (ret) return; @@ -372,7 +467,13 @@ void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec) struct qxl_release *release; int ret; - ret = make_drawable(qdev, 0, QXL_DRAW_FILL, &rect, &release); + ret = alloc_drawable(qdev, &release); + if (ret) + return; + + /* do a reservation run over all the objects we just allocated */ + + ret = make_drawable(qdev, 0, QXL_DRAW_FILL, &rect, release); if (ret) return; diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index dbc9c110befe..0df42d5247bf 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -195,9 +195,20 @@ struct qxl_release { int type; uint32_t release_offset; uint32_t surface_release_id; + struct ww_acquire_ctx ticket; struct list_head bos; }; +struct qxl_drm_chunk { + struct list_head head; + struct qxl_bo *bo; +}; + +struct qxl_drm_image { + struct qxl_bo *bo; + struct list_head chunk_list; +}; + struct qxl_fb_image { struct qxl_device *qdev; uint32_t pseudo_palette[16]; @@ -430,12 +441,18 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma); /* qxl image */ -int qxl_image_create(struct qxl_device *qdev, - struct qxl_release *release, - struct qxl_bo **image_bo, - const uint8_t *data, - int x, int y, int width, int height, - int depth, int stride); +int qxl_image_init(struct qxl_device *qdev, + struct qxl_release *release, + struct qxl_drm_image *dimage, + const uint8_t *data, + int x, int y, int width, int height, + int depth, int stride); +int +qxl_image_alloc_objects(struct qxl_device *qdev, + struct qxl_drm_image **image_ptr, + int height, int stride); +void qxl_image_free_objects(struct qxl_device *qdev, struct qxl_drm_image *dimage); + void qxl_update_screen(struct qxl_device *qxl); /* qxl io operations (qxl_cmd.c) */ @@ -485,7 +502,12 @@ qxl_push_command_ring_release(struct qxl_device *qdev, struct qxl_release *relea int qxl_push_cursor_ring_release(struct qxl_device *qdev, struct qxl_release *release, uint32_t type, bool interruptible); -int qxl_alloc_bo_reserved(struct qxl_device *qdev, unsigned long size, +int qxl_alloc_bo(struct qxl_device *qdev, + unsigned long size, + struct qxl_bo **_bo); +int qxl_alloc_bo_reserved(struct qxl_device *qdev, + struct qxl_release *release, + unsigned long size, struct qxl_bo **_bo); /* qxl drawing commands */ diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index 7137eb5be2e3..1e2b8804d2fc 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -203,6 +203,7 @@ static void qxl_fb_fillrect(struct fb_info *info, qxl_draw_fill_rec.rect = rect; qxl_draw_fill_rec.color = color; qxl_draw_fill_rec.rop = rop; + if (!drm_can_sleep()) { qxl_io_log(qdev, "%s: TODO use RCU, mysterious locks with spin_lock\n", diff --git a/drivers/gpu/drm/qxl/qxl_image.c b/drivers/gpu/drm/qxl/qxl_image.c index c9a3b88c754f..cbccd02a9594 100644 --- a/drivers/gpu/drm/qxl/qxl_image.c +++ b/drivers/gpu/drm/qxl/qxl_image.c @@ -30,30 +30,99 @@ #include "qxl_object.h" static int -qxl_image_create_helper(struct qxl_device *qdev, - struct qxl_release *release, - struct qxl_bo **image_bo, - const uint8_t *data, - int width, int height, - int depth, unsigned int hash, - int stride) +qxl_allocate_chunk(struct qxl_device *qdev, + struct qxl_drm_image *image, + unsigned int chunk_size) { + struct qxl_drm_chunk *chunk; + int ret; + + chunk = kmalloc(sizeof(struct qxl_drm_chunk), GFP_KERNEL); + if (!chunk) + return -ENOMEM; + + ret = qxl_alloc_bo(qdev, chunk_size, &chunk->bo); + if (ret) { + kfree(chunk); + return ret; + } + + list_add_tail(&image->chunk_list, &chunk->head); + return 0; +} + +int +qxl_image_alloc_objects(struct qxl_device *qdev, + struct qxl_drm_image **image_ptr, + int height, int stride) +{ + struct qxl_drm_image *image; + int ret; + + image = kmalloc(sizeof(struct qxl_drm_image), GFP_KERNEL); + if (!image) + return -ENOMEM; + + INIT_LIST_HEAD(&image->chunk_list); + + ret = qxl_alloc_bo(qdev, sizeof(struct qxl_image), &image->bo); + if (ret) { + kfree(image); + return ret; + } + + ret = qxl_allocate_chunk(qdev, image, sizeof(struct qxl_data_chunk) + stride * height); + if (ret) { + qxl_bo_unref(&image->bo); + kfree(image); + return ret; + } + *image_ptr = image; + return 0; +} + +void qxl_image_free_objects(struct qxl_device *qdev, struct qxl_drm_image *dimage) +{ + struct qxl_drm_chunk *chunk, *tmp; + + list_for_each_entry_safe(chunk, tmp, &dimage->chunk_list, head) { + qxl_bo_unref(&chunk->bo); + kfree(chunk); + } + + qxl_bo_unref(&dimage->bo); + kfree(dimage); +} + +static int +qxl_image_init_helper(struct qxl_device *qdev, + struct qxl_release *release, + struct qxl_drm_image *dimage, + const uint8_t *data, + int width, int height, + int depth, unsigned int hash, + int stride) +{ + struct qxl_drm_chunk *drv_chunk; struct qxl_image *image; struct qxl_data_chunk *chunk; int i; int chunk_stride; int linesize = width * depth / 8; - struct qxl_bo *chunk_bo; + struct qxl_bo *chunk_bo, *image_bo; int ret; void *ptr; /* Chunk */ /* FIXME: Check integer overflow */ /* TODO: variable number of chunks */ + + + drv_chunk = list_first_entry(&dimage->chunk_list, struct qxl_drm_chunk, head); + + chunk_bo = drv_chunk->bo; chunk_stride = stride; /* TODO: should use linesize, but it renders wrong (check the bitmaps are sent correctly first) */ - ret = qxl_alloc_bo_reserved(qdev, sizeof(*chunk) + height * chunk_stride, - &chunk_bo); ptr = qxl_bo_kmap_atomic_page(qdev, chunk_bo, 0); chunk = ptr; @@ -120,10 +189,8 @@ qxl_image_create_helper(struct qxl_device *qdev, qxl_bo_kunmap(chunk_bo); - /* Image */ - ret = qxl_alloc_bo_reserved(qdev, sizeof(*image), image_bo); - - ptr = qxl_bo_kmap_atomic_page(qdev, *image_bo, 0); + image_bo = dimage->bo; + ptr = qxl_bo_kmap_atomic_page(qdev, image_bo, 0); image = ptr; image->descriptor.id = 0; @@ -158,19 +225,19 @@ qxl_image_create_helper(struct qxl_device *qdev, qxl_bo_unreserve(chunk_bo); qxl_bo_unref(&chunk_bo); - qxl_bo_kunmap_atomic_page(qdev, *image_bo, ptr); + qxl_bo_kunmap_atomic_page(qdev, image_bo, ptr); return 0; } -int qxl_image_create(struct qxl_device *qdev, +int qxl_image_init(struct qxl_device *qdev, struct qxl_release *release, - struct qxl_bo **image_bo, + struct qxl_drm_image *dimage, const uint8_t *data, int x, int y, int width, int height, int depth, int stride) { data += y * stride + x * (depth / 8); - return qxl_image_create_helper(qdev, release, image_bo, data, + return qxl_image_init_helper(qdev, release, dimage, data, width, height, depth, 0, stride); } diff --git a/drivers/gpu/drm/qxl/qxl_object.h b/drivers/gpu/drm/qxl/qxl_object.h index ef22935cc2b0..0ff16d95c463 100644 --- a/drivers/gpu/drm/qxl/qxl_object.h +++ b/drivers/gpu/drm/qxl/qxl_object.h @@ -42,6 +42,22 @@ static inline int qxl_bo_reserve(struct qxl_bo *bo, bool no_wait) return 0; } +static inline int qxl_bo_ticket_reserve(struct qxl_release *release, + struct qxl_bo *bo, bool no_wait) +{ + int r; + + r = ttm_bo_reserve_nolru(&bo->tbo, true, no_wait, false, &release->ticket); + if (unlikely(r != 0)) { + if (r != -ERESTARTSYS) { + struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private; + dev_err(qdev->dev, "%p reserve failed\n", bo); + } + return r; + } + return 0; +} + static inline void qxl_bo_unreserve(struct qxl_bo *bo) { ttm_bo_unreserve(&bo->tbo); diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index 6a711c484c5f..1cc032745e6b 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -56,6 +56,8 @@ qxl_release_alloc(struct qxl_device *qdev, int type, release->release_offset = 0; release->surface_release_id = 0; INIT_LIST_HEAD(&release->bos); + ww_acquire_init(&release->ticket, &reservation_ww_class); + idr_preload(GFP_KERNEL); spin_lock(&qdev->release_idr_lock); idr_ret = idr_alloc(&qdev->release_idr, release, 1, 0, GFP_NOWAIT); @@ -123,6 +125,19 @@ int qxl_release_list_add(struct qxl_release *release, struct qxl_bo *bo) qxl_bo_ref(bo); entry->tv.bo = &bo->tbo; list_add_tail(&entry->tv.head, &release->bos); + return 0; +} + +int qxl_release_reserve_list(struct qxl_release *release, bool no_intr) +{ + struct qxl_bo_list *entry; + + return ttm_eu_reserve_buffers(&release->ticket, &release->bos); +} + +int qxl_release_validate_bo(struct qxl_release *release, struct qxl_bo *bo) +{ + int ret; ret = qxl_bo_reserve(bo, false); if (ret) @@ -156,6 +171,8 @@ void qxl_release_unreserve(struct qxl_device *qdev, list_del(&entry->tv.head); kfree(entry); } + ww_acquire_done(&release->ticket); + ww_acquire_fini(&release->ticket); } int qxl_alloc_surface_release_reserved(struct qxl_device *qdev, @@ -293,6 +310,8 @@ union qxl_release_info *qxl_release_map(struct qxl_device *qdev, struct qxl_bo *bo = to_qxl_bo(entry->tv.bo); ptr = qxl_bo_kmap_atomic_page(qdev, bo, release->release_offset & PAGE_SIZE); + if (!ptr) + return NULL; info = ptr + (release->release_offset & ~PAGE_SIZE); return info; } @@ -309,3 +328,37 @@ void qxl_release_unmap(struct qxl_device *qdev, qxl_bo_kunmap_atomic_page(qdev, bo, ptr); } +void qxl_release_fence_buffer_objects(struct qxl_release *release) +{ + struct ttm_validate_buffer *entry; + struct ttm_buffer_object *bo; + struct ttm_bo_global *glob; + struct ttm_bo_device *bdev; + struct ttm_bo_driver *driver; + struct qxl_bo *qbo; + int ret; + + bo = list_first_entry(&release->bos, struct ttm_validate_buffer, head)->bo; + bdev = bo->bdev; + driver = bdev->driver; + glob = bo->glob; + + spin_lock(&glob->lru_lock); + spin_lock(&bdev->fence_lock); + + list_for_each_entry(entry, &release->bos, head) { + bo = entry->bo; + qbo = to_qxl_bo(bo); + + if (!entry->bo->sync_obj) + entry->bo->sync_obj = &qbo->fence; + + ret = qxl_fence_add_release(&qbo->fence, release->id); + ttm_bo_add_to_lru(bo); + ww_mutex_unlock(&bo->resv->lock); + entry->reserved = false; + } + spin_unlock(&bdev->fence_lock); + spin_unlock(&glob->lru_lock); + ww_acquire_fini(&release->ticket); +} |