drm_property.c 27 KB

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