1 1.1 riastrad /* $NetBSD: virtgpu_kms.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright (C) 2015 Red Hat, Inc. 5 1.1 riastrad * All Rights Reserved. 6 1.1 riastrad * 7 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining 8 1.1 riastrad * a copy of this software and associated documentation files (the 9 1.1 riastrad * "Software"), to deal in the Software without restriction, including 10 1.1 riastrad * without limitation the rights to use, copy, modify, merge, publish, 11 1.1 riastrad * distribute, sublicense, and/or sell copies of the Software, and to 12 1.1 riastrad * permit persons to whom the Software is furnished to do so, subject to 13 1.1 riastrad * the following conditions: 14 1.1 riastrad * 15 1.1 riastrad * The above copyright notice and this permission notice (including the 16 1.1 riastrad * next paragraph) shall be included in all copies or substantial 17 1.1 riastrad * portions of the Software. 18 1.1 riastrad * 19 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 1.1 riastrad * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 1.1 riastrad * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 1.1 riastrad * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 23 1.1 riastrad * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 1.1 riastrad * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 1.1 riastrad * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 1.1 riastrad */ 27 1.1 riastrad 28 1.1 riastrad #include <sys/cdefs.h> 29 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: virtgpu_kms.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $"); 30 1.1 riastrad 31 1.1 riastrad #include <linux/virtio.h> 32 1.1 riastrad #include <linux/virtio_config.h> 33 1.1 riastrad 34 1.3 riastrad #include <drm/drm_file.h> 35 1.1 riastrad 36 1.3 riastrad #include "virtgpu_drv.h" 37 1.1 riastrad 38 1.1 riastrad static void virtio_gpu_config_changed_work_func(struct work_struct *work) 39 1.1 riastrad { 40 1.1 riastrad struct virtio_gpu_device *vgdev = 41 1.1 riastrad container_of(work, struct virtio_gpu_device, 42 1.1 riastrad config_changed_work); 43 1.1 riastrad u32 events_read, events_clear = 0; 44 1.1 riastrad 45 1.1 riastrad /* read the config space */ 46 1.1 riastrad virtio_cread(vgdev->vdev, struct virtio_gpu_config, 47 1.1 riastrad events_read, &events_read); 48 1.1 riastrad if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { 49 1.3 riastrad if (vgdev->has_edid) 50 1.3 riastrad virtio_gpu_cmd_get_edids(vgdev); 51 1.1 riastrad virtio_gpu_cmd_get_display_info(vgdev); 52 1.1 riastrad drm_helper_hpd_irq_event(vgdev->ddev); 53 1.1 riastrad events_clear |= VIRTIO_GPU_EVENT_DISPLAY; 54 1.1 riastrad } 55 1.1 riastrad virtio_cwrite(vgdev->vdev, struct virtio_gpu_config, 56 1.1 riastrad events_clear, &events_clear); 57 1.1 riastrad } 58 1.1 riastrad 59 1.3 riastrad static int virtio_gpu_context_create(struct virtio_gpu_device *vgdev, 60 1.3 riastrad uint32_t nlen, const char *name) 61 1.1 riastrad { 62 1.3 riastrad int handle = ida_alloc(&vgdev->ctx_id_ida, GFP_KERNEL); 63 1.1 riastrad 64 1.3 riastrad if (handle < 0) 65 1.3 riastrad return handle; 66 1.3 riastrad handle += 1; 67 1.3 riastrad virtio_gpu_cmd_context_create(vgdev, handle, nlen, name); 68 1.3 riastrad return handle; 69 1.1 riastrad } 70 1.1 riastrad 71 1.1 riastrad static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev, 72 1.1 riastrad uint32_t ctx_id) 73 1.1 riastrad { 74 1.1 riastrad virtio_gpu_cmd_context_destroy(vgdev, ctx_id); 75 1.3 riastrad ida_free(&vgdev->ctx_id_ida, ctx_id - 1); 76 1.1 riastrad } 77 1.1 riastrad 78 1.1 riastrad static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq, 79 1.1 riastrad void (*work_func)(struct work_struct *work)) 80 1.1 riastrad { 81 1.1 riastrad spin_lock_init(&vgvq->qlock); 82 1.1 riastrad init_waitqueue_head(&vgvq->ack_queue); 83 1.1 riastrad INIT_WORK(&vgvq->dequeue_work, work_func); 84 1.1 riastrad } 85 1.1 riastrad 86 1.1 riastrad static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev, 87 1.1 riastrad int num_capsets) 88 1.1 riastrad { 89 1.1 riastrad int i, ret; 90 1.1 riastrad 91 1.1 riastrad vgdev->capsets = kcalloc(num_capsets, 92 1.1 riastrad sizeof(struct virtio_gpu_drv_capset), 93 1.1 riastrad GFP_KERNEL); 94 1.1 riastrad if (!vgdev->capsets) { 95 1.1 riastrad DRM_ERROR("failed to allocate cap sets\n"); 96 1.1 riastrad return; 97 1.1 riastrad } 98 1.1 riastrad for (i = 0; i < num_capsets; i++) { 99 1.1 riastrad virtio_gpu_cmd_get_capset_info(vgdev, i); 100 1.1 riastrad ret = wait_event_timeout(vgdev->resp_wq, 101 1.1 riastrad vgdev->capsets[i].id > 0, 5 * HZ); 102 1.1 riastrad if (ret == 0) { 103 1.1 riastrad DRM_ERROR("timed out waiting for cap set %d\n", i); 104 1.1 riastrad kfree(vgdev->capsets); 105 1.1 riastrad vgdev->capsets = NULL; 106 1.1 riastrad return; 107 1.1 riastrad } 108 1.1 riastrad DRM_INFO("cap set %d: id %d, max-version %d, max-size %d\n", 109 1.1 riastrad i, vgdev->capsets[i].id, 110 1.1 riastrad vgdev->capsets[i].max_version, 111 1.1 riastrad vgdev->capsets[i].max_size); 112 1.1 riastrad } 113 1.1 riastrad vgdev->num_capsets = num_capsets; 114 1.1 riastrad } 115 1.1 riastrad 116 1.3 riastrad int virtio_gpu_init(struct drm_device *dev) 117 1.1 riastrad { 118 1.1 riastrad static vq_callback_t *callbacks[] = { 119 1.1 riastrad virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack 120 1.1 riastrad }; 121 1.3 riastrad static const char * const names[] = { "control", "cursor" }; 122 1.1 riastrad 123 1.1 riastrad struct virtio_gpu_device *vgdev; 124 1.1 riastrad /* this will expand later */ 125 1.1 riastrad struct virtqueue *vqs[2]; 126 1.1 riastrad u32 num_scanouts, num_capsets; 127 1.1 riastrad int ret; 128 1.1 riastrad 129 1.3 riastrad if (!virtio_has_feature(dev_to_virtio(dev->dev), VIRTIO_F_VERSION_1)) 130 1.1 riastrad return -ENODEV; 131 1.1 riastrad 132 1.1 riastrad vgdev = kzalloc(sizeof(struct virtio_gpu_device), GFP_KERNEL); 133 1.1 riastrad if (!vgdev) 134 1.1 riastrad return -ENOMEM; 135 1.1 riastrad 136 1.1 riastrad vgdev->ddev = dev; 137 1.1 riastrad dev->dev_private = vgdev; 138 1.3 riastrad vgdev->vdev = dev_to_virtio(dev->dev); 139 1.1 riastrad vgdev->dev = dev->dev; 140 1.1 riastrad 141 1.1 riastrad spin_lock_init(&vgdev->display_info_lock); 142 1.3 riastrad ida_init(&vgdev->ctx_id_ida); 143 1.3 riastrad ida_init(&vgdev->resource_ida); 144 1.1 riastrad init_waitqueue_head(&vgdev->resp_wq); 145 1.1 riastrad virtio_gpu_init_vq(&vgdev->ctrlq, virtio_gpu_dequeue_ctrl_func); 146 1.1 riastrad virtio_gpu_init_vq(&vgdev->cursorq, virtio_gpu_dequeue_cursor_func); 147 1.1 riastrad 148 1.3 riastrad vgdev->fence_drv.context = dma_fence_context_alloc(1); 149 1.1 riastrad spin_lock_init(&vgdev->fence_drv.lock); 150 1.1 riastrad INIT_LIST_HEAD(&vgdev->fence_drv.fences); 151 1.1 riastrad INIT_LIST_HEAD(&vgdev->cap_cache); 152 1.1 riastrad INIT_WORK(&vgdev->config_changed_work, 153 1.1 riastrad virtio_gpu_config_changed_work_func); 154 1.1 riastrad 155 1.3 riastrad INIT_WORK(&vgdev->obj_free_work, 156 1.3 riastrad virtio_gpu_array_put_free_work); 157 1.3 riastrad INIT_LIST_HEAD(&vgdev->obj_free_list); 158 1.3 riastrad spin_lock_init(&vgdev->obj_free_lock); 159 1.3 riastrad 160 1.3 riastrad #ifdef __LITTLE_ENDIAN 161 1.1 riastrad if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_VIRGL)) 162 1.1 riastrad vgdev->has_virgl_3d = true; 163 1.3 riastrad #endif 164 1.3 riastrad if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) { 165 1.3 riastrad vgdev->has_edid = true; 166 1.3 riastrad } 167 1.3 riastrad 168 1.3 riastrad DRM_INFO("features: %cvirgl %cedid\n", 169 1.3 riastrad vgdev->has_virgl_3d ? '+' : '-', 170 1.3 riastrad vgdev->has_edid ? '+' : '-'); 171 1.1 riastrad 172 1.3 riastrad ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); 173 1.1 riastrad if (ret) { 174 1.1 riastrad DRM_ERROR("failed to find virt queues\n"); 175 1.1 riastrad goto err_vqs; 176 1.1 riastrad } 177 1.1 riastrad vgdev->ctrlq.vq = vqs[0]; 178 1.1 riastrad vgdev->cursorq.vq = vqs[1]; 179 1.1 riastrad ret = virtio_gpu_alloc_vbufs(vgdev); 180 1.1 riastrad if (ret) { 181 1.1 riastrad DRM_ERROR("failed to alloc vbufs\n"); 182 1.1 riastrad goto err_vbufs; 183 1.1 riastrad } 184 1.1 riastrad 185 1.1 riastrad /* get display info */ 186 1.1 riastrad virtio_cread(vgdev->vdev, struct virtio_gpu_config, 187 1.1 riastrad num_scanouts, &num_scanouts); 188 1.1 riastrad vgdev->num_scanouts = min_t(uint32_t, num_scanouts, 189 1.1 riastrad VIRTIO_GPU_MAX_SCANOUTS); 190 1.1 riastrad if (!vgdev->num_scanouts) { 191 1.1 riastrad DRM_ERROR("num_scanouts is zero\n"); 192 1.1 riastrad ret = -EINVAL; 193 1.1 riastrad goto err_scanouts; 194 1.1 riastrad } 195 1.1 riastrad DRM_INFO("number of scanouts: %d\n", num_scanouts); 196 1.1 riastrad 197 1.1 riastrad virtio_cread(vgdev->vdev, struct virtio_gpu_config, 198 1.1 riastrad num_capsets, &num_capsets); 199 1.1 riastrad DRM_INFO("number of cap sets: %d\n", num_capsets); 200 1.1 riastrad 201 1.3 riastrad virtio_gpu_modeset_init(vgdev); 202 1.1 riastrad 203 1.1 riastrad virtio_device_ready(vgdev->vdev); 204 1.1 riastrad vgdev->vqs_ready = true; 205 1.1 riastrad 206 1.1 riastrad if (num_capsets) 207 1.1 riastrad virtio_gpu_get_capsets(vgdev, num_capsets); 208 1.3 riastrad if (vgdev->has_edid) 209 1.3 riastrad virtio_gpu_cmd_get_edids(vgdev); 210 1.1 riastrad virtio_gpu_cmd_get_display_info(vgdev); 211 1.1 riastrad wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, 212 1.1 riastrad 5 * HZ); 213 1.1 riastrad return 0; 214 1.1 riastrad 215 1.1 riastrad err_scanouts: 216 1.1 riastrad virtio_gpu_free_vbufs(vgdev); 217 1.1 riastrad err_vbufs: 218 1.1 riastrad vgdev->vdev->config->del_vqs(vgdev->vdev); 219 1.1 riastrad err_vqs: 220 1.1 riastrad kfree(vgdev); 221 1.1 riastrad return ret; 222 1.1 riastrad } 223 1.1 riastrad 224 1.1 riastrad static void virtio_gpu_cleanup_cap_cache(struct virtio_gpu_device *vgdev) 225 1.1 riastrad { 226 1.1 riastrad struct virtio_gpu_drv_cap_cache *cache_ent, *tmp; 227 1.1 riastrad 228 1.1 riastrad list_for_each_entry_safe(cache_ent, tmp, &vgdev->cap_cache, head) { 229 1.1 riastrad kfree(cache_ent->caps_cache); 230 1.1 riastrad kfree(cache_ent); 231 1.1 riastrad } 232 1.1 riastrad } 233 1.1 riastrad 234 1.3 riastrad void virtio_gpu_deinit(struct drm_device *dev) 235 1.1 riastrad { 236 1.1 riastrad struct virtio_gpu_device *vgdev = dev->dev_private; 237 1.1 riastrad 238 1.3 riastrad flush_work(&vgdev->obj_free_work); 239 1.1 riastrad vgdev->vqs_ready = false; 240 1.1 riastrad flush_work(&vgdev->ctrlq.dequeue_work); 241 1.1 riastrad flush_work(&vgdev->cursorq.dequeue_work); 242 1.1 riastrad flush_work(&vgdev->config_changed_work); 243 1.3 riastrad vgdev->vdev->config->reset(vgdev->vdev); 244 1.1 riastrad vgdev->vdev->config->del_vqs(vgdev->vdev); 245 1.1 riastrad 246 1.1 riastrad virtio_gpu_modeset_fini(vgdev); 247 1.1 riastrad virtio_gpu_free_vbufs(vgdev); 248 1.1 riastrad virtio_gpu_cleanup_cap_cache(vgdev); 249 1.1 riastrad kfree(vgdev->capsets); 250 1.1 riastrad kfree(vgdev); 251 1.1 riastrad } 252 1.1 riastrad 253 1.1 riastrad int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file) 254 1.1 riastrad { 255 1.1 riastrad struct virtio_gpu_device *vgdev = dev->dev_private; 256 1.1 riastrad struct virtio_gpu_fpriv *vfpriv; 257 1.3 riastrad int id; 258 1.3 riastrad char dbgname[TASK_COMM_LEN]; 259 1.1 riastrad 260 1.1 riastrad /* can't create contexts without 3d renderer */ 261 1.1 riastrad if (!vgdev->has_virgl_3d) 262 1.1 riastrad return 0; 263 1.1 riastrad 264 1.1 riastrad /* allocate a virt GPU context for this opener */ 265 1.1 riastrad vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL); 266 1.1 riastrad if (!vfpriv) 267 1.1 riastrad return -ENOMEM; 268 1.1 riastrad 269 1.3 riastrad get_task_comm(dbgname, current); 270 1.3 riastrad id = virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname); 271 1.3 riastrad if (id < 0) { 272 1.3 riastrad kfree(vfpriv); 273 1.3 riastrad return id; 274 1.3 riastrad } 275 1.1 riastrad 276 1.1 riastrad vfpriv->ctx_id = id; 277 1.1 riastrad file->driver_priv = vfpriv; 278 1.1 riastrad return 0; 279 1.1 riastrad } 280 1.1 riastrad 281 1.1 riastrad void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file) 282 1.1 riastrad { 283 1.1 riastrad struct virtio_gpu_device *vgdev = dev->dev_private; 284 1.1 riastrad struct virtio_gpu_fpriv *vfpriv; 285 1.1 riastrad 286 1.1 riastrad if (!vgdev->has_virgl_3d) 287 1.1 riastrad return; 288 1.1 riastrad 289 1.1 riastrad vfpriv = file->driver_priv; 290 1.1 riastrad 291 1.1 riastrad virtio_gpu_context_destroy(vgdev, vfpriv->ctx_id); 292 1.1 riastrad kfree(vfpriv); 293 1.1 riastrad file->driver_priv = NULL; 294 1.1 riastrad } 295