18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#ifndef _DRM_MANAGED_H_
48c2ecf20Sopenharmony_ci#define _DRM_MANAGED_H_
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/gfp.h>
78c2ecf20Sopenharmony_ci#include <linux/overflow.h>
88c2ecf20Sopenharmony_ci#include <linux/types.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistruct drm_device;
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_citypedef void (*drmres_release_t)(struct drm_device *dev, void *res);
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci/**
158c2ecf20Sopenharmony_ci * drmm_add_action - add a managed release action to a &drm_device
168c2ecf20Sopenharmony_ci * @dev: DRM device
178c2ecf20Sopenharmony_ci * @action: function which should be called when @dev is released
188c2ecf20Sopenharmony_ci * @data: opaque pointer, passed to @action
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * This function adds the @release action with optional parameter @data to the
218c2ecf20Sopenharmony_ci * list of cleanup actions for @dev. The cleanup actions will be run in reverse
228c2ecf20Sopenharmony_ci * order in the final drm_dev_put() call for @dev.
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_ci#define drmm_add_action(dev, action, data) \
258c2ecf20Sopenharmony_ci	__drmm_add_action(dev, action, data, #action)
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciint __must_check __drmm_add_action(struct drm_device *dev,
288c2ecf20Sopenharmony_ci				   drmres_release_t action,
298c2ecf20Sopenharmony_ci				   void *data, const char *name);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/**
328c2ecf20Sopenharmony_ci * drmm_add_action_or_reset - add a managed release action to a &drm_device
338c2ecf20Sopenharmony_ci * @dev: DRM device
348c2ecf20Sopenharmony_ci * @action: function which should be called when @dev is released
358c2ecf20Sopenharmony_ci * @data: opaque pointer, passed to @action
368c2ecf20Sopenharmony_ci *
378c2ecf20Sopenharmony_ci * Similar to drmm_add_action(), with the only difference that upon failure
388c2ecf20Sopenharmony_ci * @action is directly called for any cleanup work necessary on failures.
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_ci#define drmm_add_action_or_reset(dev, action, data) \
418c2ecf20Sopenharmony_ci	__drmm_add_action_or_reset(dev, action, data, #action)
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciint __must_check __drmm_add_action_or_reset(struct drm_device *dev,
448c2ecf20Sopenharmony_ci					    drmres_release_t action,
458c2ecf20Sopenharmony_ci					    void *data, const char *name);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_civoid drmm_add_final_kfree(struct drm_device *dev, void *container);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_civoid *drmm_kmalloc(struct drm_device *dev, size_t size, gfp_t gfp) __malloc;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/**
528c2ecf20Sopenharmony_ci * drmm_kzalloc - &drm_device managed kzalloc()
538c2ecf20Sopenharmony_ci * @dev: DRM device
548c2ecf20Sopenharmony_ci * @size: size of the memory allocation
558c2ecf20Sopenharmony_ci * @gfp: GFP allocation flags
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * This is a &drm_device managed version of kzalloc(). The allocated memory is
588c2ecf20Sopenharmony_ci * automatically freed on the final drm_dev_put(). Memory can also be freed
598c2ecf20Sopenharmony_ci * before the final drm_dev_put() by calling drmm_kfree().
608c2ecf20Sopenharmony_ci */
618c2ecf20Sopenharmony_cistatic inline void *drmm_kzalloc(struct drm_device *dev, size_t size, gfp_t gfp)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	return drmm_kmalloc(dev, size, gfp | __GFP_ZERO);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci/**
678c2ecf20Sopenharmony_ci * drmm_kmalloc_array - &drm_device managed kmalloc_array()
688c2ecf20Sopenharmony_ci * @dev: DRM device
698c2ecf20Sopenharmony_ci * @n: number of array elements to allocate
708c2ecf20Sopenharmony_ci * @size: size of array member
718c2ecf20Sopenharmony_ci * @flags: GFP allocation flags
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * This is a &drm_device managed version of kmalloc_array(). The allocated
748c2ecf20Sopenharmony_ci * memory is automatically freed on the final drm_dev_put() and works exactly
758c2ecf20Sopenharmony_ci * like a memory allocation obtained by drmm_kmalloc().
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_cistatic inline void *drmm_kmalloc_array(struct drm_device *dev,
788c2ecf20Sopenharmony_ci				       size_t n, size_t size, gfp_t flags)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	size_t bytes;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	if (unlikely(check_mul_overflow(n, size, &bytes)))
838c2ecf20Sopenharmony_ci		return NULL;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	return drmm_kmalloc(dev, bytes, flags);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/**
898c2ecf20Sopenharmony_ci * drmm_kcalloc - &drm_device managed kcalloc()
908c2ecf20Sopenharmony_ci * @dev: DRM device
918c2ecf20Sopenharmony_ci * @n: number of array elements to allocate
928c2ecf20Sopenharmony_ci * @size: size of array member
938c2ecf20Sopenharmony_ci * @flags: GFP allocation flags
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * This is a &drm_device managed version of kcalloc(). The allocated memory is
968c2ecf20Sopenharmony_ci * automatically freed on the final drm_dev_put() and works exactly like a
978c2ecf20Sopenharmony_ci * memory allocation obtained by drmm_kmalloc().
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_cistatic inline void *drmm_kcalloc(struct drm_device *dev,
1008c2ecf20Sopenharmony_ci				 size_t n, size_t size, gfp_t flags)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	return drmm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cichar *drmm_kstrdup(struct drm_device *dev, const char *s, gfp_t gfp);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_civoid drmm_kfree(struct drm_device *dev, void *data);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#endif
110