drm_property.c 29 KB

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