linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/1] vchiq: Replacing global structs with per device
@ 2021-11-01 11:09 Ojaswin Mujoo
  2021-11-01 11:09 ` [PATCH 1/1] staging: vchiq: Replace global state with per device state Ojaswin Mujoo
  0 siblings, 1 reply; 7+ messages in thread
From: Ojaswin Mujoo @ 2021-11-01 11:09 UTC (permalink / raw)
  To: nsaenz, gregkh, stefan.wahren
  Cc: dan.carpenter, phil, linux-arm-kernel, linux-staging, linux-kernel

Hello!

Sorry for being so late on this patch, I recently found some time to
make progress on this hence sending this here for review and suggestions

This patch is the first draft to address the following task in the vchiq TODO
(staging/vc04_services/interface/TODO):

	13) 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.

The patch is NOT complete yet but I thought it is a good time for a review so
that I can confirm if I'm approaching this correctly and not missing anything.

To start with, I have focused on making the state (g_state) as per-device instead of
global as it is one of the most frequently used global varibale in the driver
code right now. 

To achive this, I have modified the code to define a new data structure
"vchiq_device" which is initialised/allocated during probing and holds the state
as well as some other things like the miscdevice object that is needed to create
the misc device driver for vchiq.  Embedding the miscdevice structure in it
helps us retrieve vchiq_device struct when the misc_device open() is called and
then use it to retrieve the state. 

For all the ioctl and miscdevice fops, the filp->private_data stores the
vchiq_instance struct which embeds the vchiq state in it. I have modified the
code to fetch the state from here instead of using the global state or the
vchiq_get_state() function. 

This patch has been tested using vchiq_test utility and seems to be working
functional so far.

------- Changes ---------

* A short summary of the changes:

  *  Define per device structure vchiq_device 
	*  Use instance->state (per device state) instead of using the global state 
	   in the code
	*  Split vchiq_get_state() into vchiq_get_state() and vchiq_validate_state().
	   The validation function is used to validate the per device state. 
	*  Modify vchiq_dump_platform_instances(...) to pass in an extra vchiq_state
	   argument.

------- Some questions -------

**HOWEVER**, the patch is still not complete as there are some areas that still
need some work to ensure our driver is able to support multiple devices. I will
be listing them out below, would love to have some suggestions around it.

1. There is one specific function where I have not been able to replace the use
	 of global state, ie vchiq_initialise() function in vchiq_arm.c. The root
	 issue here is that vchiq_initialise is called from either the IOCTL
	 functions of the cdev or from other kernel modules directly. (Example, in
	 bcm2835_new_vchi_ctx() in bcm2835-audio)

	 When called from ioctl we have a reference to our per device state and we
	 can pass it in, but this is not possible when calling it from a different
	 kernel module.  This forces us to use a global state in the driver. 

	 I'm not sure how we can approach this in such a way that our driver is able
	 to support multiple devices. I would love to have some suggestions and
	 throughts around this.

2. In vchiq_deregister_chrdev() in vchiq_dev.c, I need the reference to the
	 miscdevice to call deregister on it. To get this reference, I use a global
	 variable but again, this wont work when we are trying to support multiple
	 devices. In this case, how do we handle registering and deregistering
	 multiple cdevs which might be created when we try to support multiple
	 VideoCore VPUs in the same driver.
	
--------------------------

Please let me know if you have any other suggestions or questions around the
patch and we can discuss the further. 

Thank you in advance!

Regards,
Ojaswin

Ojaswin Mujoo (1):
  staging: vchiq: Replace global state with per device state

 .../interface/vchiq_arm/vchiq_arm.c           | 100 ++++++++++++++----
 .../interface/vchiq_arm/vchiq_arm.h           |  12 ++-
 .../interface/vchiq_arm/vchiq_core.c          |   2 +-
 .../interface/vchiq_arm/vchiq_core.h          |   3 +-
 .../interface/vchiq_arm/vchiq_dev.c           |  64 +++++++----
 5 files changed, 138 insertions(+), 43 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/1] staging: vchiq: Replace global state with per device state
  2021-11-01 11:09 [PATCH 0/1] vchiq: Replacing global structs with per device Ojaswin Mujoo
@ 2021-11-01 11:09 ` Ojaswin Mujoo
  2021-11-01 12:19   ` Stefan Wahren
                     ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Ojaswin Mujoo @ 2021-11-01 11:09 UTC (permalink / raw)
  To: nsaenz, gregkh, stefan.wahren
  Cc: dan.carpenter, phil, linux-arm-kernel, linux-staging, linux-kernel

Currently, the driver has a global g_state variable which is initialised
during probe and directly used all over the driver code. However, this
prevents the driver to support multiple VideoCore VPUs at the same time.

Replace this global state with a per device state which is initialised
and allocated during probing.

Signed-off-by: Ojaswin Mujoo <ojaswin98@gmail.com>
---
 .../interface/vchiq_arm/vchiq_arm.c           | 100 ++++++++++++++----
 .../interface/vchiq_arm/vchiq_arm.h           |  12 ++-
 .../interface/vchiq_arm/vchiq_core.c          |   2 +-
 .../interface/vchiq_arm/vchiq_core.h          |   3 +-
 .../interface/vchiq_arm/vchiq_dev.c           |  64 +++++++----
 5 files changed, 138 insertions(+), 43 deletions(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index c650a32bcedf..a6ad0829c7e8 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -63,7 +63,7 @@ int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT;
 int vchiq_susp_log_level = VCHIQ_LOG_ERROR;
 
 DEFINE_SPINLOCK(msg_queue_spinlock);
-struct vchiq_state g_state;
+static struct vchiq_state *g_state;
 
 static struct platform_device *bcm2835_camera;
 static struct platform_device *bcm2835_audio;
@@ -156,6 +156,13 @@ static enum vchiq_status
 vchiq_blocking_bulk_transfer(unsigned int handle, void *data,
 			     unsigned int size, enum vchiq_bulk_dir dir);
 
+/* Accessor function for static state variable */
+static inline struct vchiq_state *
+vchiq_get_state(void)
+{
+	return g_state;
+}
+
 static irqreturn_t
 vchiq_doorbell_irq(int irq, void *dev_id)
 {
@@ -652,6 +659,17 @@ int vchiq_dump_platform_state(void *dump_context)
 #define VCHIQ_INIT_RETRIES 10
 int vchiq_initialise(struct vchiq_instance **instance_out)
 {
+	/*
+	 * TODO: vchiq_initialise is called from either the IOCTL functions of
+	 * the cdev or from other kernel modules directly. When called from ioctl
+	 * we have a reference to the state and we can pass it in, but this is not
+	 * possible when calling it from a different kernel module.
+	 *
+	 * This forces us to use a global state in the driver, which is not ideal
+	 * if we want to support multiple devices with a single driver. We need to
+	 * find a way around this
+	 */
+
 	struct vchiq_state *state;
 	struct vchiq_instance *instance = NULL;
 	int i, ret;
@@ -663,7 +681,7 @@ int vchiq_initialise(struct vchiq_instance **instance_out)
 	 */
 	for (i = 0; i < VCHIQ_INIT_RETRIES; i++) {
 		state = vchiq_get_state();
-		if (state)
+		if (vchiq_validate_state(state))
 			break;
 		usleep_range(500, 600);
 	}
@@ -984,9 +1002,10 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
 	       void *bulk_userdata)
 {
 	struct vchiq_completion_data_kernel *completion;
+	struct vchiq_state *state = instance->state;
 	int insert;
 
-	DEBUG_INITIALISE(g_state.local);
+	DEBUG_INITIALISE(state->local);
 
 	insert = instance->completion_insert;
 	while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) {
@@ -1052,12 +1071,9 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
 	struct user_service *user_service;
 	struct vchiq_service *service;
 	struct vchiq_instance *instance;
+	struct vchiq_state *state;
 	bool skip_completion = false;
 
-	DEBUG_INITIALISE(g_state.local);
-
-	DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-
 	service = handle_to_service(handle);
 	if (WARN_ON(!service))
 		return VCHIQ_SUCCESS;
@@ -1065,6 +1081,12 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
 	user_service = (struct user_service *)service->base.userdata;
 	instance = user_service->instance;
 
+	state = instance->state;
+
+	DEBUG_INITIALISE(state->local);
+
+	DEBUG_TRACE(SERVICE_CALLBACK_LINE);
+
 	if (!instance || instance->closing)
 		return VCHIQ_SUCCESS;
 
@@ -1186,13 +1208,15 @@ int vchiq_dump(void *dump_context, const char *str, int len)
 	return 0;
 }
 
-int vchiq_dump_platform_instances(void *dump_context)
+int vchiq_dump_platform_instances(void *dump_context, struct vchiq_state *state)
 {
-	struct vchiq_state *state = vchiq_get_state();
 	char buf[80];
 	int len;
 	int i;
 
+	if (!vchiq_validate_state(state))
+		return -EINVAL;
+
 	/*
 	 * There is no list of instances, so instead scan all services,
 	 * marking those that have been dumped.
@@ -1271,17 +1295,25 @@ int vchiq_dump_platform_service_state(void *dump_context,
 	return vchiq_dump(dump_context, buf, len + 1);
 }
 
+/**
+ *	vchiq_validate_state -	Validate the state. Return NULL if invalid
+ *				else return the state back
+ *
+ *	@state			The state to validate
+ *
+ *	Returns unchanged state if state is valid, else returns NULL.
+ */
 struct vchiq_state *
-vchiq_get_state(void)
+vchiq_validate_state(struct vchiq_state *state)
 {
-	if (!g_state.remote)
-		pr_err("%s: g_state.remote == NULL\n", __func__);
-	else if (g_state.remote->initialised != 1)
-		pr_notice("%s: g_state.remote->initialised != 1 (%d)\n",
-			  __func__, g_state.remote->initialised);
-
-	return (g_state.remote &&
-		(g_state.remote->initialised == 1)) ? &g_state : NULL;
+	if (!state->remote)
+		pr_err("%s: state->remote == NULL\n", __func__);
+	else if (state->remote->initialised != 1)
+		pr_notice("%s: state->remote->initialised != 1 (%d)\n",
+			  __func__, state->remote->initialised);
+
+	return (state->remote &&
+		(state->remote->initialised == 1)) ? state : NULL;
 }
 
 /*
@@ -1763,6 +1795,7 @@ static int vchiq_probe(struct platform_device *pdev)
 	struct device_node *fw_node;
 	const struct of_device_id *of_id;
 	struct vchiq_drvdata *drvdata;
+	struct vchiq_device *vchiq_dev;
 	int err;
 
 	of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
@@ -1784,7 +1817,18 @@ static int vchiq_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, drvdata);
 
-	err = vchiq_platform_init(pdev, &g_state);
+	vchiq_dev = kzalloc(sizeof(struct vchiq_device), GFP_KERNEL);
+	vchiq_dev->state = kzalloc(sizeof(struct vchiq_state), GFP_KERNEL);
+	vchiq_dev->vchiq_pdev = *pdev;
+
+	g_state = vchiq_dev->state;
+
+	if (!vchiq_dev || !vchiq_dev->state) {
+		dev_err(&pdev->dev, "Out of memory\n");
+		return -ENOMEM;
+	}
+
+	err = vchiq_platform_init(pdev, vchiq_dev->state);
 	if (err)
 		goto failed_platform_init;
 
@@ -1798,7 +1842,7 @@ static int vchiq_probe(struct platform_device *pdev)
 	 * Simply exit on error since the function handles cleanup in
 	 * cases of failure.
 	 */
-	err = vchiq_register_chrdev(&pdev->dev);
+	err = vchiq_register_chrdev(vchiq_dev);
 	if (err) {
 		vchiq_log_warning(vchiq_arm_log_level,
 				  "Failed to initialize vchiq cdev");
@@ -1811,6 +1855,12 @@ static int vchiq_probe(struct platform_device *pdev)
 	return 0;
 
 failed_platform_init:
+	kfree(vchiq_dev->state);
+	vchiq_dev->state = NULL;
+
+	kfree(vchiq_dev);
+	vchiq_dev = NULL;
+
 	vchiq_log_warning(vchiq_arm_log_level, "could not initialize vchiq platform");
 error_exit:
 	return err;
@@ -1818,11 +1868,21 @@ static int vchiq_probe(struct platform_device *pdev)
 
 static int vchiq_remove(struct platform_device *pdev)
 {
+	struct vchiq_device *vchiq_dev;
+
 	platform_device_unregister(bcm2835_audio);
 	platform_device_unregister(bcm2835_camera);
 	vchiq_debugfs_deinit();
 	vchiq_deregister_chrdev();
 
+	vchiq_dev = container_of(pdev, struct vchiq_device, vchiq_pdev);
+
+	kfree(vchiq_dev->state);
+	vchiq_dev->state = NULL;
+
+	kfree(vchiq_dev);
+	vchiq_dev = NULL;
+
 	return 0;
 }
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
index 2aa46b119a46..8a1d803a3423 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
@@ -69,6 +69,13 @@ struct vchiq_instance {
 	struct vchiq_debugfs_node debugfs_node;
 };
 
+/* Used to store per device information */
+struct vchiq_device {
+	struct vchiq_state *state;
+	struct miscdevice mdev;
+	struct platform_device vchiq_pdev;
+};
+
 struct dump_context {
 	char __user *buf;
 	size_t actual;
@@ -80,10 +87,9 @@ extern int vchiq_arm_log_level;
 extern int vchiq_susp_log_level;
 
 extern spinlock_t msg_queue_spinlock;
-extern struct vchiq_state g_state;
 
 extern struct vchiq_state *
-vchiq_get_state(void);
+vchiq_validate_state(struct vchiq_state *state);
 
 enum vchiq_status
 vchiq_use_service(unsigned int handle);
@@ -128,7 +134,7 @@ extern void
 vchiq_deregister_chrdev(void);
 
 extern int
-vchiq_register_chrdev(struct device *parent);
+vchiq_register_chrdev(struct vchiq_device *vdev);
 
 #else
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index ab97a35e63f9..30ca1eba658d 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -3515,7 +3515,7 @@ int vchiq_dump_state(void *dump_context, struct vchiq_state *state)
 	if (err)
 		return err;
 
-	err = vchiq_dump_platform_instances(dump_context);
+	err = vchiq_dump_platform_instances(dump_context, state);
 	if (err)
 		return err;
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
index 3e50910ecba3..6c321b959a20 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
@@ -11,6 +11,7 @@
 #include <linux/rcupdate.h>
 #include <linux/wait.h>
 #include <linux/raspberrypi/vchiq.h>
+#include <linux/miscdevice.h>
 
 #include "vchiq_cfg.h"
 
@@ -570,7 +571,7 @@ int vchiq_dump(void *dump_context, const char *str, int len);
 
 int vchiq_dump_platform_state(void *dump_context);
 
-int vchiq_dump_platform_instances(void *dump_context);
+int vchiq_dump_platform_instances(void *dump_context, struct vchiq_state *state);
 
 int vchiq_dump_platform_service_state(void *dump_context, struct vchiq_service *service);
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
index 2325844b0880..e208f334af2b 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
@@ -39,6 +39,11 @@ static const char *const ioctl_names[] = {
 
 static_assert(ARRAY_SIZE(ioctl_names) == (VCHIQ_IOC_MAX + 1));
 
+static inline struct vchiq_device *to_vchiq_device(struct miscdevice *mdev)
+{
+	return container_of(mdev, struct vchiq_device, mdev);
+}
+
 static void
 user_service_free(void *userdata)
 {
@@ -208,9 +213,10 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
 	struct user_service *user_service;
 	struct vchiq_service *service;
 	struct vchiq_header *header;
+	struct vchiq_state *state = instance->state;
 	int ret;
 
-	DEBUG_INITIALISE(g_state.local);
+	DEBUG_INITIALISE(state->local);
 	DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
 	service = find_service_for_instance(instance, args->handle);
 	if (!service)
@@ -435,12 +441,12 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
 				      struct vchiq_await_completion *args,
 				      int __user *msgbufcountp)
 {
+	struct vchiq_state *state = instance->state;
 	int msgbufcount;
 	int remove;
 	int ret;
 
-	DEBUG_INITIALISE(g_state.local);
-
+	DEBUG_INITIALISE(state->local);
 	DEBUG_TRACE(AWAIT_COMPLETION_LINE);
 	if (!instance->connected)
 		return -ENOTCONN;
@@ -1167,12 +1173,19 @@ vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 static int vchiq_open(struct inode *inode, struct file *file)
 {
-	struct vchiq_state *state = vchiq_get_state();
 	struct vchiq_instance *instance;
+	struct vchiq_state *state;
+	struct vchiq_device *vdev;
+	struct miscdevice *mdev;
+
+	mdev = file->private_data;
+
+	vdev = to_vchiq_device(mdev);
+	state = vdev->state;
 
 	vchiq_log_info(vchiq_arm_log_level, "vchiq_open");
 
-	if (!state) {
+	if (!vchiq_validate_state(state)) {
 		vchiq_log_error(vchiq_arm_log_level,
 				"vchiq has no connection to VideoCore");
 		return -ENOTCONN;
@@ -1201,7 +1214,7 @@ static int vchiq_open(struct inode *inode, struct file *file)
 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;
@@ -1209,7 +1222,7 @@ static int vchiq_release(struct inode *inode, struct file *file)
 	vchiq_log_info(vchiq_arm_log_level, "%s: instance=%lx", __func__,
 		       (unsigned long)instance);
 
-	if (!state) {
+	if (!vchiq_validate_state(state)) {
 		ret = -EPERM;
 		goto out;
 	}
@@ -1310,6 +1323,8 @@ static ssize_t
 vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct dump_context context;
+	struct vchiq_instance *instance = file->private_data;
+	struct vchiq_state *state = instance->state;
 	int err;
 
 	context.buf = buf;
@@ -1317,7 +1332,7 @@ vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	context.space = count;
 	context.offset = *ppos;
 
-	err = vchiq_dump_state(&context, &g_state);
+	err = vchiq_dump_state(&context, state);
 	if (err)
 		return err;
 
@@ -1338,12 +1353,7 @@ vchiq_fops = {
 	.read = vchiq_read
 };
 
-static struct miscdevice vchiq_miscdev = {
-	.fops = &vchiq_fops,
-	.minor = MISC_DYNAMIC_MINOR,
-	.name = "vchiq",
-
-};
+static struct miscdevice *vchiq_miscdev;
 
 /**
  *	vchiq_register_chrdev - Register the char driver for vchiq
@@ -1353,11 +1363,25 @@ static struct miscdevice vchiq_miscdev = {
  *
  *	Returns 0 on success else returns the error code.
  */
-int vchiq_register_chrdev(struct device *parent)
+int vchiq_register_chrdev(struct vchiq_device *vdev)
 {
-	vchiq_miscdev.parent = parent;
+	int err;
+
+	vdev->mdev.fops = &vchiq_fops;
+	vdev->mdev.minor = MISC_DYNAMIC_MINOR;
+	vdev->mdev.parent = &vdev->vchiq_pdev.dev;
+	// TODO: Dynamically allocate name here
+	vdev->mdev.name = "vchiq";
+
+	err = misc_register(&vdev->mdev);
+	if (err) {
+		goto error;
+	}
+
+	vchiq_miscdev = &vdev->mdev;
 
-	return misc_register(&vchiq_miscdev);
+error:
+	return err;
 }
 
 /**
@@ -1366,5 +1390,9 @@ int vchiq_register_chrdev(struct device *parent)
  */
 void vchiq_deregister_chrdev(void)
 {
-	misc_deregister(&vchiq_miscdev);
+	// TODO: This deregsiter will not be able to handle multiple devices
+	// since the vchiq_miscdev pointer will always point to the most recent
+	// cdev.
+	misc_deregister(vchiq_miscdev);
+	vchiq_miscdev = NULL;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] staging: vchiq: Replace global state with per device state
  2021-11-01 11:09 ` [PATCH 1/1] staging: vchiq: Replace global state with per device state Ojaswin Mujoo
@ 2021-11-01 12:19   ` Stefan Wahren
  2021-11-01 17:31     ` Ojaswin Mujoo
  2021-11-01 16:07   ` kernel test robot
  2021-11-01 16:45   ` kernel test robot
  2 siblings, 1 reply; 7+ messages in thread
From: Stefan Wahren @ 2021-11-01 12:19 UTC (permalink / raw)
  To: Ojaswin Mujoo, nsaenz, gregkh
  Cc: dan.carpenter, phil, linux-arm-kernel, linux-staging, linux-kernel

Hi Ojaswin,

Am 01.11.21 um 12:09 schrieb Ojaswin Mujoo:
> Currently, the driver has a global g_state variable which is initialised
> during probe and directly used all over the driver code. However, this
> prevents the driver to support multiple VideoCore VPUs at the same time.
>
> Replace this global state with a per device state which is initialised
> and allocated during probing.
>
> Signed-off-by: Ojaswin Mujoo <ojaswin98@gmail.com>
...
>  
>  /*
> @@ -1763,6 +1795,7 @@ static int vchiq_probe(struct platform_device *pdev)
>  	struct device_node *fw_node;
>  	const struct of_device_id *of_id;
>  	struct vchiq_drvdata *drvdata;
> +	struct vchiq_device *vchiq_dev;
>  	int err;
>  
>  	of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
> @@ -1784,7 +1817,18 @@ static int vchiq_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, drvdata);
>  
> -	err = vchiq_platform_init(pdev, &g_state);
> +	vchiq_dev = kzalloc(sizeof(struct vchiq_device), GFP_KERNEL);
> +	vchiq_dev->state = kzalloc(sizeof(struct vchiq_state), GFP_KERNEL);
> +	vchiq_dev->vchiq_pdev = *pdev;
> +
> +	g_state = vchiq_dev->state;
> +

just a quick idea: how about storing the global state within vchiq_drvdata?

So there is no need to reinvent somekind of vchiq device which is the
"same" as the platform device. After that you are able to access the
private driver data via platform_get_drvdata().

Best regards



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] staging: vchiq: Replace global state with per device state
  2021-11-01 11:09 ` [PATCH 1/1] staging: vchiq: Replace global state with per device state Ojaswin Mujoo
  2021-11-01 12:19   ` Stefan Wahren
@ 2021-11-01 16:07   ` kernel test robot
  2021-11-01 16:45   ` kernel test robot
  2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2021-11-01 16:07 UTC (permalink / raw)
  To: Ojaswin Mujoo, nsaenz, gregkh, stefan.wahren
  Cc: kbuild-all, dan.carpenter, phil, linux-arm-kernel, linux-staging,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3713 bytes --]

Hi Ojaswin,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]
[also build test ERROR on next-20211101]
[cannot apply to v5.15]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Ojaswin-Mujoo/vchiq-Replacing-global-structs-with-per-device/20211101-191153
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 10508ae08ed8ce8794785194ad7309f1437d43fd
config: arc-allyesconfig (attached as .config)
compiler: arceb-elf-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/7f81de8bb73f7a7d9d0a0898dbe0144d40e39254
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Ojaswin-Mujoo/vchiq-Replacing-global-structs-with-per-device/20211101-191153
        git checkout 7f81de8bb73f7a7d9d0a0898dbe0144d40e39254
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=arc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:465:5: error: no previous prototype for 'vchiq_platform_init' [-Werror=missing-prototypes]
     465 | int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
         |     ^~~~~~~~~~~~~~~~~~~
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:593:1: error: no previous prototype for 'vchiq_platform_get_arm_state' [-Werror=missing-prototypes]
     593 | vchiq_platform_get_arm_state(struct vchiq_state *state)
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:33:
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c: In function 'service_callback':
>> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h:106:33: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
     106 | #define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug
         |                                 ^~~
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:1086:9: note: in expansion of macro 'DEBUG_INITIALISE'
    1086 |         DEBUG_INITIALISE(state->local);
         |         ^~~~~~~~~~~~~~~~
   cc1: all warnings being treated as errors


vim +106 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h

71bad7f086419d popcornmix      2013-07-02  105  
8dd56723240e43 Gaston Gonzalez 2021-10-24 @106  #define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug
71bad7f086419d popcornmix      2013-07-02  107  #define DEBUG_TRACE(d) \
35b7ebda57affc Michael Zoran   2016-10-19  108  	do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(sy); } while (0)
71bad7f086419d popcornmix      2013-07-02  109  #define DEBUG_VALUE(d, v) \
35b7ebda57affc Michael Zoran   2016-10-19  110  	do { debug_ptr[DEBUG_ ## d] = (v); dsb(sy); } while (0)
71bad7f086419d popcornmix      2013-07-02  111  #define DEBUG_COUNT(d) \
35b7ebda57affc Michael Zoran   2016-10-19  112  	do { debug_ptr[DEBUG_ ## d]++; dsb(sy); } while (0)
71bad7f086419d popcornmix      2013-07-02  113  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 69474 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] staging: vchiq: Replace global state with per device state
  2021-11-01 11:09 ` [PATCH 1/1] staging: vchiq: Replace global state with per device state Ojaswin Mujoo
  2021-11-01 12:19   ` Stefan Wahren
  2021-11-01 16:07   ` kernel test robot
@ 2021-11-01 16:45   ` kernel test robot
  2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2021-11-01 16:45 UTC (permalink / raw)
  To: Ojaswin Mujoo, nsaenz, gregkh, stefan.wahren
  Cc: kbuild-all, dan.carpenter, phil, linux-arm-kernel, linux-staging,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4652 bytes --]

Hi Ojaswin,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on next-20211101]
[cannot apply to v5.15]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Ojaswin-Mujoo/vchiq-Replacing-global-structs-with-per-device/20211101-191153
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 10508ae08ed8ce8794785194ad7309f1437d43fd
config: arc-randconfig-r043-20211101 (attached as .config)
compiler: arceb-elf-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/7f81de8bb73f7a7d9d0a0898dbe0144d40e39254
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Ojaswin-Mujoo/vchiq-Replacing-global-structs-with-per-device/20211101-191153
        git checkout 7f81de8bb73f7a7d9d0a0898dbe0144d40e39254
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=arc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:465:5: warning: no previous prototype for 'vchiq_platform_init' [-Wmissing-prototypes]
     465 | int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
         |     ^~~~~~~~~~~~~~~~~~~
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:593:1: warning: no previous prototype for 'vchiq_platform_get_arm_state' [-Wmissing-prototypes]
     593 | vchiq_platform_get_arm_state(struct vchiq_state *state)
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:33:
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c: In function 'service_callback':
>> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h:106:33: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
     106 | #define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug
         |                                 ^~~
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:1086:9: note: in expansion of macro 'DEBUG_INITIALISE'
    1086 |         DEBUG_INITIALISE(state->local);
         |         ^~~~~~~~~~~~~~~~
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c: In function 'vchiq_probe':
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:1845:37: error: passing argument 1 of 'vchiq_register_chrdev' from incompatible pointer type [-Werror=incompatible-pointer-types]
    1845 |         err = vchiq_register_chrdev(vchiq_dev);
         |                                     ^~~~~~~~~
         |                                     |
         |                                     struct vchiq_device *
   In file included from drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:35:
   drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h:142:56: note: expected 'struct device *' but argument is of type 'struct vchiq_device *'
     142 | static inline int vchiq_register_chrdev(struct device *parent) { return 0; }
         |                                         ~~~~~~~~~~~~~~~^~~~~~
   cc1: some warnings being treated as errors


vim +106 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h

71bad7f086419d popcornmix      2013-07-02  105  
8dd56723240e43 Gaston Gonzalez 2021-10-24 @106  #define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug
71bad7f086419d popcornmix      2013-07-02  107  #define DEBUG_TRACE(d) \
35b7ebda57affc Michael Zoran   2016-10-19  108  	do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(sy); } while (0)
71bad7f086419d popcornmix      2013-07-02  109  #define DEBUG_VALUE(d, v) \
35b7ebda57affc Michael Zoran   2016-10-19  110  	do { debug_ptr[DEBUG_ ## d] = (v); dsb(sy); } while (0)
71bad7f086419d popcornmix      2013-07-02  111  #define DEBUG_COUNT(d) \
35b7ebda57affc Michael Zoran   2016-10-19  112  	do { debug_ptr[DEBUG_ ## d]++; dsb(sy); } while (0)
71bad7f086419d popcornmix      2013-07-02  113  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34411 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] staging: vchiq: Replace global state with per device state
  2021-11-01 12:19   ` Stefan Wahren
@ 2021-11-01 17:31     ` Ojaswin Mujoo
  2021-11-01 18:58       ` Stefan Wahren
  0 siblings, 1 reply; 7+ messages in thread
From: Ojaswin Mujoo @ 2021-11-01 17:31 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: nsaenz, gregkh, dan.carpenter, phil, linux-arm-kernel,
	linux-staging, linux-kernel

On Mon, Nov 01, 2021 at 01:19:17PM +0100, Stefan Wahren wrote:
> Hi Ojaswin,
> 
> Am 01.11.21 um 12:09 schrieb Ojaswin Mujoo:
> > Currently, the driver has a global g_state variable which is initialised
> > during probe and directly used all over the driver code. However, this
> > prevents the driver to support multiple VideoCore VPUs at the same time.
> >
> > Replace this global state with a per device state which is initialised
> > and allocated during probing.
> >
> > Signed-off-by: Ojaswin Mujoo <ojaswin98@gmail.com>
> ...
> >  
> >  /*
> > @@ -1763,6 +1795,7 @@ static int vchiq_probe(struct platform_device *pdev)
> >  	struct device_node *fw_node;
> >  	const struct of_device_id *of_id;
> >  	struct vchiq_drvdata *drvdata;
> > +	struct vchiq_device *vchiq_dev;
> >  	int err;
> >  
> >  	of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
> > @@ -1784,7 +1817,18 @@ static int vchiq_probe(struct platform_device *pdev)
> >  
> >  	platform_set_drvdata(pdev, drvdata);
> >  
> > -	err = vchiq_platform_init(pdev, &g_state);
> > +	vchiq_dev = kzalloc(sizeof(struct vchiq_device), GFP_KERNEL);
> > +	vchiq_dev->state = kzalloc(sizeof(struct vchiq_state), GFP_KERNEL);
> > +	vchiq_dev->vchiq_pdev = *pdev;
> > +
> > +	g_state = vchiq_dev->state;
> > +
> 
> just a quick idea: how about storing the global state within vchiq_drvdata?
> 
> So there is no need to reinvent somekind of vchiq device which is the
> "same" as the platform device. After that you are able to access the
> private driver data via platform_get_drvdata().
Hi Stefan, 

Thank for looking into this. I agree that the vchiq_device is just a
sorta extension of the pdev. However, regarding using the drvdata, I had
some questions.

So I understand the purpose of this patch is to make sure our driver is
able to support multiple devices, that is it can work with say, an SoC
with 2 VideoCore VPUs. In this case, we would need to maintain 2 states
for each VPU instead of a global state, however if we use something like
the following:

 	drvdata = (struct vchiq_drvdata *)of_id->data;
  drvdata->state = kzalloc(sizeof(struct vchiq_state), GFP_KERNEL);
	platform_set_drvdata(pdev, drvdata);
		
Correct me if I'm wrong but I think the assignment to drvdata in line 1
above will return a pointer to the same structure. In which case, the
line 2 will always overwrite the older state that is present. 
That's why I was initialising a separate object (vchiq_device) everytime
the probe was called so that each device can have their own device
specific structs. 

Please let me know if my understanding of drvdata is wrong here.
> 
> Best regards
> 

Thank you!
Ojaswin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] staging: vchiq: Replace global state with per device state
  2021-11-01 17:31     ` Ojaswin Mujoo
@ 2021-11-01 18:58       ` Stefan Wahren
  0 siblings, 0 replies; 7+ messages in thread
From: Stefan Wahren @ 2021-11-01 18:58 UTC (permalink / raw)
  To: Ojaswin Mujoo
  Cc: nsaenz, gregkh, dan.carpenter, phil, linux-arm-kernel,
	linux-staging, linux-kernel

Hi Ojawin,

Am 01.11.21 um 18:31 schrieb Ojaswin Mujoo:
> On Mon, Nov 01, 2021 at 01:19:17PM +0100, Stefan Wahren wrote:
>> Hi Ojaswin,
>>
>> Am 01.11.21 um 12:09 schrieb Ojaswin Mujoo:
>>> Currently, the driver has a global g_state variable which is initialised
>>> during probe and directly used all over the driver code. However, this
>>> prevents the driver to support multiple VideoCore VPUs at the same time.
>>>
>>> Replace this global state with a per device state which is initialised
>>> and allocated during probing.
>>>
>>> Signed-off-by: Ojaswin Mujoo <ojaswin98@gmail.com>
>> ...
>>>  
>>>  /*
>>> @@ -1763,6 +1795,7 @@ static int vchiq_probe(struct platform_device *pdev)
>>>  	struct device_node *fw_node;
>>>  	const struct of_device_id *of_id;
>>>  	struct vchiq_drvdata *drvdata;
>>> +	struct vchiq_device *vchiq_dev;
>>>  	int err;
>>>  
>>>  	of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
>>> @@ -1784,7 +1817,18 @@ static int vchiq_probe(struct platform_device *pdev)
>>>  
>>>  	platform_set_drvdata(pdev, drvdata);
>>>  
>>> -	err = vchiq_platform_init(pdev, &g_state);
>>> +	vchiq_dev = kzalloc(sizeof(struct vchiq_device), GFP_KERNEL);
>>> +	vchiq_dev->state = kzalloc(sizeof(struct vchiq_state), GFP_KERNEL);
>>> +	vchiq_dev->vchiq_pdev = *pdev;
>>> +
>>> +	g_state = vchiq_dev->state;
>>> +
>> just a quick idea: how about storing the global state within vchiq_drvdata?
>>
>> So there is no need to reinvent somekind of vchiq device which is the
>> "same" as the platform device. After that you are able to access the
>> private driver data via platform_get_drvdata().
> Hi Stefan, 
>
> Thank for looking into this. I agree that the vchiq_device is just a
> sorta extension of the pdev. However, regarding using the drvdata, I had
> some questions.
>
> So I understand the purpose of this patch is to make sure our driver is
> able to support multiple devices, that is it can work with say, an SoC
> with 2 VideoCore VPUs. In this case, we would need to maintain 2 states
> for each VPU instead of a global state, however if we use something like
> the following:
>
>  	drvdata = (struct vchiq_drvdata *)of_id->data;
>   drvdata->state = kzalloc(sizeof(struct vchiq_state), GFP_KERNEL);
> 	platform_set_drvdata(pdev, drvdata);
> 		

no, this wasn't my intention. We need a new container struct (maybe
vchiq_priv or so) which stores the g_state and the platform data from
the devicetree of_id->data. At first the probe function allocates this
struct and then we fill it with g_state and the devicetree stuff. After
that we attach it to the platform device.

Regards


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-11-01 18:58 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-01 11:09 [PATCH 0/1] vchiq: Replacing global structs with per device Ojaswin Mujoo
2021-11-01 11:09 ` [PATCH 1/1] staging: vchiq: Replace global state with per device state Ojaswin Mujoo
2021-11-01 12:19   ` Stefan Wahren
2021-11-01 17:31     ` Ojaswin Mujoo
2021-11-01 18:58       ` Stefan Wahren
2021-11-01 16:07   ` kernel test robot
2021-11-01 16:45   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).