@@ -543,9 +543,18 @@ static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
* Registration/unregistration
*/
-static void media_device_release(struct media_devnode *mdev)
+static void media_device_release(struct media_devnode *devnode)
{
- dev_dbg(mdev->parent, "Media device released\n");
+ struct media_device *mdev = to_media_device(devnode);
+
+ ida_destroy(&mdev->entity_internal_idx);
+ mdev->entity_internal_idx_max = 0;
+ media_entity_graph_walk_cleanup(&mdev->pm_count_walk);
+ mutex_destroy(&mdev->graph_mutex);
+ dev_dbg(devnode->parent, "Media device released\n");
+
+ if (devnode->use_kref)
+ kfree(mdev);
}
/**
@@ -692,6 +701,21 @@ void media_device_init(struct media_device *mdev)
}
EXPORT_SYMBOL_GPL(media_device_init);
+struct media_device *media_device_alloc(void)
+{
+ struct media_device *mdev;
+
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
+ return NULL;
+
+ media_devnode_init(&mdev->devnode);
+ media_device_init(mdev);
+
+ return mdev;
+}
+EXPORT_SYMBOL_GPL(media_device_alloc);
+
void media_device_cleanup(struct media_device *mdev)
{
ida_destroy(&mdev->entity_internal_idx);
@@ -428,6 +428,42 @@ static inline __must_check int media_entity_enum_init(
void media_device_init(struct media_device *mdev);
/**
+ * media_device_alloc() - Allocate and initialise a media device
+ *
+ * Allocate and initialise a media device. Returns a media device.
+ * The media device is refcounted, and this function returns a media
+ * device the refcount of which is one (1).
+ *
+ * References are taken and given using media_device_get() and
+ * media_device_put().
+ */
+struct media_device *media_device_alloc(void);
+
+/**
+ * media_device_get() - Get a reference to a media device
+ *
+ * mdev: media device
+ */
+#define media_device_get(mdev) \
+ do { \
+ dev_dbg((mdev)->dev, "%s: get media device %s\n", \
+ __func__, (mdev)->bus_info); \
+ media_devnode_get(&(mdev)->devnode); \
+ } while (0)
+
+/**
+ * media_device_put() - Put a reference to a media device
+ *
+ * mdev: media device
+ */
+#define media_device_put(mdev) \
+ do { \
+ dev_dbg((mdev)->dev, "%s: put media device %s\n", \
+ __func__, (mdev)->bus_info); \
+ media_devnode_put(&(mdev)->devnode); \
+ } while (0)
+
+/**
* media_device_cleanup() - Cleanups a media device element
*
* @mdev: pointer to struct &media_device
@@ -654,6 +690,8 @@ void __media_device_usb_init(struct media_device *mdev,
const char *driver_name);
#else
+#define media_device_get(mdev) do { } while (0)
+#define media_device_put(mdev) do { } while (0)
static inline int media_device_register(struct media_device *mdev)
{
return 0;