0001
0002
0003
0004
0005 #include <linux/file.h>
0006 #include <linux/uaccess.h>
0007
0008 #include <drm/drm_auth.h>
0009 #include <drm/drm_crtc_helper.h>
0010 #include <drm/drm_drv.h>
0011 #include <drm/drm_file.h>
0012 #include <drm/drm_lease.h>
0013 #include <drm/drm_print.h>
0014
0015 #include "drm_crtc_internal.h"
0016 #include "drm_internal.h"
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 #define drm_for_each_lessee(lessee, lessor) \
0070 list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
0071
0072 static uint64_t drm_lease_idr_object;
0073
0074 struct drm_master *drm_lease_owner(struct drm_master *master)
0075 {
0076 while (master->lessor != NULL)
0077 master = master->lessor;
0078 return master;
0079 }
0080
0081 static struct drm_master*
0082 _drm_find_lessee(struct drm_master *master, int lessee_id)
0083 {
0084 lockdep_assert_held(&master->dev->mode_config.idr_mutex);
0085 return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id);
0086 }
0087
0088 static int _drm_lease_held_master(struct drm_master *master, int id)
0089 {
0090 lockdep_assert_held(&master->dev->mode_config.idr_mutex);
0091 if (master->lessor)
0092 return idr_find(&master->leases, id) != NULL;
0093 return true;
0094 }
0095
0096
0097 static bool _drm_has_leased(struct drm_master *master, int id)
0098 {
0099 struct drm_master *lessee;
0100
0101 lockdep_assert_held(&master->dev->mode_config.idr_mutex);
0102 drm_for_each_lessee(lessee, master)
0103 if (_drm_lease_held_master(lessee, id))
0104 return true;
0105 return false;
0106 }
0107
0108
0109 bool _drm_lease_held(struct drm_file *file_priv, int id)
0110 {
0111 bool ret;
0112 struct drm_master *master;
0113
0114 if (!file_priv)
0115 return true;
0116
0117 master = drm_file_get_master(file_priv);
0118 if (!master)
0119 return true;
0120 ret = _drm_lease_held_master(master, id);
0121 drm_master_put(&master);
0122
0123 return ret;
0124 }
0125
0126 bool drm_lease_held(struct drm_file *file_priv, int id)
0127 {
0128 struct drm_master *master;
0129 bool ret;
0130
0131 if (!file_priv)
0132 return true;
0133
0134 master = drm_file_get_master(file_priv);
0135 if (!master)
0136 return true;
0137 if (!master->lessor) {
0138 ret = true;
0139 goto out;
0140 }
0141 mutex_lock(&master->dev->mode_config.idr_mutex);
0142 ret = _drm_lease_held_master(master, id);
0143 mutex_unlock(&master->dev->mode_config.idr_mutex);
0144
0145 out:
0146 drm_master_put(&master);
0147 return ret;
0148 }
0149
0150
0151
0152
0153
0154 uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
0155 {
0156 struct drm_master *master;
0157 struct drm_device *dev;
0158 struct drm_crtc *crtc;
0159 int count_in, count_out;
0160 uint32_t crtcs_out = 0;
0161
0162 if (!file_priv)
0163 return crtcs_in;
0164
0165 master = drm_file_get_master(file_priv);
0166 if (!master)
0167 return crtcs_in;
0168 if (!master->lessor) {
0169 crtcs_out = crtcs_in;
0170 goto out;
0171 }
0172 dev = master->dev;
0173
0174 count_in = count_out = 0;
0175 mutex_lock(&master->dev->mode_config.idr_mutex);
0176 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0177 if (_drm_lease_held_master(master, crtc->base.id)) {
0178 uint32_t mask_in = 1ul << count_in;
0179
0180 if ((crtcs_in & mask_in) != 0) {
0181 uint32_t mask_out = 1ul << count_out;
0182
0183 crtcs_out |= mask_out;
0184 }
0185 count_out++;
0186 }
0187 count_in++;
0188 }
0189 mutex_unlock(&master->dev->mode_config.idr_mutex);
0190
0191 out:
0192 drm_master_put(&master);
0193 return crtcs_out;
0194 }
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207 static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr *leases)
0208 {
0209 struct drm_device *dev = lessor->dev;
0210 int error;
0211 struct drm_master *lessee;
0212 int object;
0213 int id;
0214 void *entry;
0215
0216 DRM_DEBUG_LEASE("lessor %d\n", lessor->lessee_id);
0217
0218 lessee = drm_master_create(lessor->dev);
0219 if (!lessee) {
0220 DRM_DEBUG_LEASE("drm_master_create failed\n");
0221 return ERR_PTR(-ENOMEM);
0222 }
0223
0224 mutex_lock(&dev->mode_config.idr_mutex);
0225
0226 idr_for_each_entry(leases, entry, object) {
0227 error = 0;
0228 if (!idr_find(&dev->mode_config.object_idr, object))
0229 error = -ENOENT;
0230 else if (_drm_has_leased(lessor, object))
0231 error = -EBUSY;
0232
0233 if (error != 0) {
0234 DRM_DEBUG_LEASE("object %d failed %d\n", object, error);
0235 goto out_lessee;
0236 }
0237 }
0238
0239
0240 id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL);
0241 if (id < 0) {
0242 error = id;
0243 goto out_lessee;
0244 }
0245
0246 lessee->lessee_id = id;
0247 lessee->lessor = drm_master_get(lessor);
0248 list_add_tail(&lessee->lessee_list, &lessor->lessees);
0249
0250
0251 lessee->leases = *leases;
0252 DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor);
0253
0254 mutex_unlock(&dev->mode_config.idr_mutex);
0255 return lessee;
0256
0257 out_lessee:
0258 mutex_unlock(&dev->mode_config.idr_mutex);
0259
0260 drm_master_put(&lessee);
0261
0262 return ERR_PTR(error);
0263 }
0264
0265 void drm_lease_destroy(struct drm_master *master)
0266 {
0267 struct drm_device *dev = master->dev;
0268
0269 mutex_lock(&dev->mode_config.idr_mutex);
0270
0271 DRM_DEBUG_LEASE("drm_lease_destroy %d\n", master->lessee_id);
0272
0273
0274
0275
0276 WARN_ON(!list_empty(&master->lessees));
0277
0278
0279 if (master->lessee_id != 0) {
0280 DRM_DEBUG_LEASE("remove master %d from device list of lessees\n", master->lessee_id);
0281 idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id);
0282 }
0283
0284
0285 list_del(&master->lessee_list);
0286
0287 mutex_unlock(&dev->mode_config.idr_mutex);
0288
0289 if (master->lessor) {
0290
0291 drm_sysfs_lease_event(dev);
0292 drm_master_put(&master->lessor);
0293 }
0294
0295 DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id);
0296 }
0297
0298 static void _drm_lease_revoke(struct drm_master *top)
0299 {
0300 int object;
0301 void *entry;
0302 struct drm_master *master = top;
0303
0304 lockdep_assert_held(&top->dev->mode_config.idr_mutex);
0305
0306
0307
0308
0309
0310 for (;;) {
0311 DRM_DEBUG_LEASE("revoke leases for %p %d\n", master, master->lessee_id);
0312
0313
0314 idr_for_each_entry(&master->leases, entry, object)
0315 idr_remove(&master->leases, object);
0316
0317
0318
0319
0320 if (!list_empty(&master->lessees)) {
0321 master = list_first_entry(&master->lessees, struct drm_master, lessee_list);
0322 } else {
0323
0324 while (master != top && master == list_last_entry(&master->lessor->lessees, struct drm_master, lessee_list))
0325 master = master->lessor;
0326
0327 if (master == top)
0328 break;
0329
0330
0331 master = list_next_entry(master, lessee_list);
0332 }
0333 }
0334 }
0335
0336 void drm_lease_revoke(struct drm_master *top)
0337 {
0338 mutex_lock(&top->dev->mode_config.idr_mutex);
0339 _drm_lease_revoke(top);
0340 mutex_unlock(&top->dev->mode_config.idr_mutex);
0341 }
0342
0343 static int validate_lease(struct drm_device *dev,
0344 int object_count,
0345 struct drm_mode_object **objects,
0346 bool universal_planes)
0347 {
0348 int o;
0349 int has_crtc = -1;
0350 int has_connector = -1;
0351 int has_plane = -1;
0352
0353
0354
0355
0356 for (o = 0; o < object_count; o++) {
0357 if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) {
0358 has_crtc = o;
0359 }
0360 if (objects[o]->type == DRM_MODE_OBJECT_CONNECTOR && has_connector == -1)
0361 has_connector = o;
0362
0363 if (universal_planes) {
0364 if (objects[o]->type == DRM_MODE_OBJECT_PLANE && has_plane == -1)
0365 has_plane = o;
0366 }
0367 }
0368 if (has_crtc == -1 || has_connector == -1)
0369 return -EINVAL;
0370 if (universal_planes && has_plane == -1)
0371 return -EINVAL;
0372 return 0;
0373 }
0374
0375 static int fill_object_idr(struct drm_device *dev,
0376 struct drm_file *lessor_priv,
0377 struct idr *leases,
0378 int object_count,
0379 u32 *object_ids)
0380 {
0381 struct drm_mode_object **objects;
0382 u32 o;
0383 int ret;
0384 bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
0385
0386 objects = kcalloc(object_count, sizeof(struct drm_mode_object *),
0387 GFP_KERNEL);
0388 if (!objects)
0389 return -ENOMEM;
0390
0391
0392
0393 for (o = 0; o < object_count; o++) {
0394 objects[o] = drm_mode_object_find(dev, lessor_priv,
0395 object_ids[o],
0396 DRM_MODE_OBJECT_ANY);
0397 if (!objects[o]) {
0398 ret = -ENOENT;
0399 goto out_free_objects;
0400 }
0401
0402 if (!drm_mode_object_lease_required(objects[o]->type)) {
0403 DRM_DEBUG_KMS("invalid object for lease\n");
0404 ret = -EINVAL;
0405 goto out_free_objects;
0406 }
0407 }
0408
0409 ret = validate_lease(dev, object_count, objects, universal_planes);
0410 if (ret) {
0411 DRM_DEBUG_LEASE("lease validation failed\n");
0412 goto out_free_objects;
0413 }
0414
0415
0416
0417 for (o = 0; o < object_count; o++) {
0418 struct drm_mode_object *obj = objects[o];
0419 u32 object_id = objects[o]->id;
0420
0421 DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id);
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431 ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
0432 if (ret < 0) {
0433 DRM_DEBUG_LEASE("Object %d cannot be inserted into leases (%d)\n",
0434 object_id, ret);
0435 goto out_free_objects;
0436 }
0437 if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
0438 struct drm_crtc *crtc = obj_to_crtc(obj);
0439
0440 ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
0441 if (ret < 0) {
0442 DRM_DEBUG_LEASE("Object primary plane %d cannot be inserted into leases (%d)\n",
0443 object_id, ret);
0444 goto out_free_objects;
0445 }
0446 if (crtc->cursor) {
0447 ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
0448 if (ret < 0) {
0449 DRM_DEBUG_LEASE("Object cursor plane %d cannot be inserted into leases (%d)\n",
0450 object_id, ret);
0451 goto out_free_objects;
0452 }
0453 }
0454 }
0455 }
0456
0457 ret = 0;
0458 out_free_objects:
0459 for (o = 0; o < object_count; o++) {
0460 if (objects[o])
0461 drm_mode_object_put(objects[o]);
0462 }
0463 kfree(objects);
0464 return ret;
0465 }
0466
0467
0468
0469
0470
0471
0472
0473 int drm_mode_create_lease_ioctl(struct drm_device *dev,
0474 void *data, struct drm_file *lessor_priv)
0475 {
0476 struct drm_mode_create_lease *cl = data;
0477 size_t object_count;
0478 int ret = 0;
0479 struct idr leases;
0480 struct drm_master *lessor;
0481 struct drm_master *lessee = NULL;
0482 struct file *lessee_file = NULL;
0483 struct file *lessor_file = lessor_priv->filp;
0484 struct drm_file *lessee_priv;
0485 int fd = -1;
0486 uint32_t *object_ids;
0487
0488
0489 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0490 return -EOPNOTSUPP;
0491
0492 if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
0493 DRM_DEBUG_LEASE("invalid flags\n");
0494 return -EINVAL;
0495 }
0496
0497 lessor = drm_file_get_master(lessor_priv);
0498
0499 if (lessor->lessor) {
0500 DRM_DEBUG_LEASE("recursive leasing not allowed\n");
0501 ret = -EINVAL;
0502 goto out_lessor;
0503 }
0504
0505 object_count = cl->object_count;
0506
0507
0508 idr_init(&leases);
0509 if (object_count != 0) {
0510 object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
0511 array_size(object_count, sizeof(__u32)));
0512 if (IS_ERR(object_ids)) {
0513 ret = PTR_ERR(object_ids);
0514 idr_destroy(&leases);
0515 goto out_lessor;
0516 }
0517
0518
0519 ret = fill_object_idr(dev, lessor_priv, &leases,
0520 object_count, object_ids);
0521 kfree(object_ids);
0522 if (ret) {
0523 DRM_DEBUG_LEASE("lease object lookup failed: %i\n", ret);
0524 idr_destroy(&leases);
0525 goto out_lessor;
0526 }
0527 }
0528
0529
0530 fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
0531 if (fd < 0) {
0532 idr_destroy(&leases);
0533 ret = fd;
0534 goto out_lessor;
0535 }
0536
0537 DRM_DEBUG_LEASE("Creating lease\n");
0538
0539 lessee = drm_lease_create(lessor, &leases);
0540
0541 if (IS_ERR(lessee)) {
0542 ret = PTR_ERR(lessee);
0543 idr_destroy(&leases);
0544 goto out_leases;
0545 }
0546
0547
0548 DRM_DEBUG_LEASE("Allocating lease file\n");
0549 lessee_file = file_clone_open(lessor_file);
0550 if (IS_ERR(lessee_file)) {
0551 ret = PTR_ERR(lessee_file);
0552 goto out_lessee;
0553 }
0554
0555 lessee_priv = lessee_file->private_data;
0556
0557 drm_master_put(&lessee_priv->master);
0558 lessee_priv->master = lessee;
0559 lessee_priv->is_master = 1;
0560 lessee_priv->authenticated = 1;
0561
0562
0563 DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id);
0564 cl->fd = fd;
0565 cl->lessee_id = lessee->lessee_id;
0566
0567
0568 fd_install(fd, lessee_file);
0569
0570 drm_master_put(&lessor);
0571 DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
0572 return 0;
0573
0574 out_lessee:
0575 drm_master_put(&lessee);
0576
0577 out_leases:
0578 put_unused_fd(fd);
0579
0580 out_lessor:
0581 drm_master_put(&lessor);
0582 DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
0583 return ret;
0584 }
0585
0586 int drm_mode_list_lessees_ioctl(struct drm_device *dev,
0587 void *data, struct drm_file *lessor_priv)
0588 {
0589 struct drm_mode_list_lessees *arg = data;
0590 __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr);
0591 __u32 count_lessees = arg->count_lessees;
0592 struct drm_master *lessor, *lessee;
0593 int count;
0594 int ret = 0;
0595
0596 if (arg->pad)
0597 return -EINVAL;
0598
0599
0600 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0601 return -EOPNOTSUPP;
0602
0603 lessor = drm_file_get_master(lessor_priv);
0604 DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id);
0605
0606 mutex_lock(&dev->mode_config.idr_mutex);
0607
0608 count = 0;
0609 drm_for_each_lessee(lessee, lessor) {
0610
0611 if (!idr_is_empty(&lessee->leases)) {
0612 if (count_lessees > count) {
0613 DRM_DEBUG_LEASE("Add lessee %d\n", lessee->lessee_id);
0614 ret = put_user(lessee->lessee_id, lessee_ids + count);
0615 if (ret)
0616 break;
0617 }
0618 count++;
0619 }
0620 }
0621
0622 DRM_DEBUG_LEASE("Lessor leases to %d\n", count);
0623 if (ret == 0)
0624 arg->count_lessees = count;
0625
0626 mutex_unlock(&dev->mode_config.idr_mutex);
0627 drm_master_put(&lessor);
0628
0629 return ret;
0630 }
0631
0632
0633 int drm_mode_get_lease_ioctl(struct drm_device *dev,
0634 void *data, struct drm_file *lessee_priv)
0635 {
0636 struct drm_mode_get_lease *arg = data;
0637 __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr);
0638 __u32 count_objects = arg->count_objects;
0639 struct drm_master *lessee;
0640 struct idr *object_idr;
0641 int count;
0642 void *entry;
0643 int object;
0644 int ret = 0;
0645
0646 if (arg->pad)
0647 return -EINVAL;
0648
0649
0650 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0651 return -EOPNOTSUPP;
0652
0653 lessee = drm_file_get_master(lessee_priv);
0654 DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id);
0655
0656 mutex_lock(&dev->mode_config.idr_mutex);
0657
0658 if (lessee->lessor == NULL)
0659
0660 object_idr = &lessee->dev->mode_config.object_idr;
0661 else
0662
0663 object_idr = &lessee->leases;
0664
0665 count = 0;
0666 idr_for_each_entry(object_idr, entry, object) {
0667 if (count_objects > count) {
0668 DRM_DEBUG_LEASE("adding object %d\n", object);
0669 ret = put_user(object, object_ids + count);
0670 if (ret)
0671 break;
0672 }
0673 count++;
0674 }
0675
0676 DRM_DEBUG("lease holds %d objects\n", count);
0677 if (ret == 0)
0678 arg->count_objects = count;
0679
0680 mutex_unlock(&dev->mode_config.idr_mutex);
0681 drm_master_put(&lessee);
0682
0683 return ret;
0684 }
0685
0686
0687
0688
0689
0690
0691 int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
0692 void *data, struct drm_file *lessor_priv)
0693 {
0694 struct drm_mode_revoke_lease *arg = data;
0695 struct drm_master *lessor;
0696 struct drm_master *lessee;
0697 int ret = 0;
0698
0699 DRM_DEBUG_LEASE("revoke lease for %d\n", arg->lessee_id);
0700
0701
0702 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0703 return -EOPNOTSUPP;
0704
0705 lessor = drm_file_get_master(lessor_priv);
0706 mutex_lock(&dev->mode_config.idr_mutex);
0707
0708 lessee = _drm_find_lessee(lessor, arg->lessee_id);
0709
0710
0711 if (!lessee) {
0712 ret = -ENOENT;
0713 goto fail;
0714 }
0715
0716
0717 if (lessee->lessor != lessor) {
0718 ret = -EACCES;
0719 goto fail;
0720 }
0721
0722 _drm_lease_revoke(lessee);
0723
0724 fail:
0725 mutex_unlock(&dev->mode_config.idr_mutex);
0726 drm_master_put(&lessor);
0727
0728 return ret;
0729 }