drm_context.c

来自「linux2.6.16版本」· C语言 代码 · 共 595 行 · 第 1/2 页

C
595
字号
}/*@}*//******************************************************************//** \name The actual DRM context handling routines *//*@{*//** * Switch context. * * \param dev DRM device. * \param old old context handle. * \param new new context handle. * \return zero on success or a negative number on failure. * * Attempt to set drm_device::context_flag. */static int drm_context_switch(drm_device_t * dev, int old, int new){	if (test_and_set_bit(0, &dev->context_flag)) {		DRM_ERROR("Reentering -- FIXME\n");		return -EBUSY;	}	DRM_DEBUG("Context switch from %d to %d\n", old, new);	if (new == dev->last_context) {		clear_bit(0, &dev->context_flag);		return 0;	}	return 0;}/** * Complete context switch. * * \param dev DRM device. * \param new new context handle. * \return zero on success or a negative number on failure. * * Updates drm_device::last_context and drm_device::last_switch. Verifies the * hardware lock is held, clears the drm_device::context_flag and wakes up * drm_device::context_wait. */static int drm_context_switch_complete(drm_device_t * dev, int new){	dev->last_context = new;	/* PRE/POST: This is the _only_ writer. */	dev->last_switch = jiffies;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("Lock isn't held after context switch\n");	}	/* If a context switch is ever initiated	   when the kernel holds the lock, release	   that lock here. */	clear_bit(0, &dev->context_flag);	wake_up(&dev->context_wait);	return 0;}/** * Reserve contexts. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx_res structure. * \return zero on success or a negative number on failure. */int drm_resctx(struct inode *inode, struct file *filp,	       unsigned int cmd, unsigned long arg){	drm_ctx_res_t res;	drm_ctx_t __user *argp = (void __user *)arg;	drm_ctx_t ctx;	int i;	if (copy_from_user(&res, argp, sizeof(res)))		return -EFAULT;	if (res.count >= DRM_RESERVED_CONTEXTS) {		memset(&ctx, 0, sizeof(ctx));		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {			ctx.handle = i;			if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx)))				return -EFAULT;		}	}	res.count = DRM_RESERVED_CONTEXTS;	if (copy_to_user(argp, &res, sizeof(res)))		return -EFAULT;	return 0;}/** * Add context. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Get a new handle for the context and copy to userspace. */int drm_addctx(struct inode *inode, struct file *filp,	       unsigned int cmd, unsigned long arg){	drm_file_t *priv = filp->private_data;	drm_device_t *dev = priv->head->dev;	drm_ctx_list_t *ctx_entry;	drm_ctx_t __user *argp = (void __user *)arg;	drm_ctx_t ctx;	if (copy_from_user(&ctx, argp, sizeof(ctx)))		return -EFAULT;	ctx.handle = drm_ctxbitmap_next(dev);	if (ctx.handle == DRM_KERNEL_CONTEXT) {		/* Skip kernel's context and get a new one. */		ctx.handle = drm_ctxbitmap_next(dev);	}	DRM_DEBUG("%d\n", ctx.handle);	if (ctx.handle == -1) {		DRM_DEBUG("Not enough free contexts.\n");		/* Should this return -EBUSY instead? */		return -ENOMEM;	}	if (ctx.handle != DRM_KERNEL_CONTEXT) {		if (dev->driver->context_ctor)			if (!dev->driver->context_ctor(dev, ctx.handle)) {				DRM_DEBUG("Running out of ctxs or memory.\n");				return -ENOMEM;			}	}	ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);	if (!ctx_entry) {		DRM_DEBUG("out of memory\n");		return -ENOMEM;	}	INIT_LIST_HEAD(&ctx_entry->head);	ctx_entry->handle = ctx.handle;	ctx_entry->tag = priv;	mutex_lock(&dev->ctxlist_mutex);	list_add(&ctx_entry->head, &dev->ctxlist->head);	++dev->ctx_count;	mutex_unlock(&dev->ctxlist_mutex);	if (copy_to_user(argp, &ctx, sizeof(ctx)))		return -EFAULT;	return 0;}int drm_modctx(struct inode *inode, struct file *filp,	       unsigned int cmd, unsigned long arg){	/* This does nothing */	return 0;}/** * Get context. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. */int drm_getctx(struct inode *inode, struct file *filp,	       unsigned int cmd, unsigned long arg){	drm_ctx_t __user *argp = (void __user *)arg;	drm_ctx_t ctx;	if (copy_from_user(&ctx, argp, sizeof(ctx)))		return -EFAULT;	/* This is 0, because we don't handle any context flags */	ctx.flags = 0;	if (copy_to_user(argp, &ctx, sizeof(ctx)))		return -EFAULT;	return 0;}/** * Switch context. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Calls context_switch(). */int drm_switchctx(struct inode *inode, struct file *filp,		  unsigned int cmd, unsigned long arg){	drm_file_t *priv = filp->private_data;	drm_device_t *dev = priv->head->dev;	drm_ctx_t ctx;	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))		return -EFAULT;	DRM_DEBUG("%d\n", ctx.handle);	return drm_context_switch(dev, dev->last_context, ctx.handle);}/** * New context. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Calls context_switch_complete(). */int drm_newctx(struct inode *inode, struct file *filp,	       unsigned int cmd, unsigned long arg){	drm_file_t *priv = filp->private_data;	drm_device_t *dev = priv->head->dev;	drm_ctx_t ctx;	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))		return -EFAULT;	DRM_DEBUG("%d\n", ctx.handle);	drm_context_switch_complete(dev, ctx.handle);	return 0;}/** * Remove context. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * If not the special kernel context, calls ctxbitmap_free() to free the specified context. */int drm_rmctx(struct inode *inode, struct file *filp,	      unsigned int cmd, unsigned long arg){	drm_file_t *priv = filp->private_data;	drm_device_t *dev = priv->head->dev;	drm_ctx_t ctx;	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))		return -EFAULT;	DRM_DEBUG("%d\n", ctx.handle);	if (ctx.handle == DRM_KERNEL_CONTEXT + 1) {		priv->remove_auth_on_close = 1;	}	if (ctx.handle != DRM_KERNEL_CONTEXT) {		if (dev->driver->context_dtor)			dev->driver->context_dtor(dev, ctx.handle);		drm_ctxbitmap_free(dev, ctx.handle);	}	mutex_lock(&dev->ctxlist_mutex);	if (!list_empty(&dev->ctxlist->head)) {		drm_ctx_list_t *pos, *n;		list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {			if (pos->handle == ctx.handle) {				list_del(&pos->head);				drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);				--dev->ctx_count;			}		}	}	mutex_unlock(&dev->ctxlist_mutex);	return 0;}/*@}*/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?