0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <linux/slab.h>
0032 #include <linux/uaccess.h>
0033
0034 #include <drm/drm_drv.h>
0035 #include <drm/drm_file.h>
0036 #include <drm/drm_print.h>
0037
0038 #include "drm_legacy.h"
0039
0040 struct drm_ctx_list {
0041 struct list_head head;
0042 drm_context_t handle;
0043 struct drm_file *tag;
0044 };
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
0061 {
0062 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0063 !drm_core_check_feature(dev, DRIVER_LEGACY))
0064 return;
0065
0066 mutex_lock(&dev->struct_mutex);
0067 idr_remove(&dev->ctx_idr, ctx_handle);
0068 mutex_unlock(&dev->struct_mutex);
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 static int drm_legacy_ctxbitmap_next(struct drm_device * dev)
0081 {
0082 int ret;
0083
0084 mutex_lock(&dev->struct_mutex);
0085 ret = idr_alloc(&dev->ctx_idr, NULL, DRM_RESERVED_CONTEXTS, 0,
0086 GFP_KERNEL);
0087 mutex_unlock(&dev->struct_mutex);
0088 return ret;
0089 }
0090
0091
0092
0093
0094
0095
0096
0097
0098 void drm_legacy_ctxbitmap_init(struct drm_device * dev)
0099 {
0100 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0101 !drm_core_check_feature(dev, DRIVER_LEGACY))
0102 return;
0103
0104 idr_init(&dev->ctx_idr);
0105 }
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev)
0116 {
0117 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0118 !drm_core_check_feature(dev, DRIVER_LEGACY))
0119 return;
0120
0121 mutex_lock(&dev->struct_mutex);
0122 idr_destroy(&dev->ctx_idr);
0123 mutex_unlock(&dev->struct_mutex);
0124 }
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135 void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
0136 {
0137 struct drm_ctx_list *pos, *tmp;
0138
0139 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0140 !drm_core_check_feature(dev, DRIVER_LEGACY))
0141 return;
0142
0143 mutex_lock(&dev->ctxlist_mutex);
0144
0145 list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
0146 if (pos->tag == file &&
0147 pos->handle != DRM_KERNEL_CONTEXT) {
0148 if (dev->driver->context_dtor)
0149 dev->driver->context_dtor(dev, pos->handle);
0150
0151 drm_legacy_ctxbitmap_free(dev, pos->handle);
0152 list_del(&pos->head);
0153 kfree(pos);
0154 }
0155 }
0156
0157 mutex_unlock(&dev->ctxlist_mutex);
0158 }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 int drm_legacy_getsareactx(struct drm_device *dev, void *data,
0179 struct drm_file *file_priv)
0180 {
0181 struct drm_ctx_priv_map *request = data;
0182 struct drm_local_map *map;
0183 struct drm_map_list *_entry;
0184
0185 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0186 !drm_core_check_feature(dev, DRIVER_LEGACY))
0187 return -EOPNOTSUPP;
0188
0189 mutex_lock(&dev->struct_mutex);
0190
0191 map = idr_find(&dev->ctx_idr, request->ctx_id);
0192 if (!map) {
0193 mutex_unlock(&dev->struct_mutex);
0194 return -EINVAL;
0195 }
0196
0197 request->handle = NULL;
0198 list_for_each_entry(_entry, &dev->maplist, head) {
0199 if (_entry->map == map) {
0200 request->handle =
0201 (void *)(unsigned long)_entry->user_token;
0202 break;
0203 }
0204 }
0205
0206 mutex_unlock(&dev->struct_mutex);
0207
0208 if (request->handle == NULL)
0209 return -EINVAL;
0210
0211 return 0;
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 int drm_legacy_setsareactx(struct drm_device *dev, void *data,
0227 struct drm_file *file_priv)
0228 {
0229 struct drm_ctx_priv_map *request = data;
0230 struct drm_local_map *map = NULL;
0231 struct drm_map_list *r_list = NULL;
0232
0233 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0234 !drm_core_check_feature(dev, DRIVER_LEGACY))
0235 return -EOPNOTSUPP;
0236
0237 mutex_lock(&dev->struct_mutex);
0238 list_for_each_entry(r_list, &dev->maplist, head) {
0239 if (r_list->map
0240 && r_list->user_token == (unsigned long) request->handle)
0241 goto found;
0242 }
0243 bad:
0244 mutex_unlock(&dev->struct_mutex);
0245 return -EINVAL;
0246
0247 found:
0248 map = r_list->map;
0249 if (!map)
0250 goto bad;
0251
0252 if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
0253 goto bad;
0254
0255 mutex_unlock(&dev->struct_mutex);
0256
0257 return 0;
0258 }
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276 static int drm_context_switch(struct drm_device * dev, int old, int new)
0277 {
0278 if (test_and_set_bit(0, &dev->context_flag)) {
0279 DRM_ERROR("Reentering -- FIXME\n");
0280 return -EBUSY;
0281 }
0282
0283 DRM_DEBUG("Context switch from %d to %d\n", old, new);
0284
0285 if (new == dev->last_context) {
0286 clear_bit(0, &dev->context_flag);
0287 return 0;
0288 }
0289
0290 return 0;
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 static int drm_context_switch_complete(struct drm_device *dev,
0305 struct drm_file *file_priv, int new)
0306 {
0307 dev->last_context = new;
0308
0309 if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {
0310 DRM_ERROR("Lock isn't held after context switch\n");
0311 }
0312
0313
0314
0315
0316
0317 clear_bit(0, &dev->context_flag);
0318
0319 return 0;
0320 }
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331 int drm_legacy_resctx(struct drm_device *dev, void *data,
0332 struct drm_file *file_priv)
0333 {
0334 struct drm_ctx_res *res = data;
0335 struct drm_ctx ctx;
0336 int i;
0337
0338 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0339 !drm_core_check_feature(dev, DRIVER_LEGACY))
0340 return -EOPNOTSUPP;
0341
0342 if (res->count >= DRM_RESERVED_CONTEXTS) {
0343 memset(&ctx, 0, sizeof(ctx));
0344 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
0345 ctx.handle = i;
0346 if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
0347 return -EFAULT;
0348 }
0349 }
0350 res->count = DRM_RESERVED_CONTEXTS;
0351
0352 return 0;
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 int drm_legacy_addctx(struct drm_device *dev, void *data,
0367 struct drm_file *file_priv)
0368 {
0369 struct drm_ctx_list *ctx_entry;
0370 struct drm_ctx *ctx = data;
0371 int tmp_handle;
0372
0373 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0374 !drm_core_check_feature(dev, DRIVER_LEGACY))
0375 return -EOPNOTSUPP;
0376
0377 tmp_handle = drm_legacy_ctxbitmap_next(dev);
0378 if (tmp_handle == DRM_KERNEL_CONTEXT) {
0379
0380 tmp_handle = drm_legacy_ctxbitmap_next(dev);
0381 }
0382 DRM_DEBUG("%d\n", tmp_handle);
0383 if (tmp_handle < 0) {
0384 DRM_DEBUG("Not enough free contexts.\n");
0385
0386 return tmp_handle;
0387 }
0388
0389 ctx->handle = tmp_handle;
0390
0391 ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL);
0392 if (!ctx_entry) {
0393 DRM_DEBUG("out of memory\n");
0394 return -ENOMEM;
0395 }
0396
0397 INIT_LIST_HEAD(&ctx_entry->head);
0398 ctx_entry->handle = ctx->handle;
0399 ctx_entry->tag = file_priv;
0400
0401 mutex_lock(&dev->ctxlist_mutex);
0402 list_add(&ctx_entry->head, &dev->ctxlist);
0403 mutex_unlock(&dev->ctxlist_mutex);
0404
0405 return 0;
0406 }
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417 int drm_legacy_getctx(struct drm_device *dev, void *data,
0418 struct drm_file *file_priv)
0419 {
0420 struct drm_ctx *ctx = data;
0421
0422 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0423 !drm_core_check_feature(dev, DRIVER_LEGACY))
0424 return -EOPNOTSUPP;
0425
0426
0427 ctx->flags = 0;
0428
0429 return 0;
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 int drm_legacy_switchctx(struct drm_device *dev, void *data,
0444 struct drm_file *file_priv)
0445 {
0446 struct drm_ctx *ctx = data;
0447
0448 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0449 !drm_core_check_feature(dev, DRIVER_LEGACY))
0450 return -EOPNOTSUPP;
0451
0452 DRM_DEBUG("%d\n", ctx->handle);
0453 return drm_context_switch(dev, dev->last_context, ctx->handle);
0454 }
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467 int drm_legacy_newctx(struct drm_device *dev, void *data,
0468 struct drm_file *file_priv)
0469 {
0470 struct drm_ctx *ctx = data;
0471
0472 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0473 !drm_core_check_feature(dev, DRIVER_LEGACY))
0474 return -EOPNOTSUPP;
0475
0476 DRM_DEBUG("%d\n", ctx->handle);
0477 drm_context_switch_complete(dev, file_priv, ctx->handle);
0478
0479 return 0;
0480 }
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493 int drm_legacy_rmctx(struct drm_device *dev, void *data,
0494 struct drm_file *file_priv)
0495 {
0496 struct drm_ctx *ctx = data;
0497
0498 if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
0499 !drm_core_check_feature(dev, DRIVER_LEGACY))
0500 return -EOPNOTSUPP;
0501
0502 DRM_DEBUG("%d\n", ctx->handle);
0503 if (ctx->handle != DRM_KERNEL_CONTEXT) {
0504 if (dev->driver->context_dtor)
0505 dev->driver->context_dtor(dev, ctx->handle);
0506 drm_legacy_ctxbitmap_free(dev, ctx->handle);
0507 }
0508
0509 mutex_lock(&dev->ctxlist_mutex);
0510 if (!list_empty(&dev->ctxlist)) {
0511 struct drm_ctx_list *pos, *n;
0512
0513 list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
0514 if (pos->handle == ctx->handle) {
0515 list_del(&pos->head);
0516 kfree(pos);
0517 }
0518 }
0519 }
0520 mutex_unlock(&dev->ctxlist_mutex);
0521
0522 return 0;
0523 }
0524
0525