Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2015 Red Hat, Inc.
3 : : * All Rights Reserved.
4 : : *
5 : : * Permission is hereby granted, free of charge, to any person obtaining
6 : : * a copy of this software and associated documentation files (the
7 : : * "Software"), to deal in the Software without restriction, including
8 : : * without limitation the rights to use, copy, modify, merge, publish,
9 : : * distribute, sublicense, and/or sell copies of the Software, and to
10 : : * permit persons to whom the Software is furnished to do so, subject to
11 : : * the following conditions:
12 : : *
13 : : * The above copyright notice and this permission notice (including the
14 : : * next paragraph) shall be included in all copies or substantial
15 : : * portions of the Software.
16 : : *
17 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 : : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 : : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 : : * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 : : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 : : * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 : : * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 : : */
25 : :
26 : : #include <trace/events/dma_fence.h>
27 : :
28 : : #include "virtgpu_drv.h"
29 : :
30 : : #define to_virtio_fence(x) \
31 : : container_of(x, struct virtio_gpu_fence, f)
32 : :
33 : 0 : static const char *virtio_get_driver_name(struct dma_fence *f)
34 : : {
35 : 0 : return "virtio_gpu";
36 : : }
37 : :
38 : 0 : static const char *virtio_get_timeline_name(struct dma_fence *f)
39 : : {
40 : 0 : return "controlq";
41 : : }
42 : :
43 : 0 : static bool virtio_fence_signaled(struct dma_fence *f)
44 : : {
45 : 0 : struct virtio_gpu_fence *fence = to_virtio_fence(f);
46 : :
47 [ # # # # ]: 0 : if (WARN_ON_ONCE(fence->f.seqno == 0))
48 : : /* leaked fence outside driver before completing
49 : : * initialization with virtio_gpu_fence_emit */
50 : : return false;
51 [ # # ]: 0 : if (atomic64_read(&fence->drv->last_seq) >= fence->f.seqno)
52 : 0 : return true;
53 : : return false;
54 : : }
55 : :
56 : 0 : static void virtio_fence_value_str(struct dma_fence *f, char *str, int size)
57 : : {
58 : 0 : snprintf(str, size, "%llu", f->seqno);
59 : 0 : }
60 : :
61 : 0 : static void virtio_timeline_value_str(struct dma_fence *f, char *str, int size)
62 : : {
63 : 0 : struct virtio_gpu_fence *fence = to_virtio_fence(f);
64 : :
65 : 0 : snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq));
66 : 0 : }
67 : :
68 : : static const struct dma_fence_ops virtio_fence_ops = {
69 : : .get_driver_name = virtio_get_driver_name,
70 : : .get_timeline_name = virtio_get_timeline_name,
71 : : .signaled = virtio_fence_signaled,
72 : : .fence_value_str = virtio_fence_value_str,
73 : : .timeline_value_str = virtio_timeline_value_str,
74 : : };
75 : :
76 : 0 : struct virtio_gpu_fence *virtio_gpu_fence_alloc(struct virtio_gpu_device *vgdev)
77 : : {
78 : 0 : struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
79 : 0 : struct virtio_gpu_fence *fence = kzalloc(sizeof(struct virtio_gpu_fence),
80 : : GFP_KERNEL);
81 [ # # ]: 0 : if (!fence)
82 : : return fence;
83 : :
84 : 0 : fence->drv = drv;
85 : :
86 : : /* This only partially initializes the fence because the seqno is
87 : : * unknown yet. The fence must not be used outside of the driver
88 : : * until virtio_gpu_fence_emit is called.
89 : : */
90 : 0 : dma_fence_init(&fence->f, &virtio_fence_ops, &drv->lock, drv->context, 0);
91 : :
92 : 0 : return fence;
93 : : }
94 : :
95 : 0 : void virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
96 : : struct virtio_gpu_ctrl_hdr *cmd_hdr,
97 : : struct virtio_gpu_fence *fence)
98 : : {
99 : 0 : struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
100 : 0 : unsigned long irq_flags;
101 : :
102 : 0 : spin_lock_irqsave(&drv->lock, irq_flags);
103 : 0 : fence->f.seqno = ++drv->sync_seq;
104 [ # # ]: 0 : dma_fence_get(&fence->f);
105 : 0 : list_add_tail(&fence->node, &drv->fences);
106 : 0 : spin_unlock_irqrestore(&drv->lock, irq_flags);
107 : :
108 : 0 : trace_dma_fence_emit(&fence->f);
109 : :
110 : 0 : cmd_hdr->flags |= cpu_to_le32(VIRTIO_GPU_FLAG_FENCE);
111 : 0 : cmd_hdr->fence_id = cpu_to_le64(fence->f.seqno);
112 : 0 : }
113 : :
114 : 0 : void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev,
115 : : u64 last_seq)
116 : : {
117 : 0 : struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
118 : 0 : struct virtio_gpu_fence *fence, *tmp;
119 : 0 : unsigned long irq_flags;
120 : :
121 : 0 : spin_lock_irqsave(&drv->lock, irq_flags);
122 : 0 : atomic64_set(&vgdev->fence_drv.last_seq, last_seq);
123 [ # # ]: 0 : list_for_each_entry_safe(fence, tmp, &drv->fences, node) {
124 [ # # ]: 0 : if (last_seq < fence->f.seqno)
125 : 0 : continue;
126 : 0 : dma_fence_signal_locked(&fence->f);
127 : 0 : list_del(&fence->node);
128 : 0 : dma_fence_put(&fence->f);
129 : : }
130 : 0 : spin_unlock_irqrestore(&drv->lock, irq_flags);
131 : 0 : }
|