[PATCH v3 03/15] platform: goldfish: pipe: Move the file-scope goldfish_pipe_dev variable into the driver state

From: rkir
Date: Wed Oct 03 2018 - 13:17:56 EST


From: Roman Kiryanov <rkir@xxxxxxxxxx>

This is the last patch in the series of patches to move file-scope
variables into the driver state. This change will help to introduce
another version of the pipe driver (with different state) for the
older host interface or having several instances of this device.

Signed-off-by: Roman Kiryanov <rkir@xxxxxxxxxx>
---
Changes in v3:
- No change.
Changes in v2:
- Updated the commit message.

drivers/platform/goldfish/goldfish_pipe.c | 66 +++++++++++++----------
1 file changed, 37 insertions(+), 29 deletions(-)

diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
index 8ca709b45e1f..4013832f38fb 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -169,6 +169,9 @@ struct goldfish_pipe {
* waiting to be awoken.
*/
struct goldfish_pipe_dev {
+ /* A magic number to check if this is an instance of this struct */
+ void *magic;
+
/*
* Global device spinlock. Protects the following members:
* - pipes, pipes_capacity
@@ -215,8 +218,6 @@ struct goldfish_pipe_dev {
struct miscdevice miscdev;
};

-static struct goldfish_pipe_dev goldfish_pipe_dev;
-
static int goldfish_pipe_cmd_locked(struct goldfish_pipe *pipe,
enum PipeCmdCode cmd)
{
@@ -611,6 +612,9 @@ static void goldfish_interrupt_task(unsigned long dev_addr)
}
}

+static void goldfish_pipe_device_deinit(struct platform_device *pdev,
+ struct goldfish_pipe_dev *dev);
+
/*
* The general idea of the interrupt handling:
*
@@ -631,7 +635,7 @@ static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id)
unsigned long flags;
struct goldfish_pipe_dev *dev = dev_id;

- if (dev != &goldfish_pipe_dev)
+ if (dev->magic != &goldfish_pipe_device_deinit)
return IRQ_NONE;

/* Request the signalled pipes from the device */
@@ -683,6 +687,14 @@ static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev)
return id;
}

+/* A helper function to get the instance of goldfish_pipe_dev from file */
+static struct goldfish_pipe_dev *to_goldfish_pipe_dev(struct file *file)
+{
+ struct miscdevice *miscdev = file->private_data;
+
+ return container_of(miscdev, struct goldfish_pipe_dev, miscdev);
+}
+
/**
* goldfish_pipe_open - open a channel to the AVD
* @inode: inode of device
@@ -696,7 +708,7 @@ static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev)
*/
static int goldfish_pipe_open(struct inode *inode, struct file *file)
{
- struct goldfish_pipe_dev *dev = &goldfish_pipe_dev;
+ struct goldfish_pipe_dev *dev = to_goldfish_pipe_dev(file);
unsigned long flags;
int id;
int status;
@@ -804,9 +816,9 @@ static void write_pa_addr(void *addr, void __iomem *portl, void __iomem *porth)
writel(lower_32_bits(paddr), portl);
}

-static int goldfish_pipe_device_init(struct platform_device *pdev)
+static int goldfish_pipe_device_init(struct platform_device *pdev,
+ struct goldfish_pipe_dev *dev)
{
- struct goldfish_pipe_dev *dev = &goldfish_pipe_dev;
int err;

tasklet_init(&dev->irq_tasklet, &goldfish_interrupt_task,
@@ -861,26 +873,29 @@ static int goldfish_pipe_device_init(struct platform_device *pdev)
dev->base + PIPE_REG_OPEN_BUFFER,
dev->base + PIPE_REG_OPEN_BUFFER_HIGH);

+ platform_set_drvdata(pdev, dev);
return 0;
}

-static void goldfish_pipe_device_deinit(struct platform_device *pdev)
+static void goldfish_pipe_device_deinit(struct platform_device *pdev,
+ struct goldfish_pipe_dev *dev)
{
- misc_deregister(&goldfish_pipe_dev.miscdev);
- tasklet_kill(&goldfish_pipe_dev.irq_tasklet);
- kfree(goldfish_pipe_dev.pipes);
- free_page((unsigned long)goldfish_pipe_dev.buffers);
+ misc_deregister(&dev->miscdev);
+ tasklet_kill(&dev->irq_tasklet);
+ kfree(dev->pipes);
+ free_page((unsigned long)dev->buffers);
}

static int goldfish_pipe_probe(struct platform_device *pdev)
{
- int err;
struct resource *r;
- struct goldfish_pipe_dev *dev = &goldfish_pipe_dev;
+ struct goldfish_pipe_dev *dev;

- /* not thread safe, but this should not happen */
- WARN_ON(dev->base);
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;

+ dev->magic = &goldfish_pipe_device_deinit;
spin_lock_init(&dev->lock);

r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -895,10 +910,9 @@ static int goldfish_pipe_probe(struct platform_device *pdev)
}

r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!r) {
- err = -EINVAL;
- goto error;
- }
+ if (!r)
+ return -EINVAL;
+
dev->irq = r->start;

/*
@@ -913,20 +927,14 @@ static int goldfish_pipe_probe(struct platform_device *pdev)
if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION))
return -EINVAL;

- err = goldfish_pipe_device_init(pdev);
- if (!err)
- return 0;
-
-error:
- dev->base = NULL;
- return err;
+ return goldfish_pipe_device_init(pdev, dev);
}

static int goldfish_pipe_remove(struct platform_device *pdev)
{
- struct goldfish_pipe_dev *dev = &goldfish_pipe_dev;
- goldfish_pipe_device_deinit(pdev);
- dev->base = NULL;
+ struct goldfish_pipe_dev *dev = platform_get_drvdata(pdev);
+
+ goldfish_pipe_device_deinit(pdev, dev);
return 0;
}

--
2.19.0.605.g01d371f741-goog