The patch intended to drop the g_state pointer.
g_state is supposed to be a central place to track the state
via vchiq_state. This is now moved to be contained in the
struct vchiq_drv_mgmt. As a result vchiq_get_state() is also removed.
In order to have access to vchiq_drv_mgmt, vchiq_initialise()
and vchiq_mmal_init() are modified to receive a struct device pointer
as one of their function parameter
The vchiq_state pointer is now passed directly to
vchiq_dump_platform_instances() to get access to the state instead
getting it via vchiq_get_state().
For the char device, struct miscdevice is retrieved by struct file's
private data in vchiq_open and struct vchiq_drv_mgmt is retrieved
thereafter.
Removal of global variable members is now addressed hence, drop
the corresponding item from the TODO list.
Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
Link: https://lore.kernel.org/r/20240412075743.60712-11-umang.jain@ideasonboard.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 #include "bcm2835.h"
 #include "vc_vchi_audioserv_defs.h"
 
+#include "../interface/vchiq_arm/vchiq_arm.h"
+
 struct bcm2835_audio_instance {
        struct device *dev;
        unsigned int service_handle;
 
 int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx)
 {
+       struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(dev->parent);
        int ret;
 
        /* Initialize and create a VCHI connection */
-       ret = vchiq_initialise(&vchi_ctx->instance);
+       ret = vchiq_initialise(&mgmt->state, &vchi_ctx->instance);
        if (ret) {
                dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
                        ret);
 
        u32 param_size;
        struct vchiq_mmal_component  *camera;
 
-       ret = vchiq_mmal_init(&dev->instance);
+       ret = vchiq_mmal_init(dev->v4l2_dev.dev, &dev->instance);
        if (ret < 0) {
                v4l2_err(&dev->v4l2_dev, "%s: vchiq mmal init failed %d\n",
                         __func__, ret);
                return ret;
        }
 
-       ret = vchiq_mmal_init(&instance);
+       ret = vchiq_mmal_init(&device->dev, &instance);
        if (ret < 0)
                return ret;
 
 
 };
 
 struct vchiq_instance;
+struct vchiq_state;
 
 struct vchiq_service_base {
        int fourcc;
        short version_min;   /* Update for incompatible changes */
 };
 
-extern int vchiq_initialise(struct vchiq_instance **pinstance);
+extern int vchiq_initialise(struct vchiq_state *state,
+                           struct vchiq_instance **pinstance);
 extern int vchiq_shutdown(struct vchiq_instance *instance);
 extern int vchiq_connect(struct vchiq_instance *instance);
 extern int vchiq_open_service(struct vchiq_instance *instance,
 
 indentation deep making it very unpleasant to read. This is specially relevant
 in the character driver ioctl code and in the core thread functions.
 
-* Get rid of all non essential global structures and create a proper per
-device structure
-
-The first thing one generally sees in a probe function is a memory allocation
-for all the device specific data. This structure is then passed all over the
-driver. This is good practice since it makes the driver work regardless of the
-number of devices probed.
-
 * Clean up Sparse warnings from __user annotations. See
 vchiq_irq_queue_bulk_tx_rx(). Ensure that the address of "&waiter->bulk_waiter"
 is never disclosed to userspace.
 
 #define KEEPALIVE_VER 1
 #define KEEPALIVE_VER_MIN KEEPALIVE_VER
 
-struct vchiq_state g_state;
-
 /*
  * The devices implemented in the VCHIQ firmware are not discoverable,
  * so we need to maintain a list of them in order to register them with
 }
 
 #define VCHIQ_INIT_RETRIES 10
-int vchiq_initialise(struct vchiq_instance **instance_out)
+int vchiq_initialise(struct vchiq_state *state, struct vchiq_instance **instance_out)
 {
-       struct vchiq_state *state;
        struct vchiq_instance *instance = NULL;
        int i, ret;
 
         * block forever.
         */
        for (i = 0; i < VCHIQ_INIT_RETRIES; i++) {
-               state = vchiq_get_state();
                if (state)
                        break;
                usleep_range(500, 600);
               void *bulk_userdata)
 {
        struct vchiq_completion_data_kernel *completion;
+       struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(instance->state->dev);
        int insert;
 
-       DEBUG_INITIALISE(g_state.local);
+       DEBUG_INITIALISE(mgmt->state.local);
 
        insert = instance->completion_insert;
        while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) {
         * containing the original callback and the user state structure, which
         * contains a circular buffer for completion records.
         */
+       struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(instance->state->dev);
        struct user_service *user_service;
        struct vchiq_service *service;
        bool skip_completion = false;
 
-       DEBUG_INITIALISE(g_state.local);
+       DEBUG_INITIALISE(mgmt->state.local);
 
        DEBUG_TRACE(SERVICE_CALLBACK_LINE);
 
                bulk_userdata);
 }
 
-void vchiq_dump_platform_instances(struct seq_file *f)
+void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f)
 {
-       struct vchiq_state *state = vchiq_get_state();
        int i;
 
        if (!state)
        seq_puts(f, "\n");
 }
 
-struct vchiq_state *
-vchiq_get_state(void)
-{
-       if (!g_state.remote) {
-               pr_err("%s: g_state.remote == NULL\n", __func__);
-               return NULL;
-       }
-
-       if (g_state.remote->initialised != 1) {
-               pr_notice("%s: g_state.remote->initialised != 1 (%d)\n",
-                         __func__, g_state.remote->initialised);
-               return NULL;
-       }
-
-       return &g_state;
-}
-
 /*
  * Autosuspend related functionality
  */
                .version_min = KEEPALIVE_VER_MIN
        };
 
-       ret = vchiq_initialise(&instance);
+       ret = vchiq_initialise(state, &instance);
        if (ret) {
                dev_err(state->dev, "suspend: %s: vchiq_initialise failed %d\n", __func__, ret);
                goto exit;
        mgmt->info = info;
        platform_set_drvdata(pdev, mgmt);
 
-       err = vchiq_platform_init(pdev, &g_state);
+       err = vchiq_platform_init(pdev, &mgmt->state);
        if (err)
                goto failed_platform_init;
 
 
        unsigned int fragments_size;
 
        void __iomem *regs;
+
+       struct vchiq_state state;
 };
 
 struct user_service {
        struct vchiq_debugfs_node debugfs_node;
 };
 
-extern struct vchiq_state g_state;
-
-extern struct vchiq_state *
-vchiq_get_state(void);
-
 int
 vchiq_use_service(struct vchiq_instance *instance, unsigned int handle);
 
 
 
        vchiq_dump_shared_state(f, state, state->remote, "Remote");
 
-       vchiq_dump_platform_instances(f);
+       vchiq_dump_platform_instances(state, f);
 
        for (i = 0; i < state->unused_service; i++) {
                struct vchiq_service *service = find_service_by_port(state, i);
 
 
 void vchiq_dump_platform_state(struct seq_file *f);
 
-void vchiq_dump_platform_instances(struct seq_file *f);
+void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f);
 
 void vchiq_dump_platform_service_state(struct seq_file *f, struct vchiq_service *service);
 
 
 
 static int vchiq_dump_show(struct seq_file *f, void *offset)
 {
-       vchiq_dump_state(f, &g_state);
+       struct vchiq_instance *instance = f->private;
+
+       vchiq_dump_state(f, instance->state);
+
        return 0;
 }
 DEFINE_SHOW_ATTRIBUTE(vchiq_dump);
 
        struct vchiq_header *header;
        int ret;
 
-       DEBUG_INITIALISE(g_state.local);
+       DEBUG_INITIALISE(instance->state->local);
        DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
        service = find_service_for_instance(instance, args->handle);
        if (!service)
        int remove;
        int ret;
 
-       DEBUG_INITIALISE(g_state.local);
+       DEBUG_INITIALISE(instance->state->local);
 
        DEBUG_TRACE(AWAIT_COMPLETION_LINE);
        if (!instance->connected)
 
 static int vchiq_open(struct inode *inode, struct file *file)
 {
-       struct vchiq_state *state = vchiq_get_state();
+       struct miscdevice *vchiq_miscdev = file->private_data;
+       struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(vchiq_miscdev->parent);
+       struct vchiq_state *state = &mgmt->state;
        struct vchiq_instance *instance;
 
        dev_dbg(state->dev, "arm: vchiq open\n");
 static int vchiq_release(struct inode *inode, struct file *file)
 {
        struct vchiq_instance *instance = file->private_data;
-       struct vchiq_state *state = vchiq_get_state();
+       struct vchiq_state *state = instance->state;
        struct vchiq_service *service;
        int ret = 0;
        int i;
 
 #include <media/videobuf2-vmalloc.h>
 
 #include "../include/linux/raspberrypi/vchiq.h"
+#include "../interface/vchiq_arm/vchiq_arm.h"
 #include "mmal-common.h"
 #include "mmal-vchiq.h"
 #include "mmal-msg.h"
 }
 EXPORT_SYMBOL_GPL(vchiq_mmal_finalise);
 
-int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
+int vchiq_mmal_init(struct device *dev, struct vchiq_mmal_instance **out_instance)
 {
        int status;
        int err = -ENODEV;
                .callback               = mmal_service_callback,
                .userdata               = NULL,
        };
+       struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(dev->parent);
 
        /* compile time checks to ensure structure size as they are
         * directly (de)serialised from memory.
        BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
 
        /* create a vchi instance */
-       status = vchiq_initialise(&vchiq_instance);
+       status = vchiq_initialise(&mgmt->state, &vchiq_instance);
        if (status) {
                pr_err("Failed to initialise VCHI instance (status=%d)\n",
                       status);
 
 #define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
 
 struct vchiq_mmal_instance;
+struct device;
 
 enum vchiq_mmal_es_type {
        MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
        u32 client_component;   /* Used to ref back to client struct */
 };
 
-int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
+int vchiq_mmal_init(struct device *dev, struct vchiq_mmal_instance **out_instance);
 int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
 
 /* Initialise a mmal component and its ports