drm_context.c
来自「LINUX 2.6.17.4的源码」· 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 + -
显示快捷键?