drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / gpu / drm / vmwgfx / vmwgfx_context.c
CommitLineData
543831cf
TH
1/**************************************************************************
2 *
3 * Copyright © 2009-2012 VMware, Inc., Palo Alto, CA., USA
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "vmwgfx_drv.h"
29#include "vmwgfx_resource_priv.h"
30#include "ttm/ttm_placement.h"
31
32struct vmw_user_context {
33 struct ttm_base_object base;
34 struct vmw_resource res;
35};
36
37static void vmw_user_context_free(struct vmw_resource *res);
38static struct vmw_resource *
39vmw_user_context_base_to_res(struct ttm_base_object *base);
40
41static uint64_t vmw_user_context_size;
42
43static const struct vmw_user_resource_conv user_context_conv = {
44 .object_type = VMW_RES_CONTEXT,
45 .base_obj_to_res = vmw_user_context_base_to_res,
46 .res_free = vmw_user_context_free
47};
48
49const struct vmw_user_resource_conv *user_context_converter =
50 &user_context_conv;
51
52
53static const struct vmw_res_func vmw_legacy_context_func = {
54 .res_type = vmw_res_context,
55 .needs_backup = false,
56 .may_evict = false,
57 .type_name = "legacy contexts",
58 .backup_placement = NULL,
59 .create = NULL,
60 .destroy = NULL,
61 .bind = NULL,
62 .unbind = NULL
63};
64
65/**
66 * Context management:
67 */
68
69static void vmw_hw_context_destroy(struct vmw_resource *res)
70{
71
72 struct vmw_private *dev_priv = res->dev_priv;
73 struct {
74 SVGA3dCmdHeader header;
75 SVGA3dCmdDestroyContext body;
76 } *cmd;
77
78
79 vmw_execbuf_release_pinned_bo(dev_priv);
80 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
81 if (unlikely(cmd == NULL)) {
82 DRM_ERROR("Failed reserving FIFO space for surface "
83 "destruction.\n");
84 return;
85 }
86
87 cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY);
88 cmd->header.size = cpu_to_le32(sizeof(cmd->body));
89 cmd->body.cid = cpu_to_le32(res->id);
90
91 vmw_fifo_commit(dev_priv, sizeof(*cmd));
92 vmw_3d_resource_dec(dev_priv, false);
93}
94
95static int vmw_context_init(struct vmw_private *dev_priv,
96 struct vmw_resource *res,
97 void (*res_free) (struct vmw_resource *res))
98{
99 int ret;
100
101 struct {
102 SVGA3dCmdHeader header;
103 SVGA3dCmdDefineContext body;
104 } *cmd;
105
106 ret = vmw_resource_init(dev_priv, res, false,
107 res_free, &vmw_legacy_context_func);
108
109 if (unlikely(ret != 0)) {
110 DRM_ERROR("Failed to allocate a resource id.\n");
111 goto out_early;
112 }
113
114 if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
115 DRM_ERROR("Out of hw context ids.\n");
116 vmw_resource_unreference(&res);
117 return -ENOMEM;
118 }
119
120 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
121 if (unlikely(cmd == NULL)) {
122 DRM_ERROR("Fifo reserve failed.\n");
123 vmw_resource_unreference(&res);
124 return -ENOMEM;
125 }
126
127 cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE);
128 cmd->header.size = cpu_to_le32(sizeof(cmd->body));
129 cmd->body.cid = cpu_to_le32(res->id);
130
131 vmw_fifo_commit(dev_priv, sizeof(*cmd));
132 (void) vmw_3d_resource_inc(dev_priv, false);
133 vmw_resource_activate(res, vmw_hw_context_destroy);
134 return 0;
135
136out_early:
137 if (res_free == NULL)
138 kfree(res);
139 else
140 res_free(res);
141 return ret;
142}
143
144struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
145{
146 struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
147 int ret;
148
149 if (unlikely(res == NULL))
150 return NULL;
151
152 ret = vmw_context_init(dev_priv, res, NULL);
153
154 return (ret == 0) ? res : NULL;
155}
156
157/**
158 * User-space context management:
159 */
160
161static struct vmw_resource *
162vmw_user_context_base_to_res(struct ttm_base_object *base)
163{
164 return &(container_of(base, struct vmw_user_context, base)->res);
165}
166
167static void vmw_user_context_free(struct vmw_resource *res)
168{
169 struct vmw_user_context *ctx =
170 container_of(res, struct vmw_user_context, res);
171 struct vmw_private *dev_priv = res->dev_priv;
172
173 ttm_base_object_kfree(ctx, base);
174 ttm_mem_global_free(vmw_mem_glob(dev_priv),
175 vmw_user_context_size);
176}
177
178/**
179 * This function is called when user space has no more references on the
180 * base object. It releases the base-object's reference on the resource object.
181 */
182
183static void vmw_user_context_base_release(struct ttm_base_object **p_base)
184{
185 struct ttm_base_object *base = *p_base;
186 struct vmw_user_context *ctx =
187 container_of(base, struct vmw_user_context, base);
188 struct vmw_resource *res = &ctx->res;
189
190 *p_base = NULL;
191 vmw_resource_unreference(&res);
192}
193
194int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
195 struct drm_file *file_priv)
196{
197 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
198 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
199
200 return ttm_ref_object_base_unref(tfile, arg->cid, TTM_REF_USAGE);
201}
202
203int vmw_context_define_ioctl(struct drm_device *dev, void *data,
204 struct drm_file *file_priv)
205{
206 struct vmw_private *dev_priv = vmw_priv(dev);
207 struct vmw_user_context *ctx;
208 struct vmw_resource *res;
209 struct vmw_resource *tmp;
210 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
211 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
212 struct vmw_master *vmaster = vmw_master(file_priv->master);
213 int ret;
214
215
216 /*
217 * Approximate idr memory usage with 128 bytes. It will be limited
218 * by maximum number_of contexts anyway.
219 */
220
221 if (unlikely(vmw_user_context_size == 0))
222 vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
223
224 ret = ttm_read_lock(&vmaster->lock, true);
225 if (unlikely(ret != 0))
226 return ret;
227
228 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
229 vmw_user_context_size,
230 false, true);
231 if (unlikely(ret != 0)) {
232 if (ret != -ERESTARTSYS)
233 DRM_ERROR("Out of graphics memory for context"
234 " creation.\n");
235 goto out_unlock;
236 }
237
238 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
239 if (unlikely(ctx == NULL)) {
240 ttm_mem_global_free(vmw_mem_glob(dev_priv),
241 vmw_user_context_size);
242 ret = -ENOMEM;
243 goto out_unlock;
244 }
245
246 res = &ctx->res;
247 ctx->base.shareable = false;
248 ctx->base.tfile = NULL;
249
250 /*
251 * From here on, the destructor takes over resource freeing.
252 */
253
254 ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
255 if (unlikely(ret != 0))
256 goto out_unlock;
257
258 tmp = vmw_resource_reference(&ctx->res);
259 ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
260 &vmw_user_context_base_release, NULL);
261
262 if (unlikely(ret != 0)) {
263 vmw_resource_unreference(&tmp);
264 goto out_err;
265 }
266
267 arg->cid = ctx->base.hash.key;
268out_err:
269 vmw_resource_unreference(&res);
270out_unlock:
271 ttm_read_unlock(&vmaster->lock);
272 return ret;
273
274}