|
@@ -208,6 +208,9 @@ struct goldfish_pipe_dev {
|
|
|
int irq;
|
|
|
int version;
|
|
|
unsigned char __iomem *base;
|
|
|
+
|
|
|
+ /* an irq tasklet to run goldfish_interrupt_task */
|
|
|
+ struct tasklet_struct irq_tasklet;
|
|
|
};
|
|
|
|
|
|
static struct goldfish_pipe_dev goldfish_pipe_dev;
|
|
@@ -582,14 +585,14 @@ static struct goldfish_pipe *signalled_pipes_pop_front(
|
|
|
return pipe;
|
|
|
}
|
|
|
|
|
|
-static void goldfish_interrupt_task(unsigned long unused)
|
|
|
+static void goldfish_interrupt_task(unsigned long dev_addr)
|
|
|
{
|
|
|
/* Iterate over the signalled pipes and wake them one by one */
|
|
|
+ struct goldfish_pipe_dev *dev = (struct goldfish_pipe_dev *)dev_addr;
|
|
|
struct goldfish_pipe *pipe;
|
|
|
int wakes;
|
|
|
|
|
|
- while ((pipe = signalled_pipes_pop_front(&goldfish_pipe_dev, &wakes)) !=
|
|
|
- NULL) {
|
|
|
+ while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) {
|
|
|
if (wakes & PIPE_WAKE_CLOSED) {
|
|
|
pipe->flags = 1 << BIT_CLOSED_ON_HOST;
|
|
|
} else {
|
|
@@ -605,7 +608,6 @@ static void goldfish_interrupt_task(unsigned long unused)
|
|
|
wake_up_interruptible(&pipe->wake_queue);
|
|
|
}
|
|
|
}
|
|
|
-static DECLARE_TASKLET(goldfish_interrupt_tasklet, goldfish_interrupt_task, 0);
|
|
|
|
|
|
/*
|
|
|
* The general idea of the interrupt handling:
|
|
@@ -648,7 +650,7 @@ static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id)
|
|
|
|
|
|
spin_unlock_irqrestore(&dev->lock, flags);
|
|
|
|
|
|
- tasklet_schedule(&goldfish_interrupt_tasklet);
|
|
|
+ tasklet_schedule(&dev->irq_tasklet);
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
@@ -800,9 +802,14 @@ static void write_pa_addr(void *addr, void __iomem *portl, void __iomem *porth)
|
|
|
static int goldfish_pipe_device_init(struct platform_device *pdev)
|
|
|
{
|
|
|
struct goldfish_pipe_dev *dev = &goldfish_pipe_dev;
|
|
|
- int err = devm_request_irq(&pdev->dev, dev->irq,
|
|
|
- goldfish_pipe_interrupt,
|
|
|
- IRQF_SHARED, "goldfish_pipe", dev);
|
|
|
+ int err;
|
|
|
+
|
|
|
+ tasklet_init(&dev->irq_tasklet, &goldfish_interrupt_task,
|
|
|
+ (unsigned long)dev);
|
|
|
+
|
|
|
+ err = devm_request_irq(&pdev->dev, dev->irq,
|
|
|
+ goldfish_pipe_interrupt,
|
|
|
+ IRQF_SHARED, "goldfish_pipe", dev);
|
|
|
if (err) {
|
|
|
dev_err(&pdev->dev, "unable to allocate IRQ for v2\n");
|
|
|
return err;
|
|
@@ -854,6 +861,7 @@ static int goldfish_pipe_device_init(struct platform_device *pdev)
|
|
|
static void goldfish_pipe_device_deinit(struct platform_device *pdev)
|
|
|
{
|
|
|
misc_deregister(&goldfish_pipe_miscdev);
|
|
|
+ tasklet_kill(&goldfish_pipe_dev.irq_tasklet);
|
|
|
kfree(goldfish_pipe_dev.pipes);
|
|
|
free_page((unsigned long)goldfish_pipe_dev.buffers);
|
|
|
}
|