Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6578b70 authored by Abhijeet Dharmapurikar's avatar Abhijeet Dharmapurikar
Browse files

power: smb135x-charger: Handle IRQ race during suspend



After executing the device suspend handlers, the irq framework waits
for any pending IRQ's to complete before proceeding further. In the
current design if the SMB stat IRQ triggers after its suspend handler,
the driver waits in the IRQ handler to avoid any further interrupts.
This waiting leads to a deadlock where the irq framework waits for
the interrupt to complete in its synchronize_irq() called via suspend_
device_irqs().

To avoid this scenario, disable the SMB stat IRQ if it triggers after
suspend and return from the handler. Re-enable the IRQ in the resume
handler.  Explicitly call the stat IRQ handler before enabling the irq
to make sure that the un-serviced IRQ is handled.

CRs-Fixed: 601993
Change-Id: I44672d75609b45dd79e4bfc5c8a819b2e7d173ea
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent 0b48c3d7
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -286,7 +286,6 @@ struct smb135x_chg {
	bool				batt_warm;
	bool				batt_cool;

	struct completion		resumed;
	bool				resume_completed;
	bool				irq_waiting;
	u32				usb_suspended;
@@ -1889,12 +1888,12 @@ static irqreturn_t smb135x_chg_stat_handler(int irq, void *dev_id)
	int handler_count = 0;

	mutex_lock(&chip->irq_complete);

	init_completion(&chip->resumed);
	chip->irq_waiting = true;
	if (!chip->resume_completed) {
		dev_dbg(chip->dev, "IRQ triggered before device-resume\n");
		wait_for_completion_interruptible(&chip->resumed);
		disable_irq_nosync(irq);
		mutex_unlock(&chip->irq_complete);
		return IRQ_HANDLED;
	}
	chip->irq_waiting = false;

@@ -2802,7 +2801,6 @@ static int smb135x_charger_probe(struct i2c_client *client,
	}

	chip->resume_completed = true;
	init_completion(&chip->resumed);
	mutex_init(&chip->irq_complete);

	/* STAT irq configuration */
@@ -3040,10 +3038,15 @@ static int smb135x_resume(struct device *dev)
			dev_err(chip->dev,
				"Couldn't restore irq cfg regs rc=%d\n", rc);
	}

	mutex_lock(&chip->irq_complete);
	chip->resume_completed = true;
	complete(&chip->resumed);

	if (chip->irq_waiting) {
		mutex_unlock(&chip->irq_complete);
		smb135x_chg_stat_handler(client->irq, chip);
		enable_irq(client->irq);
	} else {
		mutex_unlock(&chip->irq_complete);
	}
	return 0;
}