.. | .. |
---|
25 | 25 | |
---|
26 | 26 | #include <linux/virtio.h> |
---|
27 | 27 | #include <linux/virtio_config.h> |
---|
28 | | -#include <drm/drmP.h> |
---|
| 28 | +#include <linux/virtio_ring.h> |
---|
| 29 | + |
---|
| 30 | +#include <drm/drm_file.h> |
---|
| 31 | + |
---|
29 | 32 | #include "virtgpu_drv.h" |
---|
30 | 33 | |
---|
31 | 34 | static void virtio_gpu_config_changed_work_func(struct work_struct *work) |
---|
.. | .. |
---|
36 | 39 | u32 events_read, events_clear = 0; |
---|
37 | 40 | |
---|
38 | 41 | /* read the config space */ |
---|
39 | | - virtio_cread(vgdev->vdev, struct virtio_gpu_config, |
---|
40 | | - events_read, &events_read); |
---|
| 42 | + virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, |
---|
| 43 | + events_read, &events_read); |
---|
41 | 44 | if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { |
---|
42 | 45 | if (vgdev->has_edid) |
---|
43 | 46 | virtio_gpu_cmd_get_edids(vgdev); |
---|
44 | 47 | virtio_gpu_cmd_get_display_info(vgdev); |
---|
| 48 | + virtio_gpu_notify(vgdev); |
---|
45 | 49 | drm_helper_hpd_irq_event(vgdev->ddev); |
---|
46 | 50 | events_clear |= VIRTIO_GPU_EVENT_DISPLAY; |
---|
47 | 51 | } |
---|
48 | | - virtio_cwrite(vgdev->vdev, struct virtio_gpu_config, |
---|
49 | | - events_clear, &events_clear); |
---|
50 | | -} |
---|
51 | | - |
---|
52 | | -static int virtio_gpu_context_create(struct virtio_gpu_device *vgdev, |
---|
53 | | - uint32_t nlen, const char *name) |
---|
54 | | -{ |
---|
55 | | - int handle = ida_alloc(&vgdev->ctx_id_ida, GFP_KERNEL); |
---|
56 | | - |
---|
57 | | - if (handle < 0) |
---|
58 | | - return handle; |
---|
59 | | - handle += 1; |
---|
60 | | - virtio_gpu_cmd_context_create(vgdev, handle, nlen, name); |
---|
61 | | - return handle; |
---|
62 | | -} |
---|
63 | | - |
---|
64 | | -static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev, |
---|
65 | | - uint32_t ctx_id) |
---|
66 | | -{ |
---|
67 | | - virtio_gpu_cmd_context_destroy(vgdev, ctx_id); |
---|
68 | | - ida_free(&vgdev->ctx_id_ida, ctx_id - 1); |
---|
| 52 | + virtio_cwrite_le(vgdev->vdev, struct virtio_gpu_config, |
---|
| 53 | + events_clear, &events_clear); |
---|
69 | 54 | } |
---|
70 | 55 | |
---|
71 | 56 | static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq, |
---|
.. | .. |
---|
90 | 75 | } |
---|
91 | 76 | for (i = 0; i < num_capsets; i++) { |
---|
92 | 77 | virtio_gpu_cmd_get_capset_info(vgdev, i); |
---|
| 78 | + virtio_gpu_notify(vgdev); |
---|
93 | 79 | ret = wait_event_timeout(vgdev->resp_wq, |
---|
94 | 80 | vgdev->capsets[i].id > 0, 5 * HZ); |
---|
95 | 81 | if (ret == 0) { |
---|
.. | .. |
---|
119 | 105 | /* this will expand later */ |
---|
120 | 106 | struct virtqueue *vqs[2]; |
---|
121 | 107 | u32 num_scanouts, num_capsets; |
---|
122 | | - int ret; |
---|
| 108 | + int ret = 0; |
---|
123 | 109 | |
---|
124 | 110 | if (!virtio_has_feature(dev_to_virtio(dev->dev), VIRTIO_F_VERSION_1)) |
---|
125 | 111 | return -ENODEV; |
---|
.. | .. |
---|
134 | 120 | vgdev->dev = dev->dev; |
---|
135 | 121 | |
---|
136 | 122 | spin_lock_init(&vgdev->display_info_lock); |
---|
| 123 | + spin_lock_init(&vgdev->resource_export_lock); |
---|
137 | 124 | ida_init(&vgdev->ctx_id_ida); |
---|
138 | 125 | ida_init(&vgdev->resource_ida); |
---|
139 | 126 | init_waitqueue_head(&vgdev->resp_wq); |
---|
.. | .. |
---|
147 | 134 | INIT_WORK(&vgdev->config_changed_work, |
---|
148 | 135 | virtio_gpu_config_changed_work_func); |
---|
149 | 136 | |
---|
| 137 | + INIT_WORK(&vgdev->obj_free_work, |
---|
| 138 | + virtio_gpu_array_put_free_work); |
---|
| 139 | + INIT_LIST_HEAD(&vgdev->obj_free_list); |
---|
| 140 | + spin_lock_init(&vgdev->obj_free_lock); |
---|
| 141 | + |
---|
150 | 142 | #ifdef __LITTLE_ENDIAN |
---|
151 | 143 | if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_VIRGL)) |
---|
152 | 144 | vgdev->has_virgl_3d = true; |
---|
153 | | - DRM_INFO("virgl 3d acceleration %s\n", |
---|
154 | | - vgdev->has_virgl_3d ? "enabled" : "not supported by host"); |
---|
155 | | -#else |
---|
156 | | - DRM_INFO("virgl 3d acceleration not supported by guest\n"); |
---|
157 | 145 | #endif |
---|
158 | 146 | if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) { |
---|
159 | 147 | vgdev->has_edid = true; |
---|
160 | | - DRM_INFO("EDID support available.\n"); |
---|
161 | 148 | } |
---|
| 149 | + if (virtio_has_feature(vgdev->vdev, VIRTIO_RING_F_INDIRECT_DESC)) { |
---|
| 150 | + vgdev->has_indirect = true; |
---|
| 151 | + } |
---|
| 152 | + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RESOURCE_UUID)) { |
---|
| 153 | + vgdev->has_resource_assign_uuid = true; |
---|
| 154 | + } |
---|
| 155 | + |
---|
| 156 | + DRM_INFO("features: %cvirgl %cedid\n", |
---|
| 157 | + vgdev->has_virgl_3d ? '+' : '-', |
---|
| 158 | + vgdev->has_edid ? '+' : '-'); |
---|
162 | 159 | |
---|
163 | 160 | ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); |
---|
164 | 161 | if (ret) { |
---|
.. | .. |
---|
173 | 170 | goto err_vbufs; |
---|
174 | 171 | } |
---|
175 | 172 | |
---|
176 | | - ret = virtio_gpu_ttm_init(vgdev); |
---|
177 | | - if (ret) { |
---|
178 | | - DRM_ERROR("failed to init ttm %d\n", ret); |
---|
179 | | - goto err_ttm; |
---|
180 | | - } |
---|
181 | | - |
---|
182 | 173 | /* get display info */ |
---|
183 | | - virtio_cread(vgdev->vdev, struct virtio_gpu_config, |
---|
184 | | - num_scanouts, &num_scanouts); |
---|
| 174 | + virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, |
---|
| 175 | + num_scanouts, &num_scanouts); |
---|
185 | 176 | vgdev->num_scanouts = min_t(uint32_t, num_scanouts, |
---|
186 | 177 | VIRTIO_GPU_MAX_SCANOUTS); |
---|
187 | 178 | if (!vgdev->num_scanouts) { |
---|
.. | .. |
---|
191 | 182 | } |
---|
192 | 183 | DRM_INFO("number of scanouts: %d\n", num_scanouts); |
---|
193 | 184 | |
---|
194 | | - virtio_cread(vgdev->vdev, struct virtio_gpu_config, |
---|
195 | | - num_capsets, &num_capsets); |
---|
| 185 | + virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, |
---|
| 186 | + num_capsets, &num_capsets); |
---|
196 | 187 | DRM_INFO("number of cap sets: %d\n", num_capsets); |
---|
197 | 188 | |
---|
198 | | - virtio_gpu_modeset_init(vgdev); |
---|
| 189 | + ret = virtio_gpu_modeset_init(vgdev); |
---|
| 190 | + if (ret) { |
---|
| 191 | + DRM_ERROR("modeset init failed\n"); |
---|
| 192 | + goto err_scanouts; |
---|
| 193 | + } |
---|
199 | 194 | |
---|
200 | 195 | virtio_device_ready(vgdev->vdev); |
---|
201 | | - vgdev->vqs_ready = true; |
---|
202 | 196 | |
---|
203 | 197 | if (num_capsets) |
---|
204 | 198 | virtio_gpu_get_capsets(vgdev, num_capsets); |
---|
205 | 199 | if (vgdev->has_edid) |
---|
206 | 200 | virtio_gpu_cmd_get_edids(vgdev); |
---|
207 | 201 | virtio_gpu_cmd_get_display_info(vgdev); |
---|
| 202 | + virtio_gpu_notify(vgdev); |
---|
208 | 203 | wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, |
---|
209 | 204 | 5 * HZ); |
---|
210 | 205 | return 0; |
---|
211 | 206 | |
---|
212 | 207 | err_scanouts: |
---|
213 | | - virtio_gpu_ttm_fini(vgdev); |
---|
214 | | -err_ttm: |
---|
215 | 208 | virtio_gpu_free_vbufs(vgdev); |
---|
216 | 209 | err_vbufs: |
---|
217 | 210 | vgdev->vdev->config->del_vqs(vgdev->vdev); |
---|
.. | .. |
---|
235 | 228 | { |
---|
236 | 229 | struct virtio_gpu_device *vgdev = dev->dev_private; |
---|
237 | 230 | |
---|
238 | | - vgdev->vqs_ready = false; |
---|
| 231 | + flush_work(&vgdev->obj_free_work); |
---|
239 | 232 | flush_work(&vgdev->ctrlq.dequeue_work); |
---|
240 | 233 | flush_work(&vgdev->cursorq.dequeue_work); |
---|
241 | 234 | flush_work(&vgdev->config_changed_work); |
---|
242 | 235 | vgdev->vdev->config->reset(vgdev->vdev); |
---|
243 | 236 | vgdev->vdev->config->del_vqs(vgdev->vdev); |
---|
| 237 | +} |
---|
| 238 | + |
---|
| 239 | +void virtio_gpu_release(struct drm_device *dev) |
---|
| 240 | +{ |
---|
| 241 | + struct virtio_gpu_device *vgdev = dev->dev_private; |
---|
244 | 242 | |
---|
245 | 243 | virtio_gpu_modeset_fini(vgdev); |
---|
246 | | - virtio_gpu_ttm_fini(vgdev); |
---|
247 | 244 | virtio_gpu_free_vbufs(vgdev); |
---|
248 | 245 | virtio_gpu_cleanup_cap_cache(vgdev); |
---|
249 | 246 | kfree(vgdev->capsets); |
---|
.. | .. |
---|
254 | 251 | { |
---|
255 | 252 | struct virtio_gpu_device *vgdev = dev->dev_private; |
---|
256 | 253 | struct virtio_gpu_fpriv *vfpriv; |
---|
257 | | - int id; |
---|
258 | | - char dbgname[TASK_COMM_LEN]; |
---|
| 254 | + int handle; |
---|
259 | 255 | |
---|
260 | 256 | /* can't create contexts without 3d renderer */ |
---|
261 | 257 | if (!vgdev->has_virgl_3d) |
---|
.. | .. |
---|
266 | 262 | if (!vfpriv) |
---|
267 | 263 | return -ENOMEM; |
---|
268 | 264 | |
---|
269 | | - get_task_comm(dbgname, current); |
---|
270 | | - id = virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname); |
---|
271 | | - if (id < 0) { |
---|
| 265 | + mutex_init(&vfpriv->context_lock); |
---|
| 266 | + |
---|
| 267 | + handle = ida_alloc(&vgdev->ctx_id_ida, GFP_KERNEL); |
---|
| 268 | + if (handle < 0) { |
---|
272 | 269 | kfree(vfpriv); |
---|
273 | | - return id; |
---|
| 270 | + return handle; |
---|
274 | 271 | } |
---|
275 | 272 | |
---|
276 | | - vfpriv->ctx_id = id; |
---|
| 273 | + vfpriv->ctx_id = handle + 1; |
---|
277 | 274 | file->driver_priv = vfpriv; |
---|
278 | 275 | return 0; |
---|
279 | 276 | } |
---|
.. | .. |
---|
281 | 278 | void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file) |
---|
282 | 279 | { |
---|
283 | 280 | struct virtio_gpu_device *vgdev = dev->dev_private; |
---|
284 | | - struct virtio_gpu_fpriv *vfpriv; |
---|
| 281 | + struct virtio_gpu_fpriv *vfpriv = file->driver_priv; |
---|
285 | 282 | |
---|
286 | 283 | if (!vgdev->has_virgl_3d) |
---|
287 | 284 | return; |
---|
288 | 285 | |
---|
289 | | - vfpriv = file->driver_priv; |
---|
| 286 | + if (vfpriv->context_created) { |
---|
| 287 | + virtio_gpu_cmd_context_destroy(vgdev, vfpriv->ctx_id); |
---|
| 288 | + virtio_gpu_notify(vgdev); |
---|
| 289 | + } |
---|
290 | 290 | |
---|
291 | | - virtio_gpu_context_destroy(vgdev, vfpriv->ctx_id); |
---|
| 291 | + ida_free(&vgdev->ctx_id_ida, vfpriv->ctx_id - 1); |
---|
| 292 | + mutex_destroy(&vfpriv->context_lock); |
---|
292 | 293 | kfree(vfpriv); |
---|
293 | 294 | file->driver_priv = NULL; |
---|
294 | 295 | } |
---|