131 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#ifndef _DRM_MANAGED_H_4#define _DRM_MANAGED_H_5 6#include <linux/gfp.h>7#include <linux/overflow.h>8#include <linux/types.h>9 10struct drm_device;11struct mutex;12 13typedef void (*drmres_release_t)(struct drm_device *dev, void *res);14 15/**16 * drmm_add_action - add a managed release action to a &drm_device17 * @dev: DRM device18 * @action: function which should be called when @dev is released19 * @data: opaque pointer, passed to @action20 *21 * This function adds the @release action with optional parameter @data to the22 * list of cleanup actions for @dev. The cleanup actions will be run in reverse23 * order in the final drm_dev_put() call for @dev.24 */25#define drmm_add_action(dev, action, data) \26 __drmm_add_action(dev, action, data, #action)27 28int __must_check __drmm_add_action(struct drm_device *dev,29 drmres_release_t action,30 void *data, const char *name);31 32/**33 * drmm_add_action_or_reset - add a managed release action to a &drm_device34 * @dev: DRM device35 * @action: function which should be called when @dev is released36 * @data: opaque pointer, passed to @action37 *38 * Similar to drmm_add_action(), with the only difference that upon failure39 * @action is directly called for any cleanup work necessary on failures.40 */41#define drmm_add_action_or_reset(dev, action, data) \42 __drmm_add_action_or_reset(dev, action, data, #action)43 44int __must_check __drmm_add_action_or_reset(struct drm_device *dev,45 drmres_release_t action,46 void *data, const char *name);47 48void drmm_release_action(struct drm_device *dev,49 drmres_release_t action,50 void *data);51 52void *drmm_kmalloc(struct drm_device *dev, size_t size, gfp_t gfp) __malloc;53 54/**55 * drmm_kzalloc - &drm_device managed kzalloc()56 * @dev: DRM device57 * @size: size of the memory allocation58 * @gfp: GFP allocation flags59 *60 * This is a &drm_device managed version of kzalloc(). The allocated memory is61 * automatically freed on the final drm_dev_put(). Memory can also be freed62 * before the final drm_dev_put() by calling drmm_kfree().63 */64static inline void *drmm_kzalloc(struct drm_device *dev, size_t size, gfp_t gfp)65{66 return drmm_kmalloc(dev, size, gfp | __GFP_ZERO);67}68 69/**70 * drmm_kmalloc_array - &drm_device managed kmalloc_array()71 * @dev: DRM device72 * @n: number of array elements to allocate73 * @size: size of array member74 * @flags: GFP allocation flags75 *76 * This is a &drm_device managed version of kmalloc_array(). The allocated77 * memory is automatically freed on the final drm_dev_put() and works exactly78 * like a memory allocation obtained by drmm_kmalloc().79 */80static inline void *drmm_kmalloc_array(struct drm_device *dev,81 size_t n, size_t size, gfp_t flags)82{83 size_t bytes;84 85 if (unlikely(check_mul_overflow(n, size, &bytes)))86 return NULL;87 88 return drmm_kmalloc(dev, bytes, flags);89}90 91/**92 * drmm_kcalloc - &drm_device managed kcalloc()93 * @dev: DRM device94 * @n: number of array elements to allocate95 * @size: size of array member96 * @flags: GFP allocation flags97 *98 * This is a &drm_device managed version of kcalloc(). The allocated memory is99 * automatically freed on the final drm_dev_put() and works exactly like a100 * memory allocation obtained by drmm_kmalloc().101 */102static inline void *drmm_kcalloc(struct drm_device *dev,103 size_t n, size_t size, gfp_t flags)104{105 return drmm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);106}107 108char *drmm_kstrdup(struct drm_device *dev, const char *s, gfp_t gfp);109 110void drmm_kfree(struct drm_device *dev, void *data);111 112void __drmm_mutex_release(struct drm_device *dev, void *res);113 114/**115 * drmm_mutex_init - &drm_device-managed mutex_init()116 * @dev: DRM device117 * @lock: lock to be initialized118 *119 * Returns:120 * 0 on success, or a negative errno code otherwise.121 *122 * This is a &drm_device-managed version of mutex_init(). The initialized123 * lock is automatically destroyed on the final drm_dev_put().124 */125#define drmm_mutex_init(dev, lock) ({ \126 mutex_init(lock); \127 drmm_add_action_or_reset(dev, __drmm_mutex_release, lock); \128}) \129 130#endif131