xref: /openbmc/linux/drivers/gpu/drm/qxl/qxl_object.c (revision 79e2cf2e)
1f64122c1SDave Airlie /*
2f64122c1SDave Airlie  * Copyright 2013 Red Hat Inc.
3f64122c1SDave Airlie  *
4f64122c1SDave Airlie  * Permission is hereby granted, free of charge, to any person obtaining a
5f64122c1SDave Airlie  * copy of this software and associated documentation files (the "Software"),
6f64122c1SDave Airlie  * to deal in the Software without restriction, including without limitation
7f64122c1SDave Airlie  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f64122c1SDave Airlie  * and/or sell copies of the Software, and to permit persons to whom the
9f64122c1SDave Airlie  * Software is furnished to do so, subject to the following conditions:
10f64122c1SDave Airlie  *
11f64122c1SDave Airlie  * The above copyright notice and this permission notice shall be included in
12f64122c1SDave Airlie  * all copies or substantial portions of the Software.
13f64122c1SDave Airlie  *
14f64122c1SDave Airlie  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15f64122c1SDave Airlie  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16f64122c1SDave Airlie  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17f64122c1SDave Airlie  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18f64122c1SDave Airlie  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19f64122c1SDave Airlie  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20f64122c1SDave Airlie  * OTHER DEALINGS IN THE SOFTWARE.
21f64122c1SDave Airlie  *
22f64122c1SDave Airlie  * Authors: Dave Airlie
23f64122c1SDave Airlie  *          Alon Levy
24f64122c1SDave Airlie  */
25f64122c1SDave Airlie 
267938f421SLucas De Marchi #include <linux/iosys-map.h>
2749a3f51dSThomas Zimmermann #include <linux/io-mapping.h>
2849a3f51dSThomas Zimmermann 
29f64122c1SDave Airlie #include "qxl_drv.h"
30f64122c1SDave Airlie #include "qxl_object.h"
31f64122c1SDave Airlie 
32dce39226SGerd Hoffmann static int __qxl_bo_pin(struct qxl_bo *bo);
33dce39226SGerd Hoffmann static void __qxl_bo_unpin(struct qxl_bo *bo);
34dce39226SGerd Hoffmann 
qxl_ttm_bo_destroy(struct ttm_buffer_object * tbo)35f64122c1SDave Airlie static void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo)
36f64122c1SDave Airlie {
37f64122c1SDave Airlie 	struct qxl_bo *bo;
38f64122c1SDave Airlie 	struct qxl_device *qdev;
39f64122c1SDave Airlie 
403ebf1c6dSFrediano Ziglio 	bo = to_qxl_bo(tbo);
41e304f8a0SDaniel Vetter 	qdev = to_qxl(bo->tbo.base.dev);
42f64122c1SDave Airlie 
43f64122c1SDave Airlie 	qxl_surface_evict(qdev, bo, false);
449b369116SGerd Hoffmann 	WARN_ON_ONCE(bo->map_count > 0);
45f64122c1SDave Airlie 	mutex_lock(&qdev->gem.mutex);
46f64122c1SDave Airlie 	list_del_init(&bo->list);
47f64122c1SDave Airlie 	mutex_unlock(&qdev->gem.mutex);
48e0828d54SGerd Hoffmann 	drm_gem_object_release(&bo->tbo.base);
49f64122c1SDave Airlie 	kfree(bo);
50f64122c1SDave Airlie }
51f64122c1SDave Airlie 
qxl_ttm_bo_is_qxl_bo(struct ttm_buffer_object * bo)52f64122c1SDave Airlie bool qxl_ttm_bo_is_qxl_bo(struct ttm_buffer_object *bo)
53f64122c1SDave Airlie {
54f64122c1SDave Airlie 	if (bo->destroy == &qxl_ttm_bo_destroy)
55f64122c1SDave Airlie 		return true;
56f64122c1SDave Airlie 	return false;
57f64122c1SDave Airlie }
58f64122c1SDave Airlie 
qxl_ttm_placement_from_domain(struct qxl_bo * qbo,u32 domain)599d36d432SChristian König void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain)
60f64122c1SDave Airlie {
61f64122c1SDave Airlie 	u32 c = 0;
628ee2f956SGerd Hoffmann 	u32 pflag = 0;
631b000494SShayenne da Luz Moura 	unsigned int i;
64f64122c1SDave Airlie 
658ee2f956SGerd Hoffmann 	if (qbo->tbo.base.size <= PAGE_SIZE)
668ee2f956SGerd Hoffmann 		pflag |= TTM_PL_FLAG_TOPDOWN;
678ee2f956SGerd Hoffmann 
68f64122c1SDave Airlie 	qbo->placement.placement = qbo->placements;
69f64122c1SDave Airlie 	qbo->placement.busy_placement = qbo->placements;
7048e07c23SChristian König 	if (domain == QXL_GEM_DOMAIN_VRAM) {
7148e07c23SChristian König 		qbo->placements[c].mem_type = TTM_PL_VRAM;
72ce65b874SChristian König 		qbo->placements[c++].flags = pflag;
736957c686SGerd Hoffmann 	}
7448e07c23SChristian König 	if (domain == QXL_GEM_DOMAIN_SURFACE) {
7548e07c23SChristian König 		qbo->placements[c].mem_type = TTM_PL_PRIV;
76ce65b874SChristian König 		qbo->placements[c++].flags = pflag;
7748e07c23SChristian König 		qbo->placements[c].mem_type = TTM_PL_VRAM;
78ce65b874SChristian König 		qbo->placements[c++].flags = pflag;
7948e07c23SChristian König 	}
8048e07c23SChristian König 	if (domain == QXL_GEM_DOMAIN_CPU) {
8148e07c23SChristian König 		qbo->placements[c].mem_type = TTM_PL_SYSTEM;
82ce65b874SChristian König 		qbo->placements[c++].flags = pflag;
8348e07c23SChristian König 	}
8448e07c23SChristian König 	if (!c) {
8548e07c23SChristian König 		qbo->placements[c].mem_type = TTM_PL_SYSTEM;
86ce65b874SChristian König 		qbo->placements[c++].flags = 0;
8748e07c23SChristian König 	}
88f64122c1SDave Airlie 	qbo->placement.num_placement = c;
89f64122c1SDave Airlie 	qbo->placement.num_busy_placement = c;
90f1217ed0SChristian König 	for (i = 0; i < c; ++i) {
91f1217ed0SChristian König 		qbo->placements[i].fpfn = 0;
92f1217ed0SChristian König 		qbo->placements[i].lpfn = 0;
93f1217ed0SChristian König 	}
94f64122c1SDave Airlie }
95f64122c1SDave Airlie 
96b21fc738SGerd Hoffmann static const struct drm_gem_object_funcs qxl_object_funcs = {
97b21fc738SGerd Hoffmann 	.free = qxl_gem_object_free,
98b21fc738SGerd Hoffmann 	.open = qxl_gem_object_open,
99b21fc738SGerd Hoffmann 	.close = qxl_gem_object_close,
100b21fc738SGerd Hoffmann 	.pin = qxl_gem_prime_pin,
101b21fc738SGerd Hoffmann 	.unpin = qxl_gem_prime_unpin,
102b21fc738SGerd Hoffmann 	.get_sg_table = qxl_gem_prime_get_sg_table,
103b21fc738SGerd Hoffmann 	.vmap = qxl_gem_prime_vmap,
104b21fc738SGerd Hoffmann 	.vunmap = qxl_gem_prime_vunmap,
10560f57220SGerd Hoffmann 	.mmap = drm_gem_ttm_mmap,
10678d54f1fSGerd Hoffmann 	.print_info = drm_gem_ttm_print_info,
107b21fc738SGerd Hoffmann };
108b21fc738SGerd Hoffmann 
qxl_bo_create(struct qxl_device * qdev,unsigned long size,bool kernel,bool pinned,u32 domain,u32 priority,struct qxl_surface * surf,struct qxl_bo ** bo_ptr)1094fff19aeSGerd Hoffmann int qxl_bo_create(struct qxl_device *qdev, unsigned long size,
1104fff19aeSGerd Hoffmann 		  bool kernel, bool pinned, u32 domain, u32 priority,
111f64122c1SDave Airlie 		  struct qxl_surface *surf,
112f64122c1SDave Airlie 		  struct qxl_bo **bo_ptr)
113f64122c1SDave Airlie {
114369a7210SChristian König 	struct ttm_operation_ctx ctx = { !kernel, false };
115f64122c1SDave Airlie 	struct qxl_bo *bo;
116f64122c1SDave Airlie 	enum ttm_bo_type type;
117f64122c1SDave Airlie 	int r;
118f64122c1SDave Airlie 
119f64122c1SDave Airlie 	if (kernel)
120f64122c1SDave Airlie 		type = ttm_bo_type_kernel;
121f64122c1SDave Airlie 	else
122f64122c1SDave Airlie 		type = ttm_bo_type_device;
123f64122c1SDave Airlie 	*bo_ptr = NULL;
124f64122c1SDave Airlie 	bo = kzalloc(sizeof(struct qxl_bo), GFP_KERNEL);
125f64122c1SDave Airlie 	if (bo == NULL)
126f64122c1SDave Airlie 		return -ENOMEM;
127f64122c1SDave Airlie 	size = roundup(size, PAGE_SIZE);
128e0828d54SGerd Hoffmann 	r = drm_gem_object_init(&qdev->ddev, &bo->tbo.base, size);
129f64122c1SDave Airlie 	if (unlikely(r)) {
130f64122c1SDave Airlie 		kfree(bo);
131f64122c1SDave Airlie 		return r;
132f64122c1SDave Airlie 	}
133b21fc738SGerd Hoffmann 	bo->tbo.base.funcs = &qxl_object_funcs;
134f64122c1SDave Airlie 	bo->type = domain;
135f64122c1SDave Airlie 	bo->surface_id = 0;
136f64122c1SDave Airlie 	INIT_LIST_HEAD(&bo->list);
1378002db63SDave Airlie 
138f64122c1SDave Airlie 	if (surf)
139f64122c1SDave Airlie 		bo->surf = *surf;
140f64122c1SDave Airlie 
1419d36d432SChristian König 	qxl_ttm_placement_from_domain(bo, domain);
142f64122c1SDave Airlie 
1434fff19aeSGerd Hoffmann 	bo->tbo.priority = priority;
144347987a2SChristian König 	r = ttm_bo_init_reserved(&qdev->mman.bdev, &bo->tbo, type,
145f07069daSChristian König 				 &bo->placement, 0, &ctx, NULL, NULL,
146f07069daSChristian König 				 &qxl_ttm_bo_destroy);
147f64122c1SDave Airlie 	if (unlikely(r != 0)) {
148f64122c1SDave Airlie 		if (r != -ERESTARTSYS)
149cbdded7fSGabriel Krisman Bertazi 			dev_err(qdev->ddev.dev,
150f64122c1SDave Airlie 				"object_init failed for (%lu, 0x%08X)\n",
151f64122c1SDave Airlie 				size, domain);
152f64122c1SDave Airlie 		return r;
153f64122c1SDave Airlie 	}
1549d36d432SChristian König 	if (pinned)
1559d36d432SChristian König 		ttm_bo_pin(&bo->tbo);
156369a7210SChristian König 	ttm_bo_unreserve(&bo->tbo);
157f64122c1SDave Airlie 	*bo_ptr = bo;
158f64122c1SDave Airlie 	return 0;
159f64122c1SDave Airlie }
160f64122c1SDave Airlie 
qxl_bo_vmap_locked(struct qxl_bo * bo,struct iosys_map * map)1617938f421SLucas De Marchi int qxl_bo_vmap_locked(struct qxl_bo *bo, struct iosys_map *map)
162f64122c1SDave Airlie {
163f64122c1SDave Airlie 	int r;
164f64122c1SDave Airlie 
1650345bae1SGerd Hoffmann 	dma_resv_assert_held(bo->tbo.base.resv);
1660345bae1SGerd Hoffmann 
167f64122c1SDave Airlie 	if (bo->kptr) {
1689b369116SGerd Hoffmann 		bo->map_count++;
16949a3f51dSThomas Zimmermann 		goto out;
170f64122c1SDave Airlie 	}
171*79e2cf2eSDmitry Osipenko 
172*79e2cf2eSDmitry Osipenko 	r = __qxl_bo_pin(bo);
173f64122c1SDave Airlie 	if (r)
174f64122c1SDave Airlie 		return r;
175*79e2cf2eSDmitry Osipenko 
176*79e2cf2eSDmitry Osipenko 	r = ttm_bo_vmap(&bo->tbo, &bo->map);
177*79e2cf2eSDmitry Osipenko 	if (r) {
178*79e2cf2eSDmitry Osipenko 		__qxl_bo_unpin(bo);
179*79e2cf2eSDmitry Osipenko 		return r;
180*79e2cf2eSDmitry Osipenko 	}
1819b369116SGerd Hoffmann 	bo->map_count = 1;
18249a3f51dSThomas Zimmermann 
18349a3f51dSThomas Zimmermann 	/* TODO: Remove kptr in favor of map everywhere. */
18449a3f51dSThomas Zimmermann 	if (bo->map.is_iomem)
18549a3f51dSThomas Zimmermann 		bo->kptr = (void *)bo->map.vaddr_iomem;
18649a3f51dSThomas Zimmermann 	else
18749a3f51dSThomas Zimmermann 		bo->kptr = bo->map.vaddr;
18849a3f51dSThomas Zimmermann 
18949a3f51dSThomas Zimmermann out:
19049a3f51dSThomas Zimmermann 	*map = bo->map;
191f64122c1SDave Airlie 	return 0;
192f64122c1SDave Airlie }
193f64122c1SDave Airlie 
qxl_bo_vmap(struct qxl_bo * bo,struct iosys_map * map)1947938f421SLucas De Marchi int qxl_bo_vmap(struct qxl_bo *bo, struct iosys_map *map)
195dce39226SGerd Hoffmann {
196dce39226SGerd Hoffmann 	int r;
197dce39226SGerd Hoffmann 
198dce39226SGerd Hoffmann 	r = qxl_bo_reserve(bo);
199dce39226SGerd Hoffmann 	if (r)
200dce39226SGerd Hoffmann 		return r;
201dce39226SGerd Hoffmann 
202dce39226SGerd Hoffmann 	r = qxl_bo_vmap_locked(bo, map);
203dce39226SGerd Hoffmann 	qxl_bo_unreserve(bo);
204dce39226SGerd Hoffmann 	return r;
205dce39226SGerd Hoffmann }
206dce39226SGerd Hoffmann 
qxl_bo_kmap_atomic_page(struct qxl_device * qdev,struct qxl_bo * bo,int page_offset)207f64122c1SDave Airlie void *qxl_bo_kmap_atomic_page(struct qxl_device *qdev,
208f64122c1SDave Airlie 			      struct qxl_bo *bo, int page_offset)
209f64122c1SDave Airlie {
2101ff67ce4SChristian König 	unsigned long offset;
211f64122c1SDave Airlie 	void *rptr;
212f64122c1SDave Airlie 	int ret;
213f64122c1SDave Airlie 	struct io_mapping *map;
2147938f421SLucas De Marchi 	struct iosys_map bo_map;
215f64122c1SDave Airlie 
216d3116756SChristian König 	if (bo->tbo.resource->mem_type == TTM_PL_VRAM)
217f64122c1SDave Airlie 		map = qdev->vram_mapping;
218d3116756SChristian König 	else if (bo->tbo.resource->mem_type == TTM_PL_PRIV)
219f64122c1SDave Airlie 		map = qdev->surface_mapping;
220f64122c1SDave Airlie 	else
221f64122c1SDave Airlie 		goto fallback;
222f64122c1SDave Airlie 
223d3116756SChristian König 	offset = bo->tbo.resource->start << PAGE_SHIFT;
2241ff67ce4SChristian König 	return io_mapping_map_atomic_wc(map, offset + page_offset);
225f64122c1SDave Airlie fallback:
226f64122c1SDave Airlie 	if (bo->kptr) {
227f64122c1SDave Airlie 		rptr = bo->kptr + (page_offset * PAGE_SIZE);
228f64122c1SDave Airlie 		return rptr;
229f64122c1SDave Airlie 	}
230f64122c1SDave Airlie 
231f7ed28e1SGerd Hoffmann 	ret = qxl_bo_vmap_locked(bo, &bo_map);
232f64122c1SDave Airlie 	if (ret)
233f64122c1SDave Airlie 		return NULL;
23449a3f51dSThomas Zimmermann 	rptr = bo_map.vaddr; /* TODO: Use mapping abstraction properly */
235f64122c1SDave Airlie 
236f64122c1SDave Airlie 	rptr += page_offset * PAGE_SIZE;
237f64122c1SDave Airlie 	return rptr;
238f64122c1SDave Airlie }
239f64122c1SDave Airlie 
qxl_bo_vunmap_locked(struct qxl_bo * bo)240f7ed28e1SGerd Hoffmann void qxl_bo_vunmap_locked(struct qxl_bo *bo)
241f64122c1SDave Airlie {
2420345bae1SGerd Hoffmann 	dma_resv_assert_held(bo->tbo.base.resv);
2430345bae1SGerd Hoffmann 
244f64122c1SDave Airlie 	if (bo->kptr == NULL)
245f64122c1SDave Airlie 		return;
2469b369116SGerd Hoffmann 	bo->map_count--;
2479b369116SGerd Hoffmann 	if (bo->map_count > 0)
2489b369116SGerd Hoffmann 		return;
249f64122c1SDave Airlie 	bo->kptr = NULL;
25049a3f51dSThomas Zimmermann 	ttm_bo_vunmap(&bo->tbo, &bo->map);
251*79e2cf2eSDmitry Osipenko 	__qxl_bo_unpin(bo);
252f64122c1SDave Airlie }
253f64122c1SDave Airlie 
qxl_bo_vunmap(struct qxl_bo * bo)254dce39226SGerd Hoffmann int qxl_bo_vunmap(struct qxl_bo *bo)
255dce39226SGerd Hoffmann {
256dce39226SGerd Hoffmann 	int r;
257dce39226SGerd Hoffmann 
258dce39226SGerd Hoffmann 	r = qxl_bo_reserve(bo);
259dce39226SGerd Hoffmann 	if (r)
260dce39226SGerd Hoffmann 		return r;
261dce39226SGerd Hoffmann 
262dce39226SGerd Hoffmann 	qxl_bo_vunmap_locked(bo);
263dce39226SGerd Hoffmann 	qxl_bo_unreserve(bo);
264dce39226SGerd Hoffmann 	return 0;
265dce39226SGerd Hoffmann }
266dce39226SGerd Hoffmann 
qxl_bo_kunmap_atomic_page(struct qxl_device * qdev,struct qxl_bo * bo,void * pmap)267f64122c1SDave Airlie void qxl_bo_kunmap_atomic_page(struct qxl_device *qdev,
268f64122c1SDave Airlie 			       struct qxl_bo *bo, void *pmap)
269f64122c1SDave Airlie {
270d3116756SChristian König 	if ((bo->tbo.resource->mem_type != TTM_PL_VRAM) &&
271d3116756SChristian König 	    (bo->tbo.resource->mem_type != TTM_PL_PRIV))
272f64122c1SDave Airlie 		goto fallback;
273f64122c1SDave Airlie 
274f64122c1SDave Airlie 	io_mapping_unmap_atomic(pmap);
275f64122c1SDave Airlie 	return;
276f64122c1SDave Airlie  fallback:
277f7ed28e1SGerd Hoffmann 	qxl_bo_vunmap_locked(bo);
278f64122c1SDave Airlie }
279f64122c1SDave Airlie 
qxl_bo_unref(struct qxl_bo ** bo)280f64122c1SDave Airlie void qxl_bo_unref(struct qxl_bo **bo)
281f64122c1SDave Airlie {
282f64122c1SDave Airlie 	if ((*bo) == NULL)
283f64122c1SDave Airlie 		return;
284e07154e2SFrediano Ziglio 
2859c86fb18SEmil Velikov 	drm_gem_object_put(&(*bo)->tbo.base);
286f64122c1SDave Airlie 	*bo = NULL;
287f64122c1SDave Airlie }
288f64122c1SDave Airlie 
qxl_bo_ref(struct qxl_bo * bo)289f64122c1SDave Airlie struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo)
290f64122c1SDave Airlie {
291e0828d54SGerd Hoffmann 	drm_gem_object_get(&bo->tbo.base);
292f64122c1SDave Airlie 	return bo;
293f64122c1SDave Airlie }
294f64122c1SDave Airlie 
__qxl_bo_pin(struct qxl_bo * bo)295545592fbSChristophe Fergeau static int __qxl_bo_pin(struct qxl_bo *bo)
296f64122c1SDave Airlie {
29719be5570SChristian König 	struct ttm_operation_ctx ctx = { false, false };
298e0828d54SGerd Hoffmann 	struct drm_device *ddev = bo->tbo.base.dev;
2994f49ec92SDave Airlie 	int r;
300f64122c1SDave Airlie 
3019d36d432SChristian König 	if (bo->tbo.pin_count) {
3029d36d432SChristian König 		ttm_bo_pin(&bo->tbo);
303f64122c1SDave Airlie 		return 0;
304f64122c1SDave Airlie 	}
3059d36d432SChristian König 	qxl_ttm_placement_from_domain(bo, bo->type);
30619be5570SChristian König 	r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
3079d36d432SChristian König 	if (likely(r == 0))
3089d36d432SChristian König 		ttm_bo_pin(&bo->tbo);
309f64122c1SDave Airlie 	if (unlikely(r != 0))
3105472bdeeSGabriel Krisman Bertazi 		dev_err(ddev->dev, "%p pin failed\n", bo);
311f64122c1SDave Airlie 	return r;
312f64122c1SDave Airlie }
313f64122c1SDave Airlie 
__qxl_bo_unpin(struct qxl_bo * bo)3149d36d432SChristian König static void __qxl_bo_unpin(struct qxl_bo *bo)
315f64122c1SDave Airlie {
3169d36d432SChristian König 	ttm_bo_unpin(&bo->tbo);
317f64122c1SDave Airlie }
318f64122c1SDave Airlie 
319715a11faSGabriel Krisman Bertazi /*
320715a11faSGabriel Krisman Bertazi  * Reserve the BO before pinning the object.  If the BO was reserved
321715a11faSGabriel Krisman Bertazi  * beforehand, use the internal version directly __qxl_bo_pin.
322715a11faSGabriel Krisman Bertazi  *
323715a11faSGabriel Krisman Bertazi  */
qxl_bo_pin(struct qxl_bo * bo)324545592fbSChristophe Fergeau int qxl_bo_pin(struct qxl_bo *bo)
325715a11faSGabriel Krisman Bertazi {
326715a11faSGabriel Krisman Bertazi 	int r;
327715a11faSGabriel Krisman Bertazi 
3289c4cbb3aSDave Airlie 	r = qxl_bo_reserve(bo);
329715a11faSGabriel Krisman Bertazi 	if (r)
330715a11faSGabriel Krisman Bertazi 		return r;
331715a11faSGabriel Krisman Bertazi 
332545592fbSChristophe Fergeau 	r = __qxl_bo_pin(bo);
333715a11faSGabriel Krisman Bertazi 	qxl_bo_unreserve(bo);
334715a11faSGabriel Krisman Bertazi 	return r;
335715a11faSGabriel Krisman Bertazi }
336715a11faSGabriel Krisman Bertazi 
337715a11faSGabriel Krisman Bertazi /*
338715a11faSGabriel Krisman Bertazi  * Reserve the BO before pinning the object.  If the BO was reserved
339715a11faSGabriel Krisman Bertazi  * beforehand, use the internal version directly __qxl_bo_unpin.
340715a11faSGabriel Krisman Bertazi  *
341715a11faSGabriel Krisman Bertazi  */
qxl_bo_unpin(struct qxl_bo * bo)342715a11faSGabriel Krisman Bertazi int qxl_bo_unpin(struct qxl_bo *bo)
343715a11faSGabriel Krisman Bertazi {
344715a11faSGabriel Krisman Bertazi 	int r;
345715a11faSGabriel Krisman Bertazi 
3469c4cbb3aSDave Airlie 	r = qxl_bo_reserve(bo);
347715a11faSGabriel Krisman Bertazi 	if (r)
348715a11faSGabriel Krisman Bertazi 		return r;
349715a11faSGabriel Krisman Bertazi 
3509d36d432SChristian König 	__qxl_bo_unpin(bo);
351715a11faSGabriel Krisman Bertazi 	qxl_bo_unreserve(bo);
3529d36d432SChristian König 	return 0;
353715a11faSGabriel Krisman Bertazi }
354715a11faSGabriel Krisman Bertazi 
qxl_bo_force_delete(struct qxl_device * qdev)355f64122c1SDave Airlie void qxl_bo_force_delete(struct qxl_device *qdev)
356f64122c1SDave Airlie {
357f64122c1SDave Airlie 	struct qxl_bo *bo, *n;
358f64122c1SDave Airlie 
359f64122c1SDave Airlie 	if (list_empty(&qdev->gem.objects))
360f64122c1SDave Airlie 		return;
361cbdded7fSGabriel Krisman Bertazi 	dev_err(qdev->ddev.dev, "Userspace still has active objects !\n");
362f64122c1SDave Airlie 	list_for_each_entry_safe(bo, n, &qdev->gem.objects, list) {
363cbdded7fSGabriel Krisman Bertazi 		dev_err(qdev->ddev.dev, "%p %p %lu %lu force free\n",
364e0828d54SGerd Hoffmann 			&bo->tbo.base, bo, (unsigned long)bo->tbo.base.size,
365e0828d54SGerd Hoffmann 			*((unsigned long *)&bo->tbo.base.refcount));
366f64122c1SDave Airlie 		mutex_lock(&qdev->gem.mutex);
367f64122c1SDave Airlie 		list_del_init(&bo->list);
368f64122c1SDave Airlie 		mutex_unlock(&qdev->gem.mutex);
369f64122c1SDave Airlie 		/* this should unref the ttm bo */
3709c86fb18SEmil Velikov 		drm_gem_object_put(&bo->tbo.base);
371f64122c1SDave Airlie 	}
372f64122c1SDave Airlie }
373f64122c1SDave Airlie 
qxl_bo_init(struct qxl_device * qdev)374f64122c1SDave Airlie int qxl_bo_init(struct qxl_device *qdev)
375f64122c1SDave Airlie {
376f64122c1SDave Airlie 	return qxl_ttm_init(qdev);
377f64122c1SDave Airlie }
378f64122c1SDave Airlie 
qxl_bo_fini(struct qxl_device * qdev)379f64122c1SDave Airlie void qxl_bo_fini(struct qxl_device *qdev)
380f64122c1SDave Airlie {
381f64122c1SDave Airlie 	qxl_ttm_fini(qdev);
382f64122c1SDave Airlie }
383f64122c1SDave Airlie 
qxl_bo_check_id(struct qxl_device * qdev,struct qxl_bo * bo)384f64122c1SDave Airlie int qxl_bo_check_id(struct qxl_device *qdev, struct qxl_bo *bo)
385f64122c1SDave Airlie {
386f64122c1SDave Airlie 	int ret;
387408799ebSShayenne da Luz Moura 
388f64122c1SDave Airlie 	if (bo->type == QXL_GEM_DOMAIN_SURFACE && bo->surface_id == 0) {
389f64122c1SDave Airlie 		/* allocate a surface id for this surface now */
390f64122c1SDave Airlie 		ret = qxl_surface_id_alloc(qdev, bo);
391f64122c1SDave Airlie 		if (ret)
392f64122c1SDave Airlie 			return ret;
393f64122c1SDave Airlie 
394edd38a1eSGerd Hoffmann 		ret = qxl_hw_surface_alloc(qdev, bo);
395f64122c1SDave Airlie 		if (ret)
396f64122c1SDave Airlie 			return ret;
397f64122c1SDave Airlie 	}
398f64122c1SDave Airlie 	return 0;
399f64122c1SDave Airlie }
400f64122c1SDave Airlie 
qxl_surf_evict(struct qxl_device * qdev)401b86487a6SDave Airlie int qxl_surf_evict(struct qxl_device *qdev)
402b86487a6SDave Airlie {
4034ce032d6SChristian König 	struct ttm_resource_manager *man;
4044ce032d6SChristian König 
4054ce032d6SChristian König 	man = ttm_manager_type(&qdev->mman.bdev, TTM_PL_PRIV);
4064ce032d6SChristian König 	return ttm_resource_manager_evict_all(&qdev->mman.bdev, man);
407b86487a6SDave Airlie }
408d84300bfSDave Airlie 
qxl_vram_evict(struct qxl_device * qdev)409d84300bfSDave Airlie int qxl_vram_evict(struct qxl_device *qdev)
410d84300bfSDave Airlie {
4114ce032d6SChristian König 	struct ttm_resource_manager *man;
4124ce032d6SChristian König 
4134ce032d6SChristian König 	man = ttm_manager_type(&qdev->mman.bdev, TTM_PL_VRAM);
4144ce032d6SChristian König 	return ttm_resource_manager_evict_all(&qdev->mman.bdev, man);
415d84300bfSDave Airlie }
416