aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Fertser <fercerpav@gmail.com>2009-07-28 00:41:15 +0400
committerPaul Fertser <fercerpav@gmail.com>2009-08-02 11:27:18 +0400
commit21658522b00d047212d7a78cb749648ff3bfeb04 (patch)
tree6b85e76c023c1c915c5e03ea61e986e2f10711b2
parentbcdf6f7109ea494ca84a3baea3a3c563dca9f68b (diff)
pcf50633: use a dedicated workqueue for irq processing
Using the default kernel "events" workqueue causes problems with synchronous adc readings if initiated from some task on the same workqueue. I had a deadlock trying to use pcf50633_adc_sync_read from a power_supply class driver because the reading was initiated from the workqueue and it waited for the irq processing to complete (to get the result) and that was put on the same workqueue. Signed-off-by: Paul Fertser <fercerpav@gmail.com>
-rw-r--r--drivers/mfd/pcf50633-core.c5
-rw-r--r--include/linux/mfd/pcf50633/core.h1
2 files changed, 5 insertions, 1 deletions
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 29c9395d65f..5006746ff5c 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -448,7 +448,7 @@ static irqreturn_t pcf50633_irq(int irq, void *data)
get_device(pcf->dev);
disable_irq(pcf->irq);
- schedule_work(&pcf->irq_work);
+ queue_work(pcf->work_queue, &pcf->irq_work);
return IRQ_HANDLED;
}
@@ -579,6 +579,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
pcf->dev = &client->dev;
pcf->i2c_client = client;
pcf->irq = client->irq;
+ pcf->work_queue = create_singlethread_workqueue("pcf50633");
INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
@@ -656,6 +657,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
return 0;
err:
+ destroy_workqueue(pcf->work_queue);
kfree(pcf);
return ret;
}
@@ -666,6 +668,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
int i;
free_irq(pcf->irq, pcf);
+ destroy_workqueue(pcf->work_queue);
platform_device_unregister(pcf->input_pdev);
platform_device_unregister(pcf->rtc_pdev);
diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h
index af67b4e3ec6..aed1fabb068 100644
--- a/include/linux/mfd/pcf50633/core.h
+++ b/include/linux/mfd/pcf50633/core.h
@@ -138,6 +138,7 @@ struct pcf50633 {
int irq;
struct pcf50633_irq irq_handler[PCF50633_NUM_IRQ];
struct work_struct irq_work;
+ struct workqueue_struct *work_queue;
struct mutex lock;
u8 mask_regs[5];