1 1.9 riastrad /* $NetBSD: drm_context.c,v 1.9 2021/12/19 12:30:04 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.4 riastrad * Legacy: Generic DRM Contexts 5 1.1 riastrad * 6 1.1 riastrad * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 7 1.1 riastrad * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 8 1.1 riastrad * All Rights Reserved. 9 1.1 riastrad * 10 1.4 riastrad * Author: Rickard E. (Rik) Faith <faith (at) valinux.com> 11 1.4 riastrad * Author: Gareth Hughes <gareth (at) valinux.com> 12 1.4 riastrad * 13 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 14 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 15 1.1 riastrad * to deal in the Software without restriction, including without limitation 16 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 18 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 19 1.1 riastrad * 20 1.1 riastrad * The above copyright notice and this permission notice (including the next 21 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 22 1.1 riastrad * Software. 23 1.1 riastrad * 24 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 1.1 riastrad * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 28 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 29 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 31 1.1 riastrad */ 32 1.1 riastrad 33 1.4 riastrad #include <sys/cdefs.h> 34 1.9 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_context.c,v 1.9 2021/12/19 12:30:04 riastradh Exp $"); 35 1.7 riastrad 36 1.9 riastrad #include <linux/err.h> 37 1.7 riastrad #include <linux/slab.h> 38 1.7 riastrad #include <linux/uaccess.h> 39 1.7 riastrad 40 1.7 riastrad #include <drm/drm_drv.h> 41 1.7 riastrad #include <drm/drm_file.h> 42 1.7 riastrad #include <drm/drm_print.h> 43 1.2 riastrad 44 1.4 riastrad #include "drm_legacy.h" 45 1.4 riastrad 46 1.4 riastrad struct drm_ctx_list { 47 1.4 riastrad struct list_head head; 48 1.4 riastrad drm_context_t handle; 49 1.4 riastrad struct drm_file *tag; 50 1.4 riastrad }; 51 1.1 riastrad 52 1.1 riastrad /******************************************************************/ 53 1.1 riastrad /** \name Context bitmap support */ 54 1.1 riastrad /*@{*/ 55 1.1 riastrad 56 1.1 riastrad /** 57 1.1 riastrad * Free a handle from the context bitmap. 58 1.1 riastrad * 59 1.1 riastrad * \param dev DRM device. 60 1.1 riastrad * \param ctx_handle context handle. 61 1.1 riastrad * 62 1.1 riastrad * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry 63 1.1 riastrad * in drm_device::ctx_idr, while holding the drm_device::struct_mutex 64 1.1 riastrad * lock. 65 1.1 riastrad */ 66 1.4 riastrad void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle) 67 1.1 riastrad { 68 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 69 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 70 1.4 riastrad return; 71 1.4 riastrad 72 1.1 riastrad mutex_lock(&dev->struct_mutex); 73 1.1 riastrad idr_remove(&dev->ctx_idr, ctx_handle); 74 1.1 riastrad mutex_unlock(&dev->struct_mutex); 75 1.1 riastrad } 76 1.1 riastrad 77 1.1 riastrad /** 78 1.1 riastrad * Context bitmap allocation. 79 1.1 riastrad * 80 1.1 riastrad * \param dev DRM device. 81 1.1 riastrad * \return (non-negative) context handle on success or a negative number on failure. 82 1.1 riastrad * 83 1.1 riastrad * Allocate a new idr from drm_device::ctx_idr while holding the 84 1.1 riastrad * drm_device::struct_mutex lock. 85 1.1 riastrad */ 86 1.4 riastrad static int drm_legacy_ctxbitmap_next(struct drm_device * dev) 87 1.1 riastrad { 88 1.1 riastrad int ret; 89 1.1 riastrad 90 1.5 riastrad idr_preload(GFP_KERNEL); 91 1.1 riastrad mutex_lock(&dev->struct_mutex); 92 1.3 riastrad ret = idr_alloc(&dev->ctx_idr, NULL, DRM_RESERVED_CONTEXTS, 0, 93 1.3 riastrad GFP_KERNEL); 94 1.1 riastrad mutex_unlock(&dev->struct_mutex); 95 1.5 riastrad idr_preload_end(); 96 1.3 riastrad return ret; 97 1.1 riastrad } 98 1.1 riastrad 99 1.1 riastrad /** 100 1.1 riastrad * Context bitmap initialization. 101 1.1 riastrad * 102 1.1 riastrad * \param dev DRM device. 103 1.1 riastrad * 104 1.1 riastrad * Initialise the drm_device::ctx_idr 105 1.1 riastrad */ 106 1.4 riastrad void drm_legacy_ctxbitmap_init(struct drm_device * dev) 107 1.1 riastrad { 108 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 109 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 110 1.4 riastrad return; 111 1.4 riastrad 112 1.1 riastrad idr_init(&dev->ctx_idr); 113 1.1 riastrad } 114 1.1 riastrad 115 1.1 riastrad /** 116 1.1 riastrad * Context bitmap cleanup. 117 1.1 riastrad * 118 1.1 riastrad * \param dev DRM device. 119 1.1 riastrad * 120 1.1 riastrad * Free all idr members using drm_ctx_sarea_free helper function 121 1.1 riastrad * while holding the drm_device::struct_mutex lock. 122 1.1 riastrad */ 123 1.4 riastrad void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev) 124 1.1 riastrad { 125 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 126 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 127 1.4 riastrad return; 128 1.4 riastrad 129 1.1 riastrad mutex_lock(&dev->struct_mutex); 130 1.2 riastrad idr_destroy(&dev->ctx_idr); 131 1.1 riastrad mutex_unlock(&dev->struct_mutex); 132 1.1 riastrad } 133 1.1 riastrad 134 1.4 riastrad /** 135 1.4 riastrad * drm_ctxbitmap_flush() - Flush all contexts owned by a file 136 1.4 riastrad * @dev: DRM device to operate on 137 1.4 riastrad * @file: Open file to flush contexts for 138 1.4 riastrad * 139 1.4 riastrad * This iterates over all contexts on @dev and drops them if they're owned by 140 1.4 riastrad * @file. Note that after this call returns, new contexts might be added if 141 1.4 riastrad * the file is still alive. 142 1.4 riastrad */ 143 1.4 riastrad void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file) 144 1.4 riastrad { 145 1.4 riastrad struct drm_ctx_list *pos, *tmp; 146 1.4 riastrad 147 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 148 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 149 1.4 riastrad return; 150 1.4 riastrad 151 1.4 riastrad mutex_lock(&dev->ctxlist_mutex); 152 1.4 riastrad 153 1.4 riastrad list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) { 154 1.4 riastrad if (pos->tag == file && 155 1.4 riastrad pos->handle != DRM_KERNEL_CONTEXT) { 156 1.4 riastrad if (dev->driver->context_dtor) 157 1.4 riastrad dev->driver->context_dtor(dev, pos->handle); 158 1.4 riastrad 159 1.4 riastrad drm_legacy_ctxbitmap_free(dev, pos->handle); 160 1.4 riastrad list_del(&pos->head); 161 1.4 riastrad kfree(pos); 162 1.4 riastrad } 163 1.4 riastrad } 164 1.4 riastrad 165 1.4 riastrad mutex_unlock(&dev->ctxlist_mutex); 166 1.4 riastrad } 167 1.4 riastrad 168 1.1 riastrad /*@}*/ 169 1.1 riastrad 170 1.1 riastrad /******************************************************************/ 171 1.1 riastrad /** \name Per Context SAREA Support */ 172 1.1 riastrad /*@{*/ 173 1.1 riastrad 174 1.1 riastrad /** 175 1.1 riastrad * Get per-context SAREA. 176 1.1 riastrad * 177 1.1 riastrad * \param inode device inode. 178 1.1 riastrad * \param file_priv DRM file private. 179 1.1 riastrad * \param cmd command. 180 1.1 riastrad * \param arg user argument pointing to a drm_ctx_priv_map structure. 181 1.1 riastrad * \return zero on success or a negative number on failure. 182 1.1 riastrad * 183 1.1 riastrad * Gets the map from drm_device::ctx_idr with the handle specified and 184 1.1 riastrad * returns its handle. 185 1.1 riastrad */ 186 1.4 riastrad int drm_legacy_getsareactx(struct drm_device *dev, void *data, 187 1.4 riastrad struct drm_file *file_priv) 188 1.1 riastrad { 189 1.1 riastrad struct drm_ctx_priv_map *request = data; 190 1.1 riastrad struct drm_local_map *map; 191 1.1 riastrad struct drm_map_list *_entry; 192 1.1 riastrad 193 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 194 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 195 1.7 riastrad return -EOPNOTSUPP; 196 1.4 riastrad 197 1.1 riastrad mutex_lock(&dev->struct_mutex); 198 1.1 riastrad 199 1.1 riastrad map = idr_find(&dev->ctx_idr, request->ctx_id); 200 1.1 riastrad if (!map) { 201 1.1 riastrad mutex_unlock(&dev->struct_mutex); 202 1.1 riastrad return -EINVAL; 203 1.1 riastrad } 204 1.1 riastrad 205 1.1 riastrad request->handle = NULL; 206 1.1 riastrad list_for_each_entry(_entry, &dev->maplist, head) { 207 1.1 riastrad if (_entry->map == map) { 208 1.1 riastrad request->handle = 209 1.1 riastrad (void *)(unsigned long)_entry->user_token; 210 1.1 riastrad break; 211 1.1 riastrad } 212 1.1 riastrad } 213 1.1 riastrad 214 1.1 riastrad mutex_unlock(&dev->struct_mutex); 215 1.1 riastrad 216 1.1 riastrad if (request->handle == NULL) 217 1.1 riastrad return -EINVAL; 218 1.1 riastrad 219 1.1 riastrad return 0; 220 1.1 riastrad } 221 1.1 riastrad 222 1.1 riastrad /** 223 1.1 riastrad * Set per-context SAREA. 224 1.1 riastrad * 225 1.1 riastrad * \param inode device inode. 226 1.1 riastrad * \param file_priv DRM file private. 227 1.1 riastrad * \param cmd command. 228 1.1 riastrad * \param arg user argument pointing to a drm_ctx_priv_map structure. 229 1.1 riastrad * \return zero on success or a negative number on failure. 230 1.1 riastrad * 231 1.1 riastrad * Searches the mapping specified in \p arg and update the entry in 232 1.1 riastrad * drm_device::ctx_idr with it. 233 1.1 riastrad */ 234 1.4 riastrad int drm_legacy_setsareactx(struct drm_device *dev, void *data, 235 1.4 riastrad struct drm_file *file_priv) 236 1.1 riastrad { 237 1.1 riastrad struct drm_ctx_priv_map *request = data; 238 1.1 riastrad struct drm_local_map *map = NULL; 239 1.1 riastrad struct drm_map_list *r_list = NULL; 240 1.1 riastrad 241 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 242 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 243 1.7 riastrad return -EOPNOTSUPP; 244 1.4 riastrad 245 1.1 riastrad mutex_lock(&dev->struct_mutex); 246 1.1 riastrad list_for_each_entry(r_list, &dev->maplist, head) { 247 1.1 riastrad if (r_list->map 248 1.1 riastrad && r_list->user_token == (unsigned long) request->handle) 249 1.1 riastrad goto found; 250 1.1 riastrad } 251 1.1 riastrad bad: 252 1.1 riastrad mutex_unlock(&dev->struct_mutex); 253 1.1 riastrad return -EINVAL; 254 1.1 riastrad 255 1.1 riastrad found: 256 1.1 riastrad map = r_list->map; 257 1.1 riastrad if (!map) 258 1.1 riastrad goto bad; 259 1.1 riastrad 260 1.1 riastrad if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id))) 261 1.1 riastrad goto bad; 262 1.1 riastrad 263 1.1 riastrad mutex_unlock(&dev->struct_mutex); 264 1.1 riastrad 265 1.1 riastrad return 0; 266 1.1 riastrad } 267 1.1 riastrad 268 1.1 riastrad /*@}*/ 269 1.1 riastrad 270 1.1 riastrad /******************************************************************/ 271 1.1 riastrad /** \name The actual DRM context handling routines */ 272 1.1 riastrad /*@{*/ 273 1.1 riastrad 274 1.1 riastrad /** 275 1.1 riastrad * Switch context. 276 1.1 riastrad * 277 1.1 riastrad * \param dev DRM device. 278 1.1 riastrad * \param old old context handle. 279 1.1 riastrad * \param new new context handle. 280 1.1 riastrad * \return zero on success or a negative number on failure. 281 1.1 riastrad * 282 1.1 riastrad * Attempt to set drm_device::context_flag. 283 1.1 riastrad */ 284 1.1 riastrad static int drm_context_switch(struct drm_device * dev, int old, int new) 285 1.1 riastrad { 286 1.1 riastrad if (test_and_set_bit(0, &dev->context_flag)) { 287 1.1 riastrad DRM_ERROR("Reentering -- FIXME\n"); 288 1.1 riastrad return -EBUSY; 289 1.1 riastrad } 290 1.1 riastrad 291 1.1 riastrad DRM_DEBUG("Context switch from %d to %d\n", old, new); 292 1.1 riastrad 293 1.1 riastrad if (new == dev->last_context) { 294 1.1 riastrad clear_bit(0, &dev->context_flag); 295 1.1 riastrad return 0; 296 1.1 riastrad } 297 1.1 riastrad 298 1.1 riastrad return 0; 299 1.1 riastrad } 300 1.1 riastrad 301 1.1 riastrad /** 302 1.1 riastrad * Complete context switch. 303 1.1 riastrad * 304 1.1 riastrad * \param dev DRM device. 305 1.1 riastrad * \param new new context handle. 306 1.1 riastrad * \return zero on success or a negative number on failure. 307 1.1 riastrad * 308 1.1 riastrad * Updates drm_device::last_context and drm_device::last_switch. Verifies the 309 1.1 riastrad * hardware lock is held, clears the drm_device::context_flag and wakes up 310 1.1 riastrad * drm_device::context_wait. 311 1.1 riastrad */ 312 1.1 riastrad static int drm_context_switch_complete(struct drm_device *dev, 313 1.1 riastrad struct drm_file *file_priv, int new) 314 1.1 riastrad { 315 1.1 riastrad dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ 316 1.1 riastrad 317 1.2 riastrad spin_lock(&file_priv->master->lock.spinlock); 318 1.2 riastrad if (file_priv->master->lock.hw_lock == NULL || 319 1.2 riastrad !_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) { 320 1.1 riastrad DRM_ERROR("Lock isn't held after context switch\n"); 321 1.1 riastrad } 322 1.2 riastrad spin_unlock(&file_priv->master->lock.spinlock); 323 1.1 riastrad 324 1.1 riastrad /* If a context switch is ever initiated 325 1.1 riastrad when the kernel holds the lock, release 326 1.1 riastrad that lock here. */ 327 1.1 riastrad clear_bit(0, &dev->context_flag); 328 1.1 riastrad 329 1.1 riastrad return 0; 330 1.1 riastrad } 331 1.1 riastrad 332 1.1 riastrad /** 333 1.1 riastrad * Reserve contexts. 334 1.1 riastrad * 335 1.1 riastrad * \param inode device inode. 336 1.1 riastrad * \param file_priv DRM file private. 337 1.1 riastrad * \param cmd command. 338 1.1 riastrad * \param arg user argument pointing to a drm_ctx_res structure. 339 1.1 riastrad * \return zero on success or a negative number on failure. 340 1.1 riastrad */ 341 1.4 riastrad int drm_legacy_resctx(struct drm_device *dev, void *data, 342 1.4 riastrad struct drm_file *file_priv) 343 1.1 riastrad { 344 1.1 riastrad struct drm_ctx_res *res = data; 345 1.1 riastrad struct drm_ctx ctx; 346 1.1 riastrad int i; 347 1.1 riastrad 348 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 349 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 350 1.7 riastrad return -EOPNOTSUPP; 351 1.4 riastrad 352 1.1 riastrad if (res->count >= DRM_RESERVED_CONTEXTS) { 353 1.1 riastrad memset(&ctx, 0, sizeof(ctx)); 354 1.1 riastrad for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { 355 1.1 riastrad ctx.handle = i; 356 1.1 riastrad if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx))) 357 1.1 riastrad return -EFAULT; 358 1.1 riastrad } 359 1.1 riastrad } 360 1.1 riastrad res->count = DRM_RESERVED_CONTEXTS; 361 1.1 riastrad 362 1.1 riastrad return 0; 363 1.1 riastrad } 364 1.1 riastrad 365 1.1 riastrad /** 366 1.1 riastrad * Add context. 367 1.1 riastrad * 368 1.1 riastrad * \param inode device inode. 369 1.1 riastrad * \param file_priv DRM file private. 370 1.1 riastrad * \param cmd command. 371 1.1 riastrad * \param arg user argument pointing to a drm_ctx structure. 372 1.1 riastrad * \return zero on success or a negative number on failure. 373 1.1 riastrad * 374 1.1 riastrad * Get a new handle for the context and copy to userspace. 375 1.1 riastrad */ 376 1.4 riastrad int drm_legacy_addctx(struct drm_device *dev, void *data, 377 1.4 riastrad struct drm_file *file_priv) 378 1.1 riastrad { 379 1.1 riastrad struct drm_ctx_list *ctx_entry; 380 1.1 riastrad struct drm_ctx *ctx = data; 381 1.7 riastrad int tmp_handle; 382 1.1 riastrad 383 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 384 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 385 1.7 riastrad return -EOPNOTSUPP; 386 1.4 riastrad 387 1.7 riastrad tmp_handle = drm_legacy_ctxbitmap_next(dev); 388 1.7 riastrad if (tmp_handle == DRM_KERNEL_CONTEXT) { 389 1.1 riastrad /* Skip kernel's context and get a new one. */ 390 1.7 riastrad tmp_handle = drm_legacy_ctxbitmap_next(dev); 391 1.1 riastrad } 392 1.7 riastrad DRM_DEBUG("%d\n", tmp_handle); 393 1.8 riastrad if ((int)ctx->handle < 0) { 394 1.1 riastrad DRM_DEBUG("Not enough free contexts.\n"); 395 1.1 riastrad /* Should this return -EBUSY instead? */ 396 1.7 riastrad return tmp_handle; 397 1.1 riastrad } 398 1.1 riastrad 399 1.7 riastrad ctx->handle = tmp_handle; 400 1.7 riastrad 401 1.1 riastrad ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL); 402 1.1 riastrad if (!ctx_entry) { 403 1.1 riastrad DRM_DEBUG("out of memory\n"); 404 1.1 riastrad return -ENOMEM; 405 1.1 riastrad } 406 1.1 riastrad 407 1.1 riastrad INIT_LIST_HEAD(&ctx_entry->head); 408 1.1 riastrad ctx_entry->handle = ctx->handle; 409 1.1 riastrad ctx_entry->tag = file_priv; 410 1.1 riastrad 411 1.1 riastrad mutex_lock(&dev->ctxlist_mutex); 412 1.1 riastrad list_add(&ctx_entry->head, &dev->ctxlist); 413 1.1 riastrad mutex_unlock(&dev->ctxlist_mutex); 414 1.1 riastrad 415 1.1 riastrad return 0; 416 1.1 riastrad } 417 1.1 riastrad 418 1.1 riastrad /** 419 1.1 riastrad * Get context. 420 1.1 riastrad * 421 1.1 riastrad * \param inode device inode. 422 1.1 riastrad * \param file_priv DRM file private. 423 1.1 riastrad * \param cmd command. 424 1.1 riastrad * \param arg user argument pointing to a drm_ctx structure. 425 1.1 riastrad * \return zero on success or a negative number on failure. 426 1.1 riastrad */ 427 1.4 riastrad int drm_legacy_getctx(struct drm_device *dev, void *data, 428 1.4 riastrad struct drm_file *file_priv) 429 1.1 riastrad { 430 1.1 riastrad struct drm_ctx *ctx = data; 431 1.1 riastrad 432 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 433 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 434 1.7 riastrad return -EOPNOTSUPP; 435 1.4 riastrad 436 1.1 riastrad /* This is 0, because we don't handle any context flags */ 437 1.1 riastrad ctx->flags = 0; 438 1.1 riastrad 439 1.1 riastrad return 0; 440 1.1 riastrad } 441 1.1 riastrad 442 1.1 riastrad /** 443 1.1 riastrad * Switch context. 444 1.1 riastrad * 445 1.1 riastrad * \param inode device inode. 446 1.1 riastrad * \param file_priv DRM file private. 447 1.1 riastrad * \param cmd command. 448 1.1 riastrad * \param arg user argument pointing to a drm_ctx structure. 449 1.1 riastrad * \return zero on success or a negative number on failure. 450 1.1 riastrad * 451 1.1 riastrad * Calls context_switch(). 452 1.1 riastrad */ 453 1.4 riastrad int drm_legacy_switchctx(struct drm_device *dev, void *data, 454 1.4 riastrad struct drm_file *file_priv) 455 1.1 riastrad { 456 1.1 riastrad struct drm_ctx *ctx = data; 457 1.1 riastrad 458 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 459 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 460 1.7 riastrad return -EOPNOTSUPP; 461 1.4 riastrad 462 1.1 riastrad DRM_DEBUG("%d\n", ctx->handle); 463 1.1 riastrad return drm_context_switch(dev, dev->last_context, ctx->handle); 464 1.1 riastrad } 465 1.1 riastrad 466 1.1 riastrad /** 467 1.1 riastrad * New context. 468 1.1 riastrad * 469 1.1 riastrad * \param inode device inode. 470 1.1 riastrad * \param file_priv DRM file private. 471 1.1 riastrad * \param cmd command. 472 1.1 riastrad * \param arg user argument pointing to a drm_ctx structure. 473 1.1 riastrad * \return zero on success or a negative number on failure. 474 1.1 riastrad * 475 1.1 riastrad * Calls context_switch_complete(). 476 1.1 riastrad */ 477 1.4 riastrad int drm_legacy_newctx(struct drm_device *dev, void *data, 478 1.4 riastrad struct drm_file *file_priv) 479 1.1 riastrad { 480 1.1 riastrad struct drm_ctx *ctx = data; 481 1.1 riastrad 482 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 483 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 484 1.7 riastrad return -EOPNOTSUPP; 485 1.4 riastrad 486 1.1 riastrad DRM_DEBUG("%d\n", ctx->handle); 487 1.1 riastrad drm_context_switch_complete(dev, file_priv, ctx->handle); 488 1.1 riastrad 489 1.1 riastrad return 0; 490 1.1 riastrad } 491 1.1 riastrad 492 1.1 riastrad /** 493 1.1 riastrad * Remove context. 494 1.1 riastrad * 495 1.1 riastrad * \param inode device inode. 496 1.1 riastrad * \param file_priv DRM file private. 497 1.1 riastrad * \param cmd command. 498 1.1 riastrad * \param arg user argument pointing to a drm_ctx structure. 499 1.1 riastrad * \return zero on success or a negative number on failure. 500 1.1 riastrad * 501 1.1 riastrad * If not the special kernel context, calls ctxbitmap_free() to free the specified context. 502 1.1 riastrad */ 503 1.4 riastrad int drm_legacy_rmctx(struct drm_device *dev, void *data, 504 1.4 riastrad struct drm_file *file_priv) 505 1.1 riastrad { 506 1.1 riastrad struct drm_ctx *ctx = data; 507 1.1 riastrad 508 1.4 riastrad if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && 509 1.7 riastrad !drm_core_check_feature(dev, DRIVER_LEGACY)) 510 1.7 riastrad return -EOPNOTSUPP; 511 1.4 riastrad 512 1.1 riastrad DRM_DEBUG("%d\n", ctx->handle); 513 1.1 riastrad if (ctx->handle != DRM_KERNEL_CONTEXT) { 514 1.1 riastrad if (dev->driver->context_dtor) 515 1.1 riastrad dev->driver->context_dtor(dev, ctx->handle); 516 1.4 riastrad drm_legacy_ctxbitmap_free(dev, ctx->handle); 517 1.1 riastrad } 518 1.1 riastrad 519 1.1 riastrad mutex_lock(&dev->ctxlist_mutex); 520 1.1 riastrad if (!list_empty(&dev->ctxlist)) { 521 1.1 riastrad struct drm_ctx_list *pos, *n; 522 1.1 riastrad 523 1.1 riastrad list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { 524 1.1 riastrad if (pos->handle == ctx->handle) { 525 1.1 riastrad list_del(&pos->head); 526 1.1 riastrad kfree(pos); 527 1.1 riastrad } 528 1.1 riastrad } 529 1.1 riastrad } 530 1.1 riastrad mutex_unlock(&dev->ctxlist_mutex); 531 1.1 riastrad 532 1.1 riastrad return 0; 533 1.1 riastrad } 534 1.1 riastrad 535 1.1 riastrad /*@}*/ 536