mfd: use a dedicated workqueue for pcf50633 irq processing
authorPaul Fertser <fercerpav@gmail.com>
Mon, 27 Jul 2009 20:41:15 +0000 (00:41 +0400)
committerSamuel Ortiz <sameo@linux.intel.com>
Thu, 17 Sep 2009 07:46:53 +0000 (09:46 +0200)
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>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
drivers/mfd/pcf50633-core.c
include/linux/mfd/pcf50633/core.h

index 8d3c38bf9714857fbe97507e52498a39cec122c2..d26d7747175ef107c9a34d08f44fab4d692114a7 100644 (file)
@@ -444,7 +444,7 @@ static irqreturn_t pcf50633_irq(int irq, void *data)
 
        get_device(pcf->dev);
        disable_irq_nosync(pcf->irq);
-       schedule_work(&pcf->irq_work);
+       queue_work(pcf->work_queue, &pcf->irq_work);
 
        return IRQ_HANDLED;
 }
@@ -575,6 +575,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);
 
@@ -651,6 +652,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
        return 0;
 
 err:
+       destroy_workqueue(pcf->work_queue);
        kfree(pcf);
        return ret;
 }
@@ -661,6 +663,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);
index c8f51c3c0a725d21f9906178f91d7fb868ca0299..9aba7b779fbc35ee13896e8643f97a976ee49758 100644 (file)
@@ -136,6 +136,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];