2 * Copyright (C) 2015 Red Hat, Inc.
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:
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.
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.
26 #include <linux/moduleparam.h>
28 #include "virtgpu_drv.h"
30 static int virtio_gpu_virglrenderer_workaround
= 1;
31 module_param_named(virglhack
, virtio_gpu_virglrenderer_workaround
, int, 0400);
33 static int virtio_gpu_resource_id_get(struct virtio_gpu_device
*vgdev
,
36 if (virtio_gpu_virglrenderer_workaround
) {
38 * Hack to avoid re-using resource IDs.
40 * virglrenderer versions up to (and including) 0.7.0
41 * can't deal with that. virglrenderer commit
42 * "f91a9dd35715 Fix unlinking resources from hash
43 * table." (Feb 2019) fixes the bug.
49 int handle
= ida_alloc(&vgdev
->resource_ida
, GFP_KERNEL
);
57 static void virtio_gpu_resource_id_put(struct virtio_gpu_device
*vgdev
, uint32_t id
)
59 if (!virtio_gpu_virglrenderer_workaround
) {
60 ida_free(&vgdev
->resource_ida
, id
- 1);
64 static void virtio_gpu_free_object(struct drm_gem_object
*obj
)
66 struct virtio_gpu_object
*bo
= gem_to_virtio_gpu_obj(obj
);
67 struct virtio_gpu_device
*vgdev
= bo
->base
.base
.dev
->dev_private
;
70 virtio_gpu_object_detach(vgdev
, bo
);
72 virtio_gpu_cmd_unref_resource(vgdev
, bo
->hw_res_handle
);
73 virtio_gpu_resource_id_put(vgdev
, bo
->hw_res_handle
);
75 drm_gem_shmem_free_object(obj
);
78 static const struct drm_gem_object_funcs virtio_gpu_gem_funcs
= {
79 .free
= virtio_gpu_free_object
,
80 .open
= virtio_gpu_gem_object_open
,
81 .close
= virtio_gpu_gem_object_close
,
83 .print_info
= drm_gem_shmem_print_info
,
84 .pin
= drm_gem_shmem_pin
,
85 .unpin
= drm_gem_shmem_unpin
,
86 .get_sg_table
= drm_gem_shmem_get_sg_table
,
87 .vmap
= drm_gem_shmem_vmap
,
88 .vunmap
= drm_gem_shmem_vunmap
,
89 .mmap
= &drm_gem_shmem_mmap
,
92 struct drm_gem_object
*virtio_gpu_create_object(struct drm_device
*dev
,
95 struct virtio_gpu_object
*bo
;
97 bo
= kzalloc(sizeof(*bo
), GFP_KERNEL
);
101 bo
->base
.base
.funcs
= &virtio_gpu_gem_funcs
;
102 return &bo
->base
.base
;
105 int virtio_gpu_object_create(struct virtio_gpu_device
*vgdev
,
106 struct virtio_gpu_object_params
*params
,
107 struct virtio_gpu_object
**bo_ptr
,
108 struct virtio_gpu_fence
*fence
)
110 struct virtio_gpu_object_array
*objs
= NULL
;
111 struct drm_gem_shmem_object
*shmem_obj
;
112 struct virtio_gpu_object
*bo
;
117 params
->size
= roundup(params
->size
, PAGE_SIZE
);
118 shmem_obj
= drm_gem_shmem_create(vgdev
->ddev
, params
->size
);
119 if (IS_ERR(shmem_obj
))
120 return PTR_ERR(shmem_obj
);
121 bo
= gem_to_virtio_gpu_obj(&shmem_obj
->base
);
123 ret
= virtio_gpu_resource_id_get(vgdev
, &bo
->hw_res_handle
);
127 bo
->dumb
= params
->dumb
;
131 objs
= virtio_gpu_array_alloc(1);
134 virtio_gpu_array_add_obj(objs
, &bo
->base
.base
);
136 ret
= virtio_gpu_array_lock_resv(objs
);
142 virtio_gpu_cmd_resource_create_3d(vgdev
, bo
, params
,
145 virtio_gpu_cmd_create_resource(vgdev
, bo
, params
,
149 ret
= virtio_gpu_object_attach(vgdev
, bo
, NULL
);
151 virtio_gpu_free_object(&shmem_obj
->base
);
159 virtio_gpu_array_put_free(objs
);
161 virtio_gpu_resource_id_put(vgdev
, bo
->hw_res_handle
);
163 drm_gem_shmem_free_object(&shmem_obj
->base
);