diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/Makefile.kernel | 7 | ||||
| -rw-r--r-- | linux-core/drmP.h | 18 | ||||
| -rw-r--r-- | linux-core/drm_bo.c | 729 | ||||
| -rw-r--r-- | linux-core/drm_bo_lock.c | 189 | ||||
| -rw-r--r-- | linux-core/drm_crtc_helper.c | 44 | ||||
| -rw-r--r-- | linux-core/drm_drv.c | 30 | ||||
| -rw-r--r-- | linux-core/drm_fence.c | 298 | ||||
| -rw-r--r-- | linux-core/drm_fops.c | 43 | ||||
| -rw-r--r-- | linux-core/drm_object.c | 294 | ||||
| -rw-r--r-- | linux-core/drm_objects.h | 273 | ||||
| -rw-r--r-- | linux-core/drm_ttm.c | 2 | ||||
| -rw-r--r-- | linux-core/i915_buffer.c | 311 | ||||
| -rw-r--r-- | linux-core/i915_execbuf.c | 921 | ||||
| -rw-r--r-- | linux-core/i915_fence.c | 273 | ||||
| -rw-r--r-- | linux-core/radeon_gem.c | 15 | 
15 files changed, 188 insertions, 3259 deletions
| diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 404944bf..b15a12ab 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -12,16 +12,15 @@ drm-objs    := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \  		drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \  		drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \  		drm_memory_debug.o ati_pcigart.o drm_sman.o \ -		drm_hashtab.o drm_memrange.o drm_object.o drm_compat.o \ -	        drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock.o \ +		drm_hashtab.o drm_memrange.o drm_compat.o \ +	        drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o \  		drm_crtc.o drm_edid.o drm_modes.o drm_crtc_helper.o \  		drm_regman.o drm_vm_nopage_compat.o drm_gem.o  tdfx-objs   := tdfx_drv.o  r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o  mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o  i810-objs   := i810_drv.o i810_dma.o -i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ -		i915_buffer.o i915_execbuf.o i915_gem.o \ +i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_gem.o \  	        intel_display.o intel_crt.o intel_lvds.o intel_bios.o \  		intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o \  		intel_tv.o i915_compat.o intel_dvo.o dvo_ch7xxx.o \ diff --git a/linux-core/drmP.h b/linux-core/drmP.h index e3a08e79..4938881f 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -405,14 +405,6 @@ struct drm_buf_entry {  	struct drm_freelist freelist;  }; - -enum drm_ref_type { -	_DRM_REF_USE = 0, -	_DRM_REF_TYPE1, -	_DRM_NO_REF_TYPES -}; - -  /** File private data */  struct drm_file {  	int authenticated; @@ -424,21 +416,11 @@ struct drm_file {  	struct drm_minor *minor;  	unsigned long lock_count; -	/* -	 * The user object hash table is global and resides in the -	 * drm_device structure. We protect the lists and hash tables with the -	 * device struct_mutex. A bit coarse-grained but probably the best -	 * option. -	 */ - -	struct list_head refd_objects; -  	/** Mapping of mm object handles to object pointers. */  	struct idr object_idr;  	/** Lock for synchronization of access to object_idr. */  	spinlock_t table_lock; -	struct drm_open_hash refd_object_hash[_DRM_NO_REF_TYPES];  	struct file *filp;  	void *driver_priv; diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 0021530b..84cf69bd 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -565,18 +565,6 @@ void drm_bo_usage_deref_locked(struct drm_buffer_object **bo)  }  EXPORT_SYMBOL(drm_bo_usage_deref_locked); -static void drm_bo_base_deref_locked(struct drm_file *file_priv, -				     struct drm_user_object *uo) -{ -	struct drm_buffer_object *bo = -	    drm_user_object_entry(uo, struct drm_buffer_object, base); - -	DRM_ASSERT_LOCKED(&bo->dev->struct_mutex); - -	drm_bo_takedown_vm_locked(bo); -	drm_bo_usage_deref_locked(&bo); -} -  void drm_bo_usage_deref_unlocked(struct drm_buffer_object **bo)  {  	struct drm_buffer_object *tmp_bo = *bo; @@ -1068,34 +1056,6 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo,  }  /* - * Call dev->struct_mutex locked. - */ - -struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv, -					      uint32_t handle, int check_owner) -{ -	struct drm_user_object *uo; -	struct drm_buffer_object *bo; - -	uo = drm_lookup_user_object(file_priv, handle); - -	if (!uo || (uo->type != drm_buffer_type)) { -		DRM_ERROR("Could not find buffer object 0x%08x\n", handle); -		return NULL; -	} - -	if (check_owner && file_priv != uo->owner) { -		if (!drm_lookup_ref_object(file_priv, uo, _DRM_REF_USE)) -			return NULL; -	} - -	bo = drm_user_object_entry(uo, struct drm_buffer_object, base); -	atomic_inc(&bo->usage); -	return bo; -} -EXPORT_SYMBOL(drm_lookup_buffer_object); - -/*   * Call bo->mutex locked.   * Returns -EBUSY if the buffer is currently rendered to or from. 0 otherwise.   * Doesn't do any fence flushing as opposed to the drm_bo_busy function. @@ -1158,149 +1118,6 @@ static int drm_bo_wait_unmapped(struct drm_buffer_object *bo, int no_wait)  }  /* - * Fill in the ioctl reply argument with buffer info. - * Bo locked. - */ - -void drm_bo_fill_rep_arg(struct drm_buffer_object *bo, -			 struct drm_bo_info_rep *rep) -{ -	if (!rep) -		return; - -	rep->handle = bo->base.hash.key; -	rep->flags = bo->mem.flags; -	rep->size = bo->num_pages * PAGE_SIZE; -	rep->offset = bo->offset; - -	/* -	 * drm_bo_type_device buffers have user-visible -	 * handles which can be used to share across -	 * processes. Hand that back to the application -	 */ -	if (bo->type == drm_bo_type_device) -		rep->arg_handle = bo->map_list.user_token; -	else -		rep->arg_handle = 0; - -	rep->proposed_flags = bo->mem.proposed_flags; -	rep->buffer_start = bo->buffer_start; -	rep->fence_flags = bo->fence_type; -	rep->rep_flags = 0; -	rep->page_alignment = bo->mem.page_alignment; - -	if ((bo->priv_flags & _DRM_BO_FLAG_UNFENCED) || drm_bo_quick_busy(bo, 1)) { -		DRM_FLAG_MASKED(rep->rep_flags, DRM_BO_REP_BUSY, -				DRM_BO_REP_BUSY); -	} -} -EXPORT_SYMBOL(drm_bo_fill_rep_arg); - -/* - * Wait for buffer idle and register that we've mapped the buffer. - * Mapping is registered as a drm_ref_object with type _DRM_REF_TYPE1, - * so that if the client dies, the mapping is automatically - * unregistered. - */ - -static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle, -				 uint32_t map_flags, unsigned hint, -				 struct drm_bo_info_rep *rep) -{ -	struct drm_buffer_object *bo; -	struct drm_device *dev = file_priv->minor->dev; -	int ret = 0; -	int no_wait = hint & DRM_BO_HINT_DONT_BLOCK; - -	mutex_lock(&dev->struct_mutex); -	bo = drm_lookup_buffer_object(file_priv, handle, 1); -	mutex_unlock(&dev->struct_mutex); - -	if (!bo) -		return -EINVAL; - -	mutex_lock(&bo->mutex); -	do { -		bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; - -		ret = drm_bo_wait(bo, 0, 1, no_wait, 1); -		if (unlikely(ret)) -			goto out; - -		if (bo->mem.flags & DRM_BO_FLAG_CACHED_MAPPED) -			drm_bo_evict_cached(bo); - -	} while (unlikely(bo->priv_flags & _DRM_BO_FLAG_UNLOCKED)); - -	atomic_inc(&bo->mapped); -	mutex_lock(&dev->struct_mutex); -	ret = drm_add_ref_object(file_priv, &bo->base, _DRM_REF_TYPE1); -	mutex_unlock(&dev->struct_mutex); -	if (ret) { -		if (atomic_dec_and_test(&bo->mapped)) -			wake_up_all(&bo->event_queue); - -	} else -		drm_bo_fill_rep_arg(bo, rep); - - out: -	mutex_unlock(&bo->mutex); -	drm_bo_usage_deref_unlocked(&bo); - -	return ret; -} - -static int drm_buffer_object_unmap(struct drm_file *file_priv, uint32_t handle) -{ -	struct drm_device *dev = file_priv->minor->dev; -	struct drm_buffer_object *bo; -	struct drm_ref_object *ro; -	int ret = 0; - -	mutex_lock(&dev->struct_mutex); - -	bo = drm_lookup_buffer_object(file_priv, handle, 1); -	if (!bo) { -		ret = -EINVAL; -		goto out; -	} - -	ro = drm_lookup_ref_object(file_priv, &bo->base, _DRM_REF_TYPE1); -	if (!ro) { -		ret = -EINVAL; -		goto out; -	} - -	drm_remove_ref_object(file_priv, ro); -	drm_bo_usage_deref_locked(&bo); -out: -	mutex_unlock(&dev->struct_mutex); -	return ret; -} - -/* - * Call struct-sem locked. - */ - -static void drm_buffer_user_object_unmap(struct drm_file *file_priv, -					 struct drm_user_object *uo, -					 enum drm_ref_type action) -{ -	struct drm_buffer_object *bo = -	    drm_user_object_entry(uo, struct drm_buffer_object, base); - -	/* -	 * We DON'T want to take the bo->lock here, because we want to -	 * hold it when we wait for unmapped buffer. -	 */ - -	BUG_ON(action != _DRM_REF_TYPE1); - -	if (atomic_dec_and_test(&bo->mapped)) -		wake_up_all(&bo->event_queue); -} - -/*   * bo->mutex locked.   * Note that new_mem_flags are NOT transferred to the bo->mem.proposed_flags.   */ @@ -1594,8 +1411,7 @@ static int drm_bo_prepare_for_validate(struct drm_buffer_object *bo,  int drm_bo_do_validate(struct drm_buffer_object *bo,  		       uint64_t flags, uint64_t mask, uint32_t hint, -		       uint32_t fence_class, -		       struct drm_bo_info_rep *rep) +		       uint32_t fence_class)  {  	int ret;  	int no_wait = (hint & DRM_BO_HINT_DONT_BLOCK) != 0; @@ -1622,132 +1438,12 @@ int drm_bo_do_validate(struct drm_buffer_object *bo,  	BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNLOCKED);  out: -	if (rep) -		drm_bo_fill_rep_arg(bo, rep); -  	mutex_unlock(&bo->mutex);  	return ret;  }  EXPORT_SYMBOL(drm_bo_do_validate); -/** - * drm_bo_handle_validate - * - * @file_priv: the drm file private, used to get a handle to the user context - * - * @handle: the buffer object handle - * - * @flags: access rights, mapping parameters and cacheability. See - * the DRM_BO_FLAG_* values in drm.h - * - * @mask: Which flag values to change; this allows callers to modify - * things without knowing the current state of other flags. - * - * @hint: changes the proceedure for this operation, see the DRM_BO_HINT_* - * values in drm.h. - * - * @fence_class: a driver-specific way of doing fences. Presumably, - * this would be used if the driver had more than one submission and - * fencing mechanism. At this point, there isn't any use of this - * from the user mode code. - * - * @rep: To be stuffed with the reply from validation - * - * @bp_rep: To be stuffed with the buffer object pointer - * - * Perform drm_bo_do_validate on a buffer referenced by a user-space handle instead - * of a pointer to a buffer object. Optionally return a pointer to the buffer object. - * This is a convenience wrapper only. - */ - -int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, -			   uint64_t flags, uint64_t mask, -			   uint32_t hint, -			   uint32_t fence_class, -			   struct drm_bo_info_rep *rep, -			   struct drm_buffer_object **bo_rep) -{ -	struct drm_device *dev = file_priv->minor->dev; -	struct drm_buffer_object *bo; -	int ret; - -	mutex_lock(&dev->struct_mutex); -	bo = drm_lookup_buffer_object(file_priv, handle, 1); -	mutex_unlock(&dev->struct_mutex); - -	if (!bo) -		return -EINVAL; - -	if (bo->base.owner != file_priv) -		mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE); - -	ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, rep); - -	if (!ret && bo_rep) -		*bo_rep = bo; -	else -		drm_bo_usage_deref_unlocked(&bo); - -	return ret; -} -EXPORT_SYMBOL(drm_bo_handle_validate); - - -static int drm_bo_handle_info(struct drm_file *file_priv, uint32_t handle, -			      struct drm_bo_info_rep *rep) -{ -	struct drm_device *dev = file_priv->minor->dev; -	struct drm_buffer_object *bo; - -	mutex_lock(&dev->struct_mutex); -	bo = drm_lookup_buffer_object(file_priv, handle, 1); -	mutex_unlock(&dev->struct_mutex); - -	if (!bo) -		return -EINVAL; - -	mutex_lock(&bo->mutex); - -	/* -	 * FIXME: Quick busy here? -	 */ - -	drm_bo_busy(bo, 1); -	drm_bo_fill_rep_arg(bo, rep); -	mutex_unlock(&bo->mutex); -	drm_bo_usage_deref_unlocked(&bo); -	return 0; -} - -static int drm_bo_handle_wait(struct drm_file *file_priv, uint32_t handle, -			      uint32_t hint, -			      struct drm_bo_info_rep *rep) -{ -	struct drm_device *dev = file_priv->minor->dev; -	struct drm_buffer_object *bo; -	int no_wait = hint & DRM_BO_HINT_DONT_BLOCK; -	int ret; - -	mutex_lock(&dev->struct_mutex); -	bo = drm_lookup_buffer_object(file_priv, handle, 1); -	mutex_unlock(&dev->struct_mutex); - -	if (!bo) -		return -EINVAL; - -	mutex_lock(&bo->mutex); -	ret = drm_bo_wait(bo, hint & DRM_BO_HINT_WAIT_LAZY, 1, no_wait, 1); -	if (ret) -		goto out; - -	drm_bo_fill_rep_arg(bo, rep); -out: -	mutex_unlock(&bo->mutex); -	drm_bo_usage_deref_unlocked(&bo); -	return ret; -} -  int drm_buffer_object_create(struct drm_device *dev,  			     unsigned long size,  			     enum drm_bo_type type, @@ -1822,7 +1518,7 @@ int drm_buffer_object_create(struct drm_device *dev,  	mutex_unlock(&bo->mutex);  	ret = drm_bo_do_validate(bo, 0, 0, hint | DRM_BO_HINT_DONT_FENCE, -				 0, NULL); +				 0);  	if (ret)  		goto out_err_unlocked; @@ -1837,230 +1533,6 @@ out_err_unlocked:  }  EXPORT_SYMBOL(drm_buffer_object_create); - -int drm_bo_add_user_object(struct drm_file *file_priv, -			   struct drm_buffer_object *bo, int shareable) -{ -	struct drm_device *dev = file_priv->minor->dev; -	int ret; - -	mutex_lock(&dev->struct_mutex); -	ret = drm_add_user_object(file_priv, &bo->base, shareable); -	if (ret) -		goto out; - -	bo->base.remove = drm_bo_base_deref_locked; -	bo->base.type = drm_buffer_type; -	bo->base.ref_struct_locked = NULL; -	bo->base.unref = drm_buffer_user_object_unmap; - -out: -	mutex_unlock(&dev->struct_mutex); -	return ret; -} -EXPORT_SYMBOL(drm_bo_add_user_object); - -int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_bo_create_arg *arg = data; -	struct drm_bo_create_req *req = &arg->d.req; -	struct drm_bo_info_rep *rep = &arg->d.rep; -	struct drm_buffer_object *entry; -	enum drm_bo_type bo_type; -	int ret = 0; - -	DRM_DEBUG("drm_bo_create_ioctl: %dkb, %dkb align\n", -	    (int)(req->size / 1024), req->page_alignment * 4); - -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	/* -	 * If the buffer creation request comes in with a starting address, -	 * that points at the desired user pages to map. Otherwise, create -	 * a drm_bo_type_device buffer, which uses pages allocated from the kernel -	 */ -	bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_device; - -	/* -	 * User buffers cannot be shared -	 */ -	if (bo_type == drm_bo_type_user) -		req->flags &= ~DRM_BO_FLAG_SHAREABLE; - -	ret = drm_buffer_object_create(file_priv->minor->dev, -				       req->size, bo_type, req->flags, -				       req->hint, req->page_alignment, -				       req->buffer_start, &entry); -	if (ret) -		goto out; - -	ret = drm_bo_add_user_object(file_priv, entry, -				     req->flags & DRM_BO_FLAG_SHAREABLE); -	if (ret) { -		drm_bo_usage_deref_unlocked(&entry); -		goto out; -	} - -	mutex_lock(&entry->mutex); -	drm_bo_fill_rep_arg(entry, rep); -	mutex_unlock(&entry->mutex); - -out: -	return ret; -} - -int drm_bo_setstatus_ioctl(struct drm_device *dev, -			   void *data, struct drm_file *file_priv) -{ -	struct drm_bo_map_wait_idle_arg *arg = data; -	struct drm_bo_info_req *req = &arg->d.req; -	struct drm_bo_info_rep *rep = &arg->d.rep; -	struct drm_buffer_object *bo; -	int ret; - -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	ret = drm_bo_read_lock(&dev->bm.bm_lock, 1); -	if (ret) -		return ret; - -	mutex_lock(&dev->struct_mutex); -	bo = drm_lookup_buffer_object(file_priv, req->handle, 1); -	mutex_unlock(&dev->struct_mutex); - -	if (!bo) -		return -EINVAL; - -	if (bo->base.owner != file_priv) -		req->mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE); - -	ret = drm_bo_do_validate(bo, req->flags, req->mask, -				 req->hint | DRM_BO_HINT_DONT_FENCE, -				 bo->fence_class, rep); - -	drm_bo_usage_deref_unlocked(&bo); - -	(void) drm_bo_read_unlock(&dev->bm.bm_lock); - -	return ret; -} - -int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_bo_map_wait_idle_arg *arg = data; -	struct drm_bo_info_req *req = &arg->d.req; -	struct drm_bo_info_rep *rep = &arg->d.rep; -	int ret; -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	ret = drm_buffer_object_map(file_priv, req->handle, req->mask, -				    req->hint, rep); -	if (ret) -		return ret; - -	return 0; -} - -int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_bo_handle_arg *arg = data; -	int ret; -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	ret = drm_buffer_object_unmap(file_priv, arg->handle); -	return ret; -} - - -int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_bo_reference_info_arg *arg = data; -	struct drm_bo_handle_arg *req = &arg->d.req; -	struct drm_bo_info_rep *rep = &arg->d.rep; -	struct drm_user_object *uo; -	int ret; - -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	ret = drm_user_object_ref(file_priv, req->handle, -				  drm_buffer_type, &uo); -	if (ret) -		return ret; - -	ret = drm_bo_handle_info(file_priv, req->handle, rep); -	if (ret) -		return ret; - -	return 0; -} - -int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_bo_handle_arg *arg = data; -	int ret = 0; - -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	ret = drm_user_object_unref(file_priv, arg->handle, drm_buffer_type); -	return ret; -} - -int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_bo_reference_info_arg *arg = data; -	struct drm_bo_handle_arg *req = &arg->d.req; -	struct drm_bo_info_rep *rep = &arg->d.rep; -	int ret; - -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	ret = drm_bo_handle_info(file_priv, req->handle, rep); -	if (ret) -		return ret; - -	return 0; -} - -int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_bo_map_wait_idle_arg *arg = data; -	struct drm_bo_info_req *req = &arg->d.req; -	struct drm_bo_info_rep *rep = &arg->d.rep; -	int ret; -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized.\n"); -		return -EINVAL; -	} - -	ret = drm_bo_handle_wait(file_priv, req->handle, -				 req->hint, rep); -	if (ret) -		return ret; - -	return 0; -} -  static int drm_bo_leave_list(struct drm_buffer_object *bo,  			     uint32_t mem_type,  			     int free_pinned, @@ -2435,191 +1907,6 @@ out_unlock:  }  EXPORT_SYMBOL(drm_bo_driver_init); -int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_mm_init_arg *arg = data; -	struct drm_buffer_manager *bm = &dev->bm; -	struct drm_bo_driver *driver = dev->driver->bo_driver; -	int ret; - -	if (!driver) { -		DRM_ERROR("Buffer objects are not supported by this driver\n"); -		return -EINVAL; -	} - -	ret = drm_bo_write_lock(&bm->bm_lock, 1, file_priv); -	if (ret) -		return ret; - -	ret = -EINVAL; -	if (arg->magic != DRM_BO_INIT_MAGIC) { -		DRM_ERROR("You are using an old libdrm that is not compatible with\n" -			  "\tthe kernel DRM module. Please upgrade your libdrm.\n"); -		return -EINVAL; -	} -	if (arg->major != DRM_BO_INIT_MAJOR) { -		DRM_ERROR("libdrm and kernel DRM buffer object interface major\n" -			  "\tversion don't match. Got %d, expected %d.\n", -			  arg->major, DRM_BO_INIT_MAJOR); -		return -EINVAL; -	} - -	mutex_lock(&dev->struct_mutex); -	if (!bm->initialized) { -		DRM_ERROR("DRM memory manager was not initialized.\n"); -		goto out; -	} -	if (arg->mem_type == 0) { -		DRM_ERROR("System memory buffers already initialized.\n"); -		goto out; -	} -	ret = drm_bo_init_mm(dev, arg->mem_type, -			     arg->p_offset, arg->p_size, 0); - -out: -	mutex_unlock(&dev->struct_mutex); -	(void) drm_bo_write_unlock(&bm->bm_lock, file_priv); - -	if (ret) -		return ret; - -	return 0; -} - -int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_mm_type_arg *arg = data; -	struct drm_buffer_manager *bm = &dev->bm; -	struct drm_bo_driver *driver = dev->driver->bo_driver; -	int ret; - -	if (!driver) { -		DRM_ERROR("Buffer objects are not supported by this driver\n"); -		return -EINVAL; -	} - -	ret = drm_bo_write_lock(&bm->bm_lock, 0, file_priv); -	if (ret) -		return ret; - -	mutex_lock(&dev->struct_mutex); -	ret = -EINVAL; -	if (!bm->initialized) { -		DRM_ERROR("DRM memory manager was not initialized\n"); -		goto out; -	} -	if (arg->mem_type == 0) { -		DRM_ERROR("No takedown for System memory buffers.\n"); -		goto out; -	} -	ret = 0; -	if ((ret = drm_bo_clean_mm(dev, arg->mem_type, 0))) { -		if (ret == -EINVAL) -			DRM_ERROR("Memory manager type %d not clean. " -				  "Delaying takedown\n", arg->mem_type); -		ret = 0; -	} -out: -	mutex_unlock(&dev->struct_mutex); -	(void) drm_bo_write_unlock(&bm->bm_lock, file_priv); - -	if (ret) -		return ret; - -	return 0; -} - -int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_mm_type_arg *arg = data; -	struct drm_bo_driver *driver = dev->driver->bo_driver; -	int ret; - -	if (!driver) { -		DRM_ERROR("Buffer objects are not supported by this driver\n"); -		return -EINVAL; -	} - -	if (arg->lock_flags & DRM_BO_LOCK_IGNORE_NO_EVICT) { -		DRM_ERROR("Lock flag DRM_BO_LOCK_IGNORE_NO_EVICT not supported yet.\n"); -		return -EINVAL; -	} - -	if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) { -		ret = drm_bo_write_lock(&dev->bm.bm_lock, 1, file_priv); -		if (ret) -			return ret; -	} - -	mutex_lock(&dev->struct_mutex); -	ret = drm_bo_lock_mm(dev, arg->mem_type); -	mutex_unlock(&dev->struct_mutex); -	if (ret) { -		(void) drm_bo_write_unlock(&dev->bm.bm_lock, file_priv); -		return ret; -	} - -	return 0; -} - -int drm_mm_unlock_ioctl(struct drm_device *dev, -			void *data, -			struct drm_file *file_priv) -{ -	struct drm_mm_type_arg *arg = data; -	struct drm_bo_driver *driver = dev->driver->bo_driver; -	int ret; - -	if (!driver) { -		DRM_ERROR("Buffer objects are not supported by this driver\n"); -		return -EINVAL; -	} - -	if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) { -		ret = drm_bo_write_unlock(&dev->bm.bm_lock, file_priv); -		if (ret) -			return ret; -	} - -	return 0; -} - -int drm_mm_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	struct drm_mm_info_arg *arg = data; -	struct drm_buffer_manager *bm = &dev->bm; -	struct drm_bo_driver *driver = dev->driver->bo_driver; -	struct drm_mem_type_manager *man; -	int ret = 0; -	int mem_type = arg->mem_type; - -	if (!driver) { -		DRM_ERROR("Buffer objects are not supported by this driver\n"); -		return -EINVAL; -	} - -	if (mem_type >= DRM_BO_MEM_TYPES) { -		DRM_ERROR("Illegal memory type %d\n", arg->mem_type); -		return -EINVAL; -	} - -	mutex_lock(&dev->struct_mutex); -	if (!bm->initialized) { -		DRM_ERROR("DRM memory manager was not initialized\n"); -		ret = -EINVAL; -		goto out; -	} - - -	man = &bm->man[arg->mem_type]; - -	arg->p_size = man->size; - -out: -	mutex_unlock(&dev->struct_mutex); -      -	return ret; -}  /*   * buffer object vm functions.   */ @@ -2792,15 +2079,3 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)  	return 0;  } - -int drm_bo_version_ioctl(struct drm_device *dev, void *data, -			 struct drm_file *file_priv) -{ -	struct drm_bo_version_arg *arg = (struct drm_bo_version_arg *)data; - -	arg->major = DRM_BO_INIT_MAJOR; -	arg->minor = DRM_BO_INIT_MINOR; -	arg->patchlevel = DRM_BO_INIT_PATCH; - -	return 0; -} diff --git a/linux-core/drm_bo_lock.c b/linux-core/drm_bo_lock.c deleted file mode 100644 index 08b1c6be..00000000 --- a/linux-core/drm_bo_lock.c +++ /dev/null @@ -1,189 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -/* - * This file implements a simple replacement for the buffer manager use - * of the heavyweight hardware lock. - * The lock is a read-write lock. Taking it in read mode is fast, and - * intended for in-kernel use only. - * Taking it in write mode is slow. - * - * The write mode is used only when there is a need to block all - * user-space processes from allocating a - * new memory area. - * Typical use in write mode is X server VT switching, and it's allowed - * to leave kernel space with the write lock held. If a user-space process - * dies while having the write-lock, it will be released during the file - * descriptor release. - * - * The read lock is typically placed at the start of an IOCTL- or - * user-space callable function that may end up allocating a memory area. - * This includes setstatus, super-ioctls and no_pfn; the latter may move - * unmappable regions to mappable. It's a bug to leave kernel space with the - * read lock held. - * - * Both read- and write lock taking may be interruptible for low signal-delivery - * latency. The locking functions will return -EAGAIN if interrupted by a - * signal. - * - * Locking order: The lock should be taken BEFORE any kernel mutexes - * or spinlocks. - */ - -#include "drmP.h" - -void drm_bo_init_lock(struct drm_bo_lock *lock) -{ -	DRM_INIT_WAITQUEUE(&lock->queue); -	atomic_set(&lock->write_lock_pending, 0); -	atomic_set(&lock->readers, 0); -} - -void drm_bo_read_unlock(struct drm_bo_lock *lock) -{ -	if (atomic_dec_and_test(&lock->readers)) -		wake_up_all(&lock->queue); -} -EXPORT_SYMBOL(drm_bo_read_unlock); - -int drm_bo_read_lock(struct drm_bo_lock *lock, int interruptible) -{ -	while (unlikely(atomic_read(&lock->write_lock_pending) != 0)) { -		int ret; -		 -		if (!interruptible) { -			wait_event(lock->queue, -				   atomic_read(&lock->write_lock_pending) == 0); -			continue; -		} -		ret = wait_event_interruptible -		    (lock->queue, atomic_read(&lock->write_lock_pending) == 0); -		if (ret) -			return -EAGAIN; -	} - -	while (unlikely(!atomic_add_unless(&lock->readers, 1, -1))) { -		int ret; -		if (!interruptible) { -			wait_event(lock->queue, -				   atomic_read(&lock->readers) != -1); -			continue; -		} -		ret = wait_event_interruptible -			(lock->queue, atomic_read(&lock->readers) != -1); -		if (ret) -			return -EAGAIN; -	} -	return 0; -} -EXPORT_SYMBOL(drm_bo_read_lock); - -static int __drm_bo_write_unlock(struct drm_bo_lock *lock) -{ -	if (unlikely(atomic_cmpxchg(&lock->readers, -1, 0) != -1)) -		return -EINVAL; -	wake_up_all(&lock->queue); -	return 0; -} - -static void drm_bo_write_lock_remove(struct drm_file *file_priv, -				     struct drm_user_object *item) -{ -	struct drm_bo_lock *lock = container_of(item, struct drm_bo_lock, base); -	int ret; - -	ret = __drm_bo_write_unlock(lock); -	BUG_ON(ret); -} - -int drm_bo_write_lock(struct drm_bo_lock *lock, int interruptible, -		      struct drm_file *file_priv) -{ -	int ret = 0; -	struct drm_device *dev; - -	atomic_inc(&lock->write_lock_pending); - -	while (unlikely(atomic_cmpxchg(&lock->readers, 0, -1) != 0)) { -		if (!interruptible) { -			wait_event(lock->queue, -				   atomic_read(&lock->readers) == 0); -			continue; -		} -		ret = wait_event_interruptible -		    (lock->queue, atomic_read(&lock->readers) == 0); - -		if (ret) { -			atomic_dec(&lock->write_lock_pending); -			wake_up_all(&lock->queue); -			return -EAGAIN; -		} -	} - -	/* -	 * Add a dummy user-object, the destructor of which will -	 * make sure the lock is released if the client dies -	 * while holding it. -	 */ - -	if (atomic_dec_and_test(&lock->write_lock_pending)) -		wake_up_all(&lock->queue); -	dev = file_priv->minor->dev; -	mutex_lock(&dev->struct_mutex); -	ret = drm_add_user_object(file_priv, &lock->base, 0); -	lock->base.remove = &drm_bo_write_lock_remove; -	lock->base.type = drm_lock_type; -	if (ret) -		(void)__drm_bo_write_unlock(lock); - -	mutex_unlock(&dev->struct_mutex); - -	return ret; -} - -int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv) -{ -	struct drm_device *dev = file_priv->minor->dev; -	struct drm_ref_object *ro; - -	mutex_lock(&dev->struct_mutex); - -	if (lock->base.owner != file_priv) { -		mutex_unlock(&dev->struct_mutex); -		return -EINVAL; -	} -	ro = drm_lookup_ref_object(file_priv, &lock->base, _DRM_REF_USE); -	BUG_ON(!ro); -	drm_remove_ref_object(file_priv, ro); -	lock->base.owner = NULL; - -	mutex_unlock(&dev->struct_mutex); -	return 0; -} diff --git a/linux-core/drm_crtc_helper.c b/linux-core/drm_crtc_helper.c index e0d93606..ee1dc258 100644 --- a/linux-core/drm_crtc_helper.c +++ b/linux-core/drm_crtc_helper.c @@ -715,48 +715,4 @@ int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,  }  EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); -/** - * drm_get_buffer_object - find the buffer object for a given handle - * @dev: DRM device - * @bo: pointer to caller's buffer_object pointer - * @handle: handle to lookup - * - * LOCKING: - * Must take @dev's struct_mutex to protect buffer object lookup. - * - * Given @handle, lookup the buffer object in @dev and put it in the caller's - * @bo pointer. - * - * RETURNS: - * Zero on success, -EINVAL if the handle couldn't be found. - */ -int drm_get_buffer_object(struct drm_device *dev, struct drm_buffer_object **bo, unsigned long handle) -{ -	struct drm_user_object *uo; -	struct drm_hash_item *hash; -	int ret; - -	*bo = NULL; - -	mutex_lock(&dev->struct_mutex); -	ret = drm_ht_find_item(&dev->object_hash, handle, &hash); -	if (ret) { -		DRM_ERROR("Couldn't find handle.\n"); -		ret = -EINVAL; -		goto out_err; -	} - -	uo = drm_hash_entry(hash, struct drm_user_object, hash); -	if (uo->type != drm_buffer_type) { -		ret = -EINVAL; -		goto out_err; -	} -	 -	*bo = drm_user_object_entry(uo, struct drm_buffer_object, base); -	ret = 0; -out_err: -	mutex_unlock(&dev->struct_mutex); -	return ret; -} -EXPORT_SYMBOL(drm_get_buffer_object); diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 9113fa54..2c3e29f0 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -146,36 +146,6 @@ static struct drm_ioctl_desc drm_ioctls[] = {  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER),  	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), -	DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, -		      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -	DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, -		      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -	DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, -		      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -	DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, -		      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_REFERENCE, drm_fence_reference_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_UNREFERENCE, drm_fence_unreference_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_SIGNALED, drm_fence_signaled_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_FLUSH, drm_fence_flush_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_WAIT, drm_fence_wait_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_EMIT, drm_fence_emit_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_FENCE_BUFFERS, drm_fence_buffers_ioctl, DRM_AUTH), - -	DRM_IOCTL_DEF(DRM_IOCTL_BO_CREATE, drm_bo_create_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_MAP, drm_bo_map_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_UNMAP, drm_bo_unmap_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_REFERENCE, drm_bo_reference_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_UNREFERENCE, drm_bo_unreference_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH), -	DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0), - -	DRM_IOCTL_DEF(DRM_IOCTL_MM_INFO, drm_mm_info_ioctl, 0), -  	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),  	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),  	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 7c78e09f..7130d1b0 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -134,8 +134,8 @@ void drm_fence_handler(struct drm_device *dev, uint32_t fence_class,  		if (new_type) {  			fence->signaled_types |= new_type; -			DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n", -				  fence->base.hash.key, fence->signaled_types); +			DRM_DEBUG("Fence %p signaled 0x%08x\n", +				  fence, fence->signaled_types);  			if (driver->needed_flush)  				fc->pending_flush |= driver->needed_flush(fence); @@ -147,8 +147,8 @@ void drm_fence_handler(struct drm_device *dev, uint32_t fence_class,  		fc->waiting_types |= fence->waiting_types & ~fence->signaled_types;  		if (!(fence->type & ~fence->signaled_types)) { -			DRM_DEBUG("Fence completely signaled 0x%08lx\n", -				  fence->base.hash.key); +			DRM_DEBUG("Fence completely signaled %p\n", +				  fence);  			list_del_init(&fence->ring);  		}  	} @@ -196,10 +196,9 @@ void drm_fence_usage_deref_locked(struct drm_fence_object **fence)  	*fence = NULL;  	if (atomic_dec_and_test(&tmp_fence->usage)) {  		drm_fence_unring(dev, &tmp_fence->ring); -		DRM_DEBUG("Destroyed a fence object 0x%08lx\n", -			  tmp_fence->base.hash.key); +		DRM_DEBUG("Destroyed a fence object %p\n", +			  tmp_fence);  		atomic_dec(&fm->count); -		BUG_ON(!list_empty(&tmp_fence->base.list));  		drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);  	}  } @@ -217,7 +216,6 @@ void drm_fence_usage_deref_unlocked(struct drm_fence_object **fence)  		if (atomic_read(&tmp_fence->usage) == 0) {  			drm_fence_unring(dev, &tmp_fence->ring);  			atomic_dec(&fm->count); -			BUG_ON(!list_empty(&tmp_fence->base.list));  			drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);  		}  		mutex_unlock(&dev->struct_mutex); @@ -244,15 +242,6 @@ void drm_fence_reference_unlocked(struct drm_fence_object **dst,  }  EXPORT_SYMBOL(drm_fence_reference_unlocked); -static void drm_fence_object_destroy(struct drm_file *priv, -				     struct drm_user_object *base) -{ -	struct drm_fence_object *fence = -	    drm_user_object_entry(base, struct drm_fence_object, base); - -	drm_fence_usage_deref_locked(&fence); -} -  int drm_fence_object_signaled(struct drm_fence_object *fence, uint32_t mask)  {  	unsigned long flags; @@ -477,7 +466,6 @@ static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class,  	 *  Avoid hitting BUG() for kernel-only fence objects.  	 */ -	INIT_LIST_HEAD(&fence->base.list);  	fence->fence_class = fence_class;  	fence->type = type;  	fence->signaled_types = 0; @@ -493,26 +481,6 @@ static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class,  	return ret;  } -int drm_fence_add_user_object(struct drm_file *priv, -			      struct drm_fence_object *fence, int shareable) -{ -	struct drm_device *dev = priv->minor->dev; -	int ret; - -	mutex_lock(&dev->struct_mutex); -	ret = drm_add_user_object(priv, &fence->base, shareable); -	if (ret) -		goto out; -	atomic_inc(&fence->usage); -	fence->base.type = drm_fence_type; -	fence->base.remove = &drm_fence_object_destroy; -	DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key); -out: -	mutex_unlock(&dev->struct_mutex); -	return ret; -} -EXPORT_SYMBOL(drm_fence_add_user_object); -  int drm_fence_object_create(struct drm_device *dev, uint32_t fence_class,  			    uint32_t type, unsigned flags,  			    struct drm_fence_object **c_fence) @@ -569,261 +537,7 @@ void drm_fence_manager_init(struct drm_device *dev)  	write_unlock_irqrestore(&fm->lock, flags);  } -void drm_fence_fill_arg(struct drm_fence_object *fence, -			struct drm_fence_arg *arg) -{ -	struct drm_device *dev = fence->dev; -	struct drm_fence_manager *fm = &dev->fm; -	unsigned long irq_flags; - -	read_lock_irqsave(&fm->lock, irq_flags); -	arg->handle = fence->base.hash.key; -	arg->fence_class = fence->fence_class; -	arg->type = fence->type; -	arg->signaled = fence->signaled_types; -	arg->error = fence->error; -	arg->sequence = fence->sequence; -	read_unlock_irqrestore(&fm->lock, irq_flags); -} -EXPORT_SYMBOL(drm_fence_fill_arg); -  void drm_fence_manager_takedown(struct drm_device *dev)  {  } -struct drm_fence_object *drm_lookup_fence_object(struct drm_file *priv, -						 uint32_t handle) -{ -	struct drm_device *dev = priv->minor->dev; -	struct drm_user_object *uo; -	struct drm_fence_object *fence; - -	mutex_lock(&dev->struct_mutex); -	uo = drm_lookup_user_object(priv, handle); -	if (!uo || (uo->type != drm_fence_type)) { -		mutex_unlock(&dev->struct_mutex); -		return NULL; -	} -	fence = drm_fence_reference_locked(drm_user_object_entry(uo, struct drm_fence_object, base)); -	mutex_unlock(&dev->struct_mutex); -	return fence; -} - -int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	struct drm_fence_object *fence; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	if (arg->flags & DRM_FENCE_FLAG_EMIT) -		LOCK_TEST_WITH_RETURN(dev, file_priv); -	ret = drm_fence_object_create(dev, arg->fence_class, -				      arg->type, arg->flags, &fence); -	if (ret) -		return ret; -	ret = drm_fence_add_user_object(file_priv, fence, -					arg->flags & -					DRM_FENCE_FLAG_SHAREABLE); -	if (ret) { -		drm_fence_usage_deref_unlocked(&fence); -		return ret; -	} - -	/* -	 * usage > 0. No need to lock dev->struct_mutex; -	 */ - -	arg->handle = fence->base.hash.key; - -	drm_fence_fill_arg(fence, arg); -	drm_fence_usage_deref_unlocked(&fence); - -	return ret; -} - -int drm_fence_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	struct drm_fence_object *fence; -	struct drm_user_object *uo; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	ret = drm_user_object_ref(file_priv, arg->handle, drm_fence_type, &uo); -	if (ret) -		return ret; -	fence = drm_lookup_fence_object(file_priv, arg->handle); -	drm_fence_fill_arg(fence, arg); -	drm_fence_usage_deref_unlocked(&fence); - -	return ret; -} - - -int drm_fence_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	return drm_user_object_unref(file_priv, arg->handle, drm_fence_type); -} - -int drm_fence_signaled_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	struct drm_fence_object *fence; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	fence = drm_lookup_fence_object(file_priv, arg->handle); -	if (!fence) -		return -EINVAL; - -	drm_fence_fill_arg(fence, arg); -	drm_fence_usage_deref_unlocked(&fence); - -	return ret; -} - -int drm_fence_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	struct drm_fence_object *fence; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	fence = drm_lookup_fence_object(file_priv, arg->handle); -	if (!fence) -		return -EINVAL; -	ret = drm_fence_object_flush(fence, arg->type); - -	drm_fence_fill_arg(fence, arg); -	drm_fence_usage_deref_unlocked(&fence); - -	return ret; -} - - -int drm_fence_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	struct drm_fence_object *fence; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	fence = drm_lookup_fence_object(file_priv, arg->handle); -	if (!fence) -		return -EINVAL; -	ret = drm_fence_object_wait(fence, -				    arg->flags & DRM_FENCE_FLAG_WAIT_LAZY, -				    0, arg->type); - -	drm_fence_fill_arg(fence, arg); -	drm_fence_usage_deref_unlocked(&fence); - -	return ret; -} - - -int drm_fence_emit_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	struct drm_fence_object *fence; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	LOCK_TEST_WITH_RETURN(dev, file_priv); -	fence = drm_lookup_fence_object(file_priv, arg->handle); -	if (!fence) -		return -EINVAL; -	ret = drm_fence_object_emit(fence, arg->flags, arg->fence_class, -				    arg->type); - -	drm_fence_fill_arg(fence, arg); -	drm_fence_usage_deref_unlocked(&fence); - -	return ret; -} - -int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ -	int ret; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_arg *arg = data; -	struct drm_fence_object *fence; -	ret = 0; - -	if (!fm->initialized) { -		DRM_ERROR("The DRM driver does not support fencing.\n"); -		return -EINVAL; -	} - -	if (!dev->bm.initialized) { -		DRM_ERROR("Buffer object manager is not initialized\n"); -		return -EINVAL; -	} -	LOCK_TEST_WITH_RETURN(dev, file_priv); -	ret = drm_fence_buffer_objects(dev, NULL, arg->flags, -				       NULL, &fence); -	if (ret) -		return ret; - -	if (!(arg->flags & DRM_FENCE_FLAG_NO_USER)) { -		ret = drm_fence_add_user_object(file_priv, fence, -						arg->flags & -						DRM_FENCE_FLAG_SHAREABLE); -		if (ret) -			return ret; -	} - -	arg->handle = fence->base.hash.key; - -	drm_fence_fill_arg(fence, arg); -	drm_fence_usage_deref_unlocked(&fence); - -	return ret; -} diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index 3b3a0a3c..8eb20b47 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -221,7 +221,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp,  	int minor_id = iminor(inode);  	struct drm_file *priv;  	int ret; -	int i, j;  	if (filp->f_flags & O_EXCL)  		return -EBUSY;	/* No exclusive opens */ @@ -246,22 +245,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,  	priv->lock_count = 0;  	INIT_LIST_HEAD(&priv->lhead); -	INIT_LIST_HEAD(&priv->refd_objects);  	INIT_LIST_HEAD(&priv->fbs); -	for (i = 0; i < _DRM_NO_REF_TYPES; ++i) { -		ret = drm_ht_create(&priv->refd_object_hash[i], -				    DRM_FILE_HASH_ORDER); -		if (ret) -			break; -	} - -	if (ret) { -		for (j = 0; j < i; ++j) -			drm_ht_remove(&priv->refd_object_hash[j]); -		goto out_free; -	} -  	if (dev->driver->driver_features & DRIVER_GEM)  		drm_gem_open(dev, priv); @@ -346,33 +331,6 @@ int drm_fasync(int fd, struct file *filp, int on)  }  EXPORT_SYMBOL(drm_fasync); -static void drm_object_release(struct file *filp) -{ -	struct drm_file *priv = filp->private_data; -	struct list_head *head; -	struct drm_ref_object *ref_object; -	int i; - -	/* -	 * Free leftover ref objects created by me. Note that we cannot use -	 * list_for_each() here, as the struct_mutex may be temporarily -	 * released by the remove_() functions, and thus the lists may be -	 * altered. -	 * Also, a drm_remove_ref_object() will not remove it -	 * from the list unless its refcount is 1. -	 */ - -	head = &priv->refd_objects; -	while (head->next != head) { -		ref_object = list_entry(head->next, struct drm_ref_object, list); -		drm_remove_ref_object(priv, ref_object); -		head = &priv->refd_objects; -	} - -	for (i = 0; i < _DRM_NO_REF_TYPES; ++i) -		drm_ht_remove(&priv->refd_object_hash[i]); -} -  /**   * Release file.   * @@ -512,7 +470,6 @@ int drm_release(struct inode *inode, struct file *filp)  	file_priv->is_master = 0;  	mutex_lock(&dev->struct_mutex); -	drm_object_release(filp);  	list_del(&file_priv->lhead); diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c deleted file mode 100644 index 2994b716..00000000 --- a/linux-core/drm_object.c +++ /dev/null @@ -1,294 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#include "drmP.h" - -int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item, -			int shareable) -{ -	struct drm_device *dev = priv->minor->dev; -	int ret; - -	DRM_ASSERT_LOCKED(&dev->struct_mutex); - -	/* The refcount will be bumped to 1 when we add the ref object below. */ -	atomic_set(&item->refcount, 0); -	item->shareable = shareable; -	item->owner = priv; - -	ret = drm_ht_just_insert_please(&dev->object_hash, &item->hash, -					(unsigned long)item, 31, 0, 0); -	if (ret) -		return ret; - -	ret = drm_add_ref_object(priv, item, _DRM_REF_USE); -	if (ret) -		ret = drm_ht_remove_item(&dev->object_hash, &item->hash); - -	return ret; -} -EXPORT_SYMBOL(drm_add_user_object); - -struct drm_user_object *drm_lookup_user_object(struct drm_file *priv, uint32_t key) -{ -	struct drm_device *dev = priv->minor->dev; -	struct drm_hash_item *hash; -	int ret; -	struct drm_user_object *item; - -	DRM_ASSERT_LOCKED(&dev->struct_mutex); - -	ret = drm_ht_find_item(&dev->object_hash, key, &hash); -	if (ret) -		return NULL; - -	item = drm_hash_entry(hash, struct drm_user_object, hash); - -	if (priv != item->owner) { -		struct drm_open_hash *ht = &priv->refd_object_hash[_DRM_REF_USE]; -		ret = drm_ht_find_item(ht, (unsigned long)item, &hash); -		if (ret) { -			DRM_ERROR("Object not registered for usage\n"); -			return NULL; -		} -	} -	return item; -} -EXPORT_SYMBOL(drm_lookup_user_object); - -static void drm_deref_user_object(struct drm_file *priv, struct drm_user_object *item) -{ -	struct drm_device *dev = priv->minor->dev; -	int ret; - -	if (atomic_dec_and_test(&item->refcount)) { -		ret = drm_ht_remove_item(&dev->object_hash, &item->hash); -		BUG_ON(ret); -		item->remove(priv, item); -	} -} - -static int drm_object_ref_action(struct drm_file *priv, struct drm_user_object *ro, -				 enum drm_ref_type action) -{ -	int ret = 0; - -	switch (action) { -	case _DRM_REF_USE: -		atomic_inc(&ro->refcount); -		break; -	default: -		if (!ro->ref_struct_locked) { -			break; -		} else { -			ro->ref_struct_locked(priv, ro, action); -		} -	} -	return ret; -} - -int drm_add_ref_object(struct drm_file *priv, struct drm_user_object *referenced_object, -		       enum drm_ref_type ref_action) -{ -	int ret = 0; -	struct drm_ref_object *item; -	struct drm_open_hash *ht = &priv->refd_object_hash[ref_action]; - -	DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); -	if (!referenced_object->shareable && priv != referenced_object->owner) { -		DRM_ERROR("Not allowed to reference this object\n"); -		return -EINVAL; -	} - -	/* -	 * If this is not a usage reference, Check that usage has been registered -	 * first. Otherwise strange things may happen on destruction. -	 */ - -	if ((ref_action != _DRM_REF_USE) && priv != referenced_object->owner) { -		item = -		    drm_lookup_ref_object(priv, referenced_object, -					  _DRM_REF_USE); -		if (!item) { -			DRM_ERROR -			    ("Object not registered for usage by this client\n"); -			return -EINVAL; -		} -	} - -	if (NULL != -	    (item = -	     drm_lookup_ref_object(priv, referenced_object, ref_action))) { -		atomic_inc(&item->refcount); -		return drm_object_ref_action(priv, referenced_object, -					     ref_action); -	} - -	item = drm_ctl_calloc(1, sizeof(*item), DRM_MEM_OBJECTS); -	if (item == NULL) { -		DRM_ERROR("Could not allocate reference object\n"); -		return -ENOMEM; -	} - -	atomic_set(&item->refcount, 1); -	item->hash.key = (unsigned long)referenced_object; -	ret = drm_ht_insert_item(ht, &item->hash); -	item->unref_action = ref_action; - -	if (ret) -		goto out; - -	list_add(&item->list, &priv->refd_objects); -	ret = drm_object_ref_action(priv, referenced_object, ref_action); -out: -	return ret; -} - -struct drm_ref_object *drm_lookup_ref_object(struct drm_file *priv, -					struct drm_user_object *referenced_object, -					enum drm_ref_type ref_action) -{ -	struct drm_hash_item *hash; -	int ret; - -	DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); -	ret = drm_ht_find_item(&priv->refd_object_hash[ref_action], -			       (unsigned long)referenced_object, &hash); -	if (ret) -		return NULL; - -	return drm_hash_entry(hash, struct drm_ref_object, hash); -} -EXPORT_SYMBOL(drm_lookup_ref_object); - -static void drm_remove_other_references(struct drm_file *priv, -					struct drm_user_object *ro) -{ -	int i; -	struct drm_open_hash *ht; -	struct drm_hash_item *hash; -	struct drm_ref_object *item; - -	for (i = _DRM_REF_USE + 1; i < _DRM_NO_REF_TYPES; ++i) { -		ht = &priv->refd_object_hash[i]; -		while (!drm_ht_find_item(ht, (unsigned long)ro, &hash)) { -			item = drm_hash_entry(hash, struct drm_ref_object, hash); -			drm_remove_ref_object(priv, item); -		} -	} -} - -void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item) -{ -	int ret; -	struct drm_user_object *user_object = (struct drm_user_object *) item->hash.key; -	struct drm_open_hash *ht = &priv->refd_object_hash[item->unref_action]; -	enum drm_ref_type unref_action; - -	DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); -	unref_action = item->unref_action; -	if (atomic_dec_and_test(&item->refcount)) { -		ret = drm_ht_remove_item(ht, &item->hash); -		BUG_ON(ret); -		list_del_init(&item->list); -		if (unref_action == _DRM_REF_USE) -			drm_remove_other_references(priv, user_object); -		drm_ctl_free(item, sizeof(*item), DRM_MEM_OBJECTS); -	} - -	switch (unref_action) { -	case _DRM_REF_USE: -		drm_deref_user_object(priv, user_object); -		break; -	default: -		BUG_ON(!user_object->unref); -		user_object->unref(priv, user_object, unref_action); -		break; -	} - -} -EXPORT_SYMBOL(drm_remove_ref_object); - -int drm_user_object_ref(struct drm_file *priv, uint32_t user_token, -			enum drm_object_type type, struct drm_user_object **object) -{ -	struct drm_device *dev = priv->minor->dev; -	struct drm_user_object *uo; -	struct drm_hash_item *hash; -	int ret; - -	mutex_lock(&dev->struct_mutex); -	ret = drm_ht_find_item(&dev->object_hash, user_token, &hash); -	if (ret) { -		DRM_ERROR("Could not find user object to reference.\n"); -		goto out_err; -	} -	uo = drm_hash_entry(hash, struct drm_user_object, hash); -	if (uo->type != type) { -		ret = -EINVAL; -		goto out_err; -	} -	ret = drm_add_ref_object(priv, uo, _DRM_REF_USE); -	if (ret) -		goto out_err; -	mutex_unlock(&dev->struct_mutex); -	*object = uo; -	return 0; -out_err: -	mutex_unlock(&dev->struct_mutex); -	return ret; -} - -int drm_user_object_unref(struct drm_file *priv, uint32_t user_token, -			  enum drm_object_type type) -{ -	struct drm_device *dev = priv->minor->dev; -	struct drm_user_object *uo; -	struct drm_ref_object *ro; -	int ret; - -	mutex_lock(&dev->struct_mutex); -	uo = drm_lookup_user_object(priv, user_token); -	if (!uo || (uo->type != type)) { -		ret = -EINVAL; -		goto out_err; -	} -	ro = drm_lookup_ref_object(priv, uo, _DRM_REF_USE); -	if (!ro) { -		ret = -EINVAL; -		goto out_err; -	} -	drm_remove_ref_object(priv, ro); -	mutex_unlock(&dev->struct_mutex); -	return 0; -out_err: -	mutex_unlock(&dev->struct_mutex); -	return ret; -} diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 96cfc113..032687f7 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -34,110 +34,201 @@  struct drm_device;  struct drm_bo_mem_reg; -/*************************************************** - * User space objects. (drm_object.c) - */ - -#define drm_user_object_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) - -enum drm_object_type { -	drm_fence_type, -	drm_buffer_type, -	drm_lock_type, -	    /* -	     * Add other user space object types here. -	     */ -	drm_driver_type0 = 256, -	drm_driver_type1, -	drm_driver_type2, -	drm_driver_type3, -	drm_driver_type4 +#define DRM_FENCE_FLAG_EMIT                0x00000001 +#define DRM_FENCE_FLAG_SHAREABLE           0x00000002 +/** + * On hardware with no interrupt events for operation completion, + * indicates that the kernel should sleep while waiting for any blocking + * operation to complete rather than spinning. + * + * Has no effect otherwise. + */ +#define DRM_FENCE_FLAG_WAIT_LAZY           0x00000004 +#define DRM_FENCE_FLAG_NO_USER             0x00000010 + +/* Reserved for driver use */ +#define DRM_FENCE_MASK_DRIVER              0xFF000000 + +#define DRM_FENCE_TYPE_EXE                 0x00000001 + +struct drm_fence_arg { +	unsigned int handle; +	unsigned int fence_class; +	unsigned int type; +	unsigned int flags; +	unsigned int signaled; +	unsigned int error; +	unsigned int sequence; +	unsigned int pad64; +	uint64_t expand_pad[2]; /*Future expansion */  }; +/* Buffer permissions, referring to how the GPU uses the buffers. + * these translate to fence types used for the buffers. + * Typically a texture buffer is read, A destination buffer is write and + *  a command (batch-) buffer is exe. Can be or-ed together. + */ + +#define DRM_BO_FLAG_READ        (1ULL << 0) +#define DRM_BO_FLAG_WRITE       (1ULL << 1) +#define DRM_BO_FLAG_EXE         (1ULL << 2) +  /* - * A user object is a structure that helps the drm give out user handles - * to kernel internal objects and to keep track of these objects so that - * they can be destroyed, for example when the user space process exits. - * Designed to be accessible using a user space 32-bit handle. - */ - -struct drm_user_object { -	struct drm_hash_item hash; -	struct list_head list; -	enum drm_object_type type; -	atomic_t refcount; -	int shareable; -	struct drm_file *owner; -	void (*ref_struct_locked) (struct drm_file *priv, -				   struct drm_user_object *obj, -				   enum drm_ref_type ref_action); -	void (*unref) (struct drm_file *priv, struct drm_user_object *obj, -		       enum drm_ref_type unref_action); -	void (*remove) (struct drm_file *priv, struct drm_user_object *obj); -}; + * All of the bits related to access mode + */ +#define DRM_BO_MASK_ACCESS	(DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE) +/* + * Status flags. Can be read to determine the actual state of a buffer. + * Can also be set in the buffer mask before validation. + */  /* - * A ref object is a structure which is used to - * keep track of references to user objects and to keep track of these - * references so that they can be destroyed for example when the user space - * process exits. Designed to be accessible using a pointer to the _user_ object. + * Mask: Never evict this buffer. Not even with force. This type of buffer is only + * available to root and must be manually removed before buffer manager shutdown + * or lock. + * Flags: Acknowledge   */ +#define DRM_BO_FLAG_NO_EVICT    (1ULL << 4) -struct drm_ref_object { -	struct drm_hash_item hash; -	struct list_head list; -	atomic_t refcount; -	enum drm_ref_type unref_action; -}; +/* + * Mask: Require that the buffer is placed in mappable memory when validated. + *       If not set the buffer may or may not be in mappable memory when validated. + * Flags: If set, the buffer is in mappable memory. + */ +#define DRM_BO_FLAG_MAPPABLE    (1ULL << 5) -/** - * Must be called with the struct_mutex held. +/* Mask: The buffer should be shareable with other processes. + * Flags: The buffer is shareable with other processes.   */ +#define DRM_BO_FLAG_SHAREABLE   (1ULL << 6) -extern int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item, -			       int shareable); -/** - * Must be called with the struct_mutex held. +/* Mask: If set, place the buffer in cache-coherent memory if available. + *       If clear, never place the buffer in cache coherent memory if validated. + * Flags: The buffer is currently in cache-coherent memory. + */ +#define DRM_BO_FLAG_CACHED      (1ULL << 7) + +/* Mask: Make sure that every time this buffer is validated, + *       it ends up on the same location provided that the memory mask is the same. + *       The buffer will also not be evicted when claiming space for + *       other buffers. Basically a pinned buffer but it may be thrown out as + *       part of buffer manager shutdown or locking. + * Flags: Acknowledge. + */ +#define DRM_BO_FLAG_NO_MOVE     (1ULL << 8) + +/* Mask: Make sure the buffer is in cached memory when mapped.  In conjunction + * with DRM_BO_FLAG_CACHED it also allows the buffer to be bound into the GART + * with unsnooped PTEs instead of snooped, by using chipset-specific cache + * flushing at bind time.  A better name might be DRM_BO_FLAG_TT_UNSNOOPED, + * as the eviction to local memory (TTM unbind) on map is just a side effect + * to prevent aggressive cache prefetch from the GPU disturbing the cache + * management that the DRM is doing. + * + * Flags: Acknowledge. + * Buffers allocated with this flag should not be used for suballocators + * This type may have issues on CPUs with over-aggressive caching + * http://marc.info/?l=linux-kernel&m=102376926732464&w=2   */ +#define DRM_BO_FLAG_CACHED_MAPPED    (1ULL << 19) -extern struct drm_user_object *drm_lookup_user_object(struct drm_file *priv, -						 uint32_t key); + +/* Mask: Force DRM_BO_FLAG_CACHED flag strictly also if it is set. + * Flags: Acknowledge. + */ +#define DRM_BO_FLAG_FORCE_CACHING  (1ULL << 13) + +/* + * Mask: Force DRM_BO_FLAG_MAPPABLE flag strictly also if it is clear. + * Flags: Acknowledge. + */ +#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14) +#define DRM_BO_FLAG_TILE           (1ULL << 15)  /* - * Must be called with the struct_mutex held. May temporarily release it. + * Memory type flags that can be or'ed together in the mask, but only + * one appears in flags.   */ -extern int drm_add_ref_object(struct drm_file *priv, -			      struct drm_user_object *referenced_object, -			      enum drm_ref_type ref_action); +/* System memory */ +#define DRM_BO_FLAG_MEM_LOCAL  (1ULL << 24) +/* Translation table memory */ +#define DRM_BO_FLAG_MEM_TT     (1ULL << 25) +/* Vram memory */ +#define DRM_BO_FLAG_MEM_VRAM   (1ULL << 26) +/* Up to the driver to define. */ +#define DRM_BO_FLAG_MEM_PRIV0  (1ULL << 27) +#define DRM_BO_FLAG_MEM_PRIV1  (1ULL << 28) +#define DRM_BO_FLAG_MEM_PRIV2  (1ULL << 29) +#define DRM_BO_FLAG_MEM_PRIV3  (1ULL << 30) +#define DRM_BO_FLAG_MEM_PRIV4  (1ULL << 31) +/* We can add more of these now with a 64-bit flag type */  /* - * Must be called with the struct_mutex held. + * This is a mask covering all of the memory type flags; easier to just + * use a single constant than a bunch of | values. It covers + * DRM_BO_FLAG_MEM_LOCAL through DRM_BO_FLAG_MEM_PRIV4   */ +#define DRM_BO_MASK_MEM         0x00000000FF000000ULL +/* + * This adds all of the CPU-mapping options in with the memory + * type to label all bits which change how the page gets mapped + */ +#define DRM_BO_MASK_MEMTYPE     (DRM_BO_MASK_MEM | \ +				 DRM_BO_FLAG_CACHED_MAPPED | \ +				 DRM_BO_FLAG_CACHED | \ +				 DRM_BO_FLAG_MAPPABLE) +				  +/* Driver-private flags */ +#define DRM_BO_MASK_DRIVER      0xFFFF000000000000ULL -struct drm_ref_object *drm_lookup_ref_object(struct drm_file *priv, -					struct drm_user_object *referenced_object, -					enum drm_ref_type ref_action);  /* - * Must be called with the struct_mutex held. - * If "item" has been obtained by a call to drm_lookup_ref_object. You may not - * release the struct_mutex before calling drm_remove_ref_object. - * This function may temporarily release the struct_mutex. + * Don't block on validate and map. Instead, return EBUSY. + */ +#define DRM_BO_HINT_DONT_BLOCK  0x00000002 +/* + * Don't place this buffer on the unfenced list. This means + * that the buffer will not end up having a fence associated + * with it as a result of this operation   */ +#define DRM_BO_HINT_DONT_FENCE  0x00000004 +/** + * On hardware with no interrupt events for operation completion, + * indicates that the kernel should sleep while waiting for any blocking + * operation to complete rather than spinning. + * + * Has no effect otherwise. + */ +#define DRM_BO_HINT_WAIT_LAZY   0x00000008 +/* + * The client has compute relocations refering to this buffer using the + * offset in the presumed_offset field. If that offset ends up matching + * where this buffer lands, the kernel is free to skip executing those + * relocations + */ +#define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010 + + +#define DRM_BO_MEM_LOCAL 0 +#define DRM_BO_MEM_TT 1 +#define DRM_BO_MEM_VRAM 2 +#define DRM_BO_MEM_PRIV0 3 +#define DRM_BO_MEM_PRIV1 4 +#define DRM_BO_MEM_PRIV2 5 +#define DRM_BO_MEM_PRIV3 6 +#define DRM_BO_MEM_PRIV4 7 + +#define DRM_BO_MEM_TYPES 8 /* For now. */ + +#define DRM_BO_LOCK_UNLOCK_BM       (1 << 0) +#define DRM_BO_LOCK_IGNORE_NO_EVICT (1 << 1) -extern void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item); -extern int drm_user_object_ref(struct drm_file *priv, uint32_t user_token, -			       enum drm_object_type type, -			       struct drm_user_object **object); -extern int drm_user_object_unref(struct drm_file *priv, uint32_t user_token, -				 enum drm_object_type type);  /***************************************************   * Fence objects. (drm_fence.c)   */  struct drm_fence_object { -	struct drm_user_object base;  	struct drm_device *dev;  	atomic_t usage; @@ -470,7 +561,6 @@ enum drm_bo_type {  struct drm_buffer_object {  	struct drm_device *dev; -	struct drm_user_object base;  	/*  	 * If there is a possibility that the usage variable is zero, @@ -546,7 +636,7 @@ struct drm_mem_type_manager {  };  struct drm_bo_lock { -	struct drm_user_object base; +  //	struct drm_user_object base;  	wait_queue_head_t queue;  	atomic_t write_lock_pending;  	atomic_t readers; @@ -655,22 +745,10 @@ struct drm_bo_driver {  /*   * buffer objects (drm_bo.c)   */ -extern int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int drm_bo_do_validate(struct drm_buffer_object *bo, +		       uint64_t flags, uint64_t mask, uint32_t hint, +		       uint32_t fence_class);  extern int drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, int pin); -extern int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_setstatus_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_version_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);  extern int drm_bo_driver_finish(struct drm_device *dev);  extern int drm_bo_driver_init(struct drm_device *dev);  extern int drm_bo_pci_offset(struct drm_device *dev, @@ -707,18 +785,9 @@ extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type, int kern_c  extern int drm_bo_init_mm(struct drm_device *dev, unsigned type,  			  unsigned long p_offset, unsigned long p_size,  			  int kern_init); -extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, -				  uint64_t flags, uint64_t mask, uint32_t hint, -				  uint32_t fence_class, -				  struct drm_bo_info_rep *rep, -				  struct drm_buffer_object **bo_rep);  extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv,  							  uint32_t handle,  							  int check_owner); -extern int drm_bo_do_validate(struct drm_buffer_object *bo, -			      uint64_t flags, uint64_t mask, uint32_t hint, -			      uint32_t fence_class, -			      struct drm_bo_info_rep *rep);  extern int drm_bo_evict_cached(struct drm_buffer_object *bo);  extern void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo); @@ -766,8 +835,6 @@ extern int drm_bo_pfn_prot(struct drm_buffer_object *bo,  			   unsigned long dst_offset,  			   unsigned long *pfn,  			   pgprot_t *prot); -extern void drm_bo_fill_rep_arg(struct drm_buffer_object *bo, -				struct drm_bo_info_rep *rep);  /* diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 80a8ff5d..b58a1ada 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -72,7 +72,7 @@ void drm_ttm_cache_flush(struct page *pages[], unsigned long num_pages)  		return;  	}  #endif -	if (on_each_cpu(drm_ttm_ipi_handler, NULL, 1, 1) != 0) +	if (on_each_cpu(drm_ttm_ipi_handler, NULL,1) != 0)  		DRM_ERROR("Timed out waiting for drm cache flush.\n");  }  EXPORT_SYMBOL(drm_ttm_cache_flush); diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c deleted file mode 100644 index 4224b737..00000000 --- a/linux-core/i915_buffer.c +++ /dev/null @@ -1,311 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#include "drmP.h" -#include "i915_drm.h" -#include "i915_drv.h" - -struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev) -{ -	return drm_agp_init_ttm(dev); -} - -int i915_fence_type(struct drm_buffer_object *bo, -		     uint32_t *fclass, -		     uint32_t *type) -{ -	if (bo->mem.proposed_flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) -		*type = 3; -	else -		*type = 1; -	return 0; -} - -int i915_invalidate_caches(struct drm_device *dev, uint64_t flags) -{ -	/* -	 * FIXME: Only emit once per batchbuffer submission. -	 */ - -	uint32_t flush_cmd = MI_NO_WRITE_FLUSH; - -	if (flags & DRM_BO_FLAG_READ) -		flush_cmd |= MI_READ_FLUSH; -	if (flags & DRM_BO_FLAG_EXE) -		flush_cmd |= MI_EXE_FLUSH; - -	return i915_emit_mi_flush(dev, flush_cmd); -} - -int i915_init_mem_type(struct drm_device *dev, uint32_t type, -		       struct drm_mem_type_manager *man) -{ -	switch (type) { -	case DRM_BO_MEM_LOCAL: -		man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | -		    _DRM_FLAG_MEMTYPE_CACHED; -		man->drm_bus_maptype = 0; -		man->gpu_offset = 0; -		break; -	case DRM_BO_MEM_TT: -		if (!(drm_core_has_AGP(dev) && dev->agp)) { -			DRM_ERROR("AGP is not enabled for memory type %u\n", -				  (unsigned)type); -			return -EINVAL; -		} -		man->io_offset = dev->agp->agp_info.aper_base; -		man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024; -		man->io_addr = NULL; -		man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | -		    _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; -		man->drm_bus_maptype = _DRM_AGP; -		man->gpu_offset = 0; -		break; -	case DRM_BO_MEM_VRAM: -		if (!(drm_core_has_AGP(dev) && dev->agp)) { -			DRM_ERROR("AGP is not enabled for memory type %u\n", -				  (unsigned)type); -			return -EINVAL; -		} -		man->io_offset = dev->agp->agp_info.aper_base; -		man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024; -		man->io_addr = NULL; -		man->flags =  _DRM_FLAG_MEMTYPE_MAPPABLE | -		    _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_NEEDS_IOREMAP; -		man->drm_bus_maptype = _DRM_AGP; -		man->gpu_offset = 0; -		break; -	case DRM_BO_MEM_PRIV0: /* for OS preallocated space */ -		DRM_ERROR("PRIV0 not used yet.\n"); -		break; -	default: -		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); -		return -EINVAL; -	} -	return 0; -} - -/* - * i915_evict_flags: - * - * @bo: the buffer object to be evicted - * - * Return the bo flags for a buffer which is not mapped to the hardware. - * These will be placed in proposed_flags so that when the move is - * finished, they'll end up in bo->mem.flags - */ -uint64_t i915_evict_flags(struct drm_buffer_object *bo) -{ -	switch (bo->mem.mem_type) { -	case DRM_BO_MEM_LOCAL: -	case DRM_BO_MEM_TT: -		return DRM_BO_FLAG_MEM_LOCAL; -	default: -		return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED; -	} -} - -#if 0 /* See comment below */ - -static void i915_emit_copy_blit(struct drm_device * dev, -				uint32_t src_offset, -				uint32_t dst_offset, -				uint32_t pages, int direction) -{ -	uint32_t cur_pages; -	uint32_t stride = PAGE_SIZE; -	struct drm_i915_private *dev_priv = dev->dev_private; -	RING_LOCALS; - -	if (!dev_priv) -		return; - -	i915_kernel_lost_context(dev); -	while (pages > 0) { -		cur_pages = pages; -		if (cur_pages > 2048) -			cur_pages = 2048; -		pages -= cur_pages; - -		BEGIN_LP_RING(6); -		OUT_RING(SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | -			 XY_SRC_COPY_BLT_WRITE_RGB); -		OUT_RING((stride & 0xffff) | (0xcc << 16) | (1 << 24) | -			 (1 << 25) | (direction ? (1 << 30) : 0)); -		OUT_RING((cur_pages << 16) | PAGE_SIZE); -		OUT_RING(dst_offset); -		OUT_RING(stride & 0xffff); -		OUT_RING(src_offset); -		ADVANCE_LP_RING(); -	} -	return; -} - -static int i915_move_blit(struct drm_buffer_object * bo, -			  int evict, int no_wait, struct drm_bo_mem_reg * new_mem) -{ -	struct drm_bo_mem_reg *old_mem = &bo->mem; -	int dir = 0; - -	if ((old_mem->mem_type == new_mem->mem_type) && -	    (new_mem->mm_node->start < -	     old_mem->mm_node->start + old_mem->mm_node->size)) { -		dir = 1; -	} - -	i915_emit_copy_blit(bo->dev, -			    old_mem->mm_node->start << PAGE_SHIFT, -			    new_mem->mm_node->start << PAGE_SHIFT, -			    new_mem->num_pages, dir); - -	i915_emit_mi_flush(bo->dev, MI_READ_FLUSH | MI_EXE_FLUSH); - -	return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0, -					 DRM_FENCE_TYPE_EXE | -					 DRM_I915_FENCE_TYPE_RW, -					 DRM_I915_FENCE_FLAG_FLUSHED, new_mem); -} - -/* - * Flip destination ttm into cached-coherent AGP, - * then blit and subsequently move out again. - */ - -static int i915_move_flip(struct drm_buffer_object * bo, -			  int evict, int no_wait, struct drm_bo_mem_reg * new_mem) -{ -	struct drm_device *dev = bo->dev; -	struct drm_bo_mem_reg tmp_mem; -	int ret; - -	tmp_mem = *new_mem; -	tmp_mem.mm_node = NULL; -	tmp_mem.mask = DRM_BO_FLAG_MEM_TT | -	    DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING; - -	ret = drm_bo_mem_space(bo, &tmp_mem, no_wait); -	if (ret) -		return ret; - -	ret = drm_bind_ttm(bo->ttm, &tmp_mem); -	if (ret) -		goto out_cleanup; - -	ret = i915_move_blit(bo, 1, no_wait, &tmp_mem); -	if (ret) -		goto out_cleanup; - -	ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem); -out_cleanup: -	if (tmp_mem.mm_node) { -		mutex_lock(&dev->struct_mutex); -		if (tmp_mem.mm_node != bo->pinned_node) -			drm_mm_put_block(tmp_mem.mm_node); -		tmp_mem.mm_node = NULL; -		mutex_unlock(&dev->struct_mutex); -	} -	return ret; -} - -#endif - -/* - * Disable i915_move_flip for now, since we can't guarantee that the hardware - * lock is held here. To re-enable we need to make sure either - * a) The X server is using DRM to submit commands to the ring, or - * b) DRM can use the HP ring for these blits. This means i915 needs to - *    implement a new ring submission mechanism and fence class. - */ -int i915_move(struct drm_buffer_object *bo, -	      int evict, int no_wait, struct drm_bo_mem_reg *new_mem) -{ -	struct drm_bo_mem_reg *old_mem = &bo->mem; - -	if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { -		return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); -	} else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { -		if (1) /*i915_move_flip(bo, evict, no_wait, new_mem)*/ -			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); -	} else { -		if (1) /*i915_move_blit(bo, evict, no_wait, new_mem)*/ -			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); -	} -	return 0; -} - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) -static inline void clflush(volatile void *__p) -{ -	asm volatile("clflush %0" : "+m" (*(char __force *)__p)); -} -#endif - -static inline void drm_cache_flush_addr(void *virt) -{ -#ifdef cpu_has_clflush -	int i; - -	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) -		clflush(virt+i); -#endif -} - -static inline void drm_cache_flush_page(struct page *p) -{ -	drm_cache_flush_addr(page_address(p)); -} - -void i915_flush_ttm(struct drm_ttm *ttm) -{ -	int i; - -	if (!ttm) -		return; - -	DRM_MEMORYBARRIER(); - -#ifdef CONFIG_X86_32 -#ifndef cpu_has_clflush -#define cpu_has_clflush 0 -#endif -	/* Hopefully nobody has built an x86-64 processor without clflush */ -	if (!cpu_has_clflush) { -		wbinvd(); -		DRM_MEMORYBARRIER(); -		return; -	} -#endif - -	for (i = ttm->num_pages - 1; i >= 0; i--) -		drm_cache_flush_page(drm_ttm_get_page(ttm, i)); - -	DRM_MEMORYBARRIER(); -} diff --git a/linux-core/i915_execbuf.c b/linux-core/i915_execbuf.c deleted file mode 100644 index 932882dd..00000000 --- a/linux-core/i915_execbuf.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * Copyright 2003-2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - *     Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - *     Dave Airlie - *     Keith Packard - *     ... ? - */ - -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" - -#if DRM_DEBUG_CODE -#define DRM_DEBUG_RELOCATION	(drm_debug != 0) -#else -#define DRM_DEBUG_RELOCATION	0 -#endif - -enum i915_buf_idle { -	I915_RELOC_UNCHECKED, -	I915_RELOC_IDLE, -	I915_RELOC_BUSY -}; - -struct i915_relocatee_info { -	struct drm_buffer_object *buf; -	unsigned long offset; -	uint32_t *data_page; -	unsigned page_offset; -	struct drm_bo_kmap_obj kmap; -	int is_iomem; -	int dst; -	int idle; -	int performed_ring_relocs; -#ifdef DRM_KMAP_ATOMIC_PROT_PFN -	unsigned long pfn; -	pgprot_t pg_prot; -#endif -}; - -struct drm_i915_validate_buffer { -	struct drm_buffer_object *buffer; -	int presumed_offset_correct; -	void __user *data; -	int ret; -	enum i915_buf_idle idle; -}; - -/* - * I'd like to use MI_STORE_DATA_IMM here, but I can't make - * it work. Seems like GART writes are broken with that - * instruction. Also I'm not sure that MI_FLUSH will - * act as a memory barrier for that instruction. It will - * for this single dword 2D blit. - */ - -static void i915_emit_ring_reloc(struct drm_device *dev, uint32_t offset, -				 uint32_t value) -{ -	struct drm_i915_private *dev_priv = -	    (struct drm_i915_private *)dev->dev_private; - -	RING_LOCALS; -	i915_kernel_lost_context(dev); -	BEGIN_LP_RING(6); -	OUT_RING((0x02 << 29) | (0x40 << 22) | (0x3 << 20) | (0x3)); -	OUT_RING((0x3 << 24) | (0xF0 << 16) | (0x40)); -	OUT_RING((0x1 << 16) | (0x4)); -	OUT_RING(offset); -	OUT_RING(value); -	OUT_RING(0); -	ADVANCE_LP_RING(); -} - -static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer -					    *buffers, unsigned num_buffers) -{ -	while (num_buffers--) -		drm_bo_usage_deref_locked(&buffers[num_buffers].buffer); -} - -int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, -		     struct drm_i915_validate_buffer *buffers, -		     struct i915_relocatee_info *relocatee, uint32_t * reloc) -{ -	unsigned index; -	unsigned long new_cmd_offset; -	u32 val; -	int ret, i; -	int buf_index = -1; - -	/* -	 * FIXME: O(relocs * buffers) complexity. -	 */ - -	for (i = 0; i <= num_buffers; i++) -		if (buffers[i].buffer) -			if (reloc[2] == buffers[i].buffer->base.hash.key) -				buf_index = i; - -	if (buf_index == -1) { -		DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]); -		return -EINVAL; -	} - -	/* -	 * Short-circuit relocations that were correctly -	 * guessed by the client -	 */ -	if (buffers[buf_index].presumed_offset_correct && !DRM_DEBUG_RELOCATION) -		return 0; - -	new_cmd_offset = reloc[0]; -	if (!relocatee->data_page || -	    !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { -		struct drm_bo_mem_reg *mem = &relocatee->buf->mem; - -		drm_bo_kunmap(&relocatee->kmap); -		relocatee->data_page = NULL; -		relocatee->offset = new_cmd_offset; - -		if (unlikely(relocatee->idle == I915_RELOC_UNCHECKED)) { -		  ret = drm_bo_wait(relocatee->buf, 0, 1, 0, 0); -			if (ret) -				return ret; -			relocatee->idle = I915_RELOC_IDLE; -		} - -		if (unlikely((mem->mem_type != DRM_BO_MEM_LOCAL) && -			     (mem->flags & DRM_BO_FLAG_CACHED_MAPPED))) -			drm_bo_evict_cached(relocatee->buf); - -		ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, -				  1, &relocatee->kmap); -		if (ret) { -			DRM_ERROR -			    ("Could not map command buffer to apply relocs\n %08lx", -			     new_cmd_offset); -			return ret; -		} -		relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, -						       &relocatee->is_iomem); -		relocatee->page_offset = (relocatee->offset & PAGE_MASK); -	} - -	val = buffers[buf_index].buffer->offset; -	index = (reloc[0] - relocatee->page_offset) >> 2; - -	/* add in validate */ -	val = val + reloc[1]; - -	if (DRM_DEBUG_RELOCATION) { -		if (buffers[buf_index].presumed_offset_correct && -		    relocatee->data_page[index] != val) { -			DRM_DEBUG -			    ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", -			     reloc[0], reloc[1], buf_index, -			     relocatee->data_page[index], val); -		} -	} - -	if (relocatee->is_iomem) -		iowrite32(val, relocatee->data_page + index); -	else -		relocatee->data_page[index] = val; -	return 0; -} - -int i915_process_relocs(struct drm_file *file_priv, -			uint32_t buf_handle, -			uint32_t __user ** reloc_user_ptr, -			struct i915_relocatee_info *relocatee, -			struct drm_i915_validate_buffer *buffers, -			uint32_t num_buffers) -{ -	int ret, reloc_stride; -	uint32_t cur_offset; -	uint32_t reloc_count; -	uint32_t reloc_type; -	uint32_t reloc_buf_size; -	uint32_t *reloc_buf = NULL; -	int i; - -	/* do a copy from user from the user ptr */ -	ret = get_user(reloc_count, *reloc_user_ptr); -	if (ret) { -		DRM_ERROR("Could not map relocation buffer.\n"); -		goto out; -	} - -	ret = get_user(reloc_type, (*reloc_user_ptr) + 1); -	if (ret) { -		DRM_ERROR("Could not map relocation buffer.\n"); -		goto out; -	} - -	if (reloc_type != 0) { -		DRM_ERROR("Unsupported relocation type requested\n"); -		ret = -EINVAL; -		goto out; -	} - -	reloc_buf_size = -	    (I915_RELOC_HEADER + -	     (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); -	reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); -	if (!reloc_buf) { -		DRM_ERROR("Out of memory for reloc buffer\n"); -		ret = -ENOMEM; -		goto out; -	} - -	if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) { -		ret = -EFAULT; -		goto out; -	} - -	/* get next relocate buffer handle */ -	*reloc_user_ptr = (uint32_t *) * (unsigned long *)&reloc_buf[2]; - -	reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t);	/* may be different for other types of relocs */ - -	DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, -		  *reloc_user_ptr); - -	for (i = 0; i < reloc_count; i++) { -		cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE); - -		ret = i915_apply_reloc(file_priv, num_buffers, buffers, -				       relocatee, reloc_buf + cur_offset); -		if (ret) -			goto out; -	} - -      out: -	if (reloc_buf) -		kfree(reloc_buf); - -	if (relocatee->data_page) { -		drm_bo_kunmap(&relocatee->kmap); -		relocatee->data_page = NULL; -	} - -	return ret; -} - -static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, -			   uint32_t __user * reloc_user_ptr, -			   struct drm_i915_validate_buffer *buffers, -			   uint32_t buf_count) -{ -	struct drm_device *dev = file_priv->minor->dev; -	struct i915_relocatee_info relocatee; -	int ret = 0; -	int b; - -	/* -	 * Short circuit relocations when all previous -	 * buffers offsets were correctly guessed by -	 * the client -	 */ -	if (!DRM_DEBUG_RELOCATION) { -		for (b = 0; b < buf_count; b++) -			if (!buffers[b].presumed_offset_correct) -				break; - -		if (b == buf_count) -			return 0; -	} - -	memset(&relocatee, 0, sizeof(relocatee)); -	relocatee.idle = I915_RELOC_UNCHECKED; - -	mutex_lock(&dev->struct_mutex); -	relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1); -	mutex_unlock(&dev->struct_mutex); -	if (!relocatee.buf) { -		DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle); -		ret = -EINVAL; -		goto out_err; -	} - -	mutex_lock(&relocatee.buf->mutex); -	while (reloc_user_ptr) { -		ret = -		    i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, -					&relocatee, buffers, buf_count); -		if (ret) { -			DRM_ERROR("process relocs failed\n"); -			goto out_err1; -		} -	} - -      out_err1: -	mutex_unlock(&relocatee.buf->mutex); -	drm_bo_usage_deref_unlocked(&relocatee.buf); -      out_err: -	return ret; -} - -static void i915_clear_relocatee(struct i915_relocatee_info *relocatee) -{ -	if (relocatee->data_page) { -#ifndef DRM_KMAP_ATOMIC_PROT_PFN -		drm_bo_kunmap(&relocatee->kmap); -#else -		kunmap_atomic(relocatee->data_page, KM_USER0); -#endif -		relocatee->data_page = NULL; -	} -	relocatee->buf = NULL; -	relocatee->dst = ~0; -} - -static int i915_update_relocatee(struct i915_relocatee_info *relocatee, -				 struct drm_i915_validate_buffer *buffers, -				 unsigned int dst, unsigned long dst_offset) -{ -	int ret; - -	if (unlikely(dst != relocatee->dst || NULL == relocatee->buf)) { -		i915_clear_relocatee(relocatee); -		relocatee->dst = dst; -		relocatee->buf = buffers[dst].buffer; -		relocatee->idle = buffers[dst].idle; - -		/* -		 * Check for buffer idle. If the buffer is busy, revert to -		 * ring relocations. -		 */ - -		if (relocatee->idle == I915_RELOC_UNCHECKED) { -			preempt_enable(); -			mutex_lock(&relocatee->buf->mutex); - -			ret = drm_bo_wait(relocatee->buf, 0, 1, 1, 0); -			if (ret == 0) -				relocatee->idle = I915_RELOC_IDLE; -			else { -				relocatee->idle = I915_RELOC_BUSY; -				relocatee->performed_ring_relocs = 1; -			} -			mutex_unlock(&relocatee->buf->mutex); -			preempt_disable(); -			buffers[dst].idle = relocatee->idle; -		} -	} - -	if (relocatee->idle == I915_RELOC_BUSY) -		return 0; - -	if (unlikely(dst_offset > relocatee->buf->num_pages * PAGE_SIZE)) { -		DRM_ERROR("Relocation destination out of bounds.\n"); -		return -EINVAL; -	} -	if (unlikely(!drm_bo_same_page(relocatee->page_offset, dst_offset) || -		     NULL == relocatee->data_page)) { -#ifdef DRM_KMAP_ATOMIC_PROT_PFN -		if (NULL != relocatee->data_page) { -			kunmap_atomic(relocatee->data_page, KM_USER0); -			relocatee->data_page = NULL; -		} -		ret = drm_bo_pfn_prot(relocatee->buf, dst_offset, -				      &relocatee->pfn, &relocatee->pg_prot); -		if (ret) { -			DRM_ERROR("Can't map relocation destination.\n"); -			return -EINVAL; -		} -		relocatee->data_page = -		    kmap_atomic_prot_pfn(relocatee->pfn, KM_USER0, -					 relocatee->pg_prot); -#else -		if (NULL != relocatee->data_page) { -			drm_bo_kunmap(&relocatee->kmap); -			relocatee->data_page = NULL; -		} - -		ret = drm_bo_kmap(relocatee->buf, dst_offset >> PAGE_SHIFT, -				  1, &relocatee->kmap); -		if (ret) { -			DRM_ERROR("Can't map relocation destination.\n"); -			return ret; -		} - -		relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, -						       &relocatee->is_iomem); -#endif -		relocatee->page_offset = dst_offset & PAGE_MASK; -	} -	return 0; -} - -static int i915_apply_post_reloc(uint32_t reloc[], -				 struct drm_i915_validate_buffer *buffers, -				 uint32_t num_buffers, -				 struct i915_relocatee_info *relocatee) -{ -	uint32_t reloc_buffer = reloc[2]; -	uint32_t dst_buffer = reloc[3]; -	uint32_t val; -	uint32_t index; -	int ret; - -	if (likely(buffers[reloc_buffer].presumed_offset_correct)) -		return 0; -	if (unlikely(reloc_buffer >= num_buffers)) { -		DRM_ERROR("Invalid reloc buffer index.\n"); -		return -EINVAL; -	} -	if (unlikely(dst_buffer >= num_buffers)) { -		DRM_ERROR("Invalid dest buffer index.\n"); -		return -EINVAL; -	} - -	ret = i915_update_relocatee(relocatee, buffers, dst_buffer, reloc[0]); -	if (unlikely(ret)) -		return ret; - -	val = buffers[reloc_buffer].buffer->offset; -	index = (reloc[0] - relocatee->page_offset) >> 2; -	val = val + reloc[1]; - -	if (relocatee->idle == I915_RELOC_BUSY) { -		i915_emit_ring_reloc(relocatee->buf->dev, -				     relocatee->buf->offset + reloc[0], val); -		return 0; -	} -#ifdef DRM_KMAP_ATOMIC_PROT_PFN -	relocatee->data_page[index] = val; -#else -	if (likely(relocatee->is_iomem)) -		iowrite32(val, relocatee->data_page + index); -	else -		relocatee->data_page[index] = val; -#endif - -	return 0; -} - -static int i915_post_relocs(struct drm_file *file_priv, -			    uint32_t __user * new_reloc_ptr, -			    struct drm_i915_validate_buffer *buffers, -			    unsigned int num_buffers) -{ -	uint32_t *reloc; -	uint32_t reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); -	uint32_t header_size = I915_RELOC_HEADER * sizeof(uint32_t); -	struct i915_relocatee_info relocatee; -	uint32_t reloc_type; -	uint32_t num_relocs; -	uint32_t count; -	int ret = 0; -	int i; -	int short_circuit = 1; -	uint32_t __user *reloc_ptr; -	uint64_t new_reloc_data; -	uint32_t reloc_buf_size; -	uint32_t *reloc_buf; - -	for (i = 0; i < num_buffers; ++i) { -		if (unlikely(!buffers[i].presumed_offset_correct)) { -			short_circuit = 0; -			break; -		} -	} - -	if (likely(short_circuit)) -		return 0; - -	memset(&relocatee, 0, sizeof(relocatee)); - -	while (new_reloc_ptr) { -		reloc_ptr = new_reloc_ptr; - -		ret = get_user(num_relocs, reloc_ptr); -		if (unlikely(ret)) -			goto out; -		if (unlikely(!access_ok(VERIFY_READ, reloc_ptr, -					header_size + -					num_relocs * reloc_stride))) -			return -EFAULT; - -		ret = __get_user(reloc_type, reloc_ptr + 1); -		if (unlikely(ret)) -			goto out; - -		if (unlikely(reloc_type != 1)) { -			DRM_ERROR("Unsupported relocation type requested.\n"); -			ret = -EINVAL; -			goto out; -		} - -		ret = __get_user(new_reloc_data, reloc_ptr + 2); -		new_reloc_ptr = (uint32_t __user *) (unsigned long) -		    new_reloc_data; - -		reloc_ptr += I915_RELOC_HEADER; - -		if (num_relocs == 0) -			goto out; - -		reloc_buf_size = -		    (num_relocs * I915_RELOC0_STRIDE) * sizeof(uint32_t); -		reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); -		if (!reloc_buf) { -			DRM_ERROR("Out of memory for reloc buffer\n"); -			ret = -ENOMEM; -			goto out; -		} - -		if (__copy_from_user(reloc_buf, reloc_ptr, reloc_buf_size)) { -			ret = -EFAULT; -			goto out; -		} -		reloc = reloc_buf; -		preempt_disable(); -		for (count = 0; count < num_relocs; ++count) { -			ret = i915_apply_post_reloc(reloc, buffers, -						    num_buffers, &relocatee); -			if (unlikely(ret)) { -				preempt_enable(); -				goto out; -			} -			reloc += I915_RELOC0_STRIDE; -		} -		preempt_enable(); - -		if (reloc_buf) { -			kfree(reloc_buf); -			reloc_buf = NULL; -		} -		i915_clear_relocatee(&relocatee); -	} - -      out: -	/* -	 * Flush ring relocs so the command parser will pick them up. -	 */ - -	if (relocatee.performed_ring_relocs) -		(void)i915_emit_mi_flush(file_priv->minor->dev, 0); - -	i915_clear_relocatee(&relocatee); -	if (reloc_buf) { -		kfree(reloc_buf); -		reloc_buf = NULL; -	} - -	return ret; -} - -static int i915_check_presumed(struct drm_i915_op_arg *arg, -			       struct drm_buffer_object *bo, -			       uint32_t __user * data, int *presumed_ok) -{ -	struct drm_bo_op_req *req = &arg->d.req; -	uint32_t hint_offset; -	uint32_t hint = req->bo_req.hint; - -	*presumed_ok = 0; - -	if (!(hint & DRM_BO_HINT_PRESUMED_OFFSET)) -		return 0; -	if (bo->offset == req->bo_req.presumed_offset) { -		*presumed_ok = 1; -		return 0; -	} - -	/* -	 * We need to turn off the HINT_PRESUMED_OFFSET for this buffer in -	 * the user-space IOCTL argument list, since the buffer has moved, -	 * we're about to apply relocations and we might subsequently -	 * hit an -EAGAIN. In that case the argument list will be reused by -	 * user-space, but the presumed offset is no longer valid. -	 * -	 * Needless to say, this is a bit ugly. -	 */ - -	hint_offset = (uint32_t *) & req->bo_req.hint - (uint32_t *) arg; -	hint &= ~DRM_BO_HINT_PRESUMED_OFFSET; -	return __put_user(hint, data + hint_offset); -} - -/* - * Validate, add fence and relocate a block of bos from a userspace list - */ -int i915_validate_buffer_list(struct drm_file *file_priv, -			      unsigned int fence_class, uint64_t data, -			      struct drm_i915_validate_buffer *buffers, -			      uint32_t * num_buffers, -			      uint32_t __user ** post_relocs) -{ -	struct drm_i915_op_arg arg; -	struct drm_bo_op_req *req = &arg.d.req; -	int ret = 0; -	unsigned buf_count = 0; -	uint32_t buf_handle; -	uint32_t __user *reloc_user_ptr; -	struct drm_i915_validate_buffer *item = buffers; -	*post_relocs = NULL; - -	do { -		if (buf_count >= *num_buffers) { -			DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers); -			ret = -EINVAL; -			goto out_err; -		} -		item = buffers + buf_count; -		item->buffer = NULL; -		item->presumed_offset_correct = 0; -		item->idle = I915_RELOC_UNCHECKED; - -		if (copy_from_user -		    (&arg, (void __user *)(unsigned long)data, sizeof(arg))) { -			ret = -EFAULT; -			goto out_err; -		} - -		ret = 0; -		if (req->op != drm_bo_validate) { -			DRM_ERROR -			    ("Buffer object operation wasn't \"validate\".\n"); -			ret = -EINVAL; -			goto out_err; -		} -		item->ret = 0; -		item->data = (void __user *)(unsigned long)data; - -		buf_handle = req->bo_req.handle; -		reloc_user_ptr = (uint32_t *) (unsigned long)arg.reloc_ptr; - -		/* -		 * Switch mode to post-validation relocations? -		 */ - -		if (unlikely((buf_count == 0) && (*post_relocs == NULL) && -			     (reloc_user_ptr != NULL))) { -			uint32_t reloc_type; - -			ret = get_user(reloc_type, reloc_user_ptr + 1); -			if (ret) -				goto out_err; - -			if (reloc_type == 1) -				*post_relocs = reloc_user_ptr; - -		} - -		if ((*post_relocs == NULL) && (reloc_user_ptr != NULL)) { -			ret = -			    i915_exec_reloc(file_priv, buf_handle, -					    reloc_user_ptr, buffers, buf_count); -			if (ret) -				goto out_err; -			DRM_MEMORYBARRIER(); -		} - -		ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, -					     req->bo_req.flags, -					     req->bo_req.mask, req->bo_req.hint, -					     req->bo_req.fence_class, -					     NULL, &item->buffer); -		if (ret) { -			DRM_ERROR("error on handle validate %d\n", ret); -			goto out_err; -		} - -		buf_count++; - -		ret = i915_check_presumed(&arg, item->buffer, -					  (uint32_t __user *) -					  (unsigned long)data, -					  &item->presumed_offset_correct); -		if (ret) -			goto out_err; - -		data = arg.next; -	} while (data != 0); -      out_err: -	*num_buffers = buf_count; -	item->ret = (ret != -EAGAIN) ? ret : 0; -	return ret; -} - -/* - * Remove all buffers from the unfenced list. - * If the execbuffer operation was aborted, for example due to a signal, - * this also make sure that buffers retain their original state and - * fence pointers. - * Copy back buffer information to user-space unless we were interrupted - * by a signal. In which case the IOCTL must be rerun. - */ - -static int i915_handle_copyback(struct drm_device *dev, -				struct drm_i915_validate_buffer *buffers, -				unsigned int num_buffers, int ret) -{ -	int err = ret; -	int i; -	struct drm_i915_op_arg arg; -	struct drm_buffer_object *bo; - -	if (ret) -		drm_putback_buffer_objects(dev); - -	if (ret != -EAGAIN) { -		for (i = 0; i < num_buffers; ++i) { -			arg.handled = 1; -			arg.d.rep.ret = buffers->ret; -			bo = buffers->buffer; -			mutex_lock(&bo->mutex); -			drm_bo_fill_rep_arg(bo, &arg.d.rep.bo_info); -			mutex_unlock(&bo->mutex); -			if (__copy_to_user(buffers->data, &arg, sizeof(arg))) -				err = -EFAULT; -			buffers++; -		} -	} - -	return err; -} - -/* - * Create a fence object, and if that fails, pretend that everything is - * OK and just idle the GPU. - */ - -void i915_fence_or_sync(struct drm_file *file_priv, -			uint32_t fence_flags, -			struct drm_fence_arg *fence_arg, -			struct drm_fence_object **fence_p) -{ -	struct drm_device *dev = file_priv->minor->dev; -	int ret; -	struct drm_fence_object *fence; - -	ret = drm_fence_buffer_objects(dev, NULL, fence_flags, NULL, &fence); - -	if (ret) { - -		/* -		 * Fence creation failed. -		 * Fall back to synchronous operation and idle the engine. -		 */ - -		(void)i915_emit_mi_flush(dev, MI_READ_FLUSH); -		(void)i915_quiescent(dev); - -		if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - -			/* -			 * Communicate to user-space that -			 * fence creation has failed and that -			 * the engine is idle. -			 */ - -			fence_arg->handle = ~0; -			fence_arg->error = ret; -		} -		drm_putback_buffer_objects(dev); -		if (fence_p) -			*fence_p = NULL; -		return; -	} - -	if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - -		ret = drm_fence_add_user_object(file_priv, fence, -						fence_flags & -						DRM_FENCE_FLAG_SHAREABLE); -		if (!ret) -			drm_fence_fill_arg(fence, fence_arg); -		else { -			/* -			 * Fence user object creation failed. -			 * We must idle the engine here as well, as user- -			 * space expects a fence object to wait on. Since we -			 * have a fence object we wait for it to signal -			 * to indicate engine "sufficiently" idle. -			 */ - -			(void)drm_fence_object_wait(fence, 0, 1, fence->type); -			drm_fence_usage_deref_unlocked(&fence); -			fence_arg->handle = ~0; -			fence_arg->error = ret; -		} -	} - -	if (fence_p) -		*fence_p = fence; -	else if (fence) -		drm_fence_usage_deref_unlocked(&fence); -} - -int i915_execbuffer(struct drm_device *dev, void *data, -		    struct drm_file *file_priv) -{ -	struct drm_i915_private *dev_priv = (struct drm_i915_private *)  -		dev->dev_private; -	struct drm_i915_master_private *master_priv =  -		(struct drm_i915_master_private *) -		dev->primary->master->driver_priv; -	struct drm_i915_sarea *sarea_priv = (struct drm_i915_sarea *) -		master_priv->sarea_priv; -	struct drm_i915_execbuffer *exec_buf = data; -	struct drm_i915_batchbuffer *batch = &exec_buf->batch; -	struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; -	int num_buffers; -	int ret; -	uint32_t __user *post_relocs; - -	if (!dev_priv->allow_batchbuffer) { -		DRM_ERROR("Batchbuffer ioctl disabled\n"); -		return -EINVAL; -	} - -	if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, -							batch->num_cliprects * -							sizeof(struct -							       drm_clip_rect))) -		return -EFAULT; - -	if (exec_buf->num_buffers > dev_priv->max_validate_buffers) -		return -EINVAL; - -	ret = drm_bo_read_lock(&dev->bm.bm_lock, 1); -	if (ret) -		return ret; - -	/* -	 * The cmdbuf_mutex makes sure the validate-submit-fence -	 * operation is atomic. -	 */ - -	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); -	if (ret) { -		drm_bo_read_unlock(&dev->bm.bm_lock); -		return -EAGAIN; -	} - -	num_buffers = exec_buf->num_buffers; - -	if (!dev_priv->val_bufs) { -		dev_priv->val_bufs = -		    vmalloc(sizeof(struct drm_i915_validate_buffer) * -			    dev_priv->max_validate_buffers); -	} -	if (!dev_priv->val_bufs) { -		drm_bo_read_unlock(&dev->bm.bm_lock); -		mutex_unlock(&dev_priv->cmdbuf_mutex); -		return -ENOMEM; -	} - -	/* validate buffer list + fixup relocations */ -	ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, -					dev_priv->val_bufs, &num_buffers, -					&post_relocs); -	if (ret) -		goto out_err0; - -	if (post_relocs) { -		ret = i915_post_relocs(file_priv, post_relocs, -				       dev_priv->val_bufs, num_buffers); -		if (ret) -			goto out_err0; -	} - -	/* make sure all previous memory operations have passed */ -	DRM_MEMORYBARRIER(); - -	if (!post_relocs) { -		drm_agp_chipset_flush(dev); -		batch->start = -		    dev_priv->val_bufs[num_buffers - 1].buffer->offset; -	} else { -		batch->start += dev_priv->val_bufs[0].buffer->offset; -	} - -	DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n", -		  batch->start, batch->used, batch->num_cliprects); - -	ret = i915_dispatch_batchbuffer(dev, batch); -	if (ret) -		goto out_err0; -	if (sarea_priv) -		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); -	i915_fence_or_sync(file_priv, fence_arg->flags, fence_arg, NULL); - -      out_err0: -	ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret); -	mutex_lock(&dev->struct_mutex); -	i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers); -	mutex_unlock(&dev->struct_mutex); -	mutex_unlock(&dev_priv->cmdbuf_mutex); -	drm_bo_read_unlock(&dev->bm.bm_lock); -	return ret; -} diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c deleted file mode 100644 index 436b7e1f..00000000 --- a/linux-core/i915_fence.c +++ /dev/null @@ -1,273 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" - -/* - * Initiate a sync flush if it's not already pending. - */ - -static inline void i915_initiate_rwflush(struct drm_i915_private *dev_priv, -					 struct drm_fence_class_manager *fc) -{ -	if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) && -	    !dev_priv->flush_pending) { -		dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv); -		dev_priv->flush_flags = fc->pending_flush; -		dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0); -		I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); -		dev_priv->flush_pending = 1; -		fc->pending_flush &= ~DRM_I915_FENCE_TYPE_RW; -	} -} - -static inline void i915_report_rwflush(struct drm_device *dev, -				       struct drm_i915_private *dev_priv) -{ -	if (unlikely(dev_priv->flush_pending)) { - -		uint32_t flush_flags; -		uint32_t i_status; -		uint32_t flush_sequence; - -		i_status = READ_HWSP(dev_priv, 0); -		if ((i_status & (1 << 12)) != -		    (dev_priv->saved_flush_status & (1 << 12))) { -			flush_flags = dev_priv->flush_flags; -			flush_sequence = dev_priv->flush_sequence; -			dev_priv->flush_pending = 0; -			drm_fence_handler(dev, 0, flush_sequence, -					  flush_flags, 0); -		} -	} -} - -static void i915_fence_flush(struct drm_device *dev, -			     uint32_t fence_class) -{ -	struct drm_i915_private *dev_priv =  -		(struct drm_i915_private *) dev->dev_private; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_class_manager *fc = &fm->fence_class[0]; -	unsigned long irq_flags; - -	if (unlikely(!dev_priv)) -		return; - -	write_lock_irqsave(&fm->lock, irq_flags); -	i915_initiate_rwflush(dev_priv, fc); -	write_unlock_irqrestore(&fm->lock, irq_flags); -} - - -static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class, -			    uint32_t waiting_types) -{ -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_class_manager *fc = &fm->fence_class[0]; -	uint32_t sequence; - -	if (unlikely(!dev_priv)) -		return; - -	/* -	 * First, report any executed sync flush: -	 */ - -	i915_report_rwflush(dev, dev_priv); - -	/* -	 * Report A new breadcrumb, and adjust IRQs. -	 */ - -	if (waiting_types & DRM_FENCE_TYPE_EXE) { - -		sequence = READ_BREADCRUMB(dev_priv); -		drm_fence_handler(dev, 0, sequence, -				  DRM_FENCE_TYPE_EXE, 0); - -		if (dev_priv->fence_irq_on && -		    !(fc->waiting_types & DRM_FENCE_TYPE_EXE)) { -			i915_user_irq_off(dev); -			dev_priv->fence_irq_on = 0; -		} else if (!dev_priv->fence_irq_on && -			   (fc->waiting_types & DRM_FENCE_TYPE_EXE)) { -			i915_user_irq_on(dev); -			dev_priv->fence_irq_on = 1; -		} -	} - -	/* -	 * There may be new RW flushes pending. Start them. -	 */ -	 -	i915_initiate_rwflush(dev_priv, fc);  - -	/* -	 * And possibly, but unlikely, they finish immediately. -	 */ - -	i915_report_rwflush(dev, dev_priv); - -} - -static int i915_fence_emit_sequence(struct drm_device *dev, uint32_t class, -			     uint32_t flags, uint32_t *sequence, -			     uint32_t *native_type) -{ -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; -	if (unlikely(!dev_priv)) -		return -EINVAL; - -	i915_emit_irq(dev); -	*sequence = (uint32_t) dev_priv->counter; -	*native_type = DRM_FENCE_TYPE_EXE; -	if (flags & DRM_I915_FENCE_FLAG_FLUSHED) -		*native_type |= DRM_I915_FENCE_TYPE_RW; - -	return 0; -} - -void i915_fence_handler(struct drm_device *dev) -{ -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_class_manager *fc = &fm->fence_class[0]; - -	write_lock(&fm->lock); -	if (likely(dev_priv->fence_irq_on)) -		i915_fence_poll(dev, 0, fc->waiting_types); -	write_unlock(&fm->lock); -} - -/* - * We need a separate wait function since we need to poll for - * sync flushes. - */ - -static int i915_fence_wait(struct drm_fence_object *fence, -			   int lazy, int interruptible, uint32_t mask) -{ -	struct drm_device *dev = fence->dev; -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; -	struct drm_fence_manager *fm = &dev->fm; -	struct drm_fence_class_manager *fc = &fm->fence_class[0]; -	int ret; -	unsigned long  _end = jiffies + 3 * DRM_HZ; - -	drm_fence_object_flush(fence, mask); -	if (likely(interruptible)) -		ret = wait_event_interruptible_timeout -			(fc->fence_queue, drm_fence_object_signaled(fence, DRM_FENCE_TYPE_EXE),  -			 3 * DRM_HZ); -	else  -		ret = wait_event_timeout -			(fc->fence_queue, drm_fence_object_signaled(fence, DRM_FENCE_TYPE_EXE),  -			 3 * DRM_HZ); - -	if (unlikely(ret == -ERESTARTSYS)) -		return -EAGAIN; - -	if (unlikely(ret == 0)) -		return -EBUSY; - -	if (likely(mask == DRM_FENCE_TYPE_EXE ||  -		   drm_fence_object_signaled(fence, mask)))  -		return 0; - -	/* -	 * Remove this code snippet when fixed. HWSTAM doesn't let -	 * flush info through... -	 */ - -	if (unlikely(dev_priv && !dev_priv->irq_enabled)) { -		unsigned long irq_flags; - -		DRM_ERROR("X server disabled IRQs before releasing frame buffer.\n"); -		msleep(100); -		dev_priv->flush_pending = 0; -		write_lock_irqsave(&fm->lock, irq_flags); -		drm_fence_handler(dev, fence->fence_class,  -				  fence->sequence, fence->type, 0); -		write_unlock_irqrestore(&fm->lock, irq_flags); -	} - -	/* -	 * Poll for sync flush completion. -	 */ - -	return drm_fence_wait_polling(fence, lazy, interruptible, mask, _end); -} - -static uint32_t i915_fence_needed_flush(struct drm_fence_object *fence) -{ -	uint32_t flush_flags = fence->waiting_types &  -		~(DRM_FENCE_TYPE_EXE | fence->signaled_types); - -	if (likely(flush_flags == 0 ||  -		   ((flush_flags & ~fence->native_types) == 0) ||  -		   (fence->signaled_types != DRM_FENCE_TYPE_EXE))) -		return 0; -	else { -		struct drm_device *dev = fence->dev; -		struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; -		struct drm_fence_driver *driver = dev->driver->fence_driver; -		 -		if (unlikely(!dev_priv)) -			return 0; - -		if (dev_priv->flush_pending) { -			uint32_t diff = (dev_priv->flush_sequence - fence->sequence) &  -				driver->sequence_mask; - -			if (diff < driver->wrap_diff) -				return 0; -		} -	} -	return flush_flags; -} - -struct drm_fence_driver i915_fence_driver = { -	.num_classes = 1, -	.wrap_diff = (1U << (BREADCRUMB_BITS - 1)), -	.flush_diff = (1U << (BREADCRUMB_BITS - 2)), -	.sequence_mask = BREADCRUMB_MASK, -	.has_irq = NULL, -	.emit = i915_fence_emit_sequence, -	.flush = i915_fence_flush, -	.poll = i915_fence_poll, -	.needed_flush = i915_fence_needed_flush, -	.wait = i915_fence_wait, -}; diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index e06cba5b..1aa3afbf 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -245,8 +245,7 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,  	if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) {  	  ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, -				   DRM_BO_HINT_DONT_FENCE, -				   0, NULL); +				   DRM_BO_HINT_DONT_FENCE, 0);  	} else  	  ret = 0; @@ -276,8 +275,7 @@ int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data,  	/* validate into a pin with no fence */  	ret = drm_bo_do_validate(obj_priv->bo, DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT, -				 DRM_BO_HINT_DONT_FENCE, -				 0, NULL); +				 DRM_BO_HINT_DONT_FENCE, 0);  	mutex_lock(&dev->struct_mutex);  	drm_gem_object_unreference(obj); @@ -321,7 +319,7 @@ int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data,  	//VB_AGE_TEST_WITH_RETURN(dev_priv);  	ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, -				 0 , 0, NULL); +				 0 , 0);  	if (ret)  		return ret; @@ -693,7 +691,7 @@ int radeon_gem_object_pin(struct drm_gem_object *obj,  	obj_priv = obj->driver_private;  	ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, -				 DRM_BO_HINT_DONT_FENCE, 0, NULL); +				 DRM_BO_HINT_DONT_FENCE, 0);  	return ret;  } @@ -743,7 +741,7 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32  	ret = drm_bo_do_validate(dev_priv->ib_objs[index]->bo, 0,  				 DRM_BO_FLAG_NO_EVICT, -				 0, 0, NULL); +				 0, 0);  	if (ret) {  		DRM_ERROR("Failed to validate IB %d\n", index);  		return -EINVAL; @@ -761,7 +759,6 @@ static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords  	struct drm_fence_object *fence;  	int ret;  	int i; -	RING_LOCALS;  	for (i = 0; i < RADEON_NUM_IB; i++) { @@ -821,7 +818,7 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri  		flags = DRM_BO_FLAG_MEM_TT;  	} -	ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0, NULL); +	ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0);  	if (ret)  		return ret; | 
