drm_property.c 27 KB

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