drm_property.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. /*
  2. * Copyright (c) 2016 Intel Corporation
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * the above copyright notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting documentation, and
  8. * that the name of the copyright holders not be used in advertising or
  9. * publicity pertaining to distribution of the software without specific,
  10. * written prior permission. The copyright holders make no representations
  11. * about the suitability of this software for any purpose. It is provided "as
  12. * is" without express or implied warranty.
  13. *
  14. * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20. * OF THIS SOFTWARE.
  21. */
  22. #include <linux/export.h>
  23. #include <drm/drmP.h>
  24. #include <drm/drm_property.h>
  25. #include "drm_crtc_internal.h"
  26. static bool drm_property_type_valid(struct drm_property *property)
  27. {
  28. if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
  29. return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
  30. return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
  31. }
  32. /**
  33. * drm_property_create - create a new property type
  34. * @dev: drm device
  35. * @flags: flags specifying the property type
  36. * @name: name of the property
  37. * @num_values: number of pre-defined values
  38. *
  39. * This creates a new generic drm property which can then be attached to a drm
  40. * object with drm_object_attach_property. The returned property object must be
  41. * freed with drm_property_destroy.
  42. *
  43. * Note that the DRM core keeps a per-device list of properties and that, if
  44. * drm_mode_config_cleanup() is called, it will destroy all properties created
  45. * by the driver.
  46. *
  47. * Returns:
  48. * A pointer to the newly created property on success, NULL on failure.
  49. */
  50. struct drm_property *drm_property_create(struct drm_device *dev, int flags,
  51. const char *name, int num_values)
  52. {
  53. struct drm_property *property = NULL;
  54. int ret;
  55. property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
  56. if (!property)
  57. return NULL;
  58. property->dev = dev;
  59. if (num_values) {
  60. property->values = kcalloc(num_values, sizeof(uint64_t),
  61. GFP_KERNEL);
  62. if (!property->values)
  63. goto fail;
  64. }
  65. ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
  66. if (ret)
  67. goto fail;
  68. property->flags = flags;
  69. property->num_values = num_values;
  70. INIT_LIST_HEAD(&property->enum_list);
  71. if (name) {
  72. strncpy(property->name, name, DRM_PROP_NAME_LEN);
  73. property->name[DRM_PROP_NAME_LEN-1] = '\0';
  74. }
  75. list_add_tail(&property->head, &dev->mode_config.property_list);
  76. WARN_ON(!drm_property_type_valid(property));
  77. return property;
  78. fail:
  79. kfree(property->values);
  80. kfree(property);
  81. return NULL;
  82. }
  83. EXPORT_SYMBOL(drm_property_create);
  84. /**
  85. * drm_property_create_enum - create a new enumeration property type
  86. * @dev: drm device
  87. * @flags: flags specifying the property type
  88. * @name: name of the property
  89. * @props: enumeration lists with property values
  90. * @num_values: number of pre-defined values
  91. *
  92. * This creates a new generic drm property which can then be attached to a drm
  93. * object with drm_object_attach_property. The returned property object must be
  94. * freed with drm_property_destroy.
  95. *
  96. * Userspace is only allowed to set one of the predefined values for enumeration
  97. * properties.
  98. *
  99. * Returns:
  100. * A pointer to the newly created property on success, NULL on failure.
  101. */
  102. struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
  103. const char *name,
  104. const struct drm_prop_enum_list *props,
  105. int num_values)
  106. {
  107. struct drm_property *property;
  108. int i, ret;
  109. flags |= DRM_MODE_PROP_ENUM;
  110. property = drm_property_create(dev, flags, name, num_values);
  111. if (!property)
  112. return NULL;
  113. for (i = 0; i < num_values; i++) {
  114. ret = drm_property_add_enum(property, i,
  115. props[i].type,
  116. props[i].name);
  117. if (ret) {
  118. drm_property_destroy(dev, property);
  119. return NULL;
  120. }
  121. }
  122. return property;
  123. }
  124. EXPORT_SYMBOL(drm_property_create_enum);
  125. /**
  126. * drm_property_create_bitmask - create a new bitmask property type
  127. * @dev: drm device
  128. * @flags: flags specifying the property type
  129. * @name: name of the property
  130. * @props: enumeration lists with property bitflags
  131. * @num_props: size of the @props array
  132. * @supported_bits: bitmask of all supported enumeration values
  133. *
  134. * This creates a new bitmask drm property which can then be attached to a drm
  135. * object with drm_object_attach_property. The returned property object must be
  136. * freed with drm_property_destroy.
  137. *
  138. * Compared to plain enumeration properties userspace is allowed to set any
  139. * or'ed together combination of the predefined property bitflag values
  140. *
  141. * Returns:
  142. * A pointer to the newly created property on success, NULL on failure.
  143. */
  144. struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
  145. int flags, const char *name,
  146. const struct drm_prop_enum_list *props,
  147. int num_props,
  148. uint64_t supported_bits)
  149. {
  150. struct drm_property *property;
  151. int i, ret, index = 0;
  152. int num_values = hweight64(supported_bits);
  153. flags |= DRM_MODE_PROP_BITMASK;
  154. property = drm_property_create(dev, flags, name, num_values);
  155. if (!property)
  156. return NULL;
  157. for (i = 0; i < num_props; i++) {
  158. if (!(supported_bits & (1ULL << props[i].type)))
  159. continue;
  160. if (WARN_ON(index >= num_values)) {
  161. drm_property_destroy(dev, property);
  162. return NULL;
  163. }
  164. ret = drm_property_add_enum(property, index++,
  165. props[i].type,
  166. props[i].name);
  167. if (ret) {
  168. drm_property_destroy(dev, property);
  169. return NULL;
  170. }
  171. }
  172. return property;
  173. }
  174. EXPORT_SYMBOL(drm_property_create_bitmask);
  175. static struct drm_property *property_create_range(struct drm_device *dev,
  176. int flags, const char *name,
  177. uint64_t min, uint64_t max)
  178. {
  179. struct drm_property *property;
  180. property = drm_property_create(dev, flags, name, 2);
  181. if (!property)
  182. return NULL;
  183. property->values[0] = min;
  184. property->values[1] = max;
  185. return property;
  186. }
  187. /**
  188. * drm_property_create_range - create a new unsigned ranged property type
  189. * @dev: drm device
  190. * @flags: flags specifying the property type
  191. * @name: name of the property
  192. * @min: minimum value of the property
  193. * @max: maximum value of the property
  194. *
  195. * This creates a new generic drm property which can then be attached to a drm
  196. * object with drm_object_attach_property. The returned property object must be
  197. * freed with drm_property_destroy.
  198. *
  199. * Userspace is allowed to set any unsigned integer value in the (min, max)
  200. * range inclusive.
  201. *
  202. * Returns:
  203. * A pointer to the newly created property on success, NULL on failure.
  204. */
  205. struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
  206. const char *name,
  207. uint64_t min, uint64_t max)
  208. {
  209. return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
  210. name, min, max);
  211. }
  212. EXPORT_SYMBOL(drm_property_create_range);
  213. /**
  214. * drm_property_create_signed_range - create a new signed ranged property type
  215. * @dev: drm device
  216. * @flags: flags specifying the property type
  217. * @name: name of the property
  218. * @min: minimum value of the property
  219. * @max: maximum value of the property
  220. *
  221. * This creates a new generic drm property which can then be attached to a drm
  222. * object with drm_object_attach_property. The returned property object must be
  223. * freed with drm_property_destroy.
  224. *
  225. * Userspace is allowed to set any signed integer value in the (min, max)
  226. * range inclusive.
  227. *
  228. * Returns:
  229. * A pointer to the newly created property on success, NULL on failure.
  230. */
  231. struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
  232. int flags, const char *name,
  233. int64_t min, int64_t max)
  234. {
  235. return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
  236. name, I642U64(min), I642U64(max));
  237. }
  238. EXPORT_SYMBOL(drm_property_create_signed_range);
  239. /**
  240. * drm_property_create_object - create a new object property type
  241. * @dev: drm device
  242. * @flags: flags specifying the property type
  243. * @name: name of the property
  244. * @type: object type from DRM_MODE_OBJECT_* defines
  245. *
  246. * This creates a new generic drm property which can then be attached to a drm
  247. * object with drm_object_attach_property. The returned property object must be
  248. * freed with drm_property_destroy.
  249. *
  250. * Userspace is only allowed to set this to any property value of the given
  251. * @type. Only useful for atomic properties, which is enforced.
  252. *
  253. * Returns:
  254. * A pointer to the newly created property on success, NULL on failure.
  255. */
  256. struct drm_property *drm_property_create_object(struct drm_device *dev,
  257. int flags, const char *name, uint32_t type)
  258. {
  259. struct drm_property *property;
  260. flags |= DRM_MODE_PROP_OBJECT;
  261. if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
  262. return NULL;
  263. property = drm_property_create(dev, flags, name, 1);
  264. if (!property)
  265. return NULL;
  266. property->values[0] = type;
  267. return property;
  268. }
  269. EXPORT_SYMBOL(drm_property_create_object);
  270. /**
  271. * drm_property_create_bool - create a new boolean property type
  272. * @dev: drm device
  273. * @flags: flags specifying the property type
  274. * @name: name of the property
  275. *
  276. * This creates a new generic drm property which can then be attached to a drm
  277. * object with drm_object_attach_property. The returned property object must be
  278. * freed with drm_property_destroy.
  279. *
  280. * This is implemented as a ranged property with only {0, 1} as valid values.
  281. *
  282. * Returns:
  283. * A pointer to the newly created property on success, NULL on failure.
  284. */
  285. struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
  286. const char *name)
  287. {
  288. return drm_property_create_range(dev, flags, name, 0, 1);
  289. }
  290. EXPORT_SYMBOL(drm_property_create_bool);
  291. /**
  292. * drm_property_add_enum - add a possible value to an enumeration property
  293. * @property: enumeration property to change
  294. * @index: index of the new enumeration
  295. * @value: value of the new enumeration
  296. * @name: symbolic name of the new enumeration
  297. *
  298. * This functions adds enumerations to a property.
  299. *
  300. * It's use is deprecated, drivers should use one of the more specific helpers
  301. * to directly create the property with all enumerations already attached.
  302. *
  303. * Returns:
  304. * Zero on success, error code on failure.
  305. */
  306. int drm_property_add_enum(struct drm_property *property, int index,
  307. uint64_t value, const char *name)
  308. {
  309. struct drm_property_enum *prop_enum;
  310. if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
  311. drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
  312. return -EINVAL;
  313. /*
  314. * Bitmask enum properties have the additional constraint of values
  315. * from 0 to 63
  316. */
  317. if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
  318. (value > 63))
  319. return -EINVAL;
  320. if (!list_empty(&property->enum_list)) {
  321. list_for_each_entry(prop_enum, &property->enum_list, head) {
  322. if (prop_enum->value == value) {
  323. strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
  324. prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
  325. return 0;
  326. }
  327. }
  328. }
  329. prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
  330. if (!prop_enum)
  331. return -ENOMEM;
  332. strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
  333. prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
  334. prop_enum->value = value;
  335. property->values[index] = value;
  336. list_add_tail(&prop_enum->head, &property->enum_list);
  337. return 0;
  338. }
  339. EXPORT_SYMBOL(drm_property_add_enum);
  340. /**
  341. * drm_property_destroy - destroy a drm property
  342. * @dev: drm device
  343. * @property: property to destry
  344. *
  345. * This function frees a property including any attached resources like
  346. * enumeration values.
  347. */
  348. void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
  349. {
  350. struct drm_property_enum *prop_enum, *pt;
  351. list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
  352. list_del(&prop_enum->head);
  353. kfree(prop_enum);
  354. }
  355. if (property->num_values)
  356. kfree(property->values);
  357. drm_mode_object_unregister(dev, &property->base);
  358. list_del(&property->head);
  359. kfree(property);
  360. }
  361. EXPORT_SYMBOL(drm_property_destroy);
  362. /**
  363. * drm_mode_getproperty_ioctl - get the property metadata
  364. * @dev: DRM device
  365. * @data: ioctl data
  366. * @file_priv: DRM file info
  367. *
  368. * This function retrieves the metadata for a given property, like the different
  369. * possible values for an enum property or the limits for a range property.
  370. *
  371. * Blob properties are special
  372. *
  373. * Called by the user via ioctl.
  374. *
  375. * Returns:
  376. * Zero on success, negative errno on failure.
  377. */
  378. int drm_mode_getproperty_ioctl(struct drm_device *dev,
  379. void *data, struct drm_file *file_priv)
  380. {
  381. struct drm_mode_get_property *out_resp = data;
  382. struct drm_property *property;
  383. int enum_count = 0;
  384. int value_count = 0;
  385. int ret = 0, i;
  386. int copied;
  387. struct drm_property_enum *prop_enum;
  388. struct drm_mode_property_enum __user *enum_ptr;
  389. uint64_t __user *values_ptr;
  390. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  391. return -EINVAL;
  392. drm_modeset_lock_all(dev);
  393. property = drm_property_find(dev, out_resp->prop_id);
  394. if (!property) {
  395. ret = -ENOENT;
  396. goto done;
  397. }
  398. if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
  399. drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
  400. list_for_each_entry(prop_enum, &property->enum_list, head)
  401. enum_count++;
  402. }
  403. value_count = property->num_values;
  404. strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
  405. out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
  406. out_resp->flags = property->flags;
  407. if ((out_resp->count_values >= value_count) && value_count) {
  408. values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
  409. for (i = 0; i < value_count; i++) {
  410. if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
  411. ret = -EFAULT;
  412. goto done;
  413. }
  414. }
  415. }
  416. out_resp->count_values = value_count;
  417. if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
  418. drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
  419. if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
  420. copied = 0;
  421. enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
  422. list_for_each_entry(prop_enum, &property->enum_list, head) {
  423. if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
  424. ret = -EFAULT;
  425. goto done;
  426. }
  427. if (copy_to_user(&enum_ptr[copied].name,
  428. &prop_enum->name, DRM_PROP_NAME_LEN)) {
  429. ret = -EFAULT;
  430. goto done;
  431. }
  432. copied++;
  433. }
  434. }
  435. out_resp->count_enum_blobs = enum_count;
  436. }
  437. /*
  438. * NOTE: The idea seems to have been to use this to read all the blob
  439. * property values. But nothing ever added them to the corresponding
  440. * list, userspace always used the special-purpose get_blob ioctl to
  441. * read the value for a blob property. It also doesn't make a lot of
  442. * sense to return values here when everything else is just metadata for
  443. * the property itself.
  444. */
  445. if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
  446. out_resp->count_enum_blobs = 0;
  447. done:
  448. drm_modeset_unlock_all(dev);
  449. return ret;
  450. }
  451. static void drm_property_free_blob(struct kref *kref)
  452. {
  453. struct drm_property_blob *blob =
  454. container_of(kref, struct drm_property_blob, base.refcount);
  455. mutex_lock(&blob->dev->mode_config.blob_lock);
  456. list_del(&blob->head_global);
  457. mutex_unlock(&blob->dev->mode_config.blob_lock);
  458. drm_mode_object_unregister(blob->dev, &blob->base);
  459. kfree(blob);
  460. }
  461. /**
  462. * drm_property_create_blob - Create new blob property
  463. *
  464. * Creates a new blob property for a specified DRM device, optionally
  465. * copying data.
  466. *
  467. * @dev: DRM device to create property for
  468. * @length: Length to allocate for blob data
  469. * @data: If specified, copies data into blob
  470. *
  471. * Returns:
  472. * New blob property with a single reference on success, or an ERR_PTR
  473. * value on failure.
  474. */
  475. struct drm_property_blob *
  476. drm_property_create_blob(struct drm_device *dev, size_t length,
  477. const void *data)
  478. {
  479. struct drm_property_blob *blob;
  480. int ret;
  481. if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
  482. return ERR_PTR(-EINVAL);
  483. blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
  484. if (!blob)
  485. return ERR_PTR(-ENOMEM);
  486. /* This must be explicitly initialised, so we can safely call list_del
  487. * on it in the removal handler, even if it isn't in a file list. */
  488. INIT_LIST_HEAD(&blob->head_file);
  489. blob->length = length;
  490. blob->dev = dev;
  491. if (data)
  492. memcpy(blob->data, data, length);
  493. ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
  494. true, drm_property_free_blob);
  495. if (ret) {
  496. kfree(blob);
  497. return ERR_PTR(-EINVAL);
  498. }
  499. mutex_lock(&dev->mode_config.blob_lock);
  500. list_add_tail(&blob->head_global,
  501. &dev->mode_config.property_blob_list);
  502. mutex_unlock(&dev->mode_config.blob_lock);
  503. return blob;
  504. }
  505. EXPORT_SYMBOL(drm_property_create_blob);
  506. /**
  507. * drm_property_unreference_blob - Unreference a blob property
  508. *
  509. * Drop a reference on a blob property. May free the object.
  510. *
  511. * @blob: Pointer to blob property
  512. */
  513. void drm_property_unreference_blob(struct drm_property_blob *blob)
  514. {
  515. if (!blob)
  516. return;
  517. drm_mode_object_unreference(&blob->base);
  518. }
  519. EXPORT_SYMBOL(drm_property_unreference_blob);
  520. /**
  521. * drm_property_destroy_user_blobs - destroy all blobs created by this client
  522. * @dev: DRM device
  523. * @file_priv: destroy all blobs owned by this file handle
  524. */
  525. void drm_property_destroy_user_blobs(struct drm_device *dev,
  526. struct drm_file *file_priv)
  527. {
  528. struct drm_property_blob *blob, *bt;
  529. /*
  530. * When the file gets released that means no one else can access the
  531. * blob list any more, so no need to grab dev->blob_lock.
  532. */
  533. list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
  534. list_del_init(&blob->head_file);
  535. drm_property_unreference_blob(blob);
  536. }
  537. }
  538. /**
  539. * drm_property_reference_blob - Take a reference on an existing property
  540. *
  541. * Take a new reference on an existing blob property.
  542. *
  543. * @blob: Pointer to blob property
  544. */
  545. struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
  546. {
  547. drm_mode_object_reference(&blob->base);
  548. return blob;
  549. }
  550. EXPORT_SYMBOL(drm_property_reference_blob);
  551. /**
  552. * drm_property_lookup_blob - look up a blob property and take a reference
  553. * @dev: drm device
  554. * @id: id of the blob property
  555. *
  556. * If successful, this takes an additional reference to the blob property.
  557. * callers need to make sure to eventually unreference the returned property
  558. * again, using @drm_property_unreference_blob.
  559. */
  560. struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
  561. uint32_t id)
  562. {
  563. struct drm_mode_object *obj;
  564. struct drm_property_blob *blob = NULL;
  565. obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
  566. if (obj)
  567. blob = obj_to_blob(obj);
  568. return blob;
  569. }
  570. EXPORT_SYMBOL(drm_property_lookup_blob);
  571. /**
  572. * drm_property_replace_global_blob - atomically replace existing blob property
  573. * @dev: drm device
  574. * @replace: location of blob property pointer to be replaced
  575. * @length: length of data for new blob, or 0 for no data
  576. * @data: content for new blob, or NULL for no data
  577. * @obj_holds_id: optional object for property holding blob ID
  578. * @prop_holds_id: optional property holding blob ID
  579. * @return 0 on success or error on failure
  580. *
  581. * This function will atomically replace a global property in the blob list,
  582. * optionally updating a property which holds the ID of that property. It is
  583. * guaranteed to be atomic: no caller will be allowed to see intermediate
  584. * results, and either the entire operation will succeed and clean up the
  585. * previous property, or it will fail and the state will be unchanged.
  586. *
  587. * If length is 0 or data is NULL, no new blob will be created, and the holding
  588. * property, if specified, will be set to 0.
  589. *
  590. * Access to the replace pointer is assumed to be protected by the caller, e.g.
  591. * by holding the relevant modesetting object lock for its parent.
  592. *
  593. * For example, a drm_connector has a 'PATH' property, which contains the ID
  594. * of a blob property with the value of the MST path information. Calling this
  595. * function with replace pointing to the connector's path_blob_ptr, length and
  596. * data set for the new path information, obj_holds_id set to the connector's
  597. * base object, and prop_holds_id set to the path property name, will perform
  598. * a completely atomic update. The access to path_blob_ptr is protected by the
  599. * caller holding a lock on the connector.
  600. */
  601. int drm_property_replace_global_blob(struct drm_device *dev,
  602. struct drm_property_blob **replace,
  603. size_t length,
  604. const void *data,
  605. struct drm_mode_object *obj_holds_id,
  606. struct drm_property *prop_holds_id)
  607. {
  608. struct drm_property_blob *new_blob = NULL;
  609. struct drm_property_blob *old_blob = NULL;
  610. int ret;
  611. WARN_ON(replace == NULL);
  612. old_blob = *replace;
  613. if (length && data) {
  614. new_blob = drm_property_create_blob(dev, length, data);
  615. if (IS_ERR(new_blob))
  616. return PTR_ERR(new_blob);
  617. }
  618. /* This does not need to be synchronised with blob_lock, as the
  619. * get_properties ioctl locks all modesetting objects, and
  620. * obj_holds_id must be locked before calling here, so we cannot
  621. * have its value out of sync with the list membership modified
  622. * below under blob_lock. */
  623. if (obj_holds_id) {
  624. ret = drm_object_property_set_value(obj_holds_id,
  625. prop_holds_id,
  626. new_blob ?
  627. new_blob->base.id : 0);
  628. if (ret != 0)
  629. goto err_created;
  630. }
  631. drm_property_unreference_blob(old_blob);
  632. *replace = new_blob;
  633. return 0;
  634. err_created:
  635. drm_property_unreference_blob(new_blob);
  636. return ret;
  637. }
  638. EXPORT_SYMBOL(drm_property_replace_global_blob);
  639. /**
  640. * drm_mode_getblob_ioctl - get the contents of a blob property value
  641. * @dev: DRM device
  642. * @data: ioctl data
  643. * @file_priv: DRM file info
  644. *
  645. * This function retrieves the contents of a blob property. The value stored in
  646. * an object's blob property is just a normal modeset object id.
  647. *
  648. * Called by the user via ioctl.
  649. *
  650. * Returns:
  651. * Zero on success, negative errno on failure.
  652. */
  653. int drm_mode_getblob_ioctl(struct drm_device *dev,
  654. void *data, struct drm_file *file_priv)
  655. {
  656. struct drm_mode_get_blob *out_resp = data;
  657. struct drm_property_blob *blob;
  658. int ret = 0;
  659. void __user *blob_ptr;
  660. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  661. return -EINVAL;
  662. blob = drm_property_lookup_blob(dev, out_resp->blob_id);
  663. if (!blob)
  664. return -ENOENT;
  665. if (out_resp->length == blob->length) {
  666. blob_ptr = (void __user *)(unsigned long)out_resp->data;
  667. if (copy_to_user(blob_ptr, blob->data, blob->length)) {
  668. ret = -EFAULT;
  669. goto unref;
  670. }
  671. }
  672. out_resp->length = blob->length;
  673. unref:
  674. drm_property_unreference_blob(blob);
  675. return ret;
  676. }
  677. /**
  678. * drm_mode_createblob_ioctl - create a new blob property
  679. * @dev: DRM device
  680. * @data: ioctl data
  681. * @file_priv: DRM file info
  682. *
  683. * This function creates a new blob property with user-defined values. In order
  684. * to give us sensible validation and checking when creating, rather than at
  685. * every potential use, we also require a type to be provided upfront.
  686. *
  687. * Called by the user via ioctl.
  688. *
  689. * Returns:
  690. * Zero on success, negative errno on failure.
  691. */
  692. int drm_mode_createblob_ioctl(struct drm_device *dev,
  693. void *data, struct drm_file *file_priv)
  694. {
  695. struct drm_mode_create_blob *out_resp = data;
  696. struct drm_property_blob *blob;
  697. void __user *blob_ptr;
  698. int ret = 0;
  699. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  700. return -EINVAL;
  701. blob = drm_property_create_blob(dev, out_resp->length, NULL);
  702. if (IS_ERR(blob))
  703. return PTR_ERR(blob);
  704. blob_ptr = (void __user *)(unsigned long)out_resp->data;
  705. if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
  706. ret = -EFAULT;
  707. goto out_blob;
  708. }
  709. /* Dropping the lock between create_blob and our access here is safe
  710. * as only the same file_priv can remove the blob; at this point, it is
  711. * not associated with any file_priv. */
  712. mutex_lock(&dev->mode_config.blob_lock);
  713. out_resp->blob_id = blob->base.id;
  714. list_add_tail(&blob->head_file, &file_priv->blobs);
  715. mutex_unlock(&dev->mode_config.blob_lock);
  716. return 0;
  717. out_blob:
  718. drm_property_unreference_blob(blob);
  719. return ret;
  720. }
  721. /**
  722. * drm_mode_destroyblob_ioctl - destroy a user blob property
  723. * @dev: DRM device
  724. * @data: ioctl data
  725. * @file_priv: DRM file info
  726. *
  727. * Destroy an existing user-defined blob property.
  728. *
  729. * Called by the user via ioctl.
  730. *
  731. * Returns:
  732. * Zero on success, negative errno on failure.
  733. */
  734. int drm_mode_destroyblob_ioctl(struct drm_device *dev,
  735. void *data, struct drm_file *file_priv)
  736. {
  737. struct drm_mode_destroy_blob *out_resp = data;
  738. struct drm_property_blob *blob = NULL, *bt;
  739. bool found = false;
  740. int ret = 0;
  741. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  742. return -EINVAL;
  743. blob = drm_property_lookup_blob(dev, out_resp->blob_id);
  744. if (!blob)
  745. return -ENOENT;
  746. mutex_lock(&dev->mode_config.blob_lock);
  747. /* Ensure the property was actually created by this user. */
  748. list_for_each_entry(bt, &file_priv->blobs, head_file) {
  749. if (bt == blob) {
  750. found = true;
  751. break;
  752. }
  753. }
  754. if (!found) {
  755. ret = -EPERM;
  756. goto err;
  757. }
  758. /* We must drop head_file here, because we may not be the last
  759. * reference on the blob. */
  760. list_del_init(&blob->head_file);
  761. mutex_unlock(&dev->mode_config.blob_lock);
  762. /* One reference from lookup, and one from the filp. */
  763. drm_property_unreference_blob(blob);
  764. drm_property_unreference_blob(blob);
  765. return 0;
  766. err:
  767. mutex_unlock(&dev->mode_config.blob_lock);
  768. drm_property_unreference_blob(blob);
  769. return ret;
  770. }
  771. /* Some properties could refer to dynamic refcnt'd objects, or things that
  772. * need special locking to handle lifetime issues (ie. to ensure the prop
  773. * value doesn't become invalid part way through the property update due to
  774. * race). The value returned by reference via 'obj' should be passed back
  775. * to drm_property_change_valid_put() after the property is set (and the
  776. * object to which the property is attached has a chance to take it's own
  777. * reference).
  778. */
  779. bool drm_property_change_valid_get(struct drm_property *property,
  780. uint64_t value, struct drm_mode_object **ref)
  781. {
  782. int i;
  783. if (property->flags & DRM_MODE_PROP_IMMUTABLE)
  784. return false;
  785. *ref = NULL;
  786. if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
  787. if (value < property->values[0] || value > property->values[1])
  788. return false;
  789. return true;
  790. } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
  791. int64_t svalue = U642I64(value);
  792. if (svalue < U642I64(property->values[0]) ||
  793. svalue > U642I64(property->values[1]))
  794. return false;
  795. return true;
  796. } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
  797. uint64_t valid_mask = 0;
  798. for (i = 0; i < property->num_values; i++)
  799. valid_mask |= (1ULL << property->values[i]);
  800. return !(value & ~valid_mask);
  801. } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
  802. struct drm_property_blob *blob;
  803. if (value == 0)
  804. return true;
  805. blob = drm_property_lookup_blob(property->dev, value);
  806. if (blob) {
  807. *ref = &blob->base;
  808. return true;
  809. } else {
  810. return false;
  811. }
  812. } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
  813. /* a zero value for an object property translates to null: */
  814. if (value == 0)
  815. return true;
  816. *ref = __drm_mode_object_find(property->dev, value,
  817. property->values[0]);
  818. return *ref != NULL;
  819. }
  820. for (i = 0; i < property->num_values; i++)
  821. if (property->values[i] == value)
  822. return true;
  823. return false;
  824. }
  825. void drm_property_change_valid_put(struct drm_property *property,
  826. struct drm_mode_object *ref)
  827. {
  828. if (!ref)
  829. return;
  830. if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
  831. drm_mode_object_unreference(ref);
  832. } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
  833. drm_property_unreference_blob(obj_to_blob(ref));
  834. }