diff mbox

[PATCHv7,20/23] i2c: omap: switch to threaded IRQ support

Message ID 1347356538-23835-21-git-send-email-shubhrajyoti@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Shubhrajyoti Datta Sept. 11, 2012, 9:42 a.m. UTC
From: Felipe Balbi <balbi@ti.com>

for OMAP2, we can easily switch over to threaded
IRQs on the I2C driver. This will allow us to
spend less time in hardirq context.

Signed-off-by: Felipe Balbi <balbi@ti.com>
[Trivial formating changes]
Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
---
 drivers/i2c/busses/i2c-omap.c |   43 +++++++++++++++++++++++++++++++++++-----
 1 files changed, 37 insertions(+), 6 deletions(-)

Comments

Wolfram Sang Sept. 11, 2012, 9:51 p.m. UTC | #1
On Tue, Sep 11, 2012 at 03:12:15PM +0530, Shubhrajyoti D wrote:
> From: Felipe Balbi <balbi@ti.com>
> 
> for OMAP2, we can easily switch over to threaded
> IRQs on the I2C driver. This will allow us to
> spend less time in hardirq context.
> 
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> [Trivial formating changes]
> Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
> ---
>  drivers/i2c/busses/i2c-omap.c |   43 +++++++++++++++++++++++++++++++++++-----
>  1 files changed, 37 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index 4a696bd..e391370 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -176,6 +176,7 @@ enum {
>  #define I2C_OMAP_ERRATA_I462		(1 << 1)
>  
>  struct omap_i2c_dev {
> +	spinlock_t		lock;		/* IRQ synchronization */
>  	struct device		*dev;
>  	void __iomem		*base;		/* virtual */
>  	int			irq;
> @@ -854,9 +855,30 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
>  }
>  
>  static irqreturn_t
> -omap_i2c_isr(int this_irq, void *dev_id)
> +omap_i2c_isr(int irq, void *dev_id)
>  {
>  	struct omap_i2c_dev *dev = dev_id;
> +	irqreturn_t ret = IRQ_HANDLED;

Shouldn't that be IRQ_NONE?
Shubhrajyoti Datta Sept. 12, 2012, 6:25 a.m. UTC | #2
On Wednesday 12 September 2012 03:21 AM, Wolfram Sang wrote:
>> -omap_i2c_isr(int this_irq, void *dev_id)
>> > +omap_i2c_isr(int irq, void *dev_id)
>> >  {
>> >  	struct omap_i2c_dev *dev = dev_id;
>> > +	irqreturn_t ret = IRQ_HANDLED;
> Shouldn't that be IRQ_NONE?
Actually we are processing it so I thought it to be ok.
Also a similar discussion.
 
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-June/104422.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfram Sang Sept. 12, 2012, 11:51 a.m. UTC | #3
On Wed, Sep 12, 2012 at 11:55:39AM +0530, Shubhrajyoti wrote:
> On Wednesday 12 September 2012 03:21 AM, Wolfram Sang wrote:
> >> -omap_i2c_isr(int this_irq, void *dev_id)
> >> > +omap_i2c_isr(int irq, void *dev_id)
> >> >  {
> >> >  	struct omap_i2c_dev *dev = dev_id;
> >> > +	irqreturn_t ret = IRQ_HANDLED;
> > Shouldn't that be IRQ_NONE?
> Actually we are processing it so I thought it to be ok.

Are we processing it? There is nothing acknowledged AFAICS. Anyway, we
can fix that with a later patch.

> Also a similar discussion.
>  
> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-June/104422.html

I totally agree to the things said there.
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 4a696bd..e391370 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -176,6 +176,7 @@  enum {
 #define I2C_OMAP_ERRATA_I462		(1 << 1)
 
 struct omap_i2c_dev {
+	spinlock_t		lock;		/* IRQ synchronization */
 	struct device		*dev;
 	void __iomem		*base;		/* virtual */
 	int			irq;
@@ -854,9 +855,30 @@  static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
 }
 
 static irqreturn_t
-omap_i2c_isr(int this_irq, void *dev_id)
+omap_i2c_isr(int irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
+	irqreturn_t ret = IRQ_HANDLED;
+	u16 mask;
+	u16 stat;
+
+	spin_lock(&dev->lock);
+	mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+	stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+
+	if (stat & mask)
+		ret = IRQ_WAKE_THREAD;
+
+	spin_unlock(&dev->lock);
+
+	return ret;
+}
+
+static irqreturn_t
+omap_i2c_isr_thread(int this_irq, void *dev_id)
+{
+	struct omap_i2c_dev *dev = dev_id;
+	unsigned long flags;
 	u16 bits;
 	u16 stat;
 	int err = 0, count = 0;
@@ -864,6 +886,7 @@  omap_i2c_isr(int this_irq, void *dev_id)
 	if (pm_runtime_suspended(dev->dev))
 		return IRQ_HANDLED;
 
+	spin_lock_irqsave(&dev->lock, flags);
 	do {
 		bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
 		stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
@@ -877,6 +900,7 @@  omap_i2c_isr(int this_irq, void *dev_id)
 
 		if (!stat) {
 			/* my work here is done */
+			spin_unlock_irqrestore(&dev->lock, flags);
 			return IRQ_HANDLED;
 		}
 
@@ -985,6 +1009,8 @@  omap_i2c_isr(int this_irq, void *dev_id)
 
 out:
 	omap_i2c_complete_cmd(dev, err);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
@@ -1028,7 +1054,6 @@  omap_i2c_probe(struct platform_device *pdev)
 	struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
 	struct device_node	*node = pdev->dev.of_node;
 	const struct of_device_id *match;
-	irq_handler_t isr;
 	int irq;
 	int r;
 
@@ -1078,6 +1103,8 @@  omap_i2c_probe(struct platform_device *pdev)
 	dev->dev = &pdev->dev;
 	dev->irq = irq;
 
+	spin_lock_init(&dev->lock);
+
 	platform_set_drvdata(pdev, dev);
 	init_completion(&dev->cmd_complete);
 
@@ -1130,10 +1157,14 @@  omap_i2c_probe(struct platform_device *pdev)
 	/* reset ASAP, clearing any IRQs */
 	omap_i2c_init(dev);
 
-	isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
-								   omap_i2c_isr;
-	r = devm_request_irq(&pdev->dev, dev->irq, isr, IRQF_NO_SUSPEND,
-			     pdev->name, dev);
+	if (dev->rev < OMAP_I2C_OMAP1_REV_2)
+		r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
+				IRQF_NO_SUSPEND, pdev->name, dev);
+	else
+		r = devm_request_threaded_irq(&pdev->dev, dev->irq,
+				omap_i2c_isr, omap_i2c_isr_thread,
+				IRQF_NO_SUSPEND | IRQF_ONESHOT,
+				pdev->name, dev);
 
 	if (r) {
 		dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);