Am 02.03.20 um 23:25 schrieb Daniel Vetter: <...> > + > +int __drmm_add_action(struct drm_device *dev, > + drmres_release_t action, > + void *data, const char *name) > +{ > + struct drmres *dr; > + void **void_ptr; > + > + dr = alloc_dr(action, data ? sizeof(void*) : 0, > + GFP_KERNEL | __GFP_ZERO, > + dev_to_node(dev->dev)); > + if (!dr) { > + drm_dbg_drmres(dev, "failed to add action %s for %p\n", > + name, data); > + return -ENOMEM; > + } > + > + dr->node.name = name; Maybe do a kstrdup_const() on name and later a kfree_const() during release. Just in case someone decides to allocate 'name' dynamically. > + if (data) { > + void_ptr = (void **)&dr->data; > + *void_ptr = data; > + } > + > + add_dr(dev, dr); > + > + return 0; > +} > +EXPORT_SYMBOL(__drmm_add_action); > + > +void *drmm_kmalloc(struct drm_device *dev, size_t size, gfp_t gfp) > +{ > + struct drmres *dr; > + > + dr = alloc_dr(NULL, size, gfp, dev_to_node(dev->dev)); > + if (!dr) { > + drm_dbg_drmres(dev, "failed to allocate %zu bytes, %u flags\n", > + size, gfp); > + return NULL; > + } > + dr->node.name = "kmalloc"; > + > + add_dr(dev, dr); > + > + return dr->data; > +} > +EXPORT_SYMBOL(drmm_kmalloc); > + > +void drmm_kfree(struct drm_device *dev, void *data) > +{ > + struct drmres *dr_match = NULL, *dr; > + unsigned long flags; > + > + if (!data) > + return; > + > + spin_lock_irqsave(&dev->managed.lock, flags); > + list_for_each_entry(dr, &dev->managed.resources, node.entry) { > + if (dr->data == data) { > + dr_match = dr; > + del_dr(dev, dr_match); > + break; > + } > + } > + spin_unlock_irqrestore(&dev->managed.lock, flags); > + > + if (WARN_ON(!dr_match)) > + return; > + > + kfree(dr_match); > +} > +EXPORT_SYMBOL(drmm_kfree); > diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h > index bb60a949f416..d39132b477dd 100644 > --- a/include/drm/drm_device.h > +++ b/include/drm/drm_device.h > @@ -67,6 +67,21 @@ struct drm_device { > /** @dev: Device structure of bus-device */ > struct device *dev; > > + /** > + * @managed: > + * > + * Managed resources linked to the lifetime of this &drm_device as > + * tracked by @ref. > + */ > + struct { > + /** @managed.resources: managed resources list */ > + struct list_head resources; > + /** @managed.final_kfree: pointer for final kfree() call */ > + void *final_kfree; > + /** @managed.lock: protects @managed.resources */ > + spinlock_t lock; > + } managed; > + > /** @driver: DRM driver managing the device */ > struct drm_driver *driver; > > diff --git a/include/drm/drm_managed.h b/include/drm/drm_managed.h > new file mode 100644 > index 000000000000..7b5df7d09b19 > --- /dev/null > +++ b/include/drm/drm_managed.h > @@ -0,0 +1,30 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#ifndef _DRM_MANAGED_H_ > +#define _DRM_MANAGED_H_ > + > +#include > +#include > + > +struct drm_device; > + > +typedef void (*drmres_release_t)(struct drm_device *dev, void *res); > + > +#define drmm_add_action(dev, action, data) \ > + __drmm_add_action(dev, action, data, #action) > + > +int __must_check __drmm_add_action(struct drm_device *dev, > + drmres_release_t action, > + void *data, const char *name); > + > +void drmm_add_final_kfree(struct drm_device *dev, void *parent); > + > +void *drmm_kmalloc(struct drm_device *dev, size_t size, gfp_t gfp) __malloc; > +static inline void *drmm_kzalloc(struct drm_device *dev, size_t size, gfp_t gfp) > +{ > + return drmm_kmalloc(dev, size, gfp | __GFP_ZERO); > +} > + > +void drmm_kfree(struct drm_device *dev, void *data); > + > +#endif > diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h > index ca7cee8e728a..1c9417430d08 100644 > --- a/include/drm/drm_print.h > +++ b/include/drm/drm_print.h > @@ -313,6 +313,10 @@ enum drm_debug_category { > * @DRM_UT_DP: Used in the DP code. > */ > DRM_UT_DP = 0x100, > + /** > + * @DRM_UT_DRMRES: Used in the drm managed resources code. > + */ > + DRM_UT_DRMRES = 0x200, > }; > > static inline bool drm_debug_enabled(enum drm_debug_category category) > @@ -442,6 +446,8 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category, > drm_dev_dbg((drm)->dev, DRM_UT_LEASE, fmt, ##__VA_ARGS__) > #define drm_dbg_dp(drm, fmt, ...) \ > drm_dev_dbg((drm)->dev, DRM_UT_DP, fmt, ##__VA_ARGS__) > +#define drm_dbg_drmres(drm, fmt, ...) \ > + drm_dev_dbg((drm)->dev, DRM_UT_DRMRES, fmt, ##__VA_ARGS__) > > > /* > -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer