Skip to contentSkip to conversation

mfd: tps6586x: Move interrupt handling into workqueue

PATCH In review Dmitry Osipenko 2 participants 5 messages May 13, 2018 – May 14, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mfd: tps6586x: Move interrupt handling into workqueue

Reading of status register within the interrupt handler fails with -EAGAIN if I2C is busy with handling some other request at the same time. Move the actual interrupt handling into a workqueue to avoid the unfortunate I2C failure and to avoid hanging CPU in interrupt up to 1 second (transfer timeout in the Tegra I2C driver).

---
 drivers/mfd/tps6586x.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)
drivers/mfd/tps6586x.c +29 -11
index b89379782741..9896e080b274 100644
@@ -133,6 +133,7 @@ struct tps6586x {
 	u32			irq_en;
 	u8			mask_reg[5];
 	struct irq_domain	*irq_domain;
+	struct work_struct	isr_work;
 };
 
 static inline struct tps6586x *dev_to_tps6586x(struct device *dev)
@@ -309,18 +310,19 @@ static const struct irq_domain_ops tps6586x_domain_ops = {
 	.xlate  = irq_domain_xlate_twocell,
 };
 
-static irqreturn_t tps6586x_irq(int irq, void *data)
+static void tps6586x_isr_work(struct work_struct *work)
 {
-	struct tps6586x *tps6586x = data;
+	struct tps6586x *tps6586x = container_of(work, struct tps6586x,
+						 isr_work);
 	u32 acks;
-	int ret = 0;
+	int err;
 
-	ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1,
+	err = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1,
 			     sizeof(acks), (uint8_t *)&acks);
-
-	if (ret < 0) {
-		dev_err(tps6586x->dev, "failed to read interrupt status\n");
-		return IRQ_NONE;
+	if (err < 0) {
+		dev_err(tps6586x->dev,
+			"failed to read interrupt status %d\n", err);
+		return;
 	}
 
 	acks = le32_to_cpu(acks);
@@ -335,6 +337,16 @@ static irqreturn_t tps6586x_irq(int irq, void *data)
 		acks &= ~(1 << i);
 	}
 
+	enable_irq(tps6586x->irq);
+}
+
+static irqreturn_t tps6586x_irq(int irq, void *data)
+{
+	struct tps6586x *tps6586x = data;
+
+	disable_irq_nosync(irq);
+	schedule_work(&tps6586x->isr_work);
+
 	return IRQ_HANDLED;
 }
 
@@ -542,8 +554,9 @@ static int tps6586x_i2c_probe(struct i2c_client *client,
 		return ret;
 	}
 
-
 	if (client->irq) {
+		INIT_WORK(&tps6586x->isr_work, tps6586x_isr_work);
+
 		ret = tps6586x_irq_init(tps6586x, client->irq,
 					pdata->irq_base);
 		if (ret) {
@@ -585,10 +598,15 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
 {
 	struct tps6586x *tps6586x = i2c_get_clientdata(client);
 
+	if (client->irq) {
+		disable_irq(client->irq);
+		flush_work(&tps6586x->isr_work);
+		free_irq(client->irq, tps6586x);
+	}
+
 	tps6586x_remove_subdevs(tps6586x);
 	mfd_remove_devices(tps6586x->dev);
-	if (client->irq)
-		free_irq(client->irq, tps6586x);
+
 	return 0;
 }
 
Signature · 1 line
2.17.0
#1 lore raw
Quoted 10 lines · Dmitry Osipenko

Reading of status register within the interrupt handler fails with -EAGAIN if I2C is busy with handling some other request at the same time. Move the actual interrupt handling into a workqueue to avoid the unfortunate I2C failure and to avoid hanging CPU in interrupt up to 1 second (transfer timeout in the Tegra I2C driver).

---
 drivers/mfd/tps6586x.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

Could this not be achieved with a threaded interrupt handler?

Thierry

#2 lore raw
Quoted 7 lines · Thierry Reding
Quoted 6 lines · Dmitry Osipenko

Reading of status register within the interrupt handler fails with -EAGAIN if I2C is busy with handling some other request at the same time. Move the actual interrupt handling into a workqueue to avoid the unfortunate I2C failure and to avoid hanging CPU in interrupt up to 1 second (transfer timeout in the Tegra I2C driver).

Quoted 9 lines
Quoted 4 lines
---
 drivers/mfd/tps6586x.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

Could this not be achieved with a threaded interrupt handler?

Thierry

Seems yes. I completely forgot about the threaded interrupt handlers existence. Thank you very much for the suggestion, I'll try with the threaded IRQ and send v2 if it will be fine.

#3 lore raw
Quoted 13 lines · Dmitry Osipenko
Quoted 12 lines · Thierry Reding
Quoted 10 lines · Dmitry Osipenko

Reading of status register within the interrupt handler fails with -EAGAIN if I2C is busy with handling some other request at the same time. Move the actual interrupt handling into a workqueue to avoid the unfortunate I2C failure and to avoid hanging CPU in interrupt up to 1 second (transfer timeout in the Tegra I2C driver).

---
 drivers/mfd/tps6586x.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)
Quoted 9 lines
Quoted 4 lines

Could this not be achieved with a threaded interrupt handler?

Thierry

Seems yes. I completely forgot about the threaded interrupt handlers existence. Thank you very much for the suggestion, I'll try with the threaded IRQ and send v2 if it will be fine.

Oh wait! TPS6586x driver already uses threaded interrupt handler, so everything should be fine in regards to the interrupt handling and this patch is obsolete. Thank you again for the good suggestion, then it's only the Tegra's I2C driver that causes trouble for the TPS6586x right now.

#4 lore raw
Quoted 24 lines · Dmitry Osipenko
Quoted 13 lines · Dmitry Osipenko
Quoted 12 lines · Thierry Reding
Quoted 10 lines · Dmitry Osipenko

Reading of status register within the interrupt handler fails with -EAGAIN if I2C is busy with handling some other request at the same time. Move the actual interrupt handling into a workqueue to avoid the unfortunate I2C failure and to avoid hanging CPU in interrupt up to 1 second (transfer timeout in the Tegra I2C driver).

---
 drivers/mfd/tps6586x.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)
Quoted 9 lines
Quoted 4 lines

Could this not be achieved with a threaded interrupt handler?

Thierry

Seems yes. I completely forgot about the threaded interrupt handlers existence. Thank you very much for the suggestion, I'll try with the threaded IRQ and send v2 if it will be fine.

Quoted 4 lines

Oh wait! TPS6586x driver already uses threaded interrupt handler, so everything should be fine in regards to the interrupt handling and this patch is obsolete. Thank you again for the good suggestion, then it's only the Tegra's I2C driver that causes trouble for the TPS6586x right now.

Heh... indeed. Sounds like the discussion that Wolfram pointed out is the right way forward.

Thierry