mmc: msm_sdcc: Fix race in disabling sdcc core irq

o Assume SDCC driver has SDIO clients attached and
  runtime clock gating has turned off the SDCC clocks.

o Now, if the SDIO client driver has initiated a request
  to SDCC and since the clocks are turned off, mmc framework
  tries to turn them on calling msmsdcc_set_ios().

o msmsdcc_set_ios() tries to disable the core irq first and
  reenable after the clocks are turned on. While in process
  of disabling the irq, if there is an asynchronous notification
  from SDIO client h/w, it will preempt ongoing disable and run
  msmsdcc_irq() which internally does disable_irq_nosync() since
  the clocks are still off.

o While the control returns to msmsdcc_set_ios() from preemption
  it will continue disabling the core irq (even though
  host->sdcc_irq_disabled = 1). In effect, calls disable_irq()
  twice increasing the irq desc->depth to 2.

o The enable_irq() API enables the irq in h/w if and only if
  desc->depth = 1, and hence become a noop if it is called with
  desc->depth = 2 causing sdcc failure because the interrupts
  are not enabled in h/w.

Fix the above race condition by making sure disable irq is done
atomically.

CRs-Fixed: 357406
Change-Id: Id8a4e5cc9b0ac035a83c070ede57b2c39d96e6e9
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e84d87b..eba80c5 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2877,13 +2877,14 @@
 	DBG(host, "ios->clock = %u\n", ios->clock);
 	spin_lock_irqsave(&host->lock, flags);
 	if (!host->sdcc_irq_disabled) {
-		spin_unlock_irqrestore(&host->lock, flags);
-		disable_irq(host->core_irqres->start);
-		spin_lock_irqsave(&host->lock, flags);
+		disable_irq_nosync(host->core_irqres->start);
 		host->sdcc_irq_disabled = 1;
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
 
+	/* Make sure sdcc core irq is synchronized */
+	synchronize_irq(host->core_irqres->start);
+
 	pwr = msmsdcc_setup_pwr(host, ios);
 
 	spin_lock_irqsave(&host->lock, flags);