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