mfd: use a dedicated workqueue for pcf50633 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> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
9c3664ddce
commit
ed52e62ebe
2 changed files with 5 additions and 1 deletions
|
@ -444,7 +444,7 @@ static irqreturn_t pcf50633_irq(int irq, void *data)
|
||||||
|
|
||||||
get_device(pcf->dev);
|
get_device(pcf->dev);
|
||||||
disable_irq_nosync(pcf->irq);
|
disable_irq_nosync(pcf->irq);
|
||||||
schedule_work(&pcf->irq_work);
|
queue_work(pcf->work_queue, &pcf->irq_work);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -575,6 +575,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
|
||||||
pcf->dev = &client->dev;
|
pcf->dev = &client->dev;
|
||||||
pcf->i2c_client = client;
|
pcf->i2c_client = client;
|
||||||
pcf->irq = client->irq;
|
pcf->irq = client->irq;
|
||||||
|
pcf->work_queue = create_singlethread_workqueue("pcf50633");
|
||||||
|
|
||||||
INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
|
INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
|
||||||
|
|
||||||
|
@ -651,6 +652,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
destroy_workqueue(pcf->work_queue);
|
||||||
kfree(pcf);
|
kfree(pcf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -661,6 +663,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
free_irq(pcf->irq, pcf);
|
free_irq(pcf->irq, pcf);
|
||||||
|
destroy_workqueue(pcf->work_queue);
|
||||||
|
|
||||||
platform_device_unregister(pcf->input_pdev);
|
platform_device_unregister(pcf->input_pdev);
|
||||||
platform_device_unregister(pcf->rtc_pdev);
|
platform_device_unregister(pcf->rtc_pdev);
|
||||||
|
|
|
@ -136,6 +136,7 @@ struct pcf50633 {
|
||||||
int irq;
|
int irq;
|
||||||
struct pcf50633_irq irq_handler[PCF50633_NUM_IRQ];
|
struct pcf50633_irq irq_handler[PCF50633_NUM_IRQ];
|
||||||
struct work_struct irq_work;
|
struct work_struct irq_work;
|
||||||
|
struct workqueue_struct *work_queue;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
|
|
||||||
u8 mask_regs[5];
|
u8 mask_regs[5];
|
||||||
|
|
Loading…
Reference in a new issue