uboot/include/dm/devres.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0+ */
   2/*
   3 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
   4 *
   5 * Based on the original work in Linux by
   6 * Copyright (c) 2006  SUSE Linux Products GmbH
   7 * Copyright (c) 2006  Tejun Heo <teheo@suse.de>
   8 * Copyright 2019 Google LLC
   9 */
  10
  11#ifndef _DM_DEVRES_H
  12#define _DM_DEVRES_H
  13
  14#include <linux/compat.h>
  15
  16struct udevice;
  17
  18/* device resource management */
  19typedef void (*dr_release_t)(struct udevice *dev, void *res);
  20typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
  21
  22/**
  23 * struct devres_stats - Information about devres allocations for a device
  24 *
  25 * @allocs: Number of allocations
  26 * @total_size: Total size of allocations in bytes
  27 */
  28struct devres_stats {
  29        int allocs;
  30        int total_size;
  31};
  32
  33#ifdef CONFIG_DEVRES
  34
  35#ifdef CONFIG_DEBUG_DEVRES
  36void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
  37                     const char *name);
  38#define _devres_alloc(release, size, gfp) \
  39        __devres_alloc(release, size, gfp, #release)
  40#else
  41void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
  42#endif
  43
  44/**
  45 * devres_alloc() - Allocate device resource data
  46 * @release: Release function devres will be associated with
  47 * @size: Allocation size
  48 * @gfp: Allocation flags
  49 *
  50 * Allocate devres of @size bytes.  The allocated area is associated
  51 * with @release.  The returned pointer can be passed to
  52 * other devres_*() functions.
  53 *
  54 * RETURNS:
  55 * Pointer to allocated devres on success, NULL on failure.
  56 */
  57#define devres_alloc(release, size, gfp) \
  58        _devres_alloc(release, size, (gfp) | __GFP_ZERO)
  59
  60/**
  61 * devres_free() - Free device resource data
  62 * @res: Pointer to devres data to free
  63 *
  64 * Free devres created with devres_alloc().
  65 */
  66void devres_free(void *res);
  67
  68/**
  69 * devres_add() - Register device resource
  70 * @dev: Device to add resource to
  71 * @res: Resource to register
  72 *
  73 * Register devres @res to @dev.  @res should have been allocated
  74 * using devres_alloc().  On driver detach, the associated release
  75 * function will be invoked and devres will be freed automatically.
  76 */
  77void devres_add(struct udevice *dev, void *res);
  78
  79/**
  80 * devres_find() - Find device resource
  81 * @dev: Device to lookup resource from
  82 * @release: Look for resources associated with this release function
  83 * @match: Match function (optional)
  84 * @match_data: Data for the match function
  85 *
  86 * Find the latest devres of @dev which is associated with @release
  87 * and for which @match returns 1.  If @match is NULL, it's considered
  88 * to match all.
  89 *
  90 * @return pointer to found devres, NULL if not found.
  91 */
  92void *devres_find(struct udevice *dev, dr_release_t release,
  93                  dr_match_t match, void *match_data);
  94
  95/**
  96 * devres_get() - Find devres, if non-existent, add one atomically
  97 * @dev: Device to lookup or add devres for
  98 * @new_res: Pointer to new initialized devres to add if not found
  99 * @match: Match function (optional)
 100 * @match_data: Data for the match function
 101 *
 102 * Find the latest devres of @dev which has the same release function
 103 * as @new_res and for which @match return 1.  If found, @new_res is
 104 * freed; otherwise, @new_res is added atomically.
 105 *
 106 * @return ointer to found or added devres.
 107 */
 108void *devres_get(struct udevice *dev, void *new_res,
 109                 dr_match_t match, void *match_data);
 110
 111/**
 112 * devres_remove() - Find a device resource and remove it
 113 * @dev: Device to find resource from
 114 * @release: Look for resources associated with this release function
 115 * @match: Match function (optional)
 116 * @match_data: Data for the match function
 117 *
 118 * Find the latest devres of @dev associated with @release and for
 119 * which @match returns 1.  If @match is NULL, it's considered to
 120 * match all.  If found, the resource is removed atomically and
 121 * returned.
 122 *
 123 * @return ointer to removed devres on success, NULL if not found.
 124 */
 125void *devres_remove(struct udevice *dev, dr_release_t release,
 126                    dr_match_t match, void *match_data);
 127
 128/**
 129 * devres_destroy() - Find a device resource and destroy it
 130 * @dev: Device to find resource from
 131 * @release: Look for resources associated with this release function
 132 * @match: Match function (optional)
 133 * @match_data: Data for the match function
 134 *
 135 * Find the latest devres of @dev associated with @release and for
 136 * which @match returns 1.  If @match is NULL, it's considered to
 137 * match all.  If found, the resource is removed atomically and freed.
 138 *
 139 * Note that the release function for the resource will not be called,
 140 * only the devres-allocated data will be freed.  The caller becomes
 141 * responsible for freeing any other data.
 142 *
 143 * @return 0 if devres is found and freed, -ENOENT if not found.
 144 */
 145int devres_destroy(struct udevice *dev, dr_release_t release,
 146                   dr_match_t match, void *match_data);
 147
 148/**
 149 * devres_release() - Find a device resource and destroy it, calling release
 150 * @dev: Device to find resource from
 151 * @release: Look for resources associated with this release function
 152 * @match: Match function (optional)
 153 * @match_data: Data for the match function
 154 *
 155 * Find the latest devres of @dev associated with @release and for
 156 * which @match returns 1.  If @match is NULL, it's considered to
 157 * match all.  If found, the resource is removed atomically, the
 158 * release function called and the resource freed.
 159 *
 160 * @return 0 if devres is found and freed, -ENOENT if not found.
 161 */
 162int devres_release(struct udevice *dev, dr_release_t release,
 163                   dr_match_t match, void *match_data);
 164
 165/* managed devm_k.alloc/kfree for device drivers */
 166/**
 167 * devm_kmalloc() - Resource-managed kmalloc
 168 * @dev: Device to allocate memory for
 169 * @size: Allocation size
 170 * @gfp: Allocation gfp flags
 171 *
 172 * Managed kmalloc.  Memory allocated with this function is
 173 * automatically freed on driver detach.  Like all other devres
 174 * resources, guaranteed alignment is unsigned long long.
 175 *
 176 * @return pointer to allocated memory on success, NULL on failure.
 177 */
 178void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
 179static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
 180{
 181        return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
 182}
 183
 184static inline void *devm_kmalloc_array(struct udevice *dev,
 185                                       size_t n, size_t size, gfp_t flags)
 186{
 187        if (size != 0 && n > SIZE_MAX / size)
 188                return NULL;
 189        return devm_kmalloc(dev, n * size, flags);
 190}
 191
 192static inline void *devm_kcalloc(struct udevice *dev,
 193                                 size_t n, size_t size, gfp_t flags)
 194{
 195        return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
 196}
 197
 198/**
 199 * devm_kfree() - Resource-managed kfree
 200 * @dev: Device this memory belongs to
 201 * @ptr: Memory to free
 202 *
 203 * Free memory allocated with devm_kmalloc().
 204 */
 205void devm_kfree(struct udevice *dev, void *ptr);
 206
 207/* Get basic stats on allocations */
 208void devres_get_stats(const struct udevice *dev, struct devres_stats *stats);
 209
 210#else /* ! CONFIG_DEVRES */
 211
 212static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
 213{
 214        return kzalloc(size, gfp);
 215}
 216
 217static inline void devres_free(void *res)
 218{
 219        kfree(res);
 220}
 221
 222static inline void devres_add(struct udevice *dev, void *res)
 223{
 224}
 225
 226static inline void *devres_find(struct udevice *dev, dr_release_t release,
 227                                dr_match_t match, void *match_data)
 228{
 229        return NULL;
 230}
 231
 232static inline void *devres_get(struct udevice *dev, void *new_res,
 233                               dr_match_t match, void *match_data)
 234{
 235        return NULL;
 236}
 237
 238static inline void *devres_remove(struct udevice *dev, dr_release_t release,
 239                                  dr_match_t match, void *match_data)
 240{
 241        return NULL;
 242}
 243
 244static inline int devres_destroy(struct udevice *dev, dr_release_t release,
 245                                 dr_match_t match, void *match_data)
 246{
 247        return 0;
 248}
 249
 250static inline int devres_release(struct udevice *dev, dr_release_t release,
 251                                 dr_match_t match, void *match_data)
 252{
 253        return 0;
 254}
 255
 256static inline void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
 257{
 258        return kmalloc(size, gfp);
 259}
 260
 261static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
 262{
 263        return kzalloc(size, gfp);
 264}
 265
 266static inline void *devm_kmalloc_array(struct udevice *dev,
 267                                       size_t n, size_t size, gfp_t flags)
 268{
 269        /* TODO: add kmalloc_array() to linux/compat.h */
 270        if (size != 0 && n > SIZE_MAX / size)
 271                return NULL;
 272        return kmalloc(n * size, flags);
 273}
 274
 275static inline void *devm_kcalloc(struct udevice *dev,
 276                                 size_t n, size_t size, gfp_t flags)
 277{
 278        /* TODO: add kcalloc() to linux/compat.h */
 279        return kmalloc(n * size, flags | __GFP_ZERO);
 280}
 281
 282static inline void devm_kfree(struct udevice *dev, void *ptr)
 283{
 284        kfree(ptr);
 285}
 286
 287static inline void devres_get_stats(const struct udevice *dev,
 288                                    struct devres_stats *stats)
 289{
 290}
 291
 292#endif /* DEVRES */
 293#endif /* _DM_DEVRES_H */
 294