Subversion Repositories Kolibri OS

Rev

Rev 5078 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4075 Serge 1
/**************************************************************************
2
 *
6296 serge 3
 * Copyright © 2011-2015 VMware, Inc., Palo Alto, CA., USA
4075 Serge 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 
29
 
30
#include 
31
#include "vmwgfx_drv.h"
32
 
33
 
34
/**
6296 serge 35
 * vmw_dmabuf_pin_in_placement - Validate a buffer to placement.
4075 Serge 36
 *
37
 * @dev_priv:  Driver private.
38
 * @buf:  DMA buffer to move.
6296 serge 39
 * @placement:  The placement to pin it.
4075 Serge 40
 * @interruptible:  Use interruptible wait.
41
 *
42
 * Returns
43
 *  -ERESTARTSYS if interrupted by a signal.
44
 */
6296 serge 45
int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv,
46
				struct vmw_dma_buffer *buf,
47
				struct ttm_placement *placement,
48
				bool interruptible)
4075 Serge 49
{
50
	struct ttm_buffer_object *bo = &buf->base;
51
	int ret;
52
 
6296 serge 53
	ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
54
	if (unlikely(ret != 0))
55
		return ret;
4075 Serge 56
 
57
	vmw_execbuf_release_pinned_bo(dev_priv);
58
 
5078 serge 59
	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
4075 Serge 60
	if (unlikely(ret != 0))
61
		goto err;
62
 
63
	ret = ttm_bo_validate(bo, placement, interruptible, false);
6296 serge 64
	if (!ret)
65
		vmw_bo_pin_reserved(buf, true);
4075 Serge 66
 
67
	ttm_bo_unreserve(bo);
68
 
69
err:
6296 serge 70
	ttm_write_unlock(&dev_priv->reservation_sem);
4075 Serge 71
	return ret;
72
}
73
 
74
/**
6296 serge 75
 * vmw_dmabuf_pin_in_vram_or_gmr - Move a buffer to vram or gmr.
4075 Serge 76
 *
6296 serge 77
 * This function takes the reservation_sem in write mode.
78
 * Flushes and unpins the query bo to avoid failures.
4075 Serge 79
 *
80
 * @dev_priv:  Driver private.
81
 * @buf:  DMA buffer to move.
82
 * @pin:  Pin buffer if true.
83
 * @interruptible:  Use interruptible wait.
84
 *
85
 * Returns
86
 * -ERESTARTSYS if interrupted by a signal.
87
 */
6296 serge 88
int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
89
				  struct vmw_dma_buffer *buf,
90
				  bool interruptible)
4075 Serge 91
{
92
	struct ttm_buffer_object *bo = &buf->base;
93
	int ret;
94
 
6296 serge 95
	ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
96
	if (unlikely(ret != 0))
97
		return ret;
4075 Serge 98
 
6296 serge 99
	vmw_execbuf_release_pinned_bo(dev_priv);
4075 Serge 100
 
5078 serge 101
	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
4075 Serge 102
	if (unlikely(ret != 0))
103
		goto err;
104
 
6296 serge 105
	ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, interruptible,
106
			      false);
4075 Serge 107
	if (likely(ret == 0) || ret == -ERESTARTSYS)
6296 serge 108
		goto out_unreserve;
4075 Serge 109
 
6296 serge 110
	ret = ttm_bo_validate(bo, &vmw_vram_placement, interruptible, false);
4075 Serge 111
 
6296 serge 112
out_unreserve:
113
	if (!ret)
114
		vmw_bo_pin_reserved(buf, true);
4075 Serge 115
 
116
	ttm_bo_unreserve(bo);
117
err:
6296 serge 118
	ttm_write_unlock(&dev_priv->reservation_sem);
4075 Serge 119
	return ret;
120
}
121
 
122
/**
6296 serge 123
 * vmw_dmabuf_pin_in_vram - Move a buffer to vram.
4075 Serge 124
 *
6296 serge 125
 * This function takes the reservation_sem in write mode.
126
 * Flushes and unpins the query bo to avoid failures.
4075 Serge 127
 *
128
 * @dev_priv:  Driver private.
129
 * @buf:  DMA buffer to move.
130
 * @interruptible:  Use interruptible wait.
131
 *
132
 * Returns
133
 * -ERESTARTSYS if interrupted by a signal.
134
 */
6296 serge 135
int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
136
			   struct vmw_dma_buffer *buf,
137
			   bool interruptible)
4075 Serge 138
{
6296 serge 139
	return vmw_dmabuf_pin_in_placement(dev_priv, buf, &vmw_vram_placement,
140
					   interruptible);
4075 Serge 141
}
142
 
143
/**
6296 serge 144
 * vmw_dmabuf_pin_in_start_of_vram - Move a buffer to start of vram.
4075 Serge 145
 *
6296 serge 146
 * This function takes the reservation_sem in write mode.
147
 * Flushes and unpins the query bo to avoid failures.
4075 Serge 148
 *
149
 * @dev_priv:  Driver private.
6296 serge 150
 * @buf:  DMA buffer to pin.
4075 Serge 151
 * @interruptible:  Use interruptible wait.
152
 *
153
 * Returns
154
 * -ERESTARTSYS if interrupted by a signal.
155
 */
6296 serge 156
int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *dev_priv,
157
				    struct vmw_dma_buffer *buf,
158
				    bool interruptible)
4075 Serge 159
{
160
	struct ttm_buffer_object *bo = &buf->base;
161
	struct ttm_placement placement;
6296 serge 162
	struct ttm_place place;
4075 Serge 163
	int ret = 0;
164
 
6296 serge 165
	place = vmw_vram_placement.placement[0];
166
	place.lpfn = bo->num_pages;
167
	placement.num_placement = 1;
168
	placement.placement = &place;
169
	placement.num_busy_placement = 1;
170
	placement.busy_placement = &place;
4075 Serge 171
 
6296 serge 172
	ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
173
	if (unlikely(ret != 0))
174
		return ret;
4075 Serge 175
 
6296 serge 176
	vmw_execbuf_release_pinned_bo(dev_priv);
5078 serge 177
	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
4075 Serge 178
	if (unlikely(ret != 0))
179
		goto err_unlock;
180
 
6296 serge 181
	/*
182
	 * Is this buffer already in vram but not at the start of it?
183
	 * In that case, evict it first because TTM isn't good at handling
184
	 * that situation.
185
	 */
4075 Serge 186
	if (bo->mem.mem_type == TTM_PL_VRAM &&
187
	    bo->mem.start < bo->num_pages &&
188
	    bo->mem.start > 0)
189
		(void) ttm_bo_validate(bo, &vmw_sys_placement, false, false);
190
 
191
	ret = ttm_bo_validate(bo, &placement, interruptible, false);
192
 
6296 serge 193
	/* For some reason we didn't end up at the start of vram */
4075 Serge 194
	WARN_ON(ret == 0 && bo->offset != 0);
6296 serge 195
	if (!ret)
196
		vmw_bo_pin_reserved(buf, true);
4075 Serge 197
 
198
	ttm_bo_unreserve(bo);
199
err_unlock:
6296 serge 200
	ttm_write_unlock(&dev_priv->reservation_sem);
4075 Serge 201
 
202
	return ret;
203
}
204
 
205
/**
6296 serge 206
 * vmw_dmabuf_unpin - Unpin the buffer given buffer, does not move the buffer.
4075 Serge 207
 *
6296 serge 208
 * This function takes the reservation_sem in write mode.
4075 Serge 209
 *
210
 * @dev_priv:  Driver private.
211
 * @buf:  DMA buffer to unpin.
212
 * @interruptible:  Use interruptible wait.
213
 *
214
 * Returns
215
 * -ERESTARTSYS if interrupted by a signal.
216
 */
217
int vmw_dmabuf_unpin(struct vmw_private *dev_priv,
218
		     struct vmw_dma_buffer *buf,
219
		     bool interruptible)
220
{
6296 serge 221
	struct ttm_buffer_object *bo = &buf->base;
222
	int ret;
223
 
224
	ret = ttm_read_lock(&dev_priv->reservation_sem, interruptible);
225
	if (unlikely(ret != 0))
226
		return ret;
227
 
228
	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
229
	if (unlikely(ret != 0))
230
		goto err;
231
 
232
	vmw_bo_pin_reserved(buf, false);
233
 
234
	ttm_bo_unreserve(bo);
235
 
236
err:
237
	ttm_read_unlock(&dev_priv->reservation_sem);
238
	return ret;
4075 Serge 239
}
240
 
241
/**
242
 * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement
243
 * of a buffer.
244
 *
245
 * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved.
246
 * @ptr: SVGAGuestPtr returning the result.
247
 */
248
void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
249
			  SVGAGuestPtr *ptr)
250
{
251
	if (bo->mem.mem_type == TTM_PL_VRAM) {
252
		ptr->gmrId = SVGA_GMR_FRAMEBUFFER;
253
		ptr->offset = bo->offset;
254
	} else {
255
		ptr->gmrId = bo->mem.start;
256
		ptr->offset = 0;
257
	}
258
}
259
 
260
 
261
/**
6296 serge 262
 * vmw_bo_pin_reserved - Pin or unpin a buffer object without moving it.
4075 Serge 263
 *
6296 serge 264
 * @vbo: The buffer object. Must be reserved.
4075 Serge 265
 * @pin: Whether to pin or unpin.
266
 *
267
 */
6296 serge 268
void vmw_bo_pin_reserved(struct vmw_dma_buffer *vbo, bool pin)
4075 Serge 269
{
6296 serge 270
	struct ttm_place pl;
4075 Serge 271
	struct ttm_placement placement;
6296 serge 272
	struct ttm_buffer_object *bo = &vbo->base;
4075 Serge 273
	uint32_t old_mem_type = bo->mem.mem_type;
274
	int ret;
275
 
276
	lockdep_assert_held(&bo->resv->lock.base);
277
 
6296 serge 278
	if (pin) {
279
		if (vbo->pin_count++ > 0)
280
			return;
281
	} else {
282
		WARN_ON(vbo->pin_count <= 0);
283
		if (--vbo->pin_count > 0)
284
			return;
285
	}
286
 
287
	pl.fpfn = 0;
288
	pl.lpfn = 0;
289
	pl.flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB
4569 Serge 290
		| TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED;
4075 Serge 291
	if (pin)
6296 serge 292
		pl.flags |= TTM_PL_FLAG_NO_EVICT;
4075 Serge 293
 
294
	memset(&placement, 0, sizeof(placement));
295
	placement.num_placement = 1;
6296 serge 296
	placement.placement = &pl;
4075 Serge 297
 
298
	ret = ttm_bo_validate(bo, &placement, false, true);
299
 
300
	BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type);
301
}