Home | History | Annotate | Line # | Download | only in virtio
virtgpu_fence.c revision 1.1
      1 /*	$NetBSD: virtgpu_fence.c,v 1.1 2018/08/27 01:34:59 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2015 Red Hat, Inc.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining
      8  * a copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sublicense, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial
     17  * portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     23  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     24  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     25  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: virtgpu_fence.c,v 1.1 2018/08/27 01:34:59 riastradh Exp $");
     30 
     31 #include <drm/drmP.h>
     32 #include "virtgpu_drv.h"
     33 
     34 static const char *virtio_get_driver_name(struct fence *f)
     35 {
     36 	return "virtio_gpu";
     37 }
     38 
     39 static const char *virtio_get_timeline_name(struct fence *f)
     40 {
     41 	return "controlq";
     42 }
     43 
     44 static bool virtio_enable_signaling(struct fence *f)
     45 {
     46 	return true;
     47 }
     48 
     49 static bool virtio_signaled(struct fence *f)
     50 {
     51 	struct virtio_gpu_fence *fence = to_virtio_fence(f);
     52 
     53 	if (atomic64_read(&fence->drv->last_seq) >= fence->seq)
     54 		return true;
     55 	return false;
     56 }
     57 
     58 static void virtio_fence_value_str(struct fence *f, char *str, int size)
     59 {
     60 	struct virtio_gpu_fence *fence = to_virtio_fence(f);
     61 
     62 	snprintf(str, size, "%llu", fence->seq);
     63 }
     64 
     65 static void virtio_timeline_value_str(struct fence *f, char *str, int size)
     66 {
     67 	struct virtio_gpu_fence *fence = to_virtio_fence(f);
     68 
     69 	snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq));
     70 }
     71 
     72 static const struct fence_ops virtio_fence_ops = {
     73 	.get_driver_name     = virtio_get_driver_name,
     74 	.get_timeline_name   = virtio_get_timeline_name,
     75 	.enable_signaling    = virtio_enable_signaling,
     76 	.signaled            = virtio_signaled,
     77 	.wait                = fence_default_wait,
     78 	.fence_value_str     = virtio_fence_value_str,
     79 	.timeline_value_str  = virtio_timeline_value_str,
     80 };
     81 
     82 int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
     83 			  struct virtio_gpu_ctrl_hdr *cmd_hdr,
     84 			  struct virtio_gpu_fence **fence)
     85 {
     86 	struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
     87 	unsigned long irq_flags;
     88 
     89 	*fence = kmalloc(sizeof(struct virtio_gpu_fence), GFP_ATOMIC);
     90 	if ((*fence) == NULL)
     91 		return -ENOMEM;
     92 
     93 	spin_lock_irqsave(&drv->lock, irq_flags);
     94 	(*fence)->drv = drv;
     95 	(*fence)->seq = ++drv->sync_seq;
     96 	fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock,
     97 		   0, (*fence)->seq);
     98 	fence_get(&(*fence)->f);
     99 	list_add_tail(&(*fence)->node, &drv->fences);
    100 	spin_unlock_irqrestore(&drv->lock, irq_flags);
    101 
    102 	cmd_hdr->flags |= cpu_to_le32(VIRTIO_GPU_FLAG_FENCE);
    103 	cmd_hdr->fence_id = cpu_to_le64((*fence)->seq);
    104 	return 0;
    105 }
    106 
    107 void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev,
    108 				    u64 last_seq)
    109 {
    110 	struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
    111 	struct virtio_gpu_fence *fence, *tmp;
    112 	unsigned long irq_flags;
    113 
    114 	spin_lock_irqsave(&drv->lock, irq_flags);
    115 	atomic64_set(&vgdev->fence_drv.last_seq, last_seq);
    116 	list_for_each_entry_safe(fence, tmp, &drv->fences, node) {
    117 		if (last_seq < fence->seq)
    118 			continue;
    119 		fence_signal_locked(&fence->f);
    120 		list_del(&fence->node);
    121 		fence_put(&fence->f);
    122 	}
    123 	spin_unlock_irqrestore(&drv->lock, irq_flags);
    124 }
    125