drm_lease.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright © 2017 Keith Packard <keithp@keithp.com>
  4. */
  5. #include <linux/file.h>
  6. #include <linux/uaccess.h>
  7. #include <drm/drm_auth.h>
  8. #include <drm/drm_crtc.h>
  9. #include <drm/drm_drv.h>
  10. #include <drm/drm_file.h>
  11. #include <drm/drm_lease.h>
  12. #include <drm/drm_print.h>
  13. #include "drm_crtc_internal.h"
  14. #include "drm_internal.h"
  15. /**
  16. * DOC: drm leasing
  17. *
  18. * DRM leases provide information about whether a DRM master may control a DRM
  19. * mode setting object. This enables the creation of multiple DRM masters that
  20. * manage subsets of display resources.
  21. *
  22. * The original DRM master of a device 'owns' the available drm resources. It
  23. * may create additional DRM masters and 'lease' resources which it controls
  24. * to the new DRM master. This gives the new DRM master control over the
  25. * leased resources until the owner revokes the lease, or the new DRM master
  26. * is closed. Some helpful terminology:
  27. *
  28. * - An 'owner' is a &struct drm_master that is not leasing objects from
  29. * another &struct drm_master, and hence 'owns' the objects. The owner can be
  30. * identified as the &struct drm_master for which &drm_master.lessor is NULL.
  31. *
  32. * - A 'lessor' is a &struct drm_master which is leasing objects to one or more
  33. * other &struct drm_master. Currently, lessees are not allowed to
  34. * create sub-leases, hence the lessor is the same as the owner.
  35. *
  36. * - A 'lessee' is a &struct drm_master which is leasing objects from some
  37. * other &struct drm_master. Each lessee only leases resources from a single
  38. * lessor recorded in &drm_master.lessor, and holds the set of objects that
  39. * it is leasing in &drm_master.leases.
  40. *
  41. * - A 'lease' is a contract between the lessor and lessee that identifies
  42. * which resources may be controlled by the lessee. All of the resources
  43. * that are leased must be owned by or leased to the lessor, and lessors are
  44. * not permitted to lease the same object to multiple lessees.
  45. *
  46. * The set of objects any &struct drm_master 'controls' is limited to the set
  47. * of objects it leases (for lessees) or all objects (for owners).
  48. *
  49. * Objects not controlled by a &struct drm_master cannot be modified through
  50. * the various state manipulating ioctls, and any state reported back to user
  51. * space will be edited to make them appear idle and/or unusable. For
  52. * instance, connectors always report 'disconnected', while encoders
  53. * report no possible crtcs or clones.
  54. *
  55. * Since each lessee may lease objects from a single lessor, display resource
  56. * leases form a tree of &struct drm_master. As lessees are currently not
  57. * allowed to create sub-leases, the tree depth is limited to 1. All of
  58. * these get activated simultaneously when the top level device owner changes
  59. * through the SETMASTER or DROPMASTER IOCTL, so &drm_device.master points to
  60. * the owner at the top of the lease tree (i.e. the &struct drm_master for which
  61. * &drm_master.lessor is NULL). The full list of lessees that are leasing
  62. * objects from the owner can be searched via the owner's
  63. * &drm_master.lessee_idr.
  64. */
  65. #define drm_for_each_lessee(lessee, lessor) \
  66. list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
  67. static uint64_t drm_lease_idr_object;
  68. struct drm_master *drm_lease_owner(struct drm_master *master)
  69. {
  70. while (master->lessor != NULL)
  71. master = master->lessor;
  72. return master;
  73. }
  74. static struct drm_master*
  75. _drm_find_lessee(struct drm_master *master, int lessee_id)
  76. {
  77. lockdep_assert_held(&master->dev->mode_config.idr_mutex);
  78. return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id);
  79. }
  80. static int _drm_lease_held_master(struct drm_master *master, int id)
  81. {
  82. lockdep_assert_held(&master->dev->mode_config.idr_mutex);
  83. if (master->lessor)
  84. return idr_find(&master->leases, id) != NULL;
  85. return true;
  86. }
  87. /* Checks if the given object has been leased to some lessee of drm_master */
  88. static bool _drm_has_leased(struct drm_master *master, int id)
  89. {
  90. struct drm_master *lessee;
  91. lockdep_assert_held(&master->dev->mode_config.idr_mutex);
  92. drm_for_each_lessee(lessee, master)
  93. if (_drm_lease_held_master(lessee, id))
  94. return true;
  95. return false;
  96. }
  97. /* Called with idr_mutex held */
  98. bool _drm_lease_held(struct drm_file *file_priv, int id)
  99. {
  100. bool ret;
  101. struct drm_master *master;
  102. if (!file_priv)
  103. return true;
  104. master = drm_file_get_master(file_priv);
  105. if (!master)
  106. return true;
  107. ret = _drm_lease_held_master(master, id);
  108. drm_master_put(&master);
  109. return ret;
  110. }
  111. bool drm_lease_held(struct drm_file *file_priv, int id)
  112. {
  113. struct drm_master *master;
  114. bool ret;
  115. if (!file_priv)
  116. return true;
  117. master = drm_file_get_master(file_priv);
  118. if (!master)
  119. return true;
  120. if (!master->lessor) {
  121. ret = true;
  122. goto out;
  123. }
  124. mutex_lock(&master->dev->mode_config.idr_mutex);
  125. ret = _drm_lease_held_master(master, id);
  126. mutex_unlock(&master->dev->mode_config.idr_mutex);
  127. out:
  128. drm_master_put(&master);
  129. return ret;
  130. }
  131. /*
  132. * Given a bitmask of crtcs to check, reconstructs a crtc mask based on the
  133. * crtcs which are visible through the specified file.
  134. */
  135. uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
  136. {
  137. struct drm_master *master;
  138. struct drm_device *dev;
  139. struct drm_crtc *crtc;
  140. int count_in, count_out;
  141. uint32_t crtcs_out = 0;
  142. if (!file_priv)
  143. return crtcs_in;
  144. master = drm_file_get_master(file_priv);
  145. if (!master)
  146. return crtcs_in;
  147. if (!master->lessor) {
  148. crtcs_out = crtcs_in;
  149. goto out;
  150. }
  151. dev = master->dev;
  152. count_in = count_out = 0;
  153. mutex_lock(&master->dev->mode_config.idr_mutex);
  154. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  155. if (_drm_lease_held_master(master, crtc->base.id)) {
  156. uint32_t mask_in = 1ul << count_in;
  157. if ((crtcs_in & mask_in) != 0) {
  158. uint32_t mask_out = 1ul << count_out;
  159. crtcs_out |= mask_out;
  160. }
  161. count_out++;
  162. }
  163. count_in++;
  164. }
  165. mutex_unlock(&master->dev->mode_config.idr_mutex);
  166. out:
  167. drm_master_put(&master);
  168. return crtcs_out;
  169. }
  170. /*
  171. * Uses drm_master_create to allocate a new drm_master, then checks to
  172. * make sure all of the desired objects can be leased, atomically
  173. * leasing them to the new drmmaster.
  174. *
  175. * ERR_PTR(-EACCES) some other master holds the title to any object
  176. * ERR_PTR(-ENOENT) some object is not a valid DRM object for this device
  177. * ERR_PTR(-EBUSY) some other lessee holds title to this object
  178. * ERR_PTR(-EEXIST) same object specified more than once in the provided list
  179. * ERR_PTR(-ENOMEM) allocation failed
  180. */
  181. static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr *leases)
  182. {
  183. struct drm_device *dev = lessor->dev;
  184. int error;
  185. struct drm_master *lessee;
  186. int object;
  187. int id;
  188. void *entry;
  189. drm_dbg_lease(dev, "lessor %d\n", lessor->lessee_id);
  190. lessee = drm_master_create(lessor->dev);
  191. if (!lessee) {
  192. drm_dbg_lease(dev, "drm_master_create failed\n");
  193. return ERR_PTR(-ENOMEM);
  194. }
  195. mutex_lock(&dev->mode_config.idr_mutex);
  196. idr_for_each_entry(leases, entry, object) {
  197. error = 0;
  198. if (!idr_find(&dev->mode_config.object_idr, object))
  199. error = -ENOENT;
  200. else if (_drm_has_leased(lessor, object))
  201. error = -EBUSY;
  202. if (error != 0) {
  203. drm_dbg_lease(dev, "object %d failed %d\n", object, error);
  204. goto out_lessee;
  205. }
  206. }
  207. /* Insert the new lessee into the tree */
  208. id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL);
  209. if (id < 0) {
  210. error = id;
  211. goto out_lessee;
  212. }
  213. lessee->lessee_id = id;
  214. lessee->lessor = drm_master_get(lessor);
  215. list_add_tail(&lessee->lessee_list, &lessor->lessees);
  216. /* Move the leases over */
  217. lessee->leases = *leases;
  218. drm_dbg_lease(dev, "new lessee %d %p, lessor %d %p\n",
  219. lessee->lessee_id, lessee, lessor->lessee_id, lessor);
  220. mutex_unlock(&dev->mode_config.idr_mutex);
  221. return lessee;
  222. out_lessee:
  223. mutex_unlock(&dev->mode_config.idr_mutex);
  224. drm_master_put(&lessee);
  225. return ERR_PTR(error);
  226. }
  227. void drm_lease_destroy(struct drm_master *master)
  228. {
  229. struct drm_device *dev = master->dev;
  230. mutex_lock(&dev->mode_config.idr_mutex);
  231. drm_dbg_lease(dev, "drm_lease_destroy %d\n", master->lessee_id);
  232. /* This master is referenced by all lessees, hence it cannot be destroyed
  233. * until all of them have been
  234. */
  235. WARN_ON(!list_empty(&master->lessees));
  236. /* Remove this master from the lessee idr in the owner */
  237. if (master->lessee_id != 0) {
  238. drm_dbg_lease(dev, "remove master %d from device list of lessees\n",
  239. master->lessee_id);
  240. idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id);
  241. }
  242. /* Remove this master from any lessee list it may be on */
  243. list_del(&master->lessee_list);
  244. mutex_unlock(&dev->mode_config.idr_mutex);
  245. if (master->lessor) {
  246. /* Tell the master to check the lessee list */
  247. drm_sysfs_lease_event(dev);
  248. drm_master_put(&master->lessor);
  249. }
  250. drm_dbg_lease(dev, "drm_lease_destroy done %d\n", master->lessee_id);
  251. }
  252. static void _drm_lease_revoke(struct drm_master *top)
  253. {
  254. int object;
  255. void *entry;
  256. struct drm_master *master = top;
  257. lockdep_assert_held(&top->dev->mode_config.idr_mutex);
  258. /*
  259. * Walk the tree starting at 'top' emptying all leases. Because
  260. * the tree is fully connected, we can do this without recursing
  261. */
  262. for (;;) {
  263. drm_dbg_lease(master->dev, "revoke leases for %p %d\n",
  264. master, master->lessee_id);
  265. /* Evacuate the lease */
  266. idr_for_each_entry(&master->leases, entry, object)
  267. idr_remove(&master->leases, object);
  268. /* Depth-first list walk */
  269. /* Down */
  270. if (!list_empty(&master->lessees)) {
  271. master = list_first_entry(&master->lessees, struct drm_master, lessee_list);
  272. } else {
  273. /* Up */
  274. while (master != top && master == list_last_entry(&master->lessor->lessees, struct drm_master, lessee_list))
  275. master = master->lessor;
  276. if (master == top)
  277. break;
  278. /* Over */
  279. master = list_next_entry(master, lessee_list);
  280. }
  281. }
  282. }
  283. void drm_lease_revoke(struct drm_master *top)
  284. {
  285. mutex_lock(&top->dev->mode_config.idr_mutex);
  286. _drm_lease_revoke(top);
  287. mutex_unlock(&top->dev->mode_config.idr_mutex);
  288. }
  289. static int validate_lease(struct drm_device *dev,
  290. int object_count,
  291. struct drm_mode_object **objects,
  292. bool universal_planes)
  293. {
  294. int o;
  295. int has_crtc = -1;
  296. int has_connector = -1;
  297. int has_plane = -1;
  298. /* we want to confirm that there is at least one crtc, plane
  299. connector object. */
  300. for (o = 0; o < object_count; o++) {
  301. if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) {
  302. has_crtc = o;
  303. }
  304. if (objects[o]->type == DRM_MODE_OBJECT_CONNECTOR && has_connector == -1)
  305. has_connector = o;
  306. if (universal_planes) {
  307. if (objects[o]->type == DRM_MODE_OBJECT_PLANE && has_plane == -1)
  308. has_plane = o;
  309. }
  310. }
  311. if (has_crtc == -1 || has_connector == -1)
  312. return -EINVAL;
  313. if (universal_planes && has_plane == -1)
  314. return -EINVAL;
  315. return 0;
  316. }
  317. static int fill_object_idr(struct drm_device *dev,
  318. struct drm_file *lessor_priv,
  319. struct idr *leases,
  320. int object_count,
  321. u32 *object_ids)
  322. {
  323. struct drm_mode_object **objects;
  324. u32 o;
  325. int ret;
  326. bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
  327. objects = kcalloc(object_count, sizeof(struct drm_mode_object *),
  328. GFP_KERNEL);
  329. if (!objects)
  330. return -ENOMEM;
  331. /* step one - get references to all the mode objects
  332. and check for validity. */
  333. for (o = 0; o < object_count; o++) {
  334. objects[o] = drm_mode_object_find(dev, lessor_priv,
  335. object_ids[o],
  336. DRM_MODE_OBJECT_ANY);
  337. if (!objects[o]) {
  338. ret = -ENOENT;
  339. goto out_free_objects;
  340. }
  341. if (!drm_mode_object_lease_required(objects[o]->type)) {
  342. DRM_DEBUG_KMS("invalid object for lease\n");
  343. ret = -EINVAL;
  344. goto out_free_objects;
  345. }
  346. }
  347. ret = validate_lease(dev, object_count, objects, universal_planes);
  348. if (ret) {
  349. drm_dbg_lease(dev, "lease validation failed\n");
  350. goto out_free_objects;
  351. }
  352. /* add their IDs to the lease request - taking into account
  353. universal planes */
  354. for (o = 0; o < object_count; o++) {
  355. struct drm_mode_object *obj = objects[o];
  356. u32 object_id = objects[o]->id;
  357. drm_dbg_lease(dev, "Adding object %d to lease\n", object_id);
  358. /*
  359. * We're using an IDR to hold the set of leased
  360. * objects, but we don't need to point at the object's
  361. * data structure from the lease as the main object_idr
  362. * will be used to actually find that. Instead, all we
  363. * really want is a 'leased/not-leased' result, for
  364. * which any non-NULL pointer will work fine.
  365. */
  366. ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
  367. if (ret < 0) {
  368. drm_dbg_lease(dev, "Object %d cannot be inserted into leases (%d)\n",
  369. object_id, ret);
  370. goto out_free_objects;
  371. }
  372. if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
  373. struct drm_crtc *crtc = obj_to_crtc(obj);
  374. ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
  375. if (ret < 0) {
  376. drm_dbg_lease(dev, "Object primary plane %d cannot be inserted into leases (%d)\n",
  377. object_id, ret);
  378. goto out_free_objects;
  379. }
  380. if (crtc->cursor) {
  381. ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
  382. if (ret < 0) {
  383. drm_dbg_lease(dev, "Object cursor plane %d cannot be inserted into leases (%d)\n",
  384. object_id, ret);
  385. goto out_free_objects;
  386. }
  387. }
  388. }
  389. }
  390. ret = 0;
  391. out_free_objects:
  392. for (o = 0; o < object_count; o++) {
  393. if (objects[o])
  394. drm_mode_object_put(objects[o]);
  395. }
  396. kfree(objects);
  397. return ret;
  398. }
  399. /*
  400. * The master associated with the specified file will have a lease
  401. * created containing the objects specified in the ioctl structure.
  402. * A file descriptor will be allocated for that and returned to the
  403. * application.
  404. */
  405. int drm_mode_create_lease_ioctl(struct drm_device *dev,
  406. void *data, struct drm_file *lessor_priv)
  407. {
  408. struct drm_mode_create_lease *cl = data;
  409. size_t object_count;
  410. int ret = 0;
  411. struct idr leases;
  412. struct drm_master *lessor;
  413. struct drm_master *lessee = NULL;
  414. struct file *lessee_file = NULL;
  415. struct file *lessor_file = lessor_priv->filp;
  416. struct drm_file *lessee_priv;
  417. int fd = -1;
  418. uint32_t *object_ids;
  419. /* Can't lease without MODESET */
  420. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  421. return -EOPNOTSUPP;
  422. if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
  423. drm_dbg_lease(dev, "invalid flags\n");
  424. return -EINVAL;
  425. }
  426. lessor = drm_file_get_master(lessor_priv);
  427. /* Do not allow sub-leases */
  428. if (lessor->lessor) {
  429. drm_dbg_lease(dev, "recursive leasing not allowed\n");
  430. ret = -EINVAL;
  431. goto out_lessor;
  432. }
  433. object_count = cl->object_count;
  434. /* Handle leased objects, if any */
  435. idr_init(&leases);
  436. if (object_count != 0) {
  437. object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
  438. object_count, sizeof(__u32));
  439. if (IS_ERR(object_ids)) {
  440. ret = PTR_ERR(object_ids);
  441. idr_destroy(&leases);
  442. goto out_lessor;
  443. }
  444. /* fill and validate the object idr */
  445. ret = fill_object_idr(dev, lessor_priv, &leases,
  446. object_count, object_ids);
  447. kfree(object_ids);
  448. if (ret) {
  449. drm_dbg_lease(dev, "lease object lookup failed: %i\n", ret);
  450. idr_destroy(&leases);
  451. goto out_lessor;
  452. }
  453. }
  454. /* Allocate a file descriptor for the lease */
  455. fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
  456. if (fd < 0) {
  457. idr_destroy(&leases);
  458. ret = fd;
  459. goto out_lessor;
  460. }
  461. drm_dbg_lease(dev, "Creating lease\n");
  462. /* lessee will take the ownership of leases */
  463. lessee = drm_lease_create(lessor, &leases);
  464. if (IS_ERR(lessee)) {
  465. ret = PTR_ERR(lessee);
  466. idr_destroy(&leases);
  467. goto out_leases;
  468. }
  469. /* Clone the lessor file to create a new file for us */
  470. drm_dbg_lease(dev, "Allocating lease file\n");
  471. lessee_file = file_clone_open(lessor_file);
  472. if (IS_ERR(lessee_file)) {
  473. ret = PTR_ERR(lessee_file);
  474. goto out_lessee;
  475. }
  476. lessee_priv = lessee_file->private_data;
  477. /* Change the file to a master one */
  478. drm_master_put(&lessee_priv->master);
  479. lessee_priv->master = lessee;
  480. lessee_priv->is_master = 1;
  481. lessee_priv->authenticated = 1;
  482. /* Pass fd back to userspace */
  483. drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id);
  484. cl->fd = fd;
  485. cl->lessee_id = lessee->lessee_id;
  486. /* Hook up the fd */
  487. fd_install(fd, lessee_file);
  488. drm_master_put(&lessor);
  489. drm_dbg_lease(dev, "drm_mode_create_lease_ioctl succeeded\n");
  490. return 0;
  491. out_lessee:
  492. drm_master_put(&lessee);
  493. out_leases:
  494. put_unused_fd(fd);
  495. out_lessor:
  496. drm_master_put(&lessor);
  497. drm_dbg_lease(dev, "drm_mode_create_lease_ioctl failed: %d\n", ret);
  498. return ret;
  499. }
  500. int drm_mode_list_lessees_ioctl(struct drm_device *dev,
  501. void *data, struct drm_file *lessor_priv)
  502. {
  503. struct drm_mode_list_lessees *arg = data;
  504. __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr);
  505. __u32 count_lessees = arg->count_lessees;
  506. struct drm_master *lessor, *lessee;
  507. int count;
  508. int ret = 0;
  509. if (arg->pad)
  510. return -EINVAL;
  511. /* Can't lease without MODESET */
  512. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  513. return -EOPNOTSUPP;
  514. lessor = drm_file_get_master(lessor_priv);
  515. drm_dbg_lease(dev, "List lessees for %d\n", lessor->lessee_id);
  516. mutex_lock(&dev->mode_config.idr_mutex);
  517. count = 0;
  518. drm_for_each_lessee(lessee, lessor) {
  519. /* Only list un-revoked leases */
  520. if (!idr_is_empty(&lessee->leases)) {
  521. if (count_lessees > count) {
  522. drm_dbg_lease(dev, "Add lessee %d\n",
  523. lessee->lessee_id);
  524. ret = put_user(lessee->lessee_id, lessee_ids + count);
  525. if (ret)
  526. break;
  527. }
  528. count++;
  529. }
  530. }
  531. drm_dbg_lease(dev, "Lessor leases to %d\n", count);
  532. if (ret == 0)
  533. arg->count_lessees = count;
  534. mutex_unlock(&dev->mode_config.idr_mutex);
  535. drm_master_put(&lessor);
  536. return ret;
  537. }
  538. /* Return the list of leased objects for the specified lessee */
  539. int drm_mode_get_lease_ioctl(struct drm_device *dev,
  540. void *data, struct drm_file *lessee_priv)
  541. {
  542. struct drm_mode_get_lease *arg = data;
  543. __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr);
  544. __u32 count_objects = arg->count_objects;
  545. struct drm_master *lessee;
  546. struct idr *object_idr;
  547. int count;
  548. void *entry;
  549. int object;
  550. int ret = 0;
  551. if (arg->pad)
  552. return -EINVAL;
  553. /* Can't lease without MODESET */
  554. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  555. return -EOPNOTSUPP;
  556. lessee = drm_file_get_master(lessee_priv);
  557. drm_dbg_lease(dev, "get lease for %d\n", lessee->lessee_id);
  558. mutex_lock(&dev->mode_config.idr_mutex);
  559. if (lessee->lessor == NULL)
  560. /* owner can use all objects */
  561. object_idr = &lessee->dev->mode_config.object_idr;
  562. else
  563. /* lessee can only use allowed object */
  564. object_idr = &lessee->leases;
  565. count = 0;
  566. idr_for_each_entry(object_idr, entry, object) {
  567. if (count_objects > count) {
  568. drm_dbg_lease(dev, "adding object %d\n", object);
  569. ret = put_user(object, object_ids + count);
  570. if (ret)
  571. break;
  572. }
  573. count++;
  574. }
  575. DRM_DEBUG("lease holds %d objects\n", count);
  576. if (ret == 0)
  577. arg->count_objects = count;
  578. mutex_unlock(&dev->mode_config.idr_mutex);
  579. drm_master_put(&lessee);
  580. return ret;
  581. }
  582. /*
  583. * This removes all of the objects from the lease without
  584. * actually getting rid of the lease itself; that way all
  585. * references to it still work correctly
  586. */
  587. int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
  588. void *data, struct drm_file *lessor_priv)
  589. {
  590. struct drm_mode_revoke_lease *arg = data;
  591. struct drm_master *lessor;
  592. struct drm_master *lessee;
  593. int ret = 0;
  594. drm_dbg_lease(dev, "revoke lease for %d\n", arg->lessee_id);
  595. /* Can't lease without MODESET */
  596. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  597. return -EOPNOTSUPP;
  598. lessor = drm_file_get_master(lessor_priv);
  599. mutex_lock(&dev->mode_config.idr_mutex);
  600. lessee = _drm_find_lessee(lessor, arg->lessee_id);
  601. /* No such lessee */
  602. if (!lessee) {
  603. ret = -ENOENT;
  604. goto fail;
  605. }
  606. /* Lease is not held by lessor */
  607. if (lessee->lessor != lessor) {
  608. ret = -EACCES;
  609. goto fail;
  610. }
  611. _drm_lease_revoke(lessee);
  612. fail:
  613. mutex_unlock(&dev->mode_config.idr_mutex);
  614. drm_master_put(&lessor);
  615. return ret;
  616. }