xref: /titanic_44/usr/src/uts/intel/io/drm/i915_gem.c (revision c1374a13e412c4ec42cba867e57347a0e049a822)
10035d21cSmiao chen - Sun Microsystems - Beijing China /* BEGIN CSTYLED */
20035d21cSmiao chen - Sun Microsystems - Beijing China 
30035d21cSmiao chen - Sun Microsystems - Beijing China /*
40035d21cSmiao chen - Sun Microsystems - Beijing China  * Copyright (c) 2009, Intel Corporation.
50035d21cSmiao chen - Sun Microsystems - Beijing China  * All Rights Reserved.
60035d21cSmiao chen - Sun Microsystems - Beijing China  *
70035d21cSmiao chen - Sun Microsystems - Beijing China  * Permission is hereby granted, free of charge, to any person obtaining a
80035d21cSmiao chen - Sun Microsystems - Beijing China  * copy of this software and associated documentation files (the "Software"),
90035d21cSmiao chen - Sun Microsystems - Beijing China  * to deal in the Software without restriction, including without limitation
100035d21cSmiao chen - Sun Microsystems - Beijing China  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
110035d21cSmiao chen - Sun Microsystems - Beijing China  * and/or sell copies of the Software, and to permit persons to whom the
120035d21cSmiao chen - Sun Microsystems - Beijing China  * Software is furnished to do so, subject to the following conditions:
130035d21cSmiao chen - Sun Microsystems - Beijing China  *
140035d21cSmiao chen - Sun Microsystems - Beijing China  * The above copyright notice and this permission notice (including the next
150035d21cSmiao chen - Sun Microsystems - Beijing China  * paragraph) shall be included in all copies or substantial portions of the
160035d21cSmiao chen - Sun Microsystems - Beijing China  * Software.
170035d21cSmiao chen - Sun Microsystems - Beijing China  *
180035d21cSmiao chen - Sun Microsystems - Beijing China  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
190035d21cSmiao chen - Sun Microsystems - Beijing China  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
200035d21cSmiao chen - Sun Microsystems - Beijing China  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
210035d21cSmiao chen - Sun Microsystems - Beijing China  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
220035d21cSmiao chen - Sun Microsystems - Beijing China  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
230035d21cSmiao chen - Sun Microsystems - Beijing China  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
240035d21cSmiao chen - Sun Microsystems - Beijing China  * IN THE SOFTWARE.
250035d21cSmiao chen - Sun Microsystems - Beijing China  *
260035d21cSmiao chen - Sun Microsystems - Beijing China  * Authors:
270035d21cSmiao chen - Sun Microsystems - Beijing China  *    Eric Anholt <eric@anholt.net>
280035d21cSmiao chen - Sun Microsystems - Beijing China  *
290035d21cSmiao chen - Sun Microsystems - Beijing China  */
300035d21cSmiao chen - Sun Microsystems - Beijing China 
310035d21cSmiao chen - Sun Microsystems - Beijing China /*
320035d21cSmiao chen - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
330035d21cSmiao chen - Sun Microsystems - Beijing China  * Use is subject to license terms.
340035d21cSmiao chen - Sun Microsystems - Beijing China  */
350035d21cSmiao chen - Sun Microsystems - Beijing China 
360035d21cSmiao chen - Sun Microsystems - Beijing China #include <sys/x86_archext.h>
370035d21cSmiao chen - Sun Microsystems - Beijing China #include <sys/vfs_opreg.h>
380035d21cSmiao chen - Sun Microsystems - Beijing China #include "drmP.h"
390035d21cSmiao chen - Sun Microsystems - Beijing China #include "drm.h"
400035d21cSmiao chen - Sun Microsystems - Beijing China #include "i915_drm.h"
410035d21cSmiao chen - Sun Microsystems - Beijing China #include "i915_drv.h"
420035d21cSmiao chen - Sun Microsystems - Beijing China 
430035d21cSmiao chen - Sun Microsystems - Beijing China #ifndef roundup
440035d21cSmiao chen - Sun Microsystems - Beijing China #define	roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
450035d21cSmiao chen - Sun Microsystems - Beijing China #endif /* !roundup */
460035d21cSmiao chen - Sun Microsystems - Beijing China 
470035d21cSmiao chen - Sun Microsystems - Beijing China #define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
480035d21cSmiao chen - Sun Microsystems - Beijing China 
490035d21cSmiao chen - Sun Microsystems - Beijing China static timeout_id_t worktimer_id = NULL;
500035d21cSmiao chen - Sun Microsystems - Beijing China 
510035d21cSmiao chen - Sun Microsystems - Beijing China extern int drm_mm_init(struct drm_mm *mm,
520035d21cSmiao chen - Sun Microsystems - Beijing China 		    unsigned long start, unsigned long size);
530035d21cSmiao chen - Sun Microsystems - Beijing China extern void drm_mm_put_block(struct drm_mm_node *cur);
540035d21cSmiao chen - Sun Microsystems - Beijing China extern int choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off,
550035d21cSmiao chen - Sun Microsystems - Beijing China     int vacalign, uint_t flags);
560035d21cSmiao chen - Sun Microsystems - Beijing China 
570035d21cSmiao chen - Sun Microsystems - Beijing China static void
580035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
590035d21cSmiao chen - Sun Microsystems - Beijing China 				  uint32_t read_domains,
600035d21cSmiao chen - Sun Microsystems - Beijing China 				  uint32_t write_domain);
610035d21cSmiao chen - Sun Microsystems - Beijing China static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
620035d21cSmiao chen - Sun Microsystems - Beijing China static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
630035d21cSmiao chen - Sun Microsystems - Beijing China static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
640035d21cSmiao chen - Sun Microsystems - Beijing China static int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
650035d21cSmiao chen - Sun Microsystems - Beijing China 					     int write);
660035d21cSmiao chen - Sun Microsystems - Beijing China static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
670035d21cSmiao chen - Sun Microsystems - Beijing China 					     int write);
680035d21cSmiao chen - Sun Microsystems - Beijing China static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
690035d21cSmiao chen - Sun Microsystems - Beijing China 						     uint64_t offset,
700035d21cSmiao chen - Sun Microsystems - Beijing China 						     uint64_t size);
710035d21cSmiao chen - Sun Microsystems - Beijing China static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj);
720035d21cSmiao chen - Sun Microsystems - Beijing China static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
730035d21cSmiao chen - Sun Microsystems - Beijing China static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
740035d21cSmiao chen - Sun Microsystems - Beijing China static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
750035d21cSmiao chen - Sun Microsystems - Beijing China 
760035d21cSmiao chen - Sun Microsystems - Beijing China static void
770035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_cleanup_ringbuffer(struct drm_device *dev);
780035d21cSmiao chen - Sun Microsystems - Beijing China 
790035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
800035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_init_ioctl(DRM_IOCTL_ARGS)810035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_init_ioctl(DRM_IOCTL_ARGS)
820035d21cSmiao chen - Sun Microsystems - Beijing China {
830035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
840035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
850035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_init args;
860035d21cSmiao chen - Sun Microsystems - Beijing China 
870035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
880035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
890035d21cSmiao chen - Sun Microsystems - Beijing China 
900035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_COPYFROM_WITH_RETURN(&args,
910035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_init *) data, sizeof(args));
920035d21cSmiao chen - Sun Microsystems - Beijing China 
930035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
940035d21cSmiao chen - Sun Microsystems - Beijing China 
950035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((args.gtt_start >= args.gtt_end) ||
960035d21cSmiao chen - Sun Microsystems - Beijing China 	    ((args.gtt_start & (PAGE_SIZE - 1)) != 0) ||
970035d21cSmiao chen - Sun Microsystems - Beijing China 	    ((args.gtt_end & (PAGE_SIZE - 1)) != 0)) {
980035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
990035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("i915_gem_init_ioctel invalid arg 0x%lx args.start 0x%lx end 0x%lx", &args, args.gtt_start, args.gtt_end);
1000035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
1010035d21cSmiao chen - Sun Microsystems - Beijing China 	}
1020035d21cSmiao chen - Sun Microsystems - Beijing China 
1030035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->gtt_total = (uint32_t) (args.gtt_end - args.gtt_start);
1040035d21cSmiao chen - Sun Microsystems - Beijing China 
105*c1374a13SSurya Prakki 	(void) drm_mm_init(&dev_priv->mm.gtt_space,
106*c1374a13SSurya Prakki 	    (unsigned long) args.gtt_start, dev->gtt_total);
1070035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_init_ioctl dev->gtt_total %x, dev_priv->mm.gtt_space 0x%x gtt_start 0x%lx", dev->gtt_total, dev_priv->mm.gtt_space, args.gtt_start);
1080035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(dev->gtt_total != 0);
1090035d21cSmiao chen - Sun Microsystems - Beijing China 
1100035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
1110035d21cSmiao chen - Sun Microsystems - Beijing China 
1120035d21cSmiao chen - Sun Microsystems - Beijing China 
1130035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
1140035d21cSmiao chen - Sun Microsystems - Beijing China }
1150035d21cSmiao chen - Sun Microsystems - Beijing China 
1160035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
1170035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_get_aperture_ioctl(DRM_IOCTL_ARGS)1180035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_get_aperture_ioctl(DRM_IOCTL_ARGS)
1190035d21cSmiao chen - Sun Microsystems - Beijing China {
1200035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
1210035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_get_aperture args;
1220035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
1230035d21cSmiao chen - Sun Microsystems - Beijing China 
1240035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
1250035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
1260035d21cSmiao chen - Sun Microsystems - Beijing China 
1270035d21cSmiao chen - Sun Microsystems - Beijing China 	args.aper_size = (uint64_t)dev->gtt_total;
1280035d21cSmiao chen - Sun Microsystems - Beijing China 	args.aper_available_size = (args.aper_size -
1290035d21cSmiao chen - Sun Microsystems - Beijing China 				     atomic_read(&dev->pin_memory));
1300035d21cSmiao chen - Sun Microsystems - Beijing China 
1310035d21cSmiao chen - Sun Microsystems - Beijing China         ret = DRM_COPY_TO_USER((struct drm_i915_gem_get_aperture __user *) data, &args, sizeof(args));
1320035d21cSmiao chen - Sun Microsystems - Beijing China 
1330035d21cSmiao chen - Sun Microsystems - Beijing China         if ( ret != 0)
1340035d21cSmiao chen - Sun Microsystems - Beijing China                 DRM_ERROR(" i915_gem_get_aperture_ioctl error! %d", ret);
1350035d21cSmiao chen - Sun Microsystems - Beijing China 
1360035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_get_aaperture_ioctl called sizeof %d, aper_size 0x%x, aper_available_size 0x%x\n", sizeof(args), dev->gtt_total, args.aper_available_size);
1370035d21cSmiao chen - Sun Microsystems - Beijing China 
1380035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
1390035d21cSmiao chen - Sun Microsystems - Beijing China }
1400035d21cSmiao chen - Sun Microsystems - Beijing China 
1410035d21cSmiao chen - Sun Microsystems - Beijing China /**
1420035d21cSmiao chen - Sun Microsystems - Beijing China  * Creates a new mm object and returns a handle to it.
1430035d21cSmiao chen - Sun Microsystems - Beijing China  */
1440035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
1450035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_create_ioctl(DRM_IOCTL_ARGS)1460035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_create_ioctl(DRM_IOCTL_ARGS)
1470035d21cSmiao chen - Sun Microsystems - Beijing China {
1480035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
1490035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_create args;
1500035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
1510035d21cSmiao chen - Sun Microsystems - Beijing China 	int handlep;
1520035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
1530035d21cSmiao chen - Sun Microsystems - Beijing China 
1540035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
1550035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
1560035d21cSmiao chen - Sun Microsystems - Beijing China 
1570035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_COPYFROM_WITH_RETURN(&args,
1580035d21cSmiao chen - Sun Microsystems - Beijing China 	    (struct drm_i915_gem_create *) data, sizeof(args));
1590035d21cSmiao chen - Sun Microsystems - Beijing China 
1600035d21cSmiao chen - Sun Microsystems - Beijing China 
1610035d21cSmiao chen - Sun Microsystems - Beijing China 	args.size = (uint64_t) roundup(args.size, PAGE_SIZE);
1620035d21cSmiao chen - Sun Microsystems - Beijing China 
1630035d21cSmiao chen - Sun Microsystems - Beijing China 	if (args.size == 0) {
1640035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Invalid obj size %d", args.size);
1650035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
1660035d21cSmiao chen - Sun Microsystems - Beijing China 	}
1670035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Allocate the new object */
1680035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_alloc(dev, args.size);
1690035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL) {
1700035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to alloc obj");
1710035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENOMEM;
1720035d21cSmiao chen - Sun Microsystems - Beijing China 	}
1730035d21cSmiao chen - Sun Microsystems - Beijing China 
1740035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = drm_gem_handle_create(fpriv, obj, &handlep);
1750035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
1760035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_handle_unreference(obj);
1770035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
1780035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
1790035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
1800035d21cSmiao chen - Sun Microsystems - Beijing China 
1810035d21cSmiao chen - Sun Microsystems - Beijing China 	args.handle = handlep;
1820035d21cSmiao chen - Sun Microsystems - Beijing China 
1830035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = DRM_COPY_TO_USER((struct drm_i915_gem_create *) data, &args, sizeof(args));
1840035d21cSmiao chen - Sun Microsystems - Beijing China 
1850035d21cSmiao chen - Sun Microsystems - Beijing China 	if ( ret != 0)
1860035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR(" gem create error! %d", ret);
1870035d21cSmiao chen - Sun Microsystems - Beijing China 
1880035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_create_ioctl object name %d, size 0x%lx, list 0x%lx, obj 0x%lx",handlep, args.size, &fpriv->object_idr, obj);
1890035d21cSmiao chen - Sun Microsystems - Beijing China 
1900035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
1910035d21cSmiao chen - Sun Microsystems - Beijing China }
1920035d21cSmiao chen - Sun Microsystems - Beijing China 
1930035d21cSmiao chen - Sun Microsystems - Beijing China /**
1940035d21cSmiao chen - Sun Microsystems - Beijing China  * Reads data from the object referenced by handle.
1950035d21cSmiao chen - Sun Microsystems - Beijing China  *
1960035d21cSmiao chen - Sun Microsystems - Beijing China  * On error, the contents of *data are undefined.
1970035d21cSmiao chen - Sun Microsystems - Beijing China  */
1980035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
1990035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_pread_ioctl(DRM_IOCTL_ARGS)2000035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_pread_ioctl(DRM_IOCTL_ARGS)
2010035d21cSmiao chen - Sun Microsystems - Beijing China {
2020035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
2030035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_pread args;
2040035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
2050035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
2060035d21cSmiao chen - Sun Microsystems - Beijing China 
2070035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
2080035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
2090035d21cSmiao chen - Sun Microsystems - Beijing China 
2100035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_COPYFROM_WITH_RETURN(&args,
2110035d21cSmiao chen - Sun Microsystems - Beijing China 	    (struct drm_i915_gem_pread __user *) data, sizeof(args));
2120035d21cSmiao chen - Sun Microsystems - Beijing China 
2130035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
2140035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL)
2150035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
2160035d21cSmiao chen - Sun Microsystems - Beijing China 
2170035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Bounds check source.
2180035d21cSmiao chen - Sun Microsystems - Beijing China 	 *
2190035d21cSmiao chen - Sun Microsystems - Beijing China 	 * XXX: This could use review for overflow issues...
2200035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
2210035d21cSmiao chen - Sun Microsystems - Beijing China 	if (args.offset > obj->size || args.size > obj->size ||
2220035d21cSmiao chen - Sun Microsystems - Beijing China 	    args.offset + args.size > obj->size) {
2230035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
2240035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("i915_gem_pread_ioctl invalid args");
2250035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
2260035d21cSmiao chen - Sun Microsystems - Beijing China 	}
2270035d21cSmiao chen - Sun Microsystems - Beijing China 
2280035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
2290035d21cSmiao chen - Sun Microsystems - Beijing China 
2300035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_set_cpu_read_domain_range(obj, args.offset, args.size);
2310035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0) {
2320035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
2330035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
2340035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("pread failed to read domain range ret %d!!!", ret);
2350035d21cSmiao chen - Sun Microsystems - Beijing China 		return EFAULT;
2360035d21cSmiao chen - Sun Microsystems - Beijing China 	}
2370035d21cSmiao chen - Sun Microsystems - Beijing China 
2380035d21cSmiao chen - Sun Microsystems - Beijing China 	unsigned long unwritten = 0;
2390035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t *user_data;
2400035d21cSmiao chen - Sun Microsystems - Beijing China 	user_data = (uint32_t *) (uintptr_t) args.data_ptr;
2410035d21cSmiao chen - Sun Microsystems - Beijing China 
2420035d21cSmiao chen - Sun Microsystems - Beijing China 	unwritten = DRM_COPY_TO_USER(user_data, obj->kaddr + args.offset, args.size);
2430035d21cSmiao chen - Sun Microsystems - Beijing China         if (unwritten) {
2440035d21cSmiao chen - Sun Microsystems - Beijing China                 ret = EFAULT;
2450035d21cSmiao chen - Sun Microsystems - Beijing China                 DRM_ERROR("i915_gem_pread error!!! unwritten %d", unwritten);
2460035d21cSmiao chen - Sun Microsystems - Beijing China         }
2470035d21cSmiao chen - Sun Microsystems - Beijing China 
2480035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
2490035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
2500035d21cSmiao chen - Sun Microsystems - Beijing China 
2510035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
2520035d21cSmiao chen - Sun Microsystems - Beijing China }
2530035d21cSmiao chen - Sun Microsystems - Beijing China 
2540035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
2550035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_gtt_pwrite(struct drm_device * dev,struct drm_gem_object * obj,struct drm_i915_gem_pwrite * args,struct drm_file * file_priv)2560035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
2570035d21cSmiao chen - Sun Microsystems - Beijing China 		    struct drm_i915_gem_pwrite *args,
2580035d21cSmiao chen - Sun Microsystems - Beijing China 		    struct drm_file *file_priv)
2590035d21cSmiao chen - Sun Microsystems - Beijing China {
2600035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t *user_data;
2610035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
2620035d21cSmiao chen - Sun Microsystems - Beijing China 	unsigned long unwritten = 0;
2630035d21cSmiao chen - Sun Microsystems - Beijing China 
2640035d21cSmiao chen - Sun Microsystems - Beijing China 	user_data = (uint32_t *) (uintptr_t) args->data_ptr;
2650035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
2660035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_pin(obj, 0);
2670035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
2680035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
2690035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("i915_gem_gtt_pwrite failed to pin ret %d", ret);
2700035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
2710035d21cSmiao chen - Sun Microsystems - Beijing China 	}
2720035d21cSmiao chen - Sun Microsystems - Beijing China 
2730035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_set_to_gtt_domain(obj, 1);
2740035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
2750035d21cSmiao chen - Sun Microsystems - Beijing China 		goto err;
2760035d21cSmiao chen - Sun Microsystems - Beijing China 
2770035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("obj %d write domain 0x%x read domain 0x%x", obj->name, obj->write_domain, obj->read_domains);
2780035d21cSmiao chen - Sun Microsystems - Beijing China 
2790035d21cSmiao chen - Sun Microsystems - Beijing China 	unwritten = DRM_COPY_FROM_USER(obj->kaddr + args->offset, user_data, args->size);
2800035d21cSmiao chen - Sun Microsystems - Beijing China         if (unwritten) {
2810035d21cSmiao chen - Sun Microsystems - Beijing China                 ret = EFAULT;
2820035d21cSmiao chen - Sun Microsystems - Beijing China                 DRM_ERROR("i915_gem_gtt_pwrite error!!! unwritten %d", unwritten);
2830035d21cSmiao chen - Sun Microsystems - Beijing China                 goto err;
2840035d21cSmiao chen - Sun Microsystems - Beijing China         }
2850035d21cSmiao chen - Sun Microsystems - Beijing China 
2860035d21cSmiao chen - Sun Microsystems - Beijing China err:
2870035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_unpin(obj);
2880035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
2890035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
2900035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("i915_gem_gtt_pwrite error %d", ret);
2910035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
2920035d21cSmiao chen - Sun Microsystems - Beijing China }
2930035d21cSmiao chen - Sun Microsystems - Beijing China 
2940035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
2950035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_shmem_pwrite(struct drm_device * dev,struct drm_gem_object * obj,struct drm_i915_gem_pwrite * args,struct drm_file * file_priv)2960035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
2970035d21cSmiao chen - Sun Microsystems - Beijing China 		      struct drm_i915_gem_pwrite *args,
2980035d21cSmiao chen - Sun Microsystems - Beijing China 		      struct drm_file *file_priv)
2990035d21cSmiao chen - Sun Microsystems - Beijing China {
3000035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_ERROR(" i915_gem_shmem_pwrite Not support");
3010035d21cSmiao chen - Sun Microsystems - Beijing China 	return -1;
3020035d21cSmiao chen - Sun Microsystems - Beijing China }
3030035d21cSmiao chen - Sun Microsystems - Beijing China 
3040035d21cSmiao chen - Sun Microsystems - Beijing China /**
3050035d21cSmiao chen - Sun Microsystems - Beijing China  * Writes data to the object referenced by handle.
3060035d21cSmiao chen - Sun Microsystems - Beijing China  *
3070035d21cSmiao chen - Sun Microsystems - Beijing China  * On error, the contents of the buffer that were to be modified are undefined.
3080035d21cSmiao chen - Sun Microsystems - Beijing China  */
3090035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
3100035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_pwrite_ioctl(DRM_IOCTL_ARGS)3110035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_pwrite_ioctl(DRM_IOCTL_ARGS)
3120035d21cSmiao chen - Sun Microsystems - Beijing China {
3130035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
3140035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_pwrite args;
3150035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
3160035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
3170035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
3180035d21cSmiao chen - Sun Microsystems - Beijing China 
3190035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
3200035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
3210035d21cSmiao chen - Sun Microsystems - Beijing China 
3220035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = DRM_COPY_FROM_USER(&args,
3230035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_pwrite __user *) data, sizeof(args));
3240035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
3250035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("i915_gem_pwrite_ioctl failed to copy from user");
3260035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
3270035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL)
3280035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
3290035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = obj->driver_private;
3300035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_pwrite_ioctl, obj->name %d",obj->name);
3310035d21cSmiao chen - Sun Microsystems - Beijing China 
3320035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Bounds check destination.
3330035d21cSmiao chen - Sun Microsystems - Beijing China 	 *
3340035d21cSmiao chen - Sun Microsystems - Beijing China 	 * XXX: This could use review for overflow issues...
3350035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
3360035d21cSmiao chen - Sun Microsystems - Beijing China 	if (args.offset > obj->size || args.size > obj->size ||
3370035d21cSmiao chen - Sun Microsystems - Beijing China 	    args.offset + args.size > obj->size) {
3380035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
3390035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("i915_gem_pwrite_ioctl invalid arg");
3400035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
3410035d21cSmiao chen - Sun Microsystems - Beijing China 	}
3420035d21cSmiao chen - Sun Microsystems - Beijing China 
3430035d21cSmiao chen - Sun Microsystems - Beijing China 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
3440035d21cSmiao chen - Sun Microsystems - Beijing China 	 * it would end up going through the fenced access, and we'll get
3450035d21cSmiao chen - Sun Microsystems - Beijing China 	 * different detiling behavior between reading and writing.
3460035d21cSmiao chen - Sun Microsystems - Beijing China 	 * pread/pwrite currently are reading and writing from the CPU
3470035d21cSmiao chen - Sun Microsystems - Beijing China 	 * perspective, requiring manual detiling by the client.
3480035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
3490035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->tiling_mode == I915_TILING_NONE &&
3500035d21cSmiao chen - Sun Microsystems - Beijing China 	    dev->gtt_total != 0)
3510035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_gtt_pwrite(dev, obj, &args, fpriv);
3520035d21cSmiao chen - Sun Microsystems - Beijing China 	else
3530035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_shmem_pwrite(dev, obj, &args, fpriv);
3540035d21cSmiao chen - Sun Microsystems - Beijing China 
3550035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
3560035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("pwrite failed %d\n", ret);
3570035d21cSmiao chen - Sun Microsystems - Beijing China 
3580035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
3590035d21cSmiao chen - Sun Microsystems - Beijing China 
3600035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
3610035d21cSmiao chen - Sun Microsystems - Beijing China }
3620035d21cSmiao chen - Sun Microsystems - Beijing China 
3630035d21cSmiao chen - Sun Microsystems - Beijing China /**
3640035d21cSmiao chen - Sun Microsystems - Beijing China  * Called when user space prepares to use an object with the CPU, either
3650035d21cSmiao chen - Sun Microsystems - Beijing China  * through the mmap ioctl's mapping or a GTT mapping.
3660035d21cSmiao chen - Sun Microsystems - Beijing China  */
3670035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
3680035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_set_domain_ioctl(DRM_IOCTL_ARGS)3690035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_set_domain_ioctl(DRM_IOCTL_ARGS)
3700035d21cSmiao chen - Sun Microsystems - Beijing China {
3710035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
3720035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_set_domain args;
3730035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
3740035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
3750035d21cSmiao chen - Sun Microsystems - Beijing China 
3760035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
3770035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
3780035d21cSmiao chen - Sun Microsystems - Beijing China 
3790035d21cSmiao chen - Sun Microsystems - Beijing China         DRM_COPYFROM_WITH_RETURN(&args,
3800035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_set_domain __user *) data, sizeof(args));
3810035d21cSmiao chen - Sun Microsystems - Beijing China 
3820035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t read_domains = args.read_domains;
3830035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t write_domain = args.write_domain;
3840035d21cSmiao chen - Sun Microsystems - Beijing China 
3850035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Only handle setting domains to types used by the CPU. */
3860035d21cSmiao chen - Sun Microsystems - Beijing China 	if (write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
3870035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = EINVAL;
3880035d21cSmiao chen - Sun Microsystems - Beijing China 
3890035d21cSmiao chen - Sun Microsystems - Beijing China 	if (read_domains & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
3900035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = EINVAL;
3910035d21cSmiao chen - Sun Microsystems - Beijing China 
3920035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Having something in the write domain implies it's in the read
3930035d21cSmiao chen - Sun Microsystems - Beijing China 	 * domain, and only that read domain.  Enforce that in the request.
3940035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
3950035d21cSmiao chen - Sun Microsystems - Beijing China 	if (write_domain != 0 && read_domains != write_domain)
3960035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = EINVAL;
3970035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
3980035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("set_domain invalid read or write");
3990035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
4000035d21cSmiao chen - Sun Microsystems - Beijing China 	}
4010035d21cSmiao chen - Sun Microsystems - Beijing China 
4020035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
4030035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL)
4040035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
4050035d21cSmiao chen - Sun Microsystems - Beijing China 
4060035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
4070035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("set_domain_ioctl %p(name %d size 0x%x), %08x %08x\n",
4080035d21cSmiao chen - Sun Microsystems - Beijing China 		 obj, obj->name, obj->size, args.read_domains, args.write_domain);
4090035d21cSmiao chen - Sun Microsystems - Beijing China 
4100035d21cSmiao chen - Sun Microsystems - Beijing China 	if (read_domains & I915_GEM_DOMAIN_GTT) {
4110035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
4120035d21cSmiao chen - Sun Microsystems - Beijing China 
4130035d21cSmiao chen - Sun Microsystems - Beijing China 		/* Silently promote "you're not bound, there was nothing to do"
4140035d21cSmiao chen - Sun Microsystems - Beijing China 		 * to success, since the client was just asking us to
4150035d21cSmiao chen - Sun Microsystems - Beijing China 		 * make sure everything was done.
4160035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
4170035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret == EINVAL)
4180035d21cSmiao chen - Sun Microsystems - Beijing China 			ret = 0;
4190035d21cSmiao chen - Sun Microsystems - Beijing China 	} else {
4200035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
4210035d21cSmiao chen - Sun Microsystems - Beijing China 	}
4220035d21cSmiao chen - Sun Microsystems - Beijing China 
4230035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
4240035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
4250035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
4260035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("i915_set_domain_ioctl ret %d", ret);
4270035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
4280035d21cSmiao chen - Sun Microsystems - Beijing China }
4290035d21cSmiao chen - Sun Microsystems - Beijing China 
4300035d21cSmiao chen - Sun Microsystems - Beijing China /**
4310035d21cSmiao chen - Sun Microsystems - Beijing China  * Called when user space has done writes to this buffer
4320035d21cSmiao chen - Sun Microsystems - Beijing China  */
4330035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
4340035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_sw_finish_ioctl(DRM_IOCTL_ARGS)4350035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_sw_finish_ioctl(DRM_IOCTL_ARGS)
4360035d21cSmiao chen - Sun Microsystems - Beijing China {
4370035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
4380035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_sw_finish args;
4390035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
4400035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
4410035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
4420035d21cSmiao chen - Sun Microsystems - Beijing China 
4430035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
4440035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
4450035d21cSmiao chen - Sun Microsystems - Beijing China 
4460035d21cSmiao chen - Sun Microsystems - Beijing China         DRM_COPYFROM_WITH_RETURN(&args,
4470035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_sw_finish __user *) data, sizeof(args));
4480035d21cSmiao chen - Sun Microsystems - Beijing China 
4490035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
4500035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
4510035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL) {
4520035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
4530035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
4540035d21cSmiao chen - Sun Microsystems - Beijing China 	}
4550035d21cSmiao chen - Sun Microsystems - Beijing China 
4560035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("%s: sw_finish %d (%p name %d size 0x%x)\n",
4570035d21cSmiao chen - Sun Microsystems - Beijing China 		 __func__, args.handle, obj, obj->name, obj->size);
4580035d21cSmiao chen - Sun Microsystems - Beijing China 
4590035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = obj->driver_private;
4600035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Pinned buffers may be scanout, so flush the cache */
4610035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->pin_count)
4620035d21cSmiao chen - Sun Microsystems - Beijing China 	{
4630035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_flush_cpu_write_domain(obj);
4640035d21cSmiao chen - Sun Microsystems - Beijing China 	}
4650035d21cSmiao chen - Sun Microsystems - Beijing China 
4660035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
4670035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
4680035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
4690035d21cSmiao chen - Sun Microsystems - Beijing China }
4700035d21cSmiao chen - Sun Microsystems - Beijing China 
4710035d21cSmiao chen - Sun Microsystems - Beijing China /**
4720035d21cSmiao chen - Sun Microsystems - Beijing China  * Maps the contents of an object, returning the address it is mapped
4730035d21cSmiao chen - Sun Microsystems - Beijing China  * into.
4740035d21cSmiao chen - Sun Microsystems - Beijing China  *
4750035d21cSmiao chen - Sun Microsystems - Beijing China  * While the mapping holds a reference on the contents of the object, it doesn't
4760035d21cSmiao chen - Sun Microsystems - Beijing China  * imply a ref on the object itself.
4770035d21cSmiao chen - Sun Microsystems - Beijing China  */
4780035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
4790035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_mmap_ioctl(DRM_IOCTL_ARGS)4800035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_mmap_ioctl(DRM_IOCTL_ARGS)
4810035d21cSmiao chen - Sun Microsystems - Beijing China {
4820035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
4830035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_mmap args;
4840035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
4850035d21cSmiao chen - Sun Microsystems - Beijing China 	caddr_t vvaddr = NULL;
4860035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
4870035d21cSmiao chen - Sun Microsystems - Beijing China 
4880035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
4890035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
4900035d21cSmiao chen - Sun Microsystems - Beijing China 
4910035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_COPYFROM_WITH_RETURN(
4920035d21cSmiao chen - Sun Microsystems - Beijing China 	    &args, (struct drm_i915_gem_mmap __user *)data,
4930035d21cSmiao chen - Sun Microsystems - Beijing China 	    sizeof (struct drm_i915_gem_mmap));
4940035d21cSmiao chen - Sun Microsystems - Beijing China 
4950035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
4960035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL)
4970035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
4980035d21cSmiao chen - Sun Microsystems - Beijing China 
4990035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = ddi_devmap_segmap(fpriv->dev, (off_t)obj->map->handle,
5000035d21cSmiao chen - Sun Microsystems - Beijing China 	    ttoproc(curthread)->p_as, &vvaddr, obj->map->size,
5010035d21cSmiao chen - Sun Microsystems - Beijing China 	    PROT_ALL, PROT_ALL, MAP_SHARED, fpriv->credp);
5020035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
5030035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
5040035d21cSmiao chen - Sun Microsystems - Beijing China 
5050035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
5060035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
5070035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
5080035d21cSmiao chen - Sun Microsystems - Beijing China 
5090035d21cSmiao chen - Sun Microsystems - Beijing China 	args.addr_ptr = (uint64_t)(uintptr_t)vvaddr;
5100035d21cSmiao chen - Sun Microsystems - Beijing China 
5110035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_COPYTO_WITH_RETURN(
5120035d21cSmiao chen - Sun Microsystems - Beijing China 	    (struct drm_i915_gem_mmap __user *)data,
5130035d21cSmiao chen - Sun Microsystems - Beijing China 	    &args, sizeof (struct drm_i915_gem_mmap));
5140035d21cSmiao chen - Sun Microsystems - Beijing China 
5150035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
5160035d21cSmiao chen - Sun Microsystems - Beijing China }
5170035d21cSmiao chen - Sun Microsystems - Beijing China 
5180035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_free_page_list(struct drm_gem_object * obj)5190035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_free_page_list(struct drm_gem_object *obj)
5200035d21cSmiao chen - Sun Microsystems - Beijing China {
5210035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
5220035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->page_list == NULL)
5230035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
5240035d21cSmiao chen - Sun Microsystems - Beijing China 
5250035d21cSmiao chen - Sun Microsystems - Beijing China         kmem_free(obj_priv->page_list,
5260035d21cSmiao chen - Sun Microsystems - Beijing China                  btop(obj->size) * sizeof(caddr_t));
5270035d21cSmiao chen - Sun Microsystems - Beijing China 
5280035d21cSmiao chen - Sun Microsystems - Beijing China         obj_priv->page_list = NULL;
5290035d21cSmiao chen - Sun Microsystems - Beijing China }
5300035d21cSmiao chen - Sun Microsystems - Beijing China 
5310035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_move_to_active(struct drm_gem_object * obj,uint32_t seqno)5320035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
5330035d21cSmiao chen - Sun Microsystems - Beijing China {
5340035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
5350035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
5360035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
5370035d21cSmiao chen - Sun Microsystems - Beijing China 
5380035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Add a reference if we're newly entering the active list. */
5390035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!obj_priv->active) {
5400035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_reference(obj);
5410035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->active = 1;
5420035d21cSmiao chen - Sun Microsystems - Beijing China 	}
5430035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Move from whatever list we were on to the tail of execution. */
5440035d21cSmiao chen - Sun Microsystems - Beijing China 	list_move_tail(&obj_priv->list,
5450035d21cSmiao chen - Sun Microsystems - Beijing China 		       &dev_priv->mm.active_list, (caddr_t)obj_priv);
5460035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->last_rendering_seqno = seqno;
5470035d21cSmiao chen - Sun Microsystems - Beijing China }
5480035d21cSmiao chen - Sun Microsystems - Beijing China 
5490035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_move_to_flushing(struct drm_gem_object * obj)5500035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
5510035d21cSmiao chen - Sun Microsystems - Beijing China {
5520035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
5530035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
5540035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
5550035d21cSmiao chen - Sun Microsystems - Beijing China 
5560035d21cSmiao chen - Sun Microsystems - Beijing China 	list_move_tail(&obj_priv->list, &dev_priv->mm.flushing_list, (caddr_t)obj_priv);
5570035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->last_rendering_seqno = 0;
5580035d21cSmiao chen - Sun Microsystems - Beijing China }
5590035d21cSmiao chen - Sun Microsystems - Beijing China 
5600035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_move_to_inactive(struct drm_gem_object * obj)5610035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
5620035d21cSmiao chen - Sun Microsystems - Beijing China {
5630035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
5640035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
5650035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
5660035d21cSmiao chen - Sun Microsystems - Beijing China 
5670035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->pin_count != 0)
5680035d21cSmiao chen - Sun Microsystems - Beijing China 	{
5690035d21cSmiao chen - Sun Microsystems - Beijing China 		list_del_init(&obj_priv->list);
5700035d21cSmiao chen - Sun Microsystems - Beijing China 	} else {
5710035d21cSmiao chen - Sun Microsystems - Beijing China 		list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list, (caddr_t)obj_priv);
5720035d21cSmiao chen - Sun Microsystems - Beijing China 	}
5730035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->last_rendering_seqno = 0;
5740035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->active) {
5750035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->active = 0;
5760035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
5770035d21cSmiao chen - Sun Microsystems - Beijing China 	}
5780035d21cSmiao chen - Sun Microsystems - Beijing China }
5790035d21cSmiao chen - Sun Microsystems - Beijing China 
5800035d21cSmiao chen - Sun Microsystems - Beijing China /**
5810035d21cSmiao chen - Sun Microsystems - Beijing China  * Creates a new sequence number, emitting a write of it to the status page
5820035d21cSmiao chen - Sun Microsystems - Beijing China  * plus an interrupt, which will trigger i915_user_interrupt_handler.
5830035d21cSmiao chen - Sun Microsystems - Beijing China  *
5840035d21cSmiao chen - Sun Microsystems - Beijing China  * Must be called with struct_lock held.
5850035d21cSmiao chen - Sun Microsystems - Beijing China  *
5860035d21cSmiao chen - Sun Microsystems - Beijing China  * Returned sequence numbers are nonzero on success.
5870035d21cSmiao chen - Sun Microsystems - Beijing China  */
5880035d21cSmiao chen - Sun Microsystems - Beijing China static uint32_t
i915_add_request(struct drm_device * dev,uint32_t flush_domains)5890035d21cSmiao chen - Sun Microsystems - Beijing China i915_add_request(struct drm_device *dev, uint32_t flush_domains)
5900035d21cSmiao chen - Sun Microsystems - Beijing China {
5910035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
5920035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_request *request;
5930035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t seqno;
5940035d21cSmiao chen - Sun Microsystems - Beijing China 	int was_empty;
5950035d21cSmiao chen - Sun Microsystems - Beijing China 	RING_LOCALS;
5960035d21cSmiao chen - Sun Microsystems - Beijing China 
5970035d21cSmiao chen - Sun Microsystems - Beijing China 	request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
5980035d21cSmiao chen - Sun Microsystems - Beijing China 	if (request == NULL) {
5990035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to alloc request");
6000035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
6010035d21cSmiao chen - Sun Microsystems - Beijing China 	}
6020035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Grab the seqno we're going to make this request be, and bump the
6030035d21cSmiao chen - Sun Microsystems - Beijing China 	 * next (skipping 0 so it can be the reserved no-seqno value).
6040035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
6050035d21cSmiao chen - Sun Microsystems - Beijing China 	seqno = dev_priv->mm.next_gem_seqno;
6060035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mm.next_gem_seqno++;
6070035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->mm.next_gem_seqno == 0)
6080035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->mm.next_gem_seqno++;
6090035d21cSmiao chen - Sun Microsystems - Beijing China 
6100035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("add_request seqno = %d dev 0x%lx", seqno, dev);
6110035d21cSmiao chen - Sun Microsystems - Beijing China 
6120035d21cSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(4);
6130035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_STORE_DWORD_INDEX);
6140035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
6150035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(seqno);
6160035d21cSmiao chen - Sun Microsystems - Beijing China         OUT_RING(0);
6170035d21cSmiao chen - Sun Microsystems - Beijing China         ADVANCE_LP_RING();
6180035d21cSmiao chen - Sun Microsystems - Beijing China 
6190035d21cSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(2);
6200035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(0);
6210035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_USER_INTERRUPT);
6220035d21cSmiao chen - Sun Microsystems - Beijing China 	ADVANCE_LP_RING();
6230035d21cSmiao chen - Sun Microsystems - Beijing China 
6240035d21cSmiao chen - Sun Microsystems - Beijing China 	request->seqno = seqno;
6250035d21cSmiao chen - Sun Microsystems - Beijing China 	request->emitted_jiffies = jiffies;
6260035d21cSmiao chen - Sun Microsystems - Beijing China 	was_empty = list_empty(&dev_priv->mm.request_list);
6270035d21cSmiao chen - Sun Microsystems - Beijing China 	list_add_tail(&request->list, &dev_priv->mm.request_list, (caddr_t)request);
6280035d21cSmiao chen - Sun Microsystems - Beijing China 
6290035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Associate any objects on the flushing list matching the write
6300035d21cSmiao chen - Sun Microsystems - Beijing China 	 * domain we're flushing with our flush.
6310035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
6320035d21cSmiao chen - Sun Microsystems - Beijing China 	if (flush_domains != 0) {
6330035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_i915_gem_object *obj_priv, *next;
6340035d21cSmiao chen - Sun Microsystems - Beijing China 
6350035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv = list_entry(dev_priv->mm.flushing_list.next, struct drm_i915_gem_object, list),
6360035d21cSmiao chen - Sun Microsystems - Beijing China 		next = list_entry(obj_priv->list.next, struct drm_i915_gem_object, list);
6370035d21cSmiao chen - Sun Microsystems - Beijing China 		for(; &obj_priv->list != &dev_priv->mm.flushing_list;
6380035d21cSmiao chen - Sun Microsystems - Beijing China 			obj_priv = next,
6390035d21cSmiao chen - Sun Microsystems - Beijing China 			next = list_entry(next->list.next, struct drm_i915_gem_object, list)) {
6400035d21cSmiao chen - Sun Microsystems - Beijing China 			struct drm_gem_object *obj = obj_priv->obj;
6410035d21cSmiao chen - Sun Microsystems - Beijing China 
6420035d21cSmiao chen - Sun Microsystems - Beijing China 			if ((obj->write_domain & flush_domains) ==
6430035d21cSmiao chen - Sun Microsystems - Beijing China 			    obj->write_domain) {
6440035d21cSmiao chen - Sun Microsystems - Beijing China 				obj->write_domain = 0;
6450035d21cSmiao chen - Sun Microsystems - Beijing China 				i915_gem_object_move_to_active(obj, seqno);
6460035d21cSmiao chen - Sun Microsystems - Beijing China 			}
6470035d21cSmiao chen - Sun Microsystems - Beijing China 		}
6480035d21cSmiao chen - Sun Microsystems - Beijing China 
6490035d21cSmiao chen - Sun Microsystems - Beijing China 	}
6500035d21cSmiao chen - Sun Microsystems - Beijing China 
6510035d21cSmiao chen - Sun Microsystems - Beijing China 	if (was_empty && !dev_priv->mm.suspended)
6520035d21cSmiao chen - Sun Microsystems - Beijing China 	{
6530035d21cSmiao chen - Sun Microsystems - Beijing China 		/* change to delay HZ and then run work (not insert to workqueue of Linux) */
6540035d21cSmiao chen - Sun Microsystems - Beijing China 		worktimer_id = timeout(i915_gem_retire_work_handler, (void *) dev, DRM_HZ);
6550035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("i915_gem: schedule_delayed_work");
6560035d21cSmiao chen - Sun Microsystems - Beijing China 	}
6570035d21cSmiao chen - Sun Microsystems - Beijing China 	return seqno;
6580035d21cSmiao chen - Sun Microsystems - Beijing China }
6590035d21cSmiao chen - Sun Microsystems - Beijing China 
6600035d21cSmiao chen - Sun Microsystems - Beijing China /**
6610035d21cSmiao chen - Sun Microsystems - Beijing China  * Command execution barrier
6620035d21cSmiao chen - Sun Microsystems - Beijing China  *
6630035d21cSmiao chen - Sun Microsystems - Beijing China  * Ensures that all commands in the ring are finished
6640035d21cSmiao chen - Sun Microsystems - Beijing China  * before signalling the CPU
6650035d21cSmiao chen - Sun Microsystems - Beijing China  */
6660035d21cSmiao chen - Sun Microsystems - Beijing China uint32_t
i915_retire_commands(struct drm_device * dev)6670035d21cSmiao chen - Sun Microsystems - Beijing China i915_retire_commands(struct drm_device *dev)
6680035d21cSmiao chen - Sun Microsystems - Beijing China {
6690035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
6700035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
6710035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t flush_domains = 0;
6720035d21cSmiao chen - Sun Microsystems - Beijing China 	RING_LOCALS;
6730035d21cSmiao chen - Sun Microsystems - Beijing China 
6740035d21cSmiao chen - Sun Microsystems - Beijing China 	/* The sampler always gets flushed on i965 (sigh) */
6750035d21cSmiao chen - Sun Microsystems - Beijing China 	if (IS_I965G(dev))
6760035d21cSmiao chen - Sun Microsystems - Beijing China 		flush_domains |= I915_GEM_DOMAIN_SAMPLER;
6772e6e901dSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(2);
6780035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(cmd);
6790035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(0); /* noop */
6800035d21cSmiao chen - Sun Microsystems - Beijing China 	ADVANCE_LP_RING();
6810035d21cSmiao chen - Sun Microsystems - Beijing China 
6820035d21cSmiao chen - Sun Microsystems - Beijing China 	return flush_domains;
6830035d21cSmiao chen - Sun Microsystems - Beijing China }
6840035d21cSmiao chen - Sun Microsystems - Beijing China 
6850035d21cSmiao chen - Sun Microsystems - Beijing China /**
6860035d21cSmiao chen - Sun Microsystems - Beijing China  * Moves buffers associated only with the given active seqno from the active
6870035d21cSmiao chen - Sun Microsystems - Beijing China  * to inactive list, potentially freeing them.
6880035d21cSmiao chen - Sun Microsystems - Beijing China  */
6890035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_retire_request(struct drm_device * dev,struct drm_i915_gem_request * request)6900035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_retire_request(struct drm_device *dev,
6910035d21cSmiao chen - Sun Microsystems - Beijing China 			struct drm_i915_gem_request *request)
6920035d21cSmiao chen - Sun Microsystems - Beijing China {
6930035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
6940035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Move any buffers on the active list that are no longer referenced
6950035d21cSmiao chen - Sun Microsystems - Beijing China 	 * by the ringbuffer to the flushing/inactive lists as appropriate.
6960035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
6970035d21cSmiao chen - Sun Microsystems - Beijing China 	while (!list_empty(&dev_priv->mm.active_list)) {
6980035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_gem_object *obj;
6990035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_i915_gem_object *obj_priv;
7000035d21cSmiao chen - Sun Microsystems - Beijing China 
7010035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv = list_entry(dev_priv->mm.active_list.next,
7020035d21cSmiao chen - Sun Microsystems - Beijing China 					    struct drm_i915_gem_object,
7030035d21cSmiao chen - Sun Microsystems - Beijing China 					    list);
7040035d21cSmiao chen - Sun Microsystems - Beijing China 		obj = obj_priv->obj;
7050035d21cSmiao chen - Sun Microsystems - Beijing China 
7060035d21cSmiao chen - Sun Microsystems - Beijing China 		/* If the seqno being retired doesn't match the oldest in the
7070035d21cSmiao chen - Sun Microsystems - Beijing China 		 * list, then the oldest in the list must still be newer than
7080035d21cSmiao chen - Sun Microsystems - Beijing China 		 * this seqno.
7090035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
7100035d21cSmiao chen - Sun Microsystems - Beijing China 		if (obj_priv->last_rendering_seqno != request->seqno)
7110035d21cSmiao chen - Sun Microsystems - Beijing China 			return;
7120035d21cSmiao chen - Sun Microsystems - Beijing China 
7130035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: retire %d moves to inactive list %p\n",
7140035d21cSmiao chen - Sun Microsystems - Beijing China 			 __func__, request->seqno, obj);
7150035d21cSmiao chen - Sun Microsystems - Beijing China 
7160035d21cSmiao chen - Sun Microsystems - Beijing China 		if (obj->write_domain != 0) {
7170035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_move_to_flushing(obj);
7180035d21cSmiao chen - Sun Microsystems - Beijing China 		} else {
7190035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_move_to_inactive(obj);
7200035d21cSmiao chen - Sun Microsystems - Beijing China 		}
7210035d21cSmiao chen - Sun Microsystems - Beijing China 	}
7220035d21cSmiao chen - Sun Microsystems - Beijing China }
7230035d21cSmiao chen - Sun Microsystems - Beijing China 
7240035d21cSmiao chen - Sun Microsystems - Beijing China /**
7250035d21cSmiao chen - Sun Microsystems - Beijing China  * Returns true if seq1 is later than seq2.
7260035d21cSmiao chen - Sun Microsystems - Beijing China  */
7270035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_seqno_passed(uint32_t seq1,uint32_t seq2)7280035d21cSmiao chen - Sun Microsystems - Beijing China i915_seqno_passed(uint32_t seq1, uint32_t seq2)
7290035d21cSmiao chen - Sun Microsystems - Beijing China {
7300035d21cSmiao chen - Sun Microsystems - Beijing China 	return (int32_t)(seq1 - seq2) >= 0;
7310035d21cSmiao chen - Sun Microsystems - Beijing China }
7320035d21cSmiao chen - Sun Microsystems - Beijing China 
7330035d21cSmiao chen - Sun Microsystems - Beijing China uint32_t
i915_get_gem_seqno(struct drm_device * dev)7340035d21cSmiao chen - Sun Microsystems - Beijing China i915_get_gem_seqno(struct drm_device *dev)
7350035d21cSmiao chen - Sun Microsystems - Beijing China {
7360035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
7370035d21cSmiao chen - Sun Microsystems - Beijing China 
7380035d21cSmiao chen - Sun Microsystems - Beijing China 	return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
7390035d21cSmiao chen - Sun Microsystems - Beijing China }
7400035d21cSmiao chen - Sun Microsystems - Beijing China 
7410035d21cSmiao chen - Sun Microsystems - Beijing China /**
7420035d21cSmiao chen - Sun Microsystems - Beijing China  * This function clears the request list as sequence numbers are passed.
7430035d21cSmiao chen - Sun Microsystems - Beijing China  */
7440035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_gem_retire_requests(struct drm_device * dev)7450035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_retire_requests(struct drm_device *dev)
7460035d21cSmiao chen - Sun Microsystems - Beijing China {
7470035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
7480035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t seqno;
7490035d21cSmiao chen - Sun Microsystems - Beijing China 
7500035d21cSmiao chen - Sun Microsystems - Beijing China 	seqno = i915_get_gem_seqno(dev);
7510035d21cSmiao chen - Sun Microsystems - Beijing China 
7520035d21cSmiao chen - Sun Microsystems - Beijing China 	while (!list_empty(&dev_priv->mm.request_list)) {
7530035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_i915_gem_request *request;
7540035d21cSmiao chen - Sun Microsystems - Beijing China 		uint32_t retiring_seqno;
7550035d21cSmiao chen - Sun Microsystems - Beijing China 		request = (struct drm_i915_gem_request *)(uintptr_t)(dev_priv->mm.request_list.next->contain_ptr);
7560035d21cSmiao chen - Sun Microsystems - Beijing China 		retiring_seqno = request->seqno;
7570035d21cSmiao chen - Sun Microsystems - Beijing China 
7580035d21cSmiao chen - Sun Microsystems - Beijing China 		if (i915_seqno_passed(seqno, retiring_seqno) ||
7590035d21cSmiao chen - Sun Microsystems - Beijing China 		    dev_priv->mm.wedged) {
7600035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_retire_request(dev, request);
7610035d21cSmiao chen - Sun Microsystems - Beijing China 
7620035d21cSmiao chen - Sun Microsystems - Beijing China 			list_del(&request->list);
7630035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
7640035d21cSmiao chen - Sun Microsystems - Beijing China 		} else
7650035d21cSmiao chen - Sun Microsystems - Beijing China 			break;
7660035d21cSmiao chen - Sun Microsystems - Beijing China 	}
7670035d21cSmiao chen - Sun Microsystems - Beijing China }
7680035d21cSmiao chen - Sun Microsystems - Beijing China 
7690035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_gem_retire_work_handler(void * device)7700035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_retire_work_handler(void *device)
7710035d21cSmiao chen - Sun Microsystems - Beijing China {
7720035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = (struct drm_device *)device;
7730035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
7740035d21cSmiao chen - Sun Microsystems - Beijing China 
7750035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
7760035d21cSmiao chen - Sun Microsystems - Beijing China 
7770035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Return if gem idle */
7780035d21cSmiao chen - Sun Microsystems - Beijing China 	if (worktimer_id == NULL) {
7790035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
7800035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
7810035d21cSmiao chen - Sun Microsystems - Beijing China 	}
7820035d21cSmiao chen - Sun Microsystems - Beijing China 
7830035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_retire_requests(dev);
7840035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!dev_priv->mm.suspended && !list_empty(&dev_priv->mm.request_list))
7850035d21cSmiao chen - Sun Microsystems - Beijing China 	{
7860035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("i915_gem: schedule_delayed_work");
7870035d21cSmiao chen - Sun Microsystems - Beijing China 		worktimer_id = timeout(i915_gem_retire_work_handler, (void *) dev, DRM_HZ);
7880035d21cSmiao chen - Sun Microsystems - Beijing China 	}
7890035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
7900035d21cSmiao chen - Sun Microsystems - Beijing China }
7910035d21cSmiao chen - Sun Microsystems - Beijing China 
7920035d21cSmiao chen - Sun Microsystems - Beijing China /**
7930035d21cSmiao chen - Sun Microsystems - Beijing China  * i965_reset - reset chip after a hang
7940035d21cSmiao chen - Sun Microsystems - Beijing China  * @dev: drm device to reset
7950035d21cSmiao chen - Sun Microsystems - Beijing China  * @flags: reset domains
7960035d21cSmiao chen - Sun Microsystems - Beijing China  *
7970035d21cSmiao chen - Sun Microsystems - Beijing China  * Reset the chip.  Useful if a hang is detected.
7980035d21cSmiao chen - Sun Microsystems - Beijing China  *
7990035d21cSmiao chen - Sun Microsystems - Beijing China  * Procedure is fairly simple:
8000035d21cSmiao chen - Sun Microsystems - Beijing China  *   - reset the chip using the reset reg
8010035d21cSmiao chen - Sun Microsystems - Beijing China  *   - re-init context state
8020035d21cSmiao chen - Sun Microsystems - Beijing China  *   - re-init hardware status page
8030035d21cSmiao chen - Sun Microsystems - Beijing China  *   - re-init ring buffer
8040035d21cSmiao chen - Sun Microsystems - Beijing China  *   - re-init interrupt state
8050035d21cSmiao chen - Sun Microsystems - Beijing China  *   - re-init display
8060035d21cSmiao chen - Sun Microsystems - Beijing China  */
i965_reset(struct drm_device * dev,u8 flags)8070035d21cSmiao chen - Sun Microsystems - Beijing China void i965_reset(struct drm_device *dev, u8 flags)
8080035d21cSmiao chen - Sun Microsystems - Beijing China {
8090035d21cSmiao chen - Sun Microsystems - Beijing China 	ddi_acc_handle_t conf_hdl;
8100035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
8110035d21cSmiao chen - Sun Microsystems - Beijing China 	int timeout = 0;
8120035d21cSmiao chen - Sun Microsystems - Beijing China 	uint8_t gdrst;
8130035d21cSmiao chen - Sun Microsystems - Beijing China 
8140035d21cSmiao chen - Sun Microsystems - Beijing China 	if (flags & GDRST_FULL)
8150035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_save_display(dev);
8160035d21cSmiao chen - Sun Microsystems - Beijing China 
8170035d21cSmiao chen - Sun Microsystems - Beijing China 	if (pci_config_setup(dev->dip, &conf_hdl) != DDI_SUCCESS) {
8180035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR(("i915_reset: pci_config_setup fail"));
8190035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
8200035d21cSmiao chen - Sun Microsystems - Beijing China 	}
8210035d21cSmiao chen - Sun Microsystems - Beijing China 
8220035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
8230035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Set the reset bit, wait for reset, then clear it.  Hardware
8240035d21cSmiao chen - Sun Microsystems - Beijing China 	 * will clear the status bit (bit 1) when it's actually ready
8250035d21cSmiao chen - Sun Microsystems - Beijing China 	 * for action again.
8260035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
8270035d21cSmiao chen - Sun Microsystems - Beijing China 	gdrst = pci_config_get8(conf_hdl, GDRST);
8280035d21cSmiao chen - Sun Microsystems - Beijing China 	pci_config_put8(conf_hdl, GDRST, gdrst | flags);
8290035d21cSmiao chen - Sun Microsystems - Beijing China 	drv_usecwait(50);
8300035d21cSmiao chen - Sun Microsystems - Beijing China 	pci_config_put8(conf_hdl, GDRST, gdrst | 0xfe);
8310035d21cSmiao chen - Sun Microsystems - Beijing China 
8320035d21cSmiao chen - Sun Microsystems - Beijing China 	/* ...we don't want to loop forever though, 500ms should be plenty */
8330035d21cSmiao chen - Sun Microsystems - Beijing China 	do {
8340035d21cSmiao chen - Sun Microsystems - Beijing China 		drv_usecwait(100);
8350035d21cSmiao chen - Sun Microsystems - Beijing China 		gdrst = pci_config_get8(conf_hdl, GDRST);
8360035d21cSmiao chen - Sun Microsystems - Beijing China 	} while ((gdrst & 2) && (timeout++ < 5));
8370035d21cSmiao chen - Sun Microsystems - Beijing China 
8380035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Ok now get things going again... */
8390035d21cSmiao chen - Sun Microsystems - Beijing China 
8400035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
8410035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Everything depends on having the GTT running, so we need to start
8420035d21cSmiao chen - Sun Microsystems - Beijing China 	 * there.  Fortunately we don't need to do this unless we reset the
8430035d21cSmiao chen - Sun Microsystems - Beijing China 	 * chip at a PCI level.
8440035d21cSmiao chen - Sun Microsystems - Beijing China 	 *
8450035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Next we need to restore the context, but we don't use those
8460035d21cSmiao chen - Sun Microsystems - Beijing China 	 * yet either...
8470035d21cSmiao chen - Sun Microsystems - Beijing China 	 *
8480035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Ring buffer needs to be re-initialized in the KMS case, or if X
8490035d21cSmiao chen - Sun Microsystems - Beijing China 	 * was running at the time of the reset (i.e. we weren't VT
8500035d21cSmiao chen - Sun Microsystems - Beijing China 	 * switched away).
8510035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
8520035d21cSmiao chen - Sun Microsystems - Beijing China 	 if (!dev_priv->mm.suspended) {
8530035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_i915_ring_buffer_t *ring = &dev_priv->ring;
8540035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_gem_object *obj = ring->ring_obj;
8550035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_i915_gem_object *obj_priv = obj->driver_private;
8560035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->mm.suspended = 0;
8570035d21cSmiao chen - Sun Microsystems - Beijing China 
8580035d21cSmiao chen - Sun Microsystems - Beijing China 		/* Stop the ring if it's running. */
8590035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(PRB0_CTL, 0);
8600035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(PRB0_TAIL, 0);
8610035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(PRB0_HEAD, 0);
8620035d21cSmiao chen - Sun Microsystems - Beijing China 
8630035d21cSmiao chen - Sun Microsystems - Beijing China 		/* Initialize the ring. */
8640035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(PRB0_START, obj_priv->gtt_offset);
8650035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(PRB0_CTL,
8660035d21cSmiao chen - Sun Microsystems - Beijing China 			   ((obj->size - 4096) & RING_NR_PAGES) |
8670035d21cSmiao chen - Sun Microsystems - Beijing China 			   RING_NO_REPORT |
8680035d21cSmiao chen - Sun Microsystems - Beijing China 			   RING_VALID);
8690035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_kernel_lost_context(dev);
8700035d21cSmiao chen - Sun Microsystems - Beijing China 
871*c1374a13SSurya Prakki 		(void) drm_irq_install(dev);
8720035d21cSmiao chen - Sun Microsystems - Beijing China 	}
8730035d21cSmiao chen - Sun Microsystems - Beijing China 
8740035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
8750035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Display needs restore too...
8760035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
8770035d21cSmiao chen - Sun Microsystems - Beijing China 	if (flags & GDRST_FULL)
8780035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_restore_display(dev);
8790035d21cSmiao chen - Sun Microsystems - Beijing China }
8800035d21cSmiao chen - Sun Microsystems - Beijing China 
8810035d21cSmiao chen - Sun Microsystems - Beijing China /**
8820035d21cSmiao chen - Sun Microsystems - Beijing China  * Waits for a sequence number to be signaled, and cleans up the
8830035d21cSmiao chen - Sun Microsystems - Beijing China  * request and object lists appropriately for that event.
8840035d21cSmiao chen - Sun Microsystems - Beijing China  */
8850035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_wait_request(struct drm_device * dev,uint32_t seqno)8860035d21cSmiao chen - Sun Microsystems - Beijing China i915_wait_request(struct drm_device *dev, uint32_t seqno)
8870035d21cSmiao chen - Sun Microsystems - Beijing China {
8880035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
8892e6e901dSmiao chen - Sun Microsystems - Beijing China 	u32 ier;
8900035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
8910035d21cSmiao chen - Sun Microsystems - Beijing China 
8920035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(seqno != 0);
8930035d21cSmiao chen - Sun Microsystems - Beijing China 
8940035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
8952e6e901dSmiao chen - Sun Microsystems - Beijing China 		if (IS_IGDNG(dev))
8962e6e901dSmiao chen - Sun Microsystems - Beijing China 			ier = I915_READ(DEIER) | I915_READ(GTIER);
8972e6e901dSmiao chen - Sun Microsystems - Beijing China 		else
8982e6e901dSmiao chen - Sun Microsystems - Beijing China 			ier = I915_READ(IER);
8992e6e901dSmiao chen - Sun Microsystems - Beijing China 		if (!ier) {
9002e6e901dSmiao chen - Sun Microsystems - Beijing China  			DRM_ERROR("something (likely vbetool) disabled "
9012e6e901dSmiao chen - Sun Microsystems - Beijing China  				  "interrupts, re-enabling\n");
9022e6e901dSmiao chen - Sun Microsystems - Beijing China 			(void) i915_driver_irq_preinstall(dev);
9032e6e901dSmiao chen - Sun Microsystems - Beijing China 			i915_driver_irq_postinstall(dev);
9042e6e901dSmiao chen - Sun Microsystems - Beijing China 		}
9052e6e901dSmiao chen - Sun Microsystems - Beijing China 
9060035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->mm.waiting_gem_seqno = seqno;
9070035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_user_irq_on(dev);
9080035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_WAIT(ret, &dev_priv->irq_queue,
9090035d21cSmiao chen - Sun Microsystems - Beijing China 		    (i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
9100035d21cSmiao chen - Sun Microsystems - Beijing China 				dev_priv->mm.wedged));
9110035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_user_irq_off(dev);
9120035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->mm.waiting_gem_seqno = 0;
9130035d21cSmiao chen - Sun Microsystems - Beijing China 	}
9140035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->mm.wedged) {
9150035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = EIO;
9160035d21cSmiao chen - Sun Microsystems - Beijing China 	}
9170035d21cSmiao chen - Sun Microsystems - Beijing China 
9180035d21cSmiao chen - Sun Microsystems - Beijing China 	/* GPU maybe hang, reset needed*/
9190035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret == -2 && (seqno > i915_get_gem_seqno(dev))) {
9200035d21cSmiao chen - Sun Microsystems - Beijing China 		if (IS_I965G(dev)) {
9210035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("GPU hang detected try to reset ... wait for irq_queue seqno %d, now seqno %d", seqno, i915_get_gem_seqno(dev));
9220035d21cSmiao chen - Sun Microsystems - Beijing China 			dev_priv->mm.wedged = 1;
9230035d21cSmiao chen - Sun Microsystems - Beijing China 			i965_reset(dev, GDRST_RENDER);
9240035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_retire_requests(dev);
9250035d21cSmiao chen - Sun Microsystems - Beijing China 			dev_priv->mm.wedged = 0;
9260035d21cSmiao chen - Sun Microsystems - Beijing China 		}
9270035d21cSmiao chen - Sun Microsystems - Beijing China 		else
9280035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("GPU hang detected.... reboot required");
9290035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
9300035d21cSmiao chen - Sun Microsystems - Beijing China 	}
9310035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Directly dispatch request retiring.  While we have the work queue
9320035d21cSmiao chen - Sun Microsystems - Beijing China 	 * to handle this, the waiter on a request often wants an associated
9330035d21cSmiao chen - Sun Microsystems - Beijing China 	 * buffer to have made it to the inactive list, and we would need
9340035d21cSmiao chen - Sun Microsystems - Beijing China 	 * a separate wait queue to handle that.
9350035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
9360035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret == 0)
9370035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_retire_requests(dev);
9380035d21cSmiao chen - Sun Microsystems - Beijing China 
9390035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
9400035d21cSmiao chen - Sun Microsystems - Beijing China }
9410035d21cSmiao chen - Sun Microsystems - Beijing China 
9420035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_flush(struct drm_device * dev,uint32_t invalidate_domains,uint32_t flush_domains)9430035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_flush(struct drm_device *dev,
9440035d21cSmiao chen - Sun Microsystems - Beijing China 	       uint32_t invalidate_domains,
9450035d21cSmiao chen - Sun Microsystems - Beijing China 	       uint32_t flush_domains)
9460035d21cSmiao chen - Sun Microsystems - Beijing China {
9470035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
9480035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t cmd;
9490035d21cSmiao chen - Sun Microsystems - Beijing China 	RING_LOCALS;
9500035d21cSmiao chen - Sun Microsystems - Beijing China 
9510035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("%s: invalidate %08x flush %08x\n", __func__,
9520035d21cSmiao chen - Sun Microsystems - Beijing China 		  invalidate_domains, flush_domains);
9530035d21cSmiao chen - Sun Microsystems - Beijing China 
9540035d21cSmiao chen - Sun Microsystems - Beijing China 	if (flush_domains & I915_GEM_DOMAIN_CPU)
9550035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_agp_chipset_flush(dev);
9560035d21cSmiao chen - Sun Microsystems - Beijing China 
9570035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((invalidate_domains | flush_domains) & ~(I915_GEM_DOMAIN_CPU |
9580035d21cSmiao chen - Sun Microsystems - Beijing China 						     I915_GEM_DOMAIN_GTT)) {
9590035d21cSmiao chen - Sun Microsystems - Beijing China 		/*
9600035d21cSmiao chen - Sun Microsystems - Beijing China 		 * read/write caches:
9610035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9620035d21cSmiao chen - Sun Microsystems - Beijing China 		 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
9630035d21cSmiao chen - Sun Microsystems - Beijing China 		 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
9640035d21cSmiao chen - Sun Microsystems - Beijing China 		 * also flushed at 2d versus 3d pipeline switches.
9650035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9660035d21cSmiao chen - Sun Microsystems - Beijing China 		 * read-only caches:
9670035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9680035d21cSmiao chen - Sun Microsystems - Beijing China 		 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
9690035d21cSmiao chen - Sun Microsystems - Beijing China 		 * MI_READ_FLUSH is set, and is always flushed on 965.
9700035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9710035d21cSmiao chen - Sun Microsystems - Beijing China 		 * I915_GEM_DOMAIN_COMMAND may not exist?
9720035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9730035d21cSmiao chen - Sun Microsystems - Beijing China 		 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
9740035d21cSmiao chen - Sun Microsystems - Beijing China 		 * invalidated when MI_EXE_FLUSH is set.
9750035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9760035d21cSmiao chen - Sun Microsystems - Beijing China 		 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
9770035d21cSmiao chen - Sun Microsystems - Beijing China 		 * invalidated with every MI_FLUSH.
9780035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9790035d21cSmiao chen - Sun Microsystems - Beijing China 		 * TLBs:
9800035d21cSmiao chen - Sun Microsystems - Beijing China 		 *
9810035d21cSmiao chen - Sun Microsystems - Beijing China 		 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
9820035d21cSmiao chen - Sun Microsystems - Beijing China 		 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
9830035d21cSmiao chen - Sun Microsystems - Beijing China 		 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
9840035d21cSmiao chen - Sun Microsystems - Beijing China 		 * are flushed at any MI_FLUSH.
9850035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
9860035d21cSmiao chen - Sun Microsystems - Beijing China 
9870035d21cSmiao chen - Sun Microsystems - Beijing China 		cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
9880035d21cSmiao chen - Sun Microsystems - Beijing China 		if ((invalidate_domains|flush_domains) &
9890035d21cSmiao chen - Sun Microsystems - Beijing China 		    I915_GEM_DOMAIN_RENDER)
9900035d21cSmiao chen - Sun Microsystems - Beijing China 			cmd &= ~MI_NO_WRITE_FLUSH;
9910035d21cSmiao chen - Sun Microsystems - Beijing China 		if (!IS_I965G(dev)) {
9920035d21cSmiao chen - Sun Microsystems - Beijing China 			/*
9930035d21cSmiao chen - Sun Microsystems - Beijing China 			 * On the 965, the sampler cache always gets flushed
9940035d21cSmiao chen - Sun Microsystems - Beijing China 			 * and this bit is reserved.
9950035d21cSmiao chen - Sun Microsystems - Beijing China 			 */
9960035d21cSmiao chen - Sun Microsystems - Beijing China 			if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
9970035d21cSmiao chen - Sun Microsystems - Beijing China 				cmd |= MI_READ_FLUSH;
9980035d21cSmiao chen - Sun Microsystems - Beijing China 		}
9990035d21cSmiao chen - Sun Microsystems - Beijing China 		if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
10000035d21cSmiao chen - Sun Microsystems - Beijing China 			cmd |= MI_EXE_FLUSH;
10010035d21cSmiao chen - Sun Microsystems - Beijing China 
10020035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: queue flush %08x to ring\n", __func__, cmd);
10030035d21cSmiao chen - Sun Microsystems - Beijing China 
10040035d21cSmiao chen - Sun Microsystems - Beijing China 		BEGIN_LP_RING(2);
10050035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(cmd);
10060035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(0); /* noop */
10070035d21cSmiao chen - Sun Microsystems - Beijing China 		ADVANCE_LP_RING();
10080035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10090035d21cSmiao chen - Sun Microsystems - Beijing China }
10100035d21cSmiao chen - Sun Microsystems - Beijing China 
10110035d21cSmiao chen - Sun Microsystems - Beijing China /**
10120035d21cSmiao chen - Sun Microsystems - Beijing China  * Ensures that all rendering to the object has completed and the object is
10130035d21cSmiao chen - Sun Microsystems - Beijing China  * safe to unbind from the GTT or access from the CPU.
10140035d21cSmiao chen - Sun Microsystems - Beijing China  */
10150035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_object_wait_rendering(struct drm_gem_object * obj)10160035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_wait_rendering(struct drm_gem_object *obj)
10170035d21cSmiao chen - Sun Microsystems - Beijing China {
10180035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
10190035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
10200035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret, seqno;
10210035d21cSmiao chen - Sun Microsystems - Beijing China 
10220035d21cSmiao chen - Sun Microsystems - Beijing China 	/* This function only exists to support waiting for existing rendering,
10230035d21cSmiao chen - Sun Microsystems - Beijing China 	 * not for emitting required flushes.
10240035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
10250035d21cSmiao chen - Sun Microsystems - Beijing China 
10260035d21cSmiao chen - Sun Microsystems - Beijing China 	if((obj->write_domain & I915_GEM_GPU_DOMAINS) != 0) {
10270035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("write domain should not be GPU DOMAIN %d", obj_priv->active);
10280035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
10290035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10300035d21cSmiao chen - Sun Microsystems - Beijing China 
10310035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If there is rendering queued on the buffer being evicted, wait for
10320035d21cSmiao chen - Sun Microsystems - Beijing China 	 * it.
10330035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
10340035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->active) {
10350035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: object %d %p wait for seqno %08x\n",
10360035d21cSmiao chen - Sun Microsystems - Beijing China 			  __func__, obj->name, obj, obj_priv->last_rendering_seqno);
10370035d21cSmiao chen - Sun Microsystems - Beijing China 
10380035d21cSmiao chen - Sun Microsystems - Beijing China 		seqno = obj_priv->last_rendering_seqno;
10390035d21cSmiao chen - Sun Microsystems - Beijing China 		if (seqno == 0) {
10400035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("last rendering maybe finished");
10410035d21cSmiao chen - Sun Microsystems - Beijing China 			return 0;
10420035d21cSmiao chen - Sun Microsystems - Beijing China 		}
10430035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_wait_request(dev, seqno);
10440035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
10450035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("%s: i915_wait_request request->seqno %d now %d\n", __func__, seqno, i915_get_gem_seqno(dev));
10460035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
10470035d21cSmiao chen - Sun Microsystems - Beijing China 		}
10480035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10490035d21cSmiao chen - Sun Microsystems - Beijing China 
10500035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
10510035d21cSmiao chen - Sun Microsystems - Beijing China }
10520035d21cSmiao chen - Sun Microsystems - Beijing China 
10530035d21cSmiao chen - Sun Microsystems - Beijing China /**
10540035d21cSmiao chen - Sun Microsystems - Beijing China  * Unbinds an object from the GTT aperture.
10550035d21cSmiao chen - Sun Microsystems - Beijing China  */
10560035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_object_unbind(struct drm_gem_object * obj,uint32_t type)10570035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_unbind(struct drm_gem_object *obj, uint32_t type)
10580035d21cSmiao chen - Sun Microsystems - Beijing China {
10590035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
10600035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
10610035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
10620035d21cSmiao chen - Sun Microsystems - Beijing China 
10630035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->gtt_space == NULL)
10640035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
10650035d21cSmiao chen - Sun Microsystems - Beijing China 
10660035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->pin_count != 0) {
10670035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Attempting to unbind pinned buffer\n");
10680035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
10690035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10700035d21cSmiao chen - Sun Microsystems - Beijing China 
10710035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Wait for any rendering to complete
10720035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
10730035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_wait_rendering(obj);
10740035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
10750035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("wait_rendering failed: %d\n", ret);
10760035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
10770035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10780035d21cSmiao chen - Sun Microsystems - Beijing China 
10790035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Move the object to the CPU domain to ensure that
10800035d21cSmiao chen - Sun Microsystems - Beijing China 	 * any possible CPU writes while it's not in the GTT
10810035d21cSmiao chen - Sun Microsystems - Beijing China 	 * are flushed when we go to remap it. This will
10820035d21cSmiao chen - Sun Microsystems - Beijing China 	 * also ensure that all pending GPU writes are finished
10830035d21cSmiao chen - Sun Microsystems - Beijing China 	 * before we unbind.
10840035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
10850035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_set_to_cpu_domain(obj, 1);
10860035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
10870035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("set_domain failed: %d\n", ret);
10880035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
10890035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10900035d21cSmiao chen - Sun Microsystems - Beijing China 
10910035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!obj_priv->agp_mem) {
1092*c1374a13SSurya Prakki 		(void) drm_agp_unbind_pages(dev, obj->size / PAGE_SIZE,
1093*c1374a13SSurya Prakki 		    obj_priv->gtt_offset, type);
10940035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->agp_mem = -1;
10950035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10960035d21cSmiao chen - Sun Microsystems - Beijing China 
10970035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!obj_priv->active);
10980035d21cSmiao chen - Sun Microsystems - Beijing China 
10990035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_free_page_list(obj);
11000035d21cSmiao chen - Sun Microsystems - Beijing China 
11010035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->gtt_space) {
11020035d21cSmiao chen - Sun Microsystems - Beijing China 		atomic_dec(&dev->gtt_count);
11030035d21cSmiao chen - Sun Microsystems - Beijing China 		atomic_sub(obj->size, &dev->gtt_memory);
11040035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_mm_put_block(obj_priv->gtt_space);
11050035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->gtt_space = NULL;
11060035d21cSmiao chen - Sun Microsystems - Beijing China 	}
11070035d21cSmiao chen - Sun Microsystems - Beijing China 
11080035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Remove ourselves from the LRU list if present. */
11090035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!list_empty(&obj_priv->list))
11100035d21cSmiao chen - Sun Microsystems - Beijing China 		list_del_init(&obj_priv->list);
11110035d21cSmiao chen - Sun Microsystems - Beijing China 
11120035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
11130035d21cSmiao chen - Sun Microsystems - Beijing China }
11140035d21cSmiao chen - Sun Microsystems - Beijing China 
11150035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_evict_something(struct drm_device * dev)11160035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_evict_something(struct drm_device *dev)
11170035d21cSmiao chen - Sun Microsystems - Beijing China {
11180035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
11190035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
11200035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
11210035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
11220035d21cSmiao chen - Sun Microsystems - Beijing China 
11230035d21cSmiao chen - Sun Microsystems - Beijing China 	for (;;) {
11240035d21cSmiao chen - Sun Microsystems - Beijing China 		/* If there's an inactive buffer available now, grab it
11250035d21cSmiao chen - Sun Microsystems - Beijing China 		 * and be done.
11260035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
11270035d21cSmiao chen - Sun Microsystems - Beijing China 		if (!list_empty(&dev_priv->mm.inactive_list)) {
11280035d21cSmiao chen - Sun Microsystems - Beijing China 			obj_priv = list_entry(dev_priv->mm.inactive_list.next,
11290035d21cSmiao chen - Sun Microsystems - Beijing China 						    struct drm_i915_gem_object,
11300035d21cSmiao chen - Sun Microsystems - Beijing China 						    list);
11310035d21cSmiao chen - Sun Microsystems - Beijing China 			obj = obj_priv->obj;
11320035d21cSmiao chen - Sun Microsystems - Beijing China 			ASSERT(!(obj_priv->pin_count != 0));
11330035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("%s: evicting %d\n", __func__, obj->name);
11340035d21cSmiao chen - Sun Microsystems - Beijing China 			ASSERT(!(obj_priv->active));
11350035d21cSmiao chen - Sun Microsystems - Beijing China 			/* Wait on the rendering and unbind the buffer. */
11360035d21cSmiao chen - Sun Microsystems - Beijing China 			ret = i915_gem_object_unbind(obj, 1);
11370035d21cSmiao chen - Sun Microsystems - Beijing China 			break;
11380035d21cSmiao chen - Sun Microsystems - Beijing China 		}
11390035d21cSmiao chen - Sun Microsystems - Beijing China 		/* If we didn't get anything, but the ring is still processing
11400035d21cSmiao chen - Sun Microsystems - Beijing China 		 * things, wait for one of those things to finish and hopefully
11410035d21cSmiao chen - Sun Microsystems - Beijing China 		 * leave us a buffer to evict.
11420035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
11430035d21cSmiao chen - Sun Microsystems - Beijing China 		if (!list_empty(&dev_priv->mm.request_list)) {
11440035d21cSmiao chen - Sun Microsystems - Beijing China 			struct drm_i915_gem_request *request;
11450035d21cSmiao chen - Sun Microsystems - Beijing China 
11460035d21cSmiao chen - Sun Microsystems - Beijing China 			request = list_entry(dev_priv->mm.request_list.next,
11470035d21cSmiao chen - Sun Microsystems - Beijing China 						   struct drm_i915_gem_request,
11480035d21cSmiao chen - Sun Microsystems - Beijing China 						   list);
11490035d21cSmiao chen - Sun Microsystems - Beijing China 
11500035d21cSmiao chen - Sun Microsystems - Beijing China 			ret = i915_wait_request(dev, request->seqno);
11510035d21cSmiao chen - Sun Microsystems - Beijing China 			if (ret) {
11520035d21cSmiao chen - Sun Microsystems - Beijing China 				break;
11530035d21cSmiao chen - Sun Microsystems - Beijing China 			}
11540035d21cSmiao chen - Sun Microsystems - Beijing China 			/* if waiting caused an object to become inactive,
11550035d21cSmiao chen - Sun Microsystems - Beijing China 			 * then loop around and wait for it. Otherwise, we
11560035d21cSmiao chen - Sun Microsystems - Beijing China 			 * assume that waiting freed and unbound something,
11570035d21cSmiao chen - Sun Microsystems - Beijing China 			 * so there should now be some space in the GTT
11580035d21cSmiao chen - Sun Microsystems - Beijing China 			 */
11590035d21cSmiao chen - Sun Microsystems - Beijing China 			if (!list_empty(&dev_priv->mm.inactive_list))
11600035d21cSmiao chen - Sun Microsystems - Beijing China 				continue;
11610035d21cSmiao chen - Sun Microsystems - Beijing China 			break;
11620035d21cSmiao chen - Sun Microsystems - Beijing China 		}
11630035d21cSmiao chen - Sun Microsystems - Beijing China 
11640035d21cSmiao chen - Sun Microsystems - Beijing China 		/* If we didn't have anything on the request list but there
11650035d21cSmiao chen - Sun Microsystems - Beijing China 		 * are buffers awaiting a flush, emit one and try again.
11660035d21cSmiao chen - Sun Microsystems - Beijing China 		 * When we wait on it, those buffers waiting for that flush
11670035d21cSmiao chen - Sun Microsystems - Beijing China 		 * will get moved to inactive.
11680035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
11690035d21cSmiao chen - Sun Microsystems - Beijing China 		if (!list_empty(&dev_priv->mm.flushing_list)) {
11700035d21cSmiao chen - Sun Microsystems - Beijing China 			obj_priv = list_entry(dev_priv->mm.flushing_list.next,
11710035d21cSmiao chen - Sun Microsystems - Beijing China 						    struct drm_i915_gem_object,
11720035d21cSmiao chen - Sun Microsystems - Beijing China 						    list);
11730035d21cSmiao chen - Sun Microsystems - Beijing China 			obj = obj_priv->obj;
11740035d21cSmiao chen - Sun Microsystems - Beijing China 
11750035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_flush(dev,
11760035d21cSmiao chen - Sun Microsystems - Beijing China 				       obj->write_domain,
11770035d21cSmiao chen - Sun Microsystems - Beijing China 				       obj->write_domain);
11780035d21cSmiao chen - Sun Microsystems - Beijing China 			(void) i915_add_request(dev, obj->write_domain);
11790035d21cSmiao chen - Sun Microsystems - Beijing China 
11800035d21cSmiao chen - Sun Microsystems - Beijing China 			obj = NULL;
11810035d21cSmiao chen - Sun Microsystems - Beijing China 			continue;
11820035d21cSmiao chen - Sun Microsystems - Beijing China 		}
11830035d21cSmiao chen - Sun Microsystems - Beijing China 
11840035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("inactive empty %d request empty %d "
11850035d21cSmiao chen - Sun Microsystems - Beijing China 			  "flushing empty %d\n",
11860035d21cSmiao chen - Sun Microsystems - Beijing China 			  list_empty(&dev_priv->mm.inactive_list),
11870035d21cSmiao chen - Sun Microsystems - Beijing China 			  list_empty(&dev_priv->mm.request_list),
11880035d21cSmiao chen - Sun Microsystems - Beijing China 			  list_empty(&dev_priv->mm.flushing_list));
11890035d21cSmiao chen - Sun Microsystems - Beijing China 		/* If we didn't do any of the above, there's nothing to be done
11900035d21cSmiao chen - Sun Microsystems - Beijing China 		 * and we just can't fit it in.
11910035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
11920035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENOMEM;
11930035d21cSmiao chen - Sun Microsystems - Beijing China 	}
11940035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
11950035d21cSmiao chen - Sun Microsystems - Beijing China }
11960035d21cSmiao chen - Sun Microsystems - Beijing China 
11970035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_evict_everything(struct drm_device * dev)11980035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_evict_everything(struct drm_device *dev)
11990035d21cSmiao chen - Sun Microsystems - Beijing China {
12000035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
12010035d21cSmiao chen - Sun Microsystems - Beijing China 
12020035d21cSmiao chen - Sun Microsystems - Beijing China 	for (;;) {
12030035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_evict_something(dev);
12040035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0)
12050035d21cSmiao chen - Sun Microsystems - Beijing China 			break;
12060035d21cSmiao chen - Sun Microsystems - Beijing China 	}
12070035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret == ENOMEM)
12080035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
12090035d21cSmiao chen - Sun Microsystems - Beijing China 	else
12100035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("evict_everything ret %d", ret);
12110035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
12120035d21cSmiao chen - Sun Microsystems - Beijing China }
12130035d21cSmiao chen - Sun Microsystems - Beijing China 
12140035d21cSmiao chen - Sun Microsystems - Beijing China /**
12150035d21cSmiao chen - Sun Microsystems - Beijing China  * Finds free space in the GTT aperture and binds the object there.
12160035d21cSmiao chen - Sun Microsystems - Beijing China  */
12170035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_object_bind_to_gtt(struct drm_gem_object * obj,uint32_t alignment)12180035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, uint32_t alignment)
12190035d21cSmiao chen - Sun Microsystems - Beijing China {
12200035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
12210035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
12220035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
12230035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_mm_node *free_space;
12240035d21cSmiao chen - Sun Microsystems - Beijing China 	int page_count, ret;
12250035d21cSmiao chen - Sun Microsystems - Beijing China 
12260035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->mm.suspended)
12270035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBUSY;
12280035d21cSmiao chen - Sun Microsystems - Beijing China 	if (alignment == 0)
12290035d21cSmiao chen - Sun Microsystems - Beijing China 		alignment = PAGE_SIZE;
12300035d21cSmiao chen - Sun Microsystems - Beijing China 	if (alignment & (PAGE_SIZE - 1)) {
12310035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Invalid object alignment requested %u\n", alignment);
12320035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
12330035d21cSmiao chen - Sun Microsystems - Beijing China 	}
12340035d21cSmiao chen - Sun Microsystems - Beijing China 
12350035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->gtt_space) {
12360035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Already bind!!");
12370035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
12380035d21cSmiao chen - Sun Microsystems - Beijing China 	}
12390035d21cSmiao chen - Sun Microsystems - Beijing China search_free:
12400035d21cSmiao chen - Sun Microsystems - Beijing China 	free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
12410035d21cSmiao chen - Sun Microsystems - Beijing China 					(unsigned long) obj->size, alignment, 0);
12420035d21cSmiao chen - Sun Microsystems - Beijing China 	if (free_space != NULL) {
12430035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->gtt_space = drm_mm_get_block(free_space, (unsigned long) obj->size,
12440035d21cSmiao chen - Sun Microsystems - Beijing China 						       alignment);
12450035d21cSmiao chen - Sun Microsystems - Beijing China 		if (obj_priv->gtt_space != NULL) {
12460035d21cSmiao chen - Sun Microsystems - Beijing China 			obj_priv->gtt_space->private = obj;
12470035d21cSmiao chen - Sun Microsystems - Beijing China 			obj_priv->gtt_offset = obj_priv->gtt_space->start;
12480035d21cSmiao chen - Sun Microsystems - Beijing China 		}
12490035d21cSmiao chen - Sun Microsystems - Beijing China 	}
12500035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->gtt_space == NULL) {
12510035d21cSmiao chen - Sun Microsystems - Beijing China 		/* If the gtt is empty and we're still having trouble
12520035d21cSmiao chen - Sun Microsystems - Beijing China 		 * fitting our object in, we're out of memory.
12530035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
12540035d21cSmiao chen - Sun Microsystems - Beijing China 		if (list_empty(&dev_priv->mm.inactive_list) &&
12550035d21cSmiao chen - Sun Microsystems - Beijing China 		    list_empty(&dev_priv->mm.flushing_list) &&
12560035d21cSmiao chen - Sun Microsystems - Beijing China 		    list_empty(&dev_priv->mm.active_list)) {
12570035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("GTT full, but LRU list empty\n");
12580035d21cSmiao chen - Sun Microsystems - Beijing China 			return ENOMEM;
12590035d21cSmiao chen - Sun Microsystems - Beijing China 		}
12600035d21cSmiao chen - Sun Microsystems - Beijing China 
12610035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_evict_something(dev);
12620035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
12630035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Failed to evict a buffer %d\n", ret);
12640035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
12650035d21cSmiao chen - Sun Microsystems - Beijing China 		}
12660035d21cSmiao chen - Sun Microsystems - Beijing China 		goto search_free;
12670035d21cSmiao chen - Sun Microsystems - Beijing China 	}
12680035d21cSmiao chen - Sun Microsystems - Beijing China 
12690035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_get_page_list(obj);
12700035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
12710035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_mm_put_block(obj_priv->gtt_space);
12720035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->gtt_space = NULL;
12730035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("bind to gtt failed to get page list");
12740035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
12750035d21cSmiao chen - Sun Microsystems - Beijing China 	}
12760035d21cSmiao chen - Sun Microsystems - Beijing China 
12770035d21cSmiao chen - Sun Microsystems - Beijing China 	page_count = obj->size / PAGE_SIZE;
12780035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Create an AGP memory structure pointing at our pages, and bind it
12790035d21cSmiao chen - Sun Microsystems - Beijing China 	 * into the GTT.
12800035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
12810035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("Binding object %d of page_count %d at gtt_offset 0x%x obj->pfnarray = 0x%lx",
12820035d21cSmiao chen - Sun Microsystems - Beijing China 		 obj->name, page_count, obj_priv->gtt_offset, obj->pfnarray);
12830035d21cSmiao chen - Sun Microsystems - Beijing China 
12840035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->agp_mem = drm_agp_bind_pages(dev,
12850035d21cSmiao chen - Sun Microsystems - Beijing China 					       obj->pfnarray,
12860035d21cSmiao chen - Sun Microsystems - Beijing China 					       page_count,
12870035d21cSmiao chen - Sun Microsystems - Beijing China 					       obj_priv->gtt_offset);
12880035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->agp_mem) {
12890035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_free_page_list(obj);
12900035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_mm_put_block(obj_priv->gtt_space);
12910035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->gtt_space = NULL;
12920035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to bind pages obj %d, obj 0x%lx", obj->name, obj);
12930035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENOMEM;
12940035d21cSmiao chen - Sun Microsystems - Beijing China 	}
12950035d21cSmiao chen - Sun Microsystems - Beijing China 	atomic_inc(&dev->gtt_count);
12960035d21cSmiao chen - Sun Microsystems - Beijing China 	atomic_add(obj->size, &dev->gtt_memory);
12970035d21cSmiao chen - Sun Microsystems - Beijing China 
12980035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Assert that the object is not currently in any GPU domain. As it
12990035d21cSmiao chen - Sun Microsystems - Beijing China 	 * wasn't in the GTT, there shouldn't be any way it could have been in
13000035d21cSmiao chen - Sun Microsystems - Beijing China 	 * a GPU cache
13010035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
13020035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!(obj->read_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)));
13030035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!(obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)));
13040035d21cSmiao chen - Sun Microsystems - Beijing China 
13050035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
13060035d21cSmiao chen - Sun Microsystems - Beijing China }
13070035d21cSmiao chen - Sun Microsystems - Beijing China 
13080035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_gem_clflush_object(struct drm_gem_object * obj)13090035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_clflush_object(struct drm_gem_object *obj)
13100035d21cSmiao chen - Sun Microsystems - Beijing China {
13110035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object	*obj_priv = obj->driver_private;
13120035d21cSmiao chen - Sun Microsystems - Beijing China 
13130035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If we don't have a page list set up, then we're not pinned
13140035d21cSmiao chen - Sun Microsystems - Beijing China 	 * to GPU, and we can ignore the cache flush because it'll happen
13150035d21cSmiao chen - Sun Microsystems - Beijing China 	 * again at bind time.
13160035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
13170035d21cSmiao chen - Sun Microsystems - Beijing China 
13180035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->page_list == NULL)
13190035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
13200035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE);
13210035d21cSmiao chen - Sun Microsystems - Beijing China }
13220035d21cSmiao chen - Sun Microsystems - Beijing China 
13230035d21cSmiao chen - Sun Microsystems - Beijing China /** Flushes any GPU write domain for the object if it's dirty. */
13240035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_flush_gpu_write_domain(struct drm_gem_object * obj)13250035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
13260035d21cSmiao chen - Sun Microsystems - Beijing China {
13270035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
13280035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t seqno;
13290035d21cSmiao chen - Sun Microsystems - Beijing China 
13300035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
13310035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
13320035d21cSmiao chen - Sun Microsystems - Beijing China 
13330035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Queue the GPU write cache flushing we need. */
13340035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_flush(dev, 0, obj->write_domain);
13350035d21cSmiao chen - Sun Microsystems - Beijing China 	seqno = i915_add_request(dev, obj->write_domain);
13360035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("flush_gpu_write_domain seqno = %d", seqno);
13370035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->write_domain = 0;
13380035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_move_to_active(obj, seqno);
13390035d21cSmiao chen - Sun Microsystems - Beijing China }
13400035d21cSmiao chen - Sun Microsystems - Beijing China 
13410035d21cSmiao chen - Sun Microsystems - Beijing China /** Flushes the GTT write domain for the object if it's dirty. */
13420035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_flush_gtt_write_domain(struct drm_gem_object * obj)13430035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj)
13440035d21cSmiao chen - Sun Microsystems - Beijing China {
13450035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj->write_domain != I915_GEM_DOMAIN_GTT)
13460035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
13470035d21cSmiao chen - Sun Microsystems - Beijing China 
13480035d21cSmiao chen - Sun Microsystems - Beijing China 	/* No actual flushing is required for the GTT write domain.   Writes
13490035d21cSmiao chen - Sun Microsystems - Beijing China 	 * to it immediately go to main memory as far as we know, so there's
13500035d21cSmiao chen - Sun Microsystems - Beijing China 	 * no chipset flush.  It also doesn't land in render cache.
13510035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
13520035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->write_domain = 0;
13530035d21cSmiao chen - Sun Microsystems - Beijing China }
13540035d21cSmiao chen - Sun Microsystems - Beijing China 
13550035d21cSmiao chen - Sun Microsystems - Beijing China /** Flushes the CPU write domain for the object if it's dirty. */
13560035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_flush_cpu_write_domain(struct drm_gem_object * obj)13570035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj)
13580035d21cSmiao chen - Sun Microsystems - Beijing China {
13590035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
13600035d21cSmiao chen - Sun Microsystems - Beijing China 
13610035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj->write_domain != I915_GEM_DOMAIN_CPU)
13620035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
13630035d21cSmiao chen - Sun Microsystems - Beijing China 
13640035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_clflush_object(obj);
13650035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_agp_chipset_flush(dev);
13660035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->write_domain = 0;
13670035d21cSmiao chen - Sun Microsystems - Beijing China }
13680035d21cSmiao chen - Sun Microsystems - Beijing China 
13690035d21cSmiao chen - Sun Microsystems - Beijing China /**
13700035d21cSmiao chen - Sun Microsystems - Beijing China  * Moves a single object to the GTT read, and possibly write domain.
13710035d21cSmiao chen - Sun Microsystems - Beijing China  *
13720035d21cSmiao chen - Sun Microsystems - Beijing China  * This function returns when the move is complete, including waiting on
13730035d21cSmiao chen - Sun Microsystems - Beijing China  * flushes to occur.
13740035d21cSmiao chen - Sun Microsystems - Beijing China  */
13750035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_object_set_to_gtt_domain(struct drm_gem_object * obj,int write)13760035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
13770035d21cSmiao chen - Sun Microsystems - Beijing China {
13780035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
13790035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
13800035d21cSmiao chen - Sun Microsystems - Beijing China 
13810035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Not valid to be called on unbound objects. */
13820035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->gtt_space == NULL)
13830035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
13840035d21cSmiao chen - Sun Microsystems - Beijing China 
13850035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_flush_gpu_write_domain(obj);
13860035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Wait on any GPU rendering and flushing to occur. */
13870035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_wait_rendering(obj);
13880035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0) {
13890035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("set_to_gtt_domain wait_rendering ret %d", ret);
13900035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
13910035d21cSmiao chen - Sun Microsystems - Beijing China 	}
13920035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If we're writing through the GTT domain, then CPU and GPU caches
13930035d21cSmiao chen - Sun Microsystems - Beijing China 	 * will need to be invalidated at next use.
13940035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
13950035d21cSmiao chen - Sun Microsystems - Beijing China 	if (write)
13960035d21cSmiao chen - Sun Microsystems - Beijing China 		obj->read_domains &= I915_GEM_DOMAIN_GTT;
13970035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_flush_cpu_write_domain(obj);
13980035d21cSmiao chen - Sun Microsystems - Beijing China 
13990035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_object_set_to_gtt_domain obj->read_domains %x ", obj->read_domains);
14000035d21cSmiao chen - Sun Microsystems - Beijing China 	/* It should now be out of any other write domains, and we can update
14010035d21cSmiao chen - Sun Microsystems - Beijing China 	 * the domain values for our changes.
14020035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
14030035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0));
14040035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->read_domains |= I915_GEM_DOMAIN_GTT;
14050035d21cSmiao chen - Sun Microsystems - Beijing China 	if (write) {
14060035d21cSmiao chen - Sun Microsystems - Beijing China 		obj->write_domain = I915_GEM_DOMAIN_GTT;
14070035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->dirty = 1;
14080035d21cSmiao chen - Sun Microsystems - Beijing China 	}
14090035d21cSmiao chen - Sun Microsystems - Beijing China 
14100035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
14110035d21cSmiao chen - Sun Microsystems - Beijing China }
14120035d21cSmiao chen - Sun Microsystems - Beijing China 
14130035d21cSmiao chen - Sun Microsystems - Beijing China /**
14140035d21cSmiao chen - Sun Microsystems - Beijing China  * Moves a single object to the CPU read, and possibly write domain.
14150035d21cSmiao chen - Sun Microsystems - Beijing China  *
14160035d21cSmiao chen - Sun Microsystems - Beijing China  * This function returns when the move is complete, including waiting on
14170035d21cSmiao chen - Sun Microsystems - Beijing China  * flushes to occur.
14180035d21cSmiao chen - Sun Microsystems - Beijing China  */
14190035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_object_set_to_cpu_domain(struct drm_gem_object * obj,int write)14200035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
14210035d21cSmiao chen - Sun Microsystems - Beijing China {
14220035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
14230035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
14240035d21cSmiao chen - Sun Microsystems - Beijing China 
14250035d21cSmiao chen - Sun Microsystems - Beijing China 
14260035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_flush_gpu_write_domain(obj);
14270035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Wait on any GPU rendering and flushing to occur. */
14280035d21cSmiao chen - Sun Microsystems - Beijing China 
14290035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_wait_rendering(obj);
14300035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0)
14310035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
14320035d21cSmiao chen - Sun Microsystems - Beijing China 
14330035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_flush_gtt_write_domain(obj);
14340035d21cSmiao chen - Sun Microsystems - Beijing China 
14350035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If we have a partially-valid cache of the object in the CPU,
14360035d21cSmiao chen - Sun Microsystems - Beijing China 	 * finish invalidating it and free the per-page flags.
14370035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
14380035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_set_to_full_cpu_read_domain(obj);
14390035d21cSmiao chen - Sun Microsystems - Beijing China 
14400035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Flush the CPU cache if it's still invalid. */
14410035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) {
14420035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_clflush_object(obj);
14430035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_agp_chipset_flush(dev);
14440035d21cSmiao chen - Sun Microsystems - Beijing China 		obj->read_domains |= I915_GEM_DOMAIN_CPU;
14450035d21cSmiao chen - Sun Microsystems - Beijing China 	}
14460035d21cSmiao chen - Sun Microsystems - Beijing China 
14470035d21cSmiao chen - Sun Microsystems - Beijing China 	/* It should now be out of any other write domains, and we can update
14480035d21cSmiao chen - Sun Microsystems - Beijing China 	 * the domain values for our changes.
14490035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
14500035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0));
14510035d21cSmiao chen - Sun Microsystems - Beijing China 
14520035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If we're writing through the CPU, then the GPU read domains will
14530035d21cSmiao chen - Sun Microsystems - Beijing China 	 * need to be invalidated at next use.
14540035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
14550035d21cSmiao chen - Sun Microsystems - Beijing China 	if (write) {
14560035d21cSmiao chen - Sun Microsystems - Beijing China 		obj->read_domains &= I915_GEM_DOMAIN_CPU;
14570035d21cSmiao chen - Sun Microsystems - Beijing China 		obj->write_domain = I915_GEM_DOMAIN_CPU;
14580035d21cSmiao chen - Sun Microsystems - Beijing China 	}
14590035d21cSmiao chen - Sun Microsystems - Beijing China 
14600035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
14610035d21cSmiao chen - Sun Microsystems - Beijing China }
14620035d21cSmiao chen - Sun Microsystems - Beijing China 
14630035d21cSmiao chen - Sun Microsystems - Beijing China /*
14640035d21cSmiao chen - Sun Microsystems - Beijing China  * Set the next domain for the specified object. This
14650035d21cSmiao chen - Sun Microsystems - Beijing China  * may not actually perform the necessary flushing/invaliding though,
14660035d21cSmiao chen - Sun Microsystems - Beijing China  * as that may want to be batched with other set_domain operations
14670035d21cSmiao chen - Sun Microsystems - Beijing China  *
14680035d21cSmiao chen - Sun Microsystems - Beijing China  * This is (we hope) the only really tricky part of gem. The goal
14690035d21cSmiao chen - Sun Microsystems - Beijing China  * is fairly simple -- track which caches hold bits of the object
14700035d21cSmiao chen - Sun Microsystems - Beijing China  * and make sure they remain coherent. A few concrete examples may
14710035d21cSmiao chen - Sun Microsystems - Beijing China  * help to explain how it works. For shorthand, we use the notation
14720035d21cSmiao chen - Sun Microsystems - Beijing China  * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
14730035d21cSmiao chen - Sun Microsystems - Beijing China  * a pair of read and write domain masks.
14740035d21cSmiao chen - Sun Microsystems - Beijing China  *
14750035d21cSmiao chen - Sun Microsystems - Beijing China  * Case 1: the batch buffer
14760035d21cSmiao chen - Sun Microsystems - Beijing China  *
14770035d21cSmiao chen - Sun Microsystems - Beijing China  *	1. Allocated
14780035d21cSmiao chen - Sun Microsystems - Beijing China  *	2. Written by CPU
14790035d21cSmiao chen - Sun Microsystems - Beijing China  *	3. Mapped to GTT
14800035d21cSmiao chen - Sun Microsystems - Beijing China  *	4. Read by GPU
14810035d21cSmiao chen - Sun Microsystems - Beijing China  *	5. Unmapped from GTT
14820035d21cSmiao chen - Sun Microsystems - Beijing China  *	6. Freed
14830035d21cSmiao chen - Sun Microsystems - Beijing China  *
14840035d21cSmiao chen - Sun Microsystems - Beijing China  *	Let's take these a step at a time
14850035d21cSmiao chen - Sun Microsystems - Beijing China  *
14860035d21cSmiao chen - Sun Microsystems - Beijing China  *	1. Allocated
14870035d21cSmiao chen - Sun Microsystems - Beijing China  *		Pages allocated from the kernel may still have
14880035d21cSmiao chen - Sun Microsystems - Beijing China  *		cache contents, so we set them to (CPU, CPU) always.
14890035d21cSmiao chen - Sun Microsystems - Beijing China  *	2. Written by CPU (using pwrite)
14900035d21cSmiao chen - Sun Microsystems - Beijing China  *		The pwrite function calls set_domain (CPU, CPU) and
14910035d21cSmiao chen - Sun Microsystems - Beijing China  *		this function does nothing (as nothing changes)
14920035d21cSmiao chen - Sun Microsystems - Beijing China  *	3. Mapped by GTT
14930035d21cSmiao chen - Sun Microsystems - Beijing China  *		This function asserts that the object is not
14940035d21cSmiao chen - Sun Microsystems - Beijing China  *		currently in any GPU-based read or write domains
14950035d21cSmiao chen - Sun Microsystems - Beijing China  *	4. Read by GPU
14960035d21cSmiao chen - Sun Microsystems - Beijing China  *		i915_gem_execbuffer calls set_domain (COMMAND, 0).
14970035d21cSmiao chen - Sun Microsystems - Beijing China  *		As write_domain is zero, this function adds in the
14980035d21cSmiao chen - Sun Microsystems - Beijing China  *		current read domains (CPU+COMMAND, 0).
14990035d21cSmiao chen - Sun Microsystems - Beijing China  *		flush_domains is set to CPU.
15000035d21cSmiao chen - Sun Microsystems - Beijing China  *		invalidate_domains is set to COMMAND
15010035d21cSmiao chen - Sun Microsystems - Beijing China  *		clflush is run to get data out of the CPU caches
15020035d21cSmiao chen - Sun Microsystems - Beijing China  *		then i915_dev_set_domain calls i915_gem_flush to
15030035d21cSmiao chen - Sun Microsystems - Beijing China  *		emit an MI_FLUSH and drm_agp_chipset_flush
15040035d21cSmiao chen - Sun Microsystems - Beijing China  *	5. Unmapped from GTT
15050035d21cSmiao chen - Sun Microsystems - Beijing China  *		i915_gem_object_unbind calls set_domain (CPU, CPU)
15060035d21cSmiao chen - Sun Microsystems - Beijing China  *		flush_domains and invalidate_domains end up both zero
15070035d21cSmiao chen - Sun Microsystems - Beijing China  *		so no flushing/invalidating happens
15080035d21cSmiao chen - Sun Microsystems - Beijing China  *	6. Freed
15090035d21cSmiao chen - Sun Microsystems - Beijing China  *		yay, done
15100035d21cSmiao chen - Sun Microsystems - Beijing China  *
15110035d21cSmiao chen - Sun Microsystems - Beijing China  * Case 2: The shared render buffer
15120035d21cSmiao chen - Sun Microsystems - Beijing China  *
15130035d21cSmiao chen - Sun Microsystems - Beijing China  *	1. Allocated
15140035d21cSmiao chen - Sun Microsystems - Beijing China  *	2. Mapped to GTT
15150035d21cSmiao chen - Sun Microsystems - Beijing China  *	3. Read/written by GPU
15160035d21cSmiao chen - Sun Microsystems - Beijing China  *	4. set_domain to (CPU,CPU)
15170035d21cSmiao chen - Sun Microsystems - Beijing China  *	5. Read/written by CPU
15180035d21cSmiao chen - Sun Microsystems - Beijing China  *	6. Read/written by GPU
15190035d21cSmiao chen - Sun Microsystems - Beijing China  *
15200035d21cSmiao chen - Sun Microsystems - Beijing China  *	1. Allocated
15210035d21cSmiao chen - Sun Microsystems - Beijing China  *		Same as last example, (CPU, CPU)
15220035d21cSmiao chen - Sun Microsystems - Beijing China  *	2. Mapped to GTT
15230035d21cSmiao chen - Sun Microsystems - Beijing China  *		Nothing changes (assertions find that it is not in the GPU)
15240035d21cSmiao chen - Sun Microsystems - Beijing China  *	3. Read/written by GPU
15250035d21cSmiao chen - Sun Microsystems - Beijing China  *		execbuffer calls set_domain (RENDER, RENDER)
15260035d21cSmiao chen - Sun Microsystems - Beijing China  *		flush_domains gets CPU
15270035d21cSmiao chen - Sun Microsystems - Beijing China  *		invalidate_domains gets GPU
15280035d21cSmiao chen - Sun Microsystems - Beijing China  *		clflush (obj)
15290035d21cSmiao chen - Sun Microsystems - Beijing China  *		MI_FLUSH and drm_agp_chipset_flush
15300035d21cSmiao chen - Sun Microsystems - Beijing China  *	4. set_domain (CPU, CPU)
15310035d21cSmiao chen - Sun Microsystems - Beijing China  *		flush_domains gets GPU
15320035d21cSmiao chen - Sun Microsystems - Beijing China  *		invalidate_domains gets CPU
15330035d21cSmiao chen - Sun Microsystems - Beijing China  *		wait_rendering (obj) to make sure all drawing is complete.
15340035d21cSmiao chen - Sun Microsystems - Beijing China  *		This will include an MI_FLUSH to get the data from GPU
15350035d21cSmiao chen - Sun Microsystems - Beijing China  *		to memory
15360035d21cSmiao chen - Sun Microsystems - Beijing China  *		clflush (obj) to invalidate the CPU cache
15370035d21cSmiao chen - Sun Microsystems - Beijing China  *		Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
15380035d21cSmiao chen - Sun Microsystems - Beijing China  *	5. Read/written by CPU
15390035d21cSmiao chen - Sun Microsystems - Beijing China  *		cache lines are loaded and dirtied
15400035d21cSmiao chen - Sun Microsystems - Beijing China  *	6. Read written by GPU
15410035d21cSmiao chen - Sun Microsystems - Beijing China  *		Same as last GPU access
15420035d21cSmiao chen - Sun Microsystems - Beijing China  *
15430035d21cSmiao chen - Sun Microsystems - Beijing China  * Case 3: The constant buffer
15440035d21cSmiao chen - Sun Microsystems - Beijing China  *
15450035d21cSmiao chen - Sun Microsystems - Beijing China  *	1. Allocated
15460035d21cSmiao chen - Sun Microsystems - Beijing China  *	2. Written by CPU
15470035d21cSmiao chen - Sun Microsystems - Beijing China  *	3. Read by GPU
15480035d21cSmiao chen - Sun Microsystems - Beijing China  *	4. Updated (written) by CPU again
15490035d21cSmiao chen - Sun Microsystems - Beijing China  *	5. Read by GPU
15500035d21cSmiao chen - Sun Microsystems - Beijing China  *
15510035d21cSmiao chen - Sun Microsystems - Beijing China  *	1. Allocated
15520035d21cSmiao chen - Sun Microsystems - Beijing China  *		(CPU, CPU)
15530035d21cSmiao chen - Sun Microsystems - Beijing China  *	2. Written by CPU
15540035d21cSmiao chen - Sun Microsystems - Beijing China  *		(CPU, CPU)
15550035d21cSmiao chen - Sun Microsystems - Beijing China  *	3. Read by GPU
15560035d21cSmiao chen - Sun Microsystems - Beijing China  *		(CPU+RENDER, 0)
15570035d21cSmiao chen - Sun Microsystems - Beijing China  *		flush_domains = CPU
15580035d21cSmiao chen - Sun Microsystems - Beijing China  *		invalidate_domains = RENDER
15590035d21cSmiao chen - Sun Microsystems - Beijing China  *		clflush (obj)
15600035d21cSmiao chen - Sun Microsystems - Beijing China  *		MI_FLUSH
15610035d21cSmiao chen - Sun Microsystems - Beijing China  *		drm_agp_chipset_flush
15620035d21cSmiao chen - Sun Microsystems - Beijing China  *	4. Updated (written) by CPU again
15630035d21cSmiao chen - Sun Microsystems - Beijing China  *		(CPU, CPU)
15640035d21cSmiao chen - Sun Microsystems - Beijing China  *		flush_domains = 0 (no previous write domain)
15650035d21cSmiao chen - Sun Microsystems - Beijing China  *		invalidate_domains = 0 (no new read domains)
15660035d21cSmiao chen - Sun Microsystems - Beijing China  *	5. Read by GPU
15670035d21cSmiao chen - Sun Microsystems - Beijing China  *		(CPU+RENDER, 0)
15680035d21cSmiao chen - Sun Microsystems - Beijing China  *		flush_domains = CPU
15690035d21cSmiao chen - Sun Microsystems - Beijing China  *		invalidate_domains = RENDER
15700035d21cSmiao chen - Sun Microsystems - Beijing China  *		clflush (obj)
15710035d21cSmiao chen - Sun Microsystems - Beijing China  *		MI_FLUSH
15720035d21cSmiao chen - Sun Microsystems - Beijing China  *		drm_agp_chipset_flush
15730035d21cSmiao chen - Sun Microsystems - Beijing China  */
15740035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_set_to_gpu_domain(struct drm_gem_object * obj,uint32_t read_domains,uint32_t write_domain)15750035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
15760035d21cSmiao chen - Sun Microsystems - Beijing China 			    uint32_t read_domains,
15770035d21cSmiao chen - Sun Microsystems - Beijing China 			    uint32_t write_domain)
15780035d21cSmiao chen - Sun Microsystems - Beijing China {
15790035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device		*dev = obj->dev;
15800035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object	*obj_priv = obj->driver_private;
15810035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t			invalidate_domains = 0;
15820035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t			flush_domains = 0;
15830035d21cSmiao chen - Sun Microsystems - Beijing China 
15840035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("%s: object %p read %08x -> %08x write %08x -> %08x\n",
15850035d21cSmiao chen - Sun Microsystems - Beijing China 		 __func__, obj,
15860035d21cSmiao chen - Sun Microsystems - Beijing China 		 obj->read_domains, read_domains,
15870035d21cSmiao chen - Sun Microsystems - Beijing China 		 obj->write_domain, write_domain);
15880035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
15890035d21cSmiao chen - Sun Microsystems - Beijing China 	 * If the object isn't moving to a new write domain,
15900035d21cSmiao chen - Sun Microsystems - Beijing China 	 * let the object stay in multiple read domains
15910035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
15920035d21cSmiao chen - Sun Microsystems - Beijing China 	if (write_domain == 0)
15930035d21cSmiao chen - Sun Microsystems - Beijing China 		read_domains |= obj->read_domains;
15940035d21cSmiao chen - Sun Microsystems - Beijing China 	else
15950035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->dirty = 1;
15960035d21cSmiao chen - Sun Microsystems - Beijing China 
15970035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
15980035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Flush the current write domain if
15990035d21cSmiao chen - Sun Microsystems - Beijing China 	 * the new read domains don't match. Invalidate
16000035d21cSmiao chen - Sun Microsystems - Beijing China 	 * any read domains which differ from the old
16010035d21cSmiao chen - Sun Microsystems - Beijing China 	 * write domain
16020035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
16030035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj->write_domain && obj->write_domain != read_domains) {
16040035d21cSmiao chen - Sun Microsystems - Beijing China 		flush_domains |= obj->write_domain;
16050035d21cSmiao chen - Sun Microsystems - Beijing China 		invalidate_domains |= read_domains & ~obj->write_domain;
16060035d21cSmiao chen - Sun Microsystems - Beijing China 	}
16070035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
16080035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Invalidate any read caches which may have
16090035d21cSmiao chen - Sun Microsystems - Beijing China 	 * stale data. That is, any new read domains.
16100035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
16110035d21cSmiao chen - Sun Microsystems - Beijing China 	invalidate_domains |= read_domains & ~obj->read_domains;
16120035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
16130035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: CPU domain flush %08x invalidate %08x\n",
16140035d21cSmiao chen - Sun Microsystems - Beijing China 			 __func__, flush_domains, invalidate_domains);
16150035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_clflush_object(obj);
16160035d21cSmiao chen - Sun Microsystems - Beijing China 	}
16170035d21cSmiao chen - Sun Microsystems - Beijing China 
16180035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((write_domain | flush_domains) != 0)
16190035d21cSmiao chen - Sun Microsystems - Beijing China 		obj->write_domain = write_domain;
16200035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->read_domains = read_domains;
16210035d21cSmiao chen - Sun Microsystems - Beijing China 
16220035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->invalidate_domains |= invalidate_domains;
16230035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->flush_domains |= flush_domains;
16240035d21cSmiao chen - Sun Microsystems - Beijing China 
16250035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("%s: read %08x write %08x invalidate %08x flush %08x\n",
16260035d21cSmiao chen - Sun Microsystems - Beijing China 		 __func__,
16270035d21cSmiao chen - Sun Microsystems - Beijing China 		 obj->read_domains, obj->write_domain,
16280035d21cSmiao chen - Sun Microsystems - Beijing China 		 dev->invalidate_domains, dev->flush_domains);
16290035d21cSmiao chen - Sun Microsystems - Beijing China 
16300035d21cSmiao chen - Sun Microsystems - Beijing China }
16310035d21cSmiao chen - Sun Microsystems - Beijing China 
16320035d21cSmiao chen - Sun Microsystems - Beijing China /**
16330035d21cSmiao chen - Sun Microsystems - Beijing China  * Moves the object from a partially CPU read to a full one.
16340035d21cSmiao chen - Sun Microsystems - Beijing China  *
16350035d21cSmiao chen - Sun Microsystems - Beijing China  * Note that this only resolves i915_gem_object_set_cpu_read_domain_range(),
16360035d21cSmiao chen - Sun Microsystems - Beijing China  * and doesn't handle transitioning from !(read_domains & I915_GEM_DOMAIN_CPU).
16370035d21cSmiao chen - Sun Microsystems - Beijing China  */
16380035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object * obj)16390035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj)
16400035d21cSmiao chen - Sun Microsystems - Beijing China {
16410035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
16420035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
16430035d21cSmiao chen - Sun Microsystems - Beijing China 
16440035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!obj_priv->page_cpu_valid)
16450035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
16460035d21cSmiao chen - Sun Microsystems - Beijing China 
16470035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If we're partially in the CPU read domain, finish moving it in.
16480035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
16490035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj->read_domains & I915_GEM_DOMAIN_CPU) {
16500035d21cSmiao chen - Sun Microsystems - Beijing China 		int i;
16510035d21cSmiao chen - Sun Microsystems - Beijing China 
16520035d21cSmiao chen - Sun Microsystems - Beijing China 		for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) {
16530035d21cSmiao chen - Sun Microsystems - Beijing China 			if (obj_priv->page_cpu_valid[i])
16540035d21cSmiao chen - Sun Microsystems - Beijing China 				continue;
16550035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_clflush_pages(obj_priv->page_list + i, 1);
16560035d21cSmiao chen - Sun Microsystems - Beijing China 		}
16570035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_agp_chipset_flush(dev);
16580035d21cSmiao chen - Sun Microsystems - Beijing China 	}
16590035d21cSmiao chen - Sun Microsystems - Beijing China 
16600035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Free the page_cpu_valid mappings which are now stale, whether
16610035d21cSmiao chen - Sun Microsystems - Beijing China 	 * or not we've got I915_GEM_DOMAIN_CPU.
16620035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
16630035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
16640035d21cSmiao chen - Sun Microsystems - Beijing China 		 DRM_MEM_DRIVER);
16650035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->page_cpu_valid = NULL;
16660035d21cSmiao chen - Sun Microsystems - Beijing China }
16670035d21cSmiao chen - Sun Microsystems - Beijing China 
16680035d21cSmiao chen - Sun Microsystems - Beijing China /**
16690035d21cSmiao chen - Sun Microsystems - Beijing China  * Set the CPU read domain on a range of the object.
16700035d21cSmiao chen - Sun Microsystems - Beijing China  *
16710035d21cSmiao chen - Sun Microsystems - Beijing China  * The object ends up with I915_GEM_DOMAIN_CPU in its read flags although it's
16720035d21cSmiao chen - Sun Microsystems - Beijing China  * not entirely valid.  The page_cpu_valid member of the object flags which
16730035d21cSmiao chen - Sun Microsystems - Beijing China  * pages have been flushed, and will be respected by
16740035d21cSmiao chen - Sun Microsystems - Beijing China  * i915_gem_object_set_to_cpu_domain() if it's called on to get a valid mapping
16750035d21cSmiao chen - Sun Microsystems - Beijing China  * of the whole object.
16760035d21cSmiao chen - Sun Microsystems - Beijing China  *
16770035d21cSmiao chen - Sun Microsystems - Beijing China  * This function returns when the move is complete, including waiting on
16780035d21cSmiao chen - Sun Microsystems - Beijing China  * flushes to occur.
16790035d21cSmiao chen - Sun Microsystems - Beijing China  */
16800035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object * obj,uint64_t offset,uint64_t size)16810035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
16820035d21cSmiao chen - Sun Microsystems - Beijing China 					  uint64_t offset, uint64_t size)
16830035d21cSmiao chen - Sun Microsystems - Beijing China {
16840035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
16850035d21cSmiao chen - Sun Microsystems - Beijing China 	int i, ret;
16860035d21cSmiao chen - Sun Microsystems - Beijing China 
16870035d21cSmiao chen - Sun Microsystems - Beijing China 	if (offset == 0 && size == obj->size)
16880035d21cSmiao chen - Sun Microsystems - Beijing China 		return i915_gem_object_set_to_cpu_domain(obj, 0);
16890035d21cSmiao chen - Sun Microsystems - Beijing China 
16900035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_flush_gpu_write_domain(obj);
16910035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Wait on any GPU rendering and flushing to occur. */
16920035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_wait_rendering(obj);
16930035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0)
16940035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
16950035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_flush_gtt_write_domain(obj);
16960035d21cSmiao chen - Sun Microsystems - Beijing China 
16970035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If we're already fully in the CPU read domain, we're done. */
16980035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->page_cpu_valid == NULL &&
16990035d21cSmiao chen - Sun Microsystems - Beijing China 	    (obj->read_domains & I915_GEM_DOMAIN_CPU) != 0)
17000035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
17010035d21cSmiao chen - Sun Microsystems - Beijing China 
17020035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Otherwise, create/clear the per-page CPU read domain flag if we're
17030035d21cSmiao chen - Sun Microsystems - Beijing China 	 * newly adding I915_GEM_DOMAIN_CPU
17040035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
17050035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->page_cpu_valid == NULL) {
17060035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
17070035d21cSmiao chen - Sun Microsystems - Beijing China 						      DRM_MEM_DRIVER);
17080035d21cSmiao chen - Sun Microsystems - Beijing China 		if (obj_priv->page_cpu_valid == NULL)
17090035d21cSmiao chen - Sun Microsystems - Beijing China 			return ENOMEM;
17100035d21cSmiao chen - Sun Microsystems - Beijing China 	} else if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0)
17110035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) memset(obj_priv->page_cpu_valid, 0, obj->size / PAGE_SIZE);
17120035d21cSmiao chen - Sun Microsystems - Beijing China 
17130035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Flush the cache on any pages that are still invalid from the CPU's
17140035d21cSmiao chen - Sun Microsystems - Beijing China 	 * perspective.
17150035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
17160035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE;
17170035d21cSmiao chen - Sun Microsystems - Beijing China 	     i++) {
17180035d21cSmiao chen - Sun Microsystems - Beijing China 		if (obj_priv->page_cpu_valid[i])
17190035d21cSmiao chen - Sun Microsystems - Beijing China 			continue;
17200035d21cSmiao chen - Sun Microsystems - Beijing China 
17210035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_clflush_pages(obj_priv->page_list + i, 1);
17220035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->page_cpu_valid[i] = 1;
17230035d21cSmiao chen - Sun Microsystems - Beijing China 	}
17240035d21cSmiao chen - Sun Microsystems - Beijing China 
17250035d21cSmiao chen - Sun Microsystems - Beijing China 	/* It should now be out of any other write domains, and we can update
17260035d21cSmiao chen - Sun Microsystems - Beijing China 	 * the domain values for our changes.
17270035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
17280035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0));
17290035d21cSmiao chen - Sun Microsystems - Beijing China 
17300035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->read_domains |= I915_GEM_DOMAIN_CPU;
17310035d21cSmiao chen - Sun Microsystems - Beijing China 
17320035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
17330035d21cSmiao chen - Sun Microsystems - Beijing China }
17340035d21cSmiao chen - Sun Microsystems - Beijing China 
17350035d21cSmiao chen - Sun Microsystems - Beijing China /**
17360035d21cSmiao chen - Sun Microsystems - Beijing China  * Pin an object to the GTT and evaluate the relocations landing in it.
17370035d21cSmiao chen - Sun Microsystems - Beijing China  */
17380035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_object_pin_and_relocate(struct drm_gem_object * obj,struct drm_file * file_priv,struct drm_i915_gem_exec_object * entry)17390035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
17400035d21cSmiao chen - Sun Microsystems - Beijing China 				 struct drm_file *file_priv,
17410035d21cSmiao chen - Sun Microsystems - Beijing China 				 struct drm_i915_gem_exec_object *entry)
17420035d21cSmiao chen - Sun Microsystems - Beijing China {
17430035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_relocation_entry reloc;
17440035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_relocation_entry __user *relocs;
17450035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
17460035d21cSmiao chen - Sun Microsystems - Beijing China 	int i, ret;
17470035d21cSmiao chen - Sun Microsystems - Beijing China 
17480035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Choose the GTT offset for our buffer and put it there. */
17490035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
17500035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
17510035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("failed to pin");
17520035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
17530035d21cSmiao chen - Sun Microsystems - Beijing China 	}
17540035d21cSmiao chen - Sun Microsystems - Beijing China 	entry->offset = obj_priv->gtt_offset;
17550035d21cSmiao chen - Sun Microsystems - Beijing China 
17560035d21cSmiao chen - Sun Microsystems - Beijing China 	relocs = (struct drm_i915_gem_relocation_entry __user *)
17570035d21cSmiao chen - Sun Microsystems - Beijing China 		 (uintptr_t) entry->relocs_ptr;
17580035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Apply the relocations, using the GTT aperture to avoid cache
17590035d21cSmiao chen - Sun Microsystems - Beijing China 	 * flushing requirements.
17600035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
17610035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = 0; i < entry->relocation_count; i++) {
17620035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_gem_object *target_obj;
17630035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_i915_gem_object *target_obj_priv;
17640035d21cSmiao chen - Sun Microsystems - Beijing China 		uint32_t reloc_val, reloc_offset, *reloc_entry;
17650035d21cSmiao chen - Sun Microsystems - Beijing China 
17660035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = DRM_COPY_FROM_USER(&reloc, relocs + i, sizeof(reloc));
17670035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
17680035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
17690035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("failed to copy from user");
17700035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
17710035d21cSmiao chen - Sun Microsystems - Beijing China 		}
17720035d21cSmiao chen - Sun Microsystems - Beijing China 
17730035d21cSmiao chen - Sun Microsystems - Beijing China 		target_obj = drm_gem_object_lookup(file_priv,
17740035d21cSmiao chen - Sun Microsystems - Beijing China 						   reloc.target_handle);
17750035d21cSmiao chen - Sun Microsystems - Beijing China 		if (target_obj == NULL) {
17760035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
17770035d21cSmiao chen - Sun Microsystems - Beijing China 			return EBADF;
17780035d21cSmiao chen - Sun Microsystems - Beijing China 		}
17790035d21cSmiao chen - Sun Microsystems - Beijing China 		target_obj_priv = target_obj->driver_private;
17800035d21cSmiao chen - Sun Microsystems - Beijing China 
17810035d21cSmiao chen - Sun Microsystems - Beijing China 		/* The target buffer should have appeared before us in the
17820035d21cSmiao chen - Sun Microsystems - Beijing China 		 * exec_object list, so it should have a GTT space bound by now.
17830035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
17840035d21cSmiao chen - Sun Microsystems - Beijing China 		if (target_obj_priv->gtt_space == NULL) {
17850035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("No GTT space found for object %d\n",
17860035d21cSmiao chen - Sun Microsystems - Beijing China 				  reloc.target_handle);
17870035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
17880035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
17890035d21cSmiao chen - Sun Microsystems - Beijing China 			return EINVAL;
17900035d21cSmiao chen - Sun Microsystems - Beijing China 		}
17910035d21cSmiao chen - Sun Microsystems - Beijing China 
17920035d21cSmiao chen - Sun Microsystems - Beijing China 		if (reloc.offset > obj->size - 4) {
17930035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Relocation beyond object bounds: "
17940035d21cSmiao chen - Sun Microsystems - Beijing China 				  "obj %p target %d offset %d size %d.\n",
17950035d21cSmiao chen - Sun Microsystems - Beijing China 				  obj, reloc.target_handle,
17960035d21cSmiao chen - Sun Microsystems - Beijing China 				  (int) reloc.offset, (int) obj->size);
17970035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
17980035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
17990035d21cSmiao chen - Sun Microsystems - Beijing China 			return EINVAL;
18000035d21cSmiao chen - Sun Microsystems - Beijing China 		}
18010035d21cSmiao chen - Sun Microsystems - Beijing China 		if (reloc.offset & 3) {
18020035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Relocation not 4-byte aligned: "
18030035d21cSmiao chen - Sun Microsystems - Beijing China 				  "obj %p target %d offset %d.\n",
18040035d21cSmiao chen - Sun Microsystems - Beijing China 				  obj, reloc.target_handle,
18050035d21cSmiao chen - Sun Microsystems - Beijing China 				  (int) reloc.offset);
18060035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
18070035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
18080035d21cSmiao chen - Sun Microsystems - Beijing China 			return EINVAL;
18090035d21cSmiao chen - Sun Microsystems - Beijing China 		}
18100035d21cSmiao chen - Sun Microsystems - Beijing China 
18110035d21cSmiao chen - Sun Microsystems - Beijing China 		if (reloc.write_domain & I915_GEM_DOMAIN_CPU ||
18120035d21cSmiao chen - Sun Microsystems - Beijing China 		    reloc.read_domains & I915_GEM_DOMAIN_CPU) {
18130035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("reloc with read/write CPU domains: "
18140035d21cSmiao chen - Sun Microsystems - Beijing China 				  "obj %p target %d offset %d "
18150035d21cSmiao chen - Sun Microsystems - Beijing China 				  "read %08x write %08x",
18160035d21cSmiao chen - Sun Microsystems - Beijing China 				  obj, reloc.target_handle,
18170035d21cSmiao chen - Sun Microsystems - Beijing China 				  (int) reloc.offset,
18180035d21cSmiao chen - Sun Microsystems - Beijing China 				  reloc.read_domains,
18190035d21cSmiao chen - Sun Microsystems - Beijing China 				  reloc.write_domain);
18200035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
18210035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
18220035d21cSmiao chen - Sun Microsystems - Beijing China 			return EINVAL;
18230035d21cSmiao chen - Sun Microsystems - Beijing China 		}
18240035d21cSmiao chen - Sun Microsystems - Beijing China 
18250035d21cSmiao chen - Sun Microsystems - Beijing China 		if (reloc.write_domain && target_obj->pending_write_domain &&
18260035d21cSmiao chen - Sun Microsystems - Beijing China 		    reloc.write_domain != target_obj->pending_write_domain) {
18270035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Write domain conflict: "
18280035d21cSmiao chen - Sun Microsystems - Beijing China 				  "obj %p target %d offset %d "
18290035d21cSmiao chen - Sun Microsystems - Beijing China 				  "new %08x old %08x\n",
18300035d21cSmiao chen - Sun Microsystems - Beijing China 				  obj, reloc.target_handle,
18310035d21cSmiao chen - Sun Microsystems - Beijing China 				  (int) reloc.offset,
18320035d21cSmiao chen - Sun Microsystems - Beijing China 				  reloc.write_domain,
18330035d21cSmiao chen - Sun Microsystems - Beijing China 				  target_obj->pending_write_domain);
18340035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
18350035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
18360035d21cSmiao chen - Sun Microsystems - Beijing China 			return EINVAL;
18370035d21cSmiao chen - Sun Microsystems - Beijing China 		}
18380035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: obj %p offset %08x target %d "
18390035d21cSmiao chen - Sun Microsystems - Beijing China 			 "read %08x write %08x gtt %08x "
18400035d21cSmiao chen - Sun Microsystems - Beijing China 			 "presumed %08x delta %08x\n",
18410035d21cSmiao chen - Sun Microsystems - Beijing China 			 __func__,
18420035d21cSmiao chen - Sun Microsystems - Beijing China 			 obj,
18430035d21cSmiao chen - Sun Microsystems - Beijing China 			 (int) reloc.offset,
18440035d21cSmiao chen - Sun Microsystems - Beijing China 			 (int) reloc.target_handle,
18450035d21cSmiao chen - Sun Microsystems - Beijing China 			 (int) reloc.read_domains,
18460035d21cSmiao chen - Sun Microsystems - Beijing China 			 (int) reloc.write_domain,
18470035d21cSmiao chen - Sun Microsystems - Beijing China 			 (int) target_obj_priv->gtt_offset,
18480035d21cSmiao chen - Sun Microsystems - Beijing China 			 (int) reloc.presumed_offset,
18490035d21cSmiao chen - Sun Microsystems - Beijing China 			 reloc.delta);
18500035d21cSmiao chen - Sun Microsystems - Beijing China 
18510035d21cSmiao chen - Sun Microsystems - Beijing China 		target_obj->pending_read_domains |= reloc.read_domains;
18520035d21cSmiao chen - Sun Microsystems - Beijing China 		target_obj->pending_write_domain |= reloc.write_domain;
18530035d21cSmiao chen - Sun Microsystems - Beijing China 
18540035d21cSmiao chen - Sun Microsystems - Beijing China 		/* If the relocation already has the right value in it, no
18550035d21cSmiao chen - Sun Microsystems - Beijing China 		 * more work needs to be done.
18560035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
18570035d21cSmiao chen - Sun Microsystems - Beijing China 		if (target_obj_priv->gtt_offset == reloc.presumed_offset) {
18580035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
18590035d21cSmiao chen - Sun Microsystems - Beijing China 			continue;
18600035d21cSmiao chen - Sun Microsystems - Beijing China 		}
18610035d21cSmiao chen - Sun Microsystems - Beijing China 
18620035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_object_set_to_gtt_domain(obj, 1);
18630035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
18640035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
18650035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
18660035d21cSmiao chen - Sun Microsystems - Beijing China 			return EINVAL;
18670035d21cSmiao chen - Sun Microsystems - Beijing China 		}
18680035d21cSmiao chen - Sun Microsystems - Beijing China 
18690035d21cSmiao chen - Sun Microsystems - Beijing China                /* Map the page containing the relocation we're going to
18700035d21cSmiao chen - Sun Microsystems - Beijing China                 * perform.
18710035d21cSmiao chen - Sun Microsystems - Beijing China                 */
18720035d21cSmiao chen - Sun Microsystems - Beijing China 
18730035d21cSmiao chen - Sun Microsystems - Beijing China 		int reloc_base = (reloc.offset & ~(PAGE_SIZE-1));
18740035d21cSmiao chen - Sun Microsystems - Beijing China 		reloc_offset = reloc.offset & (PAGE_SIZE-1);
18750035d21cSmiao chen - Sun Microsystems - Beijing China 		reloc_entry = (uint32_t *)(uintptr_t)(obj_priv->page_list[reloc_base/PAGE_SIZE] + reloc_offset);
18760035d21cSmiao chen - Sun Microsystems - Beijing China 		reloc_val = target_obj_priv->gtt_offset + reloc.delta;
18770035d21cSmiao chen - Sun Microsystems - Beijing China 		*reloc_entry = reloc_val;
18780035d21cSmiao chen - Sun Microsystems - Beijing China 
18790035d21cSmiao chen - Sun Microsystems - Beijing China 		/* Write the updated presumed offset for this entry back out
18800035d21cSmiao chen - Sun Microsystems - Beijing China 		 * to the user.
18810035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
18820035d21cSmiao chen - Sun Microsystems - Beijing China 		reloc.presumed_offset = target_obj_priv->gtt_offset;
18830035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = DRM_COPY_TO_USER(relocs + i, &reloc, sizeof(reloc));
18840035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
18850035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(target_obj);
18860035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(obj);
18870035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("%s: Failed to copy to user ret %d", __func__, ret);
18880035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
18890035d21cSmiao chen - Sun Microsystems - Beijing China 		}
18900035d21cSmiao chen - Sun Microsystems - Beijing China 
18910035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(target_obj);
18920035d21cSmiao chen - Sun Microsystems - Beijing China 	}
18930035d21cSmiao chen - Sun Microsystems - Beijing China 
18940035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
18950035d21cSmiao chen - Sun Microsystems - Beijing China }
18960035d21cSmiao chen - Sun Microsystems - Beijing China 
18970035d21cSmiao chen - Sun Microsystems - Beijing China /** Dispatch a batchbuffer to the ring
18980035d21cSmiao chen - Sun Microsystems - Beijing China  */
18990035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_dispatch_gem_execbuffer(struct drm_device * dev,struct drm_i915_gem_execbuffer * exec,uint64_t exec_offset)19000035d21cSmiao chen - Sun Microsystems - Beijing China i915_dispatch_gem_execbuffer(struct drm_device *dev,
19010035d21cSmiao chen - Sun Microsystems - Beijing China 			      struct drm_i915_gem_execbuffer *exec,
19020035d21cSmiao chen - Sun Microsystems - Beijing China 			      uint64_t exec_offset)
19030035d21cSmiao chen - Sun Microsystems - Beijing China {
19040035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
19050035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *)
19060035d21cSmiao chen - Sun Microsystems - Beijing China 					     (uintptr_t) exec->cliprects_ptr;
19070035d21cSmiao chen - Sun Microsystems - Beijing China 	int nbox = exec->num_cliprects;
19080035d21cSmiao chen - Sun Microsystems - Beijing China 	int i = 0, count;
19090035d21cSmiao chen - Sun Microsystems - Beijing China 	uint64_t	exec_start, exec_len;
19100035d21cSmiao chen - Sun Microsystems - Beijing China 	RING_LOCALS;
19110035d21cSmiao chen - Sun Microsystems - Beijing China 
19120035d21cSmiao chen - Sun Microsystems - Beijing China 	exec_start = exec_offset + exec->batch_start_offset;
19130035d21cSmiao chen - Sun Microsystems - Beijing China 	exec_len = exec->batch_len;
19140035d21cSmiao chen - Sun Microsystems - Beijing China 
19150035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((exec_start | exec_len) & 0x7) {
19160035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("alignment\n");
19170035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
19180035d21cSmiao chen - Sun Microsystems - Beijing China 	}
19190035d21cSmiao chen - Sun Microsystems - Beijing China 
19200035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!exec_start) {
19210035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("wrong arg");
19220035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
19230035d21cSmiao chen - Sun Microsystems - Beijing China 	}
19240035d21cSmiao chen - Sun Microsystems - Beijing China 
19250035d21cSmiao chen - Sun Microsystems - Beijing China 	count = nbox ? nbox : 1;
19260035d21cSmiao chen - Sun Microsystems - Beijing China 
19270035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = 0; i < count; i++) {
19280035d21cSmiao chen - Sun Microsystems - Beijing China 		if (i < nbox) {
19290035d21cSmiao chen - Sun Microsystems - Beijing China 			int ret = i915_emit_box(dev, boxes, i,
19300035d21cSmiao chen - Sun Microsystems - Beijing China 						exec->DR1, exec->DR4);
19310035d21cSmiao chen - Sun Microsystems - Beijing China 			if (ret) {
19320035d21cSmiao chen - Sun Microsystems - Beijing China 				DRM_ERROR("i915_emit_box %d DR1 0x%lx DRI2 0x%lx", ret, exec->DR1, exec->DR4);
19330035d21cSmiao chen - Sun Microsystems - Beijing China 				return ret;
19340035d21cSmiao chen - Sun Microsystems - Beijing China 			}
19350035d21cSmiao chen - Sun Microsystems - Beijing China 		}
19360035d21cSmiao chen - Sun Microsystems - Beijing China 		if (IS_I830(dev) || IS_845G(dev)) {
19370035d21cSmiao chen - Sun Microsystems - Beijing China 			BEGIN_LP_RING(4);
19380035d21cSmiao chen - Sun Microsystems - Beijing China 			OUT_RING(MI_BATCH_BUFFER);
19390035d21cSmiao chen - Sun Microsystems - Beijing China 			OUT_RING(exec_start | MI_BATCH_NON_SECURE);
19400035d21cSmiao chen - Sun Microsystems - Beijing China 			OUT_RING(exec_start + exec_len - 4);
19410035d21cSmiao chen - Sun Microsystems - Beijing China 			OUT_RING(0);
19420035d21cSmiao chen - Sun Microsystems - Beijing China 			ADVANCE_LP_RING();
19430035d21cSmiao chen - Sun Microsystems - Beijing China 		} else {
19440035d21cSmiao chen - Sun Microsystems - Beijing China 			BEGIN_LP_RING(2);
19450035d21cSmiao chen - Sun Microsystems - Beijing China 			if (IS_I965G(dev)) {
19460035d21cSmiao chen - Sun Microsystems - Beijing China 				OUT_RING(MI_BATCH_BUFFER_START |
19470035d21cSmiao chen - Sun Microsystems - Beijing China 					 (2 << 6) |
19480035d21cSmiao chen - Sun Microsystems - Beijing China 					 (3 << 9) |
19490035d21cSmiao chen - Sun Microsystems - Beijing China 					 MI_BATCH_NON_SECURE_I965);
19500035d21cSmiao chen - Sun Microsystems - Beijing China 				OUT_RING(exec_start);
19510035d21cSmiao chen - Sun Microsystems - Beijing China 
19520035d21cSmiao chen - Sun Microsystems - Beijing China 			} else {
19530035d21cSmiao chen - Sun Microsystems - Beijing China 				OUT_RING(MI_BATCH_BUFFER_START |
19540035d21cSmiao chen - Sun Microsystems - Beijing China 					 (2 << 6));
19550035d21cSmiao chen - Sun Microsystems - Beijing China 				OUT_RING(exec_start | MI_BATCH_NON_SECURE);
19560035d21cSmiao chen - Sun Microsystems - Beijing China 			}
19570035d21cSmiao chen - Sun Microsystems - Beijing China 			ADVANCE_LP_RING();
19580035d21cSmiao chen - Sun Microsystems - Beijing China 		}
19590035d21cSmiao chen - Sun Microsystems - Beijing China 	}
19600035d21cSmiao chen - Sun Microsystems - Beijing China 	/* XXX breadcrumb */
19610035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
19620035d21cSmiao chen - Sun Microsystems - Beijing China }
19630035d21cSmiao chen - Sun Microsystems - Beijing China 
19640035d21cSmiao chen - Sun Microsystems - Beijing China /* Throttle our rendering by waiting until the ring has completed our requests
19650035d21cSmiao chen - Sun Microsystems - Beijing China  * emitted over 20 msec ago.
19660035d21cSmiao chen - Sun Microsystems - Beijing China  *
19670035d21cSmiao chen - Sun Microsystems - Beijing China  * This should get us reasonable parallelism between CPU and GPU but also
19680035d21cSmiao chen - Sun Microsystems - Beijing China  * relatively low latency when blocking on a particular request to finish.
19690035d21cSmiao chen - Sun Microsystems - Beijing China  */
19700035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_ring_throttle(struct drm_device * dev,struct drm_file * file_priv)19710035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
19720035d21cSmiao chen - Sun Microsystems - Beijing China {
19730035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
19740035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0;
19750035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t seqno;
19760035d21cSmiao chen - Sun Microsystems - Beijing China 
19770035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
19780035d21cSmiao chen - Sun Microsystems - Beijing China 	seqno = i915_file_priv->mm.last_gem_throttle_seqno;
19790035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_file_priv->mm.last_gem_throttle_seqno =
19800035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_file_priv->mm.last_gem_seqno;
19810035d21cSmiao chen - Sun Microsystems - Beijing China 	if (seqno) {
19820035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_wait_request(dev, seqno);
19830035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0)
19840035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("%s: i915_wait_request request->seqno %d now %d\n", __func__, seqno, i915_get_gem_seqno(dev));
19850035d21cSmiao chen - Sun Microsystems - Beijing China 	}
19860035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
19870035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
19880035d21cSmiao chen - Sun Microsystems - Beijing China }
19890035d21cSmiao chen - Sun Microsystems - Beijing China 
19900035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
19910035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_execbuffer(DRM_IOCTL_ARGS)19920035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_execbuffer(DRM_IOCTL_ARGS)
19930035d21cSmiao chen - Sun Microsystems - Beijing China {
19940035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
19950035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
19960035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_file_private *i915_file_priv = fpriv->driver_priv;
19970035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_execbuffer args;
19980035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_exec_object *exec_list = NULL;
19990035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object **object_list = NULL;
20000035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *batch_obj;
20010035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
20020035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0, i, pinned = 0;
20030035d21cSmiao chen - Sun Microsystems - Beijing China 	uint64_t exec_offset;
20040035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t seqno, flush_domains;
20050035d21cSmiao chen - Sun Microsystems - Beijing China 	int pin_tries;
20060035d21cSmiao chen - Sun Microsystems - Beijing China 
20070035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
20080035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
20090035d21cSmiao chen - Sun Microsystems - Beijing China 
20100035d21cSmiao chen - Sun Microsystems - Beijing China         DRM_COPYFROM_WITH_RETURN(&args,
20110035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_execbuffer __user *) data, sizeof(args));
20120035d21cSmiao chen - Sun Microsystems - Beijing China 
20130035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("buffer_count %d len %x\n", args.buffer_count, args.batch_len);
20140035d21cSmiao chen - Sun Microsystems - Beijing China 
20150035d21cSmiao chen - Sun Microsystems - Beijing China 	if (args.buffer_count < 1) {
20160035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("execbuf with %d buffers\n", args.buffer_count);
20170035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
20180035d21cSmiao chen - Sun Microsystems - Beijing China 	}
20190035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Copy in the exec list from userland */
20200035d21cSmiao chen - Sun Microsystems - Beijing China 	exec_list = drm_calloc(sizeof(*exec_list), args.buffer_count,
20210035d21cSmiao chen - Sun Microsystems - Beijing China 			       DRM_MEM_DRIVER);
20220035d21cSmiao chen - Sun Microsystems - Beijing China 	object_list = drm_calloc(sizeof(*object_list), args.buffer_count,
20230035d21cSmiao chen - Sun Microsystems - Beijing China 				 DRM_MEM_DRIVER);
20240035d21cSmiao chen - Sun Microsystems - Beijing China 	if (exec_list == NULL || object_list == NULL) {
20250035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to allocate exec or object list "
20260035d21cSmiao chen - Sun Microsystems - Beijing China 			  "for %d buffers\n",
20270035d21cSmiao chen - Sun Microsystems - Beijing China 			  args.buffer_count);
20280035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = ENOMEM;
20290035d21cSmiao chen - Sun Microsystems - Beijing China 		goto pre_mutex_err;
20300035d21cSmiao chen - Sun Microsystems - Beijing China 	}
20310035d21cSmiao chen - Sun Microsystems - Beijing China 
20320035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = DRM_COPY_FROM_USER(exec_list,
20330035d21cSmiao chen - Sun Microsystems - Beijing China 			     (struct drm_i915_gem_exec_object __user *)
20340035d21cSmiao chen - Sun Microsystems - Beijing China 			     (uintptr_t) args.buffers_ptr,
20350035d21cSmiao chen - Sun Microsystems - Beijing China 			     sizeof(*exec_list) * args.buffer_count);
20360035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0) {
20370035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("copy %d exec entries failed %d\n",
20380035d21cSmiao chen - Sun Microsystems - Beijing China 			  args.buffer_count, ret);
20390035d21cSmiao chen - Sun Microsystems - Beijing China 		goto pre_mutex_err;
20400035d21cSmiao chen - Sun Microsystems - Beijing China 	}
20410035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
20420035d21cSmiao chen - Sun Microsystems - Beijing China 
20430035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->mm.wedged) {
20440035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Execbuf while wedged\n");
20450035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
20460035d21cSmiao chen - Sun Microsystems - Beijing China 		return EIO;
20470035d21cSmiao chen - Sun Microsystems - Beijing China 	}
20480035d21cSmiao chen - Sun Microsystems - Beijing China 
20490035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->mm.suspended) {
20500035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Execbuf while VT-switched.\n");
20510035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
20520035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBUSY;
20530035d21cSmiao chen - Sun Microsystems - Beijing China 	}
20540035d21cSmiao chen - Sun Microsystems - Beijing China 
20550035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Look up object handles */
20560035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = 0; i < args.buffer_count; i++) {
20570035d21cSmiao chen - Sun Microsystems - Beijing China 		object_list[i] = drm_gem_object_lookup(fpriv,
20580035d21cSmiao chen - Sun Microsystems - Beijing China 						       exec_list[i].handle);
20590035d21cSmiao chen - Sun Microsystems - Beijing China 		if (object_list[i] == NULL) {
20600035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Invalid object handle %d at index %d\n",
20610035d21cSmiao chen - Sun Microsystems - Beijing China 				   exec_list[i].handle, i);
20620035d21cSmiao chen - Sun Microsystems - Beijing China 			ret = EBADF;
20630035d21cSmiao chen - Sun Microsystems - Beijing China 			goto err;
20640035d21cSmiao chen - Sun Microsystems - Beijing China 		}
20650035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv = object_list[i]->driver_private;
20660035d21cSmiao chen - Sun Microsystems - Beijing China 		if (obj_priv->in_execbuffer) {
20670035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Object[%d] (%d) %p appears more than once in object list in args.buffer_count %d \n",
20680035d21cSmiao chen - Sun Microsystems - Beijing China 				   i, object_list[i]->name, object_list[i], args.buffer_count);
20690035d21cSmiao chen - Sun Microsystems - Beijing China 
20700035d21cSmiao chen - Sun Microsystems - Beijing China 			ret = EBADF;
20710035d21cSmiao chen - Sun Microsystems - Beijing China 			goto err;
20720035d21cSmiao chen - Sun Microsystems - Beijing China 		}
20730035d21cSmiao chen - Sun Microsystems - Beijing China 
20740035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->in_execbuffer = 1;
20750035d21cSmiao chen - Sun Microsystems - Beijing China 	}
20760035d21cSmiao chen - Sun Microsystems - Beijing China 
20770035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Pin and relocate */
20780035d21cSmiao chen - Sun Microsystems - Beijing China 	for (pin_tries = 0; ; pin_tries++) {
20790035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = 0;
20800035d21cSmiao chen - Sun Microsystems - Beijing China 		for (i = 0; i < args.buffer_count; i++) {
20810035d21cSmiao chen - Sun Microsystems - Beijing China 			object_list[i]->pending_read_domains = 0;
20820035d21cSmiao chen - Sun Microsystems - Beijing China 			object_list[i]->pending_write_domain = 0;
20830035d21cSmiao chen - Sun Microsystems - Beijing China 			ret = i915_gem_object_pin_and_relocate(object_list[i],
20840035d21cSmiao chen - Sun Microsystems - Beijing China 							       fpriv,
20850035d21cSmiao chen - Sun Microsystems - Beijing China 							       &exec_list[i]);
20860035d21cSmiao chen - Sun Microsystems - Beijing China 			if (ret) {
20870035d21cSmiao chen - Sun Microsystems - Beijing China 				DRM_ERROR("Not all object pinned");
20880035d21cSmiao chen - Sun Microsystems - Beijing China 				break;
20890035d21cSmiao chen - Sun Microsystems - Beijing China 			}
20900035d21cSmiao chen - Sun Microsystems - Beijing China 			pinned = i + 1;
20910035d21cSmiao chen - Sun Microsystems - Beijing China 		}
20920035d21cSmiao chen - Sun Microsystems - Beijing China 		/* success */
20930035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret == 0)
20940035d21cSmiao chen - Sun Microsystems - Beijing China 		{
20950035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("gem_execbuffer pin_relocate success");
20960035d21cSmiao chen - Sun Microsystems - Beijing China 			break;
20970035d21cSmiao chen - Sun Microsystems - Beijing China 		}
20980035d21cSmiao chen - Sun Microsystems - Beijing China 		/* error other than GTT full, or we've already tried again */
20990035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != ENOMEM || pin_tries >= 1) {
21000035d21cSmiao chen - Sun Microsystems - Beijing China 			if (ret != ERESTART)
21010035d21cSmiao chen - Sun Microsystems - Beijing China 				DRM_ERROR("Failed to pin buffers %d\n", ret);
21020035d21cSmiao chen - Sun Microsystems - Beijing China 			goto err;
21030035d21cSmiao chen - Sun Microsystems - Beijing China 		}
21040035d21cSmiao chen - Sun Microsystems - Beijing China 
21050035d21cSmiao chen - Sun Microsystems - Beijing China 		/* unpin all of our buffers */
21060035d21cSmiao chen - Sun Microsystems - Beijing China 		for (i = 0; i < pinned; i++)
21070035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(object_list[i]);
21080035d21cSmiao chen - Sun Microsystems - Beijing China 		pinned = 0;
21090035d21cSmiao chen - Sun Microsystems - Beijing China 
21100035d21cSmiao chen - Sun Microsystems - Beijing China 		/* evict everyone we can from the aperture */
21110035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_evict_everything(dev);
21120035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret)
21130035d21cSmiao chen - Sun Microsystems - Beijing China 			goto err;
21140035d21cSmiao chen - Sun Microsystems - Beijing China 	}
21150035d21cSmiao chen - Sun Microsystems - Beijing China 
21160035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Set the pending read domains for the batch buffer to COMMAND */
21170035d21cSmiao chen - Sun Microsystems - Beijing China 	batch_obj = object_list[args.buffer_count-1];
21180035d21cSmiao chen - Sun Microsystems - Beijing China 	batch_obj->pending_read_domains = I915_GEM_DOMAIN_COMMAND;
21190035d21cSmiao chen - Sun Microsystems - Beijing China 	batch_obj->pending_write_domain = 0;
21200035d21cSmiao chen - Sun Microsystems - Beijing China 
21210035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Zero the gloabl flush/invalidate flags. These
21220035d21cSmiao chen - Sun Microsystems - Beijing China 	 * will be modified as each object is bound to the
21230035d21cSmiao chen - Sun Microsystems - Beijing China 	 * gtt
21240035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
21250035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->invalidate_domains = 0;
21260035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->flush_domains = 0;
21270035d21cSmiao chen - Sun Microsystems - Beijing China 
21280035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = 0; i < args.buffer_count; i++) {
21290035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_gem_object *obj = object_list[i];
21300035d21cSmiao chen - Sun Microsystems - Beijing China 
21310035d21cSmiao chen - Sun Microsystems - Beijing China 		/* Compute new gpu domains and update invalidate/flush */
21320035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_set_to_gpu_domain(obj,
21330035d21cSmiao chen - Sun Microsystems - Beijing China 						  obj->pending_read_domains,
21340035d21cSmiao chen - Sun Microsystems - Beijing China 						  obj->pending_write_domain);
21350035d21cSmiao chen - Sun Microsystems - Beijing China 	}
21360035d21cSmiao chen - Sun Microsystems - Beijing China 
21370035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->invalidate_domains | dev->flush_domains) {
21380035d21cSmiao chen - Sun Microsystems - Beijing China 
21390035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: invalidate_domains %08x flush_domains %08x Then flush\n",
21400035d21cSmiao chen - Sun Microsystems - Beijing China 			  __func__,
21410035d21cSmiao chen - Sun Microsystems - Beijing China 			 dev->invalidate_domains,
21420035d21cSmiao chen - Sun Microsystems - Beijing China 			 dev->flush_domains);
21430035d21cSmiao chen - Sun Microsystems - Beijing China                 i915_gem_flush(dev,
21440035d21cSmiao chen - Sun Microsystems - Beijing China                                dev->invalidate_domains,
21450035d21cSmiao chen - Sun Microsystems - Beijing China                                dev->flush_domains);
21460035d21cSmiao chen - Sun Microsystems - Beijing China                 if (dev->flush_domains) {
21470035d21cSmiao chen - Sun Microsystems - Beijing China                         (void) i915_add_request(dev, dev->flush_domains);
21480035d21cSmiao chen - Sun Microsystems - Beijing China 
21490035d21cSmiao chen - Sun Microsystems - Beijing China 		}
21500035d21cSmiao chen - Sun Microsystems - Beijing China 	}
21510035d21cSmiao chen - Sun Microsystems - Beijing China 
21520035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = 0; i < args.buffer_count; i++) {
21530035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_gem_object *obj = object_list[i];
21540035d21cSmiao chen - Sun Microsystems - Beijing China 
21550035d21cSmiao chen - Sun Microsystems - Beijing China 		obj->write_domain = obj->pending_write_domain;
21560035d21cSmiao chen - Sun Microsystems - Beijing China 	}
21570035d21cSmiao chen - Sun Microsystems - Beijing China 
21580035d21cSmiao chen - Sun Microsystems - Beijing China 	exec_offset = exec_list[args.buffer_count - 1].offset;
21590035d21cSmiao chen - Sun Microsystems - Beijing China 
21600035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Exec the batchbuffer */
21610035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_dispatch_gem_execbuffer(dev, &args, exec_offset);
21620035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
21630035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("dispatch failed %d\n", ret);
21640035d21cSmiao chen - Sun Microsystems - Beijing China 		goto err;
21650035d21cSmiao chen - Sun Microsystems - Beijing China 	}
21660035d21cSmiao chen - Sun Microsystems - Beijing China 
21670035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
21680035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Ensure that the commands in the batch buffer are
21690035d21cSmiao chen - Sun Microsystems - Beijing China 	 * finished before the interrupt fires
21700035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
21710035d21cSmiao chen - Sun Microsystems - Beijing China 	flush_domains = i915_retire_commands(dev);
21720035d21cSmiao chen - Sun Microsystems - Beijing China 
21730035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
21740035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Get a seqno representing the execution of the current buffer,
21750035d21cSmiao chen - Sun Microsystems - Beijing China 	 * which we can wait on.  We would like to mitigate these interrupts,
21760035d21cSmiao chen - Sun Microsystems - Beijing China 	 * likely by only creating seqnos occasionally (so that we have
21770035d21cSmiao chen - Sun Microsystems - Beijing China 	 * *some* interrupts representing completion of buffers that we can
21780035d21cSmiao chen - Sun Microsystems - Beijing China 	 * wait on when trying to clear up gtt space).
21790035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
21800035d21cSmiao chen - Sun Microsystems - Beijing China 	seqno = i915_add_request(dev, flush_domains);
21810035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!(seqno == 0));
21820035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_file_priv->mm.last_gem_seqno = seqno;
21830035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = 0; i < args.buffer_count; i++) {
21840035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_gem_object *obj = object_list[i];
21850035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_move_to_active(obj, seqno);
21860035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: move to exec list %p\n", __func__, obj);
21870035d21cSmiao chen - Sun Microsystems - Beijing China 	}
21880035d21cSmiao chen - Sun Microsystems - Beijing China 
21890035d21cSmiao chen - Sun Microsystems - Beijing China err:
21900035d21cSmiao chen - Sun Microsystems - Beijing China 	if (object_list != NULL) {
21910035d21cSmiao chen - Sun Microsystems - Beijing China 		for (i = 0; i < pinned; i++)
21920035d21cSmiao chen - Sun Microsystems - Beijing China 			i915_gem_object_unpin(object_list[i]);
21930035d21cSmiao chen - Sun Microsystems - Beijing China 
21940035d21cSmiao chen - Sun Microsystems - Beijing China 		for (i = 0; i < args.buffer_count; i++) {
21950035d21cSmiao chen - Sun Microsystems - Beijing China 			if (object_list[i]) {
21960035d21cSmiao chen - Sun Microsystems - Beijing China 				obj_priv = object_list[i]->driver_private;
21970035d21cSmiao chen - Sun Microsystems - Beijing China 				obj_priv->in_execbuffer = 0;
21980035d21cSmiao chen - Sun Microsystems - Beijing China 			}
21990035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(object_list[i]);
22000035d21cSmiao chen - Sun Microsystems - Beijing China 		}
22010035d21cSmiao chen - Sun Microsystems - Beijing China 	}
22020035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
22030035d21cSmiao chen - Sun Microsystems - Beijing China 
22040035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!ret) {
22050035d21cSmiao chen - Sun Microsystems - Beijing China 	        /* Copy the new buffer offsets back to the user's exec list. */
22060035d21cSmiao chen - Sun Microsystems - Beijing China 	        ret = DRM_COPY_TO_USER((struct drm_i915_relocation_entry __user *)
22070035d21cSmiao chen - Sun Microsystems - Beijing China 	                           (uintptr_t) args.buffers_ptr,
22080035d21cSmiao chen - Sun Microsystems - Beijing China 	                           exec_list,
22090035d21cSmiao chen - Sun Microsystems - Beijing China 	                           sizeof(*exec_list) * args.buffer_count);
22100035d21cSmiao chen - Sun Microsystems - Beijing China 	        if (ret)
22110035d21cSmiao chen - Sun Microsystems - Beijing China 	                DRM_ERROR("failed to copy %d exec entries "
22120035d21cSmiao chen - Sun Microsystems - Beijing China 	                          "back to user (%d)\n",
22130035d21cSmiao chen - Sun Microsystems - Beijing China 	                           args.buffer_count, ret);
22140035d21cSmiao chen - Sun Microsystems - Beijing China 	}
22150035d21cSmiao chen - Sun Microsystems - Beijing China 
22160035d21cSmiao chen - Sun Microsystems - Beijing China pre_mutex_err:
22170035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_free(object_list, sizeof(*object_list) * args.buffer_count,
22180035d21cSmiao chen - Sun Microsystems - Beijing China 		 DRM_MEM_DRIVER);
22190035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_free(exec_list, sizeof(*exec_list) * args.buffer_count,
22200035d21cSmiao chen - Sun Microsystems - Beijing China 		 DRM_MEM_DRIVER);
22210035d21cSmiao chen - Sun Microsystems - Beijing China 
22220035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
22230035d21cSmiao chen - Sun Microsystems - Beijing China }
22240035d21cSmiao chen - Sun Microsystems - Beijing China 
22250035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_object_pin(struct drm_gem_object * obj,uint32_t alignment)22260035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
22270035d21cSmiao chen - Sun Microsystems - Beijing China {
22280035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
22290035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
22300035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
22310035d21cSmiao chen - Sun Microsystems - Beijing China 
22320035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->gtt_space == NULL) {
22330035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_object_bind_to_gtt(obj, alignment);
22340035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
22350035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Failure to bind: %d", ret);
22360035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
22370035d21cSmiao chen - Sun Microsystems - Beijing China 		}
22380035d21cSmiao chen - Sun Microsystems - Beijing China 	}
22390035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->pin_count++;
22400035d21cSmiao chen - Sun Microsystems - Beijing China 
22410035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If the object is not active and not pending a flush,
22420035d21cSmiao chen - Sun Microsystems - Beijing China 	 * remove it from the inactive list
22430035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
22440035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->pin_count == 1) {
22450035d21cSmiao chen - Sun Microsystems - Beijing China 		atomic_inc(&dev->pin_count);
22460035d21cSmiao chen - Sun Microsystems - Beijing China 		atomic_add(obj->size, &dev->pin_memory);
22470035d21cSmiao chen - Sun Microsystems - Beijing China 		if (!obj_priv->active &&
22480035d21cSmiao chen - Sun Microsystems - Beijing China 		    (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
22490035d21cSmiao chen - Sun Microsystems - Beijing China 					   I915_GEM_DOMAIN_GTT)) == 0 &&
22500035d21cSmiao chen - Sun Microsystems - Beijing China 		    !list_empty(&obj_priv->list))
22510035d21cSmiao chen - Sun Microsystems - Beijing China 			list_del_init(&obj_priv->list);
22520035d21cSmiao chen - Sun Microsystems - Beijing China 	}
22530035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
22540035d21cSmiao chen - Sun Microsystems - Beijing China }
22550035d21cSmiao chen - Sun Microsystems - Beijing China 
22560035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_gem_object_unpin(struct drm_gem_object * obj)22570035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_unpin(struct drm_gem_object *obj)
22580035d21cSmiao chen - Sun Microsystems - Beijing China {
22590035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_device *dev = obj->dev;
22600035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
22610035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
22620035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->pin_count--;
22630035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!(obj_priv->pin_count < 0));
22640035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(!(obj_priv->gtt_space == NULL));
22650035d21cSmiao chen - Sun Microsystems - Beijing China 
22660035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If the object is no longer pinned, and is
22670035d21cSmiao chen - Sun Microsystems - Beijing China 	 * neither active nor being flushed, then stick it on
22680035d21cSmiao chen - Sun Microsystems - Beijing China 	 * the inactive list
22690035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
22700035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->pin_count == 0) {
22710035d21cSmiao chen - Sun Microsystems - Beijing China 		if (!obj_priv->active &&
22720035d21cSmiao chen - Sun Microsystems - Beijing China 		    (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
22730035d21cSmiao chen - Sun Microsystems - Beijing China 					   I915_GEM_DOMAIN_GTT)) == 0)
22740035d21cSmiao chen - Sun Microsystems - Beijing China 			list_move_tail(&obj_priv->list,
22750035d21cSmiao chen - Sun Microsystems - Beijing China 				       &dev_priv->mm.inactive_list, (caddr_t)obj_priv);
22760035d21cSmiao chen - Sun Microsystems - Beijing China 		atomic_dec(&dev->pin_count);
22770035d21cSmiao chen - Sun Microsystems - Beijing China 		atomic_sub(obj->size, &dev->pin_memory);
22780035d21cSmiao chen - Sun Microsystems - Beijing China 	}
22790035d21cSmiao chen - Sun Microsystems - Beijing China }
22800035d21cSmiao chen - Sun Microsystems - Beijing China 
22810035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
22820035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_pin_ioctl(DRM_IOCTL_ARGS)22830035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_pin_ioctl(DRM_IOCTL_ARGS)
22840035d21cSmiao chen - Sun Microsystems - Beijing China {
22850035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
22860035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_pin args;
22870035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
22880035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
22890035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
22900035d21cSmiao chen - Sun Microsystems - Beijing China 
22910035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
22920035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
22930035d21cSmiao chen - Sun Microsystems - Beijing China 
22940035d21cSmiao chen - Sun Microsystems - Beijing China         DRM_COPYFROM_WITH_RETURN(&args,
22950035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_pin __user *) data, sizeof(args));
22960035d21cSmiao chen - Sun Microsystems - Beijing China 
22970035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
22980035d21cSmiao chen - Sun Microsystems - Beijing China 
22990035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
23000035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL) {
23010035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n",
23020035d21cSmiao chen - Sun Microsystems - Beijing China 			  args.handle);
23030035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
23040035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
23050035d21cSmiao chen - Sun Microsystems - Beijing China 	}
23060035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_pin_ioctl obj->name %d", obj->name);
23070035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = obj->driver_private;
23080035d21cSmiao chen - Sun Microsystems - Beijing China 
23090035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != fpriv) {
23100035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
23110035d21cSmiao chen - Sun Microsystems - Beijing China 			  args.handle);
23120035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
23130035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
23140035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
23150035d21cSmiao chen - Sun Microsystems - Beijing China 	}
23160035d21cSmiao chen - Sun Microsystems - Beijing China 
23170035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->user_pin_count++;
23180035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->pin_filp = fpriv;
23190035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->user_pin_count == 1) {
23200035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_object_pin(obj, args.alignment);
23210035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
23220035d21cSmiao chen - Sun Microsystems - Beijing China 			drm_gem_object_unreference(obj);
23230035d21cSmiao chen - Sun Microsystems - Beijing China 			spin_unlock(&dev->struct_mutex);
23240035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
23250035d21cSmiao chen - Sun Microsystems - Beijing China 		}
23260035d21cSmiao chen - Sun Microsystems - Beijing China 	}
23270035d21cSmiao chen - Sun Microsystems - Beijing China 
23280035d21cSmiao chen - Sun Microsystems - Beijing China 	/* XXX - flush the CPU caches for pinned objects
23290035d21cSmiao chen - Sun Microsystems - Beijing China 	 * as the X server doesn't manage domains yet
23300035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
23310035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_flush_cpu_write_domain(obj);
23320035d21cSmiao chen - Sun Microsystems - Beijing China 	args.offset = obj_priv->gtt_offset;
23330035d21cSmiao chen - Sun Microsystems - Beijing China 
23340035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = DRM_COPY_TO_USER((struct drm_i915_gem_pin __user *) data, &args, sizeof(args));
23350035d21cSmiao chen - Sun Microsystems - Beijing China 	if ( ret != 0)
23360035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR(" gem pin ioctl error! %d", ret);
23370035d21cSmiao chen - Sun Microsystems - Beijing China 
23380035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
23390035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
23400035d21cSmiao chen - Sun Microsystems - Beijing China 
23410035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
23420035d21cSmiao chen - Sun Microsystems - Beijing China }
23430035d21cSmiao chen - Sun Microsystems - Beijing China 
23440035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
23450035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_unpin_ioctl(DRM_IOCTL_ARGS)23460035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_unpin_ioctl(DRM_IOCTL_ARGS)
23470035d21cSmiao chen - Sun Microsystems - Beijing China {
23480035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
23490035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_pin args;
23500035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
23510035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
23520035d21cSmiao chen - Sun Microsystems - Beijing China 
23530035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
23540035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
23550035d21cSmiao chen - Sun Microsystems - Beijing China 
23560035d21cSmiao chen - Sun Microsystems - Beijing China         DRM_COPYFROM_WITH_RETURN(&args,
23570035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_pin __user *) data, sizeof(args));
23580035d21cSmiao chen - Sun Microsystems - Beijing China 
23590035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
23600035d21cSmiao chen - Sun Microsystems - Beijing China 
23610035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
23620035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL) {
23630035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n",
23640035d21cSmiao chen - Sun Microsystems - Beijing China 			  args.handle);
23650035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
23660035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
23670035d21cSmiao chen - Sun Microsystems - Beijing China 	}
23680035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = obj->driver_private;
23690035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_unpin_ioctl, obj->name %d", obj->name);
23700035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->pin_filp != fpriv) {
23710035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
23720035d21cSmiao chen - Sun Microsystems - Beijing China 			  args.handle);
23730035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
23740035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
23750035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
23760035d21cSmiao chen - Sun Microsystems - Beijing China 	}
23770035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->user_pin_count--;
23780035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->user_pin_count == 0) {
23790035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->pin_filp = NULL;
23800035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_unpin(obj);
23810035d21cSmiao chen - Sun Microsystems - Beijing China 	}
23820035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
23830035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
23840035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
23850035d21cSmiao chen - Sun Microsystems - Beijing China }
23860035d21cSmiao chen - Sun Microsystems - Beijing China 
23870035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
23880035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_busy_ioctl(DRM_IOCTL_ARGS)23890035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_busy_ioctl(DRM_IOCTL_ARGS)
23900035d21cSmiao chen - Sun Microsystems - Beijing China {
23910035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
23920035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_busy args;
23930035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
23940035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
23950035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
23960035d21cSmiao chen - Sun Microsystems - Beijing China 
23970035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
23980035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
23990035d21cSmiao chen - Sun Microsystems - Beijing China 
24000035d21cSmiao chen - Sun Microsystems - Beijing China         DRM_COPYFROM_WITH_RETURN(&args,
24010035d21cSmiao chen - Sun Microsystems - Beijing China             (struct drm_i915_gem_busy __user *) data, sizeof(args));
24020035d21cSmiao chen - Sun Microsystems - Beijing China 
24030035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
24040035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_lookup(fpriv, args.handle);
24050035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL) {
24060035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
24070035d21cSmiao chen - Sun Microsystems - Beijing China 			  args.handle);
24080035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
24090035d21cSmiao chen - Sun Microsystems - Beijing China 		return EBADF;
24100035d21cSmiao chen - Sun Microsystems - Beijing China 	}
24110035d21cSmiao chen - Sun Microsystems - Beijing China 
24120035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = obj->driver_private;
24130035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Don't count being on the flushing list against the object being
24140035d21cSmiao chen - Sun Microsystems - Beijing China 	 * done.  Otherwise, a buffer left on the flushing list but not getting
24150035d21cSmiao chen - Sun Microsystems - Beijing China 	 * flushed (because nobody's flushing that domain) won't ever return
24160035d21cSmiao chen - Sun Microsystems - Beijing China 	 * unbusy and get reused by libdrm's bo cache.  The other expected
24170035d21cSmiao chen - Sun Microsystems - Beijing China 	 * consumer of this interface, OpenGL's occlusion queries, also specs
24180035d21cSmiao chen - Sun Microsystems - Beijing China 	 * that the objects get unbusy "eventually" without any interference.
24190035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
24200035d21cSmiao chen - Sun Microsystems - Beijing China 	args.busy = obj_priv->active && obj_priv->last_rendering_seqno != 0;
24210035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_gem_busy_ioctl call obj->name %d busy %d", obj->name, args.busy);
24220035d21cSmiao chen - Sun Microsystems - Beijing China 
24230035d21cSmiao chen - Sun Microsystems - Beijing China         ret = DRM_COPY_TO_USER((struct drm_i915_gem_busy __user *) data, &args, sizeof(args));
24240035d21cSmiao chen - Sun Microsystems - Beijing China         if ( ret != 0)
24250035d21cSmiao chen - Sun Microsystems - Beijing China                 DRM_ERROR(" gem busy error! %d", ret);
24260035d21cSmiao chen - Sun Microsystems - Beijing China 
24270035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
24280035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
24290035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
24300035d21cSmiao chen - Sun Microsystems - Beijing China }
24310035d21cSmiao chen - Sun Microsystems - Beijing China 
24320035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
24330035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_throttle_ioctl(DRM_IOCTL_ARGS)24340035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_throttle_ioctl(DRM_IOCTL_ARGS)
24350035d21cSmiao chen - Sun Microsystems - Beijing China {
24360035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
24370035d21cSmiao chen - Sun Microsystems - Beijing China 
24380035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
24390035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
24400035d21cSmiao chen - Sun Microsystems - Beijing China 
24410035d21cSmiao chen - Sun Microsystems - Beijing China 	return i915_gem_ring_throttle(dev, fpriv);
24420035d21cSmiao chen - Sun Microsystems - Beijing China }
24430035d21cSmiao chen - Sun Microsystems - Beijing China 
24440035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_object_get_page_list(struct drm_gem_object * obj)24450035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_object_get_page_list(struct drm_gem_object *obj)
24460035d21cSmiao chen - Sun Microsystems - Beijing China {
24470035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
24480035d21cSmiao chen - Sun Microsystems - Beijing China         caddr_t va;
24490035d21cSmiao chen - Sun Microsystems - Beijing China         long i;
24500035d21cSmiao chen - Sun Microsystems - Beijing China 
24510035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->page_list)
24520035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
24530035d21cSmiao chen - Sun Microsystems - Beijing China         pgcnt_t np = btop(obj->size);
24540035d21cSmiao chen - Sun Microsystems - Beijing China 
24550035d21cSmiao chen - Sun Microsystems - Beijing China         obj_priv->page_list = kmem_zalloc(np * sizeof(caddr_t), KM_SLEEP);
24560035d21cSmiao chen - Sun Microsystems - Beijing China         if (obj_priv->page_list == NULL) {
24570035d21cSmiao chen - Sun Microsystems - Beijing China                 DRM_ERROR("Faled to allocate page list\n");
24580035d21cSmiao chen - Sun Microsystems - Beijing China                 return ENOMEM;
24590035d21cSmiao chen - Sun Microsystems - Beijing China         }
24600035d21cSmiao chen - Sun Microsystems - Beijing China 
24610035d21cSmiao chen - Sun Microsystems - Beijing China 	for (i = 0, va = obj->kaddr; i < np; i++, va += PAGESIZE) {
24620035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->page_list[i] = va;
24630035d21cSmiao chen - Sun Microsystems - Beijing China 	}
24640035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
24650035d21cSmiao chen - Sun Microsystems - Beijing China }
24660035d21cSmiao chen - Sun Microsystems - Beijing China 
24670035d21cSmiao chen - Sun Microsystems - Beijing China 
i915_gem_init_object(struct drm_gem_object * obj)24680035d21cSmiao chen - Sun Microsystems - Beijing China int i915_gem_init_object(struct drm_gem_object *obj)
24690035d21cSmiao chen - Sun Microsystems - Beijing China {
24700035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
24710035d21cSmiao chen - Sun Microsystems - Beijing China 
24720035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
24730035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv == NULL)
24740035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENOMEM;
24750035d21cSmiao chen - Sun Microsystems - Beijing China 
24760035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
24770035d21cSmiao chen - Sun Microsystems - Beijing China 	 * We've just allocated pages from the kernel,
24780035d21cSmiao chen - Sun Microsystems - Beijing China 	 * so they've just been written by the CPU with
24790035d21cSmiao chen - Sun Microsystems - Beijing China 	 * zeros. They'll need to be clflushed before we
24800035d21cSmiao chen - Sun Microsystems - Beijing China 	 * use them with the GPU.
24810035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
24820035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->write_domain = I915_GEM_DOMAIN_CPU;
24830035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->read_domains = I915_GEM_DOMAIN_CPU;
24840035d21cSmiao chen - Sun Microsystems - Beijing China 
24850035d21cSmiao chen - Sun Microsystems - Beijing China 	obj->driver_private = obj_priv;
24860035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv->obj = obj;
24870035d21cSmiao chen - Sun Microsystems - Beijing China 	INIT_LIST_HEAD(&obj_priv->list);
24880035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
24890035d21cSmiao chen - Sun Microsystems - Beijing China }
24900035d21cSmiao chen - Sun Microsystems - Beijing China 
i915_gem_free_object(struct drm_gem_object * obj)24910035d21cSmiao chen - Sun Microsystems - Beijing China void i915_gem_free_object(struct drm_gem_object *obj)
24920035d21cSmiao chen - Sun Microsystems - Beijing China {
24930035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
24940035d21cSmiao chen - Sun Microsystems - Beijing China 
24950035d21cSmiao chen - Sun Microsystems - Beijing China 	while (obj_priv->pin_count > 0)
24960035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_unpin(obj);
24970035d21cSmiao chen - Sun Microsystems - Beijing China 
24980035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("%s: obj %d",__func__, obj->name);
24990035d21cSmiao chen - Sun Microsystems - Beijing China 
25000035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) i915_gem_object_unbind(obj, 1);
25010035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj_priv->page_cpu_valid != NULL)
25020035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE, DRM_MEM_DRIVER);
25030035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_free(obj->driver_private, sizeof(*obj_priv), DRM_MEM_DRIVER);
25040035d21cSmiao chen - Sun Microsystems - Beijing China }
25050035d21cSmiao chen - Sun Microsystems - Beijing China 
25060035d21cSmiao chen - Sun Microsystems - Beijing China /** Unbinds all objects that are on the given buffer list. */
25070035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_evict_from_list(struct drm_device * dev,struct list_head * head,uint32_t type)25080035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head, uint32_t type)
25090035d21cSmiao chen - Sun Microsystems - Beijing China {
25100035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
25110035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
25120035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
25130035d21cSmiao chen - Sun Microsystems - Beijing China 
25140035d21cSmiao chen - Sun Microsystems - Beijing China 	while (!list_empty(head)) {
25150035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv = list_entry(head->next,
25160035d21cSmiao chen - Sun Microsystems - Beijing China 				struct drm_i915_gem_object,
25170035d21cSmiao chen - Sun Microsystems - Beijing China 			    	list);
25180035d21cSmiao chen - Sun Microsystems - Beijing China 		obj = obj_priv->obj;
25190035d21cSmiao chen - Sun Microsystems - Beijing China 
25200035d21cSmiao chen - Sun Microsystems - Beijing China 		if (obj_priv->pin_count != 0) {
25210035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Pinned object in unbind list\n");
25220035d21cSmiao chen - Sun Microsystems - Beijing China 			spin_unlock(&dev->struct_mutex);
25230035d21cSmiao chen - Sun Microsystems - Beijing China 			return EINVAL;
25240035d21cSmiao chen - Sun Microsystems - Beijing China 		}
25250035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%s: obj %d type %d",__func__, obj->name, type);
25260035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_gem_object_unbind(obj, type);
25270035d21cSmiao chen - Sun Microsystems - Beijing China 		if (ret != 0) {
25280035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Error unbinding object in LeaveVT: %d\n",
25290035d21cSmiao chen - Sun Microsystems - Beijing China 				  ret);
25300035d21cSmiao chen - Sun Microsystems - Beijing China 			spin_unlock(&dev->struct_mutex);
25310035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
25320035d21cSmiao chen - Sun Microsystems - Beijing China 		}
25330035d21cSmiao chen - Sun Microsystems - Beijing China 	}
25340035d21cSmiao chen - Sun Microsystems - Beijing China 
25350035d21cSmiao chen - Sun Microsystems - Beijing China 
25360035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
25370035d21cSmiao chen - Sun Microsystems - Beijing China }
25380035d21cSmiao chen - Sun Microsystems - Beijing China 
25390035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_idle(struct drm_device * dev,uint32_t type)25400035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_idle(struct drm_device *dev, uint32_t type)
25410035d21cSmiao chen - Sun Microsystems - Beijing China {
25420035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
25430035d21cSmiao chen - Sun Microsystems - Beijing China 	uint32_t seqno, cur_seqno, last_seqno;
25440035d21cSmiao chen - Sun Microsystems - Beijing China 	int stuck, ret;
25450035d21cSmiao chen - Sun Microsystems - Beijing China 
25460035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
25470035d21cSmiao chen - Sun Microsystems - Beijing China 
25480035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) {
25490035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
25500035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
25510035d21cSmiao chen - Sun Microsystems - Beijing China 	}
25520035d21cSmiao chen - Sun Microsystems - Beijing China 
25530035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Hack!  Don't let anybody do execbuf while we don't control the chip.
25540035d21cSmiao chen - Sun Microsystems - Beijing China 	 * We need to replace this with a semaphore, or something.
25550035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
25560035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mm.suspended = 1;
25570035d21cSmiao chen - Sun Microsystems - Beijing China 
25580035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Cancel the retire work handler, wait for it to finish if running
25590035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
25600035d21cSmiao chen - Sun Microsystems - Beijing China 	if (worktimer_id != NULL) {
25610035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) untimeout(worktimer_id);
25620035d21cSmiao chen - Sun Microsystems - Beijing China 		worktimer_id = NULL;
25630035d21cSmiao chen - Sun Microsystems - Beijing China 	}
25640035d21cSmiao chen - Sun Microsystems - Beijing China 
25650035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_kernel_lost_context(dev);
25660035d21cSmiao chen - Sun Microsystems - Beijing China 
25670035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Flush the GPU along with all non-CPU write domains
25680035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
25690035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT),
25700035d21cSmiao chen - Sun Microsystems - Beijing China 		       ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
25710035d21cSmiao chen - Sun Microsystems - Beijing China 	seqno = i915_add_request(dev, ~(I915_GEM_DOMAIN_CPU |
25720035d21cSmiao chen - Sun Microsystems - Beijing China 					I915_GEM_DOMAIN_GTT));
25730035d21cSmiao chen - Sun Microsystems - Beijing China 	if (seqno == 0) {
25740035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
25750035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENOMEM;
25760035d21cSmiao chen - Sun Microsystems - Beijing China 	}
25770035d21cSmiao chen - Sun Microsystems - Beijing China 
25780035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mm.waiting_gem_seqno = seqno;
25790035d21cSmiao chen - Sun Microsystems - Beijing China 	last_seqno = 0;
25800035d21cSmiao chen - Sun Microsystems - Beijing China 	stuck = 0;
25810035d21cSmiao chen - Sun Microsystems - Beijing China 	for (;;) {
25820035d21cSmiao chen - Sun Microsystems - Beijing China 		cur_seqno = i915_get_gem_seqno(dev);
25830035d21cSmiao chen - Sun Microsystems - Beijing China 		if (i915_seqno_passed(cur_seqno, seqno))
25840035d21cSmiao chen - Sun Microsystems - Beijing China 			break;
25850035d21cSmiao chen - Sun Microsystems - Beijing China 		if (last_seqno == cur_seqno) {
25860035d21cSmiao chen - Sun Microsystems - Beijing China 			if (stuck++ > 100) {
25870035d21cSmiao chen - Sun Microsystems - Beijing China 				DRM_ERROR("hardware wedged\n");
25880035d21cSmiao chen - Sun Microsystems - Beijing China 				dev_priv->mm.wedged = 1;
25890035d21cSmiao chen - Sun Microsystems - Beijing China 				DRM_WAKEUP(&dev_priv->irq_queue);
25900035d21cSmiao chen - Sun Microsystems - Beijing China 				break;
25910035d21cSmiao chen - Sun Microsystems - Beijing China 			}
25920035d21cSmiao chen - Sun Microsystems - Beijing China 		}
25930035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_UDELAY(10);
25940035d21cSmiao chen - Sun Microsystems - Beijing China 		last_seqno = cur_seqno;
25950035d21cSmiao chen - Sun Microsystems - Beijing China 	}
25960035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mm.waiting_gem_seqno = 0;
25970035d21cSmiao chen - Sun Microsystems - Beijing China 
25980035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_retire_requests(dev);
25990035d21cSmiao chen - Sun Microsystems - Beijing China 
26000035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Empty the active and flushing lists to inactive.  If there's
26010035d21cSmiao chen - Sun Microsystems - Beijing China 	 * anything left at this point, it means that we're wedged and
26020035d21cSmiao chen - Sun Microsystems - Beijing China 	 * nothing good's going to happen by leaving them there.  So strip
26030035d21cSmiao chen - Sun Microsystems - Beijing China 	 * the GPU domains and just stuff them onto inactive.
26040035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
26050035d21cSmiao chen - Sun Microsystems - Beijing China 	while (!list_empty(&dev_priv->mm.active_list)) {
26060035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_i915_gem_object *obj_priv;
26070035d21cSmiao chen - Sun Microsystems - Beijing China 
26080035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv = list_entry(dev_priv->mm.active_list.next,
26090035d21cSmiao chen - Sun Microsystems - Beijing China 					    struct drm_i915_gem_object,
26100035d21cSmiao chen - Sun Microsystems - Beijing China 					    list);
26110035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
26120035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_move_to_inactive(obj_priv->obj);
26130035d21cSmiao chen - Sun Microsystems - Beijing China 	}
26140035d21cSmiao chen - Sun Microsystems - Beijing China 
26150035d21cSmiao chen - Sun Microsystems - Beijing China 	while (!list_empty(&dev_priv->mm.flushing_list)) {
26160035d21cSmiao chen - Sun Microsystems - Beijing China 		struct drm_i915_gem_object *obj_priv;
26170035d21cSmiao chen - Sun Microsystems - Beijing China 
26180035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv = list_entry(dev_priv->mm.flushing_list.next,
26190035d21cSmiao chen - Sun Microsystems - Beijing China 					    struct drm_i915_gem_object,
26200035d21cSmiao chen - Sun Microsystems - Beijing China 					    list);
26210035d21cSmiao chen - Sun Microsystems - Beijing China 		obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
26220035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_object_move_to_inactive(obj_priv->obj);
26230035d21cSmiao chen - Sun Microsystems - Beijing China 	}
26240035d21cSmiao chen - Sun Microsystems - Beijing China 
26250035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Move all inactive buffers out of the GTT. */
26260035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list, type);
26270035d21cSmiao chen - Sun Microsystems - Beijing China 	ASSERT(list_empty(&dev_priv->mm.inactive_list));
26280035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret) {
26290035d21cSmiao chen - Sun Microsystems - Beijing China 		spin_unlock(&dev->struct_mutex);
26300035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
26310035d21cSmiao chen - Sun Microsystems - Beijing China 	}
26320035d21cSmiao chen - Sun Microsystems - Beijing China 
26330035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_cleanup_ringbuffer(dev);
26340035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
26350035d21cSmiao chen - Sun Microsystems - Beijing China 
26360035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
26370035d21cSmiao chen - Sun Microsystems - Beijing China }
26380035d21cSmiao chen - Sun Microsystems - Beijing China 
26390035d21cSmiao chen - Sun Microsystems - Beijing China static int
i915_gem_init_hws(struct drm_device * dev)26400035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_init_hws(struct drm_device *dev)
26410035d21cSmiao chen - Sun Microsystems - Beijing China {
26420035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
26430035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
26440035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
26450035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
26460035d21cSmiao chen - Sun Microsystems - Beijing China 
26470035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If we need a physical address for the status page, it's already
26480035d21cSmiao chen - Sun Microsystems - Beijing China 	 * initialized at driver load time.
26490035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
26500035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!I915_NEED_GFX_HWS(dev))
26510035d21cSmiao chen - Sun Microsystems - Beijing China 		return 0;
26520035d21cSmiao chen - Sun Microsystems - Beijing China 
26530035d21cSmiao chen - Sun Microsystems - Beijing China 
26540035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_alloc(dev, 4096);
26550035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL) {
26560035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to allocate status page\n");
26570035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENOMEM;
26580035d21cSmiao chen - Sun Microsystems - Beijing China 	}
26590035d21cSmiao chen - Sun Microsystems - Beijing China 
26600035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = obj->driver_private;
26610035d21cSmiao chen - Sun Microsystems - Beijing China 
26620035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_pin(obj, 4096);
26630035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0) {
26640035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
26650035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
26660035d21cSmiao chen - Sun Microsystems - Beijing China 	}
26670035d21cSmiao chen - Sun Microsystems - Beijing China 
26680035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->status_gfx_addr = obj_priv->gtt_offset;
26690035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_map.offset = dev->agp->agp_info.agpi_aperbase + obj_priv->gtt_offset;
26700035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_map.size = 4096;
26710035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_map.type = 0;
26720035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_map.flags = 0;
26730035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_map.mtrr = 0;
26740035d21cSmiao chen - Sun Microsystems - Beijing China 
26750035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_core_ioremap(&dev_priv->hws_map, dev);
26760035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->hws_map.handle == NULL) {
26770035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to map status page.\n");
26780035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
26790035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
26800035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
26810035d21cSmiao chen - Sun Microsystems - Beijing China 	}
26820035d21cSmiao chen - Sun Microsystems - Beijing China 
26830035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_obj = obj;
26840035d21cSmiao chen - Sun Microsystems - Beijing China 
26850035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hw_status_page = dev_priv->hws_map.handle;
26860035d21cSmiao chen - Sun Microsystems - Beijing China 
26870035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
26880035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
26890035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) I915_READ(HWS_PGA); /* posting read */
26900035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
26910035d21cSmiao chen - Sun Microsystems - Beijing China 
26920035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
26930035d21cSmiao chen - Sun Microsystems - Beijing China }
26940035d21cSmiao chen - Sun Microsystems - Beijing China 
26950035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_cleanup_hws(struct drm_device * dev)26960035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_cleanup_hws(struct drm_device *dev)
26970035d21cSmiao chen - Sun Microsystems - Beijing China {
26980035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
26990035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
27000035d21cSmiao chen - Sun Microsystems - Beijing China 
27010035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->hws_obj == NULL)
27020035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
27030035d21cSmiao chen - Sun Microsystems - Beijing China 
27040035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = dev_priv->hws_obj;
27050035d21cSmiao chen - Sun Microsystems - Beijing China 
27060035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_core_ioremapfree(&dev_priv->hws_map, dev);
27070035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_unpin(obj);
27080035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(obj);
27090035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_obj = NULL;
27100035d21cSmiao chen - Sun Microsystems - Beijing China 
27110035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
27120035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->hw_status_page = NULL;
27130035d21cSmiao chen - Sun Microsystems - Beijing China 
27140035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Write high address into HWS_PGA when disabling. */
27150035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(HWS_PGA, 0x1ffff000);
27160035d21cSmiao chen - Sun Microsystems - Beijing China }
27170035d21cSmiao chen - Sun Microsystems - Beijing China 
27180035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_init_ringbuffer(struct drm_device * dev)27190035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_init_ringbuffer(struct drm_device *dev)
27200035d21cSmiao chen - Sun Microsystems - Beijing China {
27210035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
27220035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_gem_object *obj;
27230035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_gem_object *obj_priv;
27240035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
27250035d21cSmiao chen - Sun Microsystems - Beijing China 	u32 head;
27260035d21cSmiao chen - Sun Microsystems - Beijing China 
27270035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_init_hws(dev);
27280035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0)
27290035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
27300035d21cSmiao chen - Sun Microsystems - Beijing China 	obj = drm_gem_object_alloc(dev, 128 * 1024);
27310035d21cSmiao chen - Sun Microsystems - Beijing China 	if (obj == NULL) {
27320035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to allocate ringbuffer\n");
27330035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_cleanup_hws(dev);
27340035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENOMEM;
27350035d21cSmiao chen - Sun Microsystems - Beijing China 	}
27360035d21cSmiao chen - Sun Microsystems - Beijing China 
27370035d21cSmiao chen - Sun Microsystems - Beijing China 	obj_priv = obj->driver_private;
27380035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_object_pin(obj, 4096);
27390035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0) {
27400035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
27410035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_cleanup_hws(dev);
27420035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
27430035d21cSmiao chen - Sun Microsystems - Beijing China 	}
27440035d21cSmiao chen - Sun Microsystems - Beijing China 
27450035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Set up the kernel mapping for the ring. */
27460035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.Size = obj->size;
27470035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.tail_mask = obj->size - 1;
27480035d21cSmiao chen - Sun Microsystems - Beijing China 
27490035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.map.offset = dev->agp->agp_info.agpi_aperbase + obj_priv->gtt_offset;
27500035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.map.size = obj->size;
27510035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.map.type = 0;
27520035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.map.flags = 0;
27530035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.map.mtrr = 0;
27540035d21cSmiao chen - Sun Microsystems - Beijing China 
27550035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_core_ioremap(&dev_priv->ring.map, dev);
27560035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->ring.map.handle == NULL) {
27570035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Failed to map ringbuffer.\n");
27580035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
27590035d21cSmiao chen - Sun Microsystems - Beijing China 		drm_gem_object_unreference(obj);
27600035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_gem_cleanup_hws(dev);
27610035d21cSmiao chen - Sun Microsystems - Beijing China 		return EINVAL;
27620035d21cSmiao chen - Sun Microsystems - Beijing China 	}
27630035d21cSmiao chen - Sun Microsystems - Beijing China 
27640035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.ring_obj = obj;
27650035d21cSmiao chen - Sun Microsystems - Beijing China 
27660035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.virtual_start = (u8 *) dev_priv->ring.map.handle;
27670035d21cSmiao chen - Sun Microsystems - Beijing China 
27680035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Stop the ring if it's running. */
27690035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PRB0_CTL, 0);
27700035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PRB0_HEAD, 0);
27710035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PRB0_TAIL, 0);
27720035d21cSmiao chen - Sun Microsystems - Beijing China 
27730035d21cSmiao chen - Sun Microsystems - Beijing China 
27740035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Initialize the ring. */
27750035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PRB0_START, obj_priv->gtt_offset);
27760035d21cSmiao chen - Sun Microsystems - Beijing China 	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
27770035d21cSmiao chen - Sun Microsystems - Beijing China 
27780035d21cSmiao chen - Sun Microsystems - Beijing China 	/* G45 ring initialization fails to reset head to zero */
27790035d21cSmiao chen - Sun Microsystems - Beijing China 	if (head != 0) {
27800035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Ring head not reset to zero "
27810035d21cSmiao chen - Sun Microsystems - Beijing China 			  "ctl %08x head %08x tail %08x start %08x\n",
27820035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_CTL),
27830035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_HEAD),
27840035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_TAIL),
27850035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_START));
27860035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(PRB0_HEAD, 0);
27870035d21cSmiao chen - Sun Microsystems - Beijing China 
27880035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Ring head forced to zero "
27890035d21cSmiao chen - Sun Microsystems - Beijing China 			  "ctl %08x head %08x tail %08x start %08x\n",
27900035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_CTL),
27910035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_HEAD),
27920035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_TAIL),
27930035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_START));
27940035d21cSmiao chen - Sun Microsystems - Beijing China 	}
27950035d21cSmiao chen - Sun Microsystems - Beijing China 
27960035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PRB0_CTL,
27970035d21cSmiao chen - Sun Microsystems - Beijing China 		   ((obj->size - 4096) & RING_NR_PAGES) |
27980035d21cSmiao chen - Sun Microsystems - Beijing China 		   RING_NO_REPORT |
27990035d21cSmiao chen - Sun Microsystems - Beijing China 		   RING_VALID);
28000035d21cSmiao chen - Sun Microsystems - Beijing China 
28010035d21cSmiao chen - Sun Microsystems - Beijing China 	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
28020035d21cSmiao chen - Sun Microsystems - Beijing China 
28030035d21cSmiao chen - Sun Microsystems - Beijing China 	/* If the head is still not zero, the ring is dead */
28040035d21cSmiao chen - Sun Microsystems - Beijing China 	if (head != 0) {
28050035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Ring initialization failed "
28060035d21cSmiao chen - Sun Microsystems - Beijing China 			  "ctl %08x head %08x tail %08x start %08x\n",
28070035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_CTL),
28080035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_HEAD),
28090035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_TAIL),
28100035d21cSmiao chen - Sun Microsystems - Beijing China 			  I915_READ(PRB0_START));
28110035d21cSmiao chen - Sun Microsystems - Beijing China 		return EIO;
28120035d21cSmiao chen - Sun Microsystems - Beijing China 	}
28130035d21cSmiao chen - Sun Microsystems - Beijing China 
28140035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Update our cache of the ring state */
28150035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_kernel_lost_context(dev);
28160035d21cSmiao chen - Sun Microsystems - Beijing China 
28170035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
28180035d21cSmiao chen - Sun Microsystems - Beijing China }
28190035d21cSmiao chen - Sun Microsystems - Beijing China 
28200035d21cSmiao chen - Sun Microsystems - Beijing China static void
i915_gem_cleanup_ringbuffer(struct drm_device * dev)28210035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_cleanup_ringbuffer(struct drm_device *dev)
28220035d21cSmiao chen - Sun Microsystems - Beijing China {
28230035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
28240035d21cSmiao chen - Sun Microsystems - Beijing China 
28250035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->ring.ring_obj == NULL)
28260035d21cSmiao chen - Sun Microsystems - Beijing China 		return;
28270035d21cSmiao chen - Sun Microsystems - Beijing China 
28280035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_core_ioremapfree(&dev_priv->ring.map, dev);
28290035d21cSmiao chen - Sun Microsystems - Beijing China 
28300035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_object_unpin(dev_priv->ring.ring_obj);
28310035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_gem_object_unreference(dev_priv->ring.ring_obj);
28320035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.ring_obj = NULL;
28330035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
28340035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_cleanup_hws(dev);
28350035d21cSmiao chen - Sun Microsystems - Beijing China }
28360035d21cSmiao chen - Sun Microsystems - Beijing China 
28370035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
28380035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_entervt_ioctl(DRM_IOCTL_ARGS)28390035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_entervt_ioctl(DRM_IOCTL_ARGS)
28400035d21cSmiao chen - Sun Microsystems - Beijing China {
28410035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
28420035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
28430035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
28440035d21cSmiao chen - Sun Microsystems - Beijing China 
28450035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
28460035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
28470035d21cSmiao chen - Sun Microsystems - Beijing China 
28480035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->mm.wedged) {
28490035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Reenabling wedged hardware, good luck\n");
28500035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->mm.wedged = 0;
28510035d21cSmiao chen - Sun Microsystems - Beijing China 	}
28520035d21cSmiao chen - Sun Microsystems - Beijing China         /* Set up the kernel mapping for the ring. */
28530035d21cSmiao chen - Sun Microsystems - Beijing China         dev_priv->mm.gtt_mapping.offset = dev->agp->agp_info.agpi_aperbase;
28540035d21cSmiao chen - Sun Microsystems - Beijing China         dev_priv->mm.gtt_mapping.size = dev->agp->agp_info.agpi_apersize;
28550035d21cSmiao chen - Sun Microsystems - Beijing China         dev_priv->mm.gtt_mapping.type = 0;
28560035d21cSmiao chen - Sun Microsystems - Beijing China         dev_priv->mm.gtt_mapping.flags = 0;
28570035d21cSmiao chen - Sun Microsystems - Beijing China         dev_priv->mm.gtt_mapping.mtrr = 0;
28580035d21cSmiao chen - Sun Microsystems - Beijing China 
28590035d21cSmiao chen - Sun Microsystems - Beijing China         drm_core_ioremap(&dev_priv->mm.gtt_mapping, dev);
28600035d21cSmiao chen - Sun Microsystems - Beijing China 
28610035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
28620035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mm.suspended = 0;
28630035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_init_ringbuffer(dev);
28640035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret != 0)
28650035d21cSmiao chen - Sun Microsystems - Beijing China 		return ret;
28660035d21cSmiao chen - Sun Microsystems - Beijing China 
28670035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
28680035d21cSmiao chen - Sun Microsystems - Beijing China 
2869*c1374a13SSurya Prakki 	(void) drm_irq_install(dev);
28700035d21cSmiao chen - Sun Microsystems - Beijing China 
28710035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
28720035d21cSmiao chen - Sun Microsystems - Beijing China }
28730035d21cSmiao chen - Sun Microsystems - Beijing China 
28740035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
28750035d21cSmiao chen - Sun Microsystems - Beijing China int
i915_gem_leavevt_ioctl(DRM_IOCTL_ARGS)28760035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_leavevt_ioctl(DRM_IOCTL_ARGS)
28770035d21cSmiao chen - Sun Microsystems - Beijing China {
28780035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
28790035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
28800035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
28810035d21cSmiao chen - Sun Microsystems - Beijing China 
28820035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->driver->use_gem != 1)
28830035d21cSmiao chen - Sun Microsystems - Beijing China 		return ENODEV;
28840035d21cSmiao chen - Sun Microsystems - Beijing China 
28850035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_idle(dev, 0);
2886*c1374a13SSurya Prakki 	(void) drm_irq_uninstall(dev);
28870035d21cSmiao chen - Sun Microsystems - Beijing China 
28880035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_core_ioremapfree(&dev_priv->mm.gtt_mapping, dev);
28890035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
28900035d21cSmiao chen - Sun Microsystems - Beijing China }
28910035d21cSmiao chen - Sun Microsystems - Beijing China 
28920035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_gem_lastclose(struct drm_device * dev)28930035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_lastclose(struct drm_device *dev)
28940035d21cSmiao chen - Sun Microsystems - Beijing China {
28950035d21cSmiao chen - Sun Microsystems - Beijing China         drm_i915_private_t *dev_priv = dev->dev_private;
28960035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
28970035d21cSmiao chen - Sun Microsystems - Beijing China 
28980035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_gem_idle(dev, 1);
28990035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret)
29000035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("failed to idle hardware: %d\n", ret);
29010035d21cSmiao chen - Sun Microsystems - Beijing China 
29020035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_mm_clean_ml(&dev_priv->mm.gtt_space);
29030035d21cSmiao chen - Sun Microsystems - Beijing China }
29040035d21cSmiao chen - Sun Microsystems - Beijing China 
29050035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_gem_load(struct drm_device * dev)29060035d21cSmiao chen - Sun Microsystems - Beijing China i915_gem_load(struct drm_device *dev)
29070035d21cSmiao chen - Sun Microsystems - Beijing China {
29080035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
29090035d21cSmiao chen - Sun Microsystems - Beijing China 
29100035d21cSmiao chen - Sun Microsystems - Beijing China 	INIT_LIST_HEAD(&dev_priv->mm.active_list);
29110035d21cSmiao chen - Sun Microsystems - Beijing China 	INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
29120035d21cSmiao chen - Sun Microsystems - Beijing China 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
29130035d21cSmiao chen - Sun Microsystems - Beijing China 	INIT_LIST_HEAD(&dev_priv->mm.request_list);
29140035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mm.next_gem_seqno = 1;
29150035d21cSmiao chen - Sun Microsystems - Beijing China 
29160035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_detect_bit_6_swizzle(dev);
29170035d21cSmiao chen - Sun Microsystems - Beijing China 
29180035d21cSmiao chen - Sun Microsystems - Beijing China }
29190035d21cSmiao chen - Sun Microsystems - Beijing China 
2920