Message ID | 1398670860-30695-3-git-send-email-afenkart@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Monday 28 April 2014 01:10 PM, Andreas Fenkart wrote: > on multicores, an sdio irq handler could be running in parallel to > runtime suspend. In the worst case it could be waiting for the spinlock > held by the runtime suspend. When runtime suspend is complete and the > functional clock (fclk) turned off, the irq handler will continue and > cause a SIGBUS on the first register access. > > Signed-off-by: Andreas Fenkart <afenkart@gmail.com> > > diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c > index 700fb91..e675042 100644 > --- a/drivers/mmc/host/omap_hsmmc.c > +++ b/drivers/mmc/host/omap_hsmmc.c > @@ -56,6 +56,7 @@ > #define OMAP_HSMMC_RSP54 0x0118 > #define OMAP_HSMMC_RSP76 0x011C > #define OMAP_HSMMC_DATA 0x0120 > +#define OMAP_HSMMC_PSTATE 0x0124 > #define OMAP_HSMMC_HCTL 0x0128 > #define OMAP_HSMMC_SYSCTL 0x012C > #define OMAP_HSMMC_STAT 0x0130 > @@ -2400,6 +2401,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) > { > struct omap_hsmmc_host *host; > unsigned long flags; > + int ret = 0; > > host = platform_get_drvdata(to_platform_device(dev)); > omap_hsmmc_context_save(host); > @@ -2411,14 +2413,29 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) > /* disable sdio irq handling to prevent race */ > OMAP_HSMMC_WRITE(host->base, ISE, 0); > OMAP_HSMMC_WRITE(host->base, IE, 0); > - OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); > + > + if (!(OMAP_HSMMC_READ(host->base, PSTATE) & BIT(21))) { Please use #define for BIT(21), something like DLEV_DAT1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 700fb91..e675042 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -56,6 +56,7 @@ #define OMAP_HSMMC_RSP54 0x0118 #define OMAP_HSMMC_RSP76 0x011C #define OMAP_HSMMC_DATA 0x0120 +#define OMAP_HSMMC_PSTATE 0x0124 #define OMAP_HSMMC_HCTL 0x0128 #define OMAP_HSMMC_SYSCTL 0x012C #define OMAP_HSMMC_STAT 0x0130 @@ -2400,6 +2401,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) { struct omap_hsmmc_host *host; unsigned long flags; + int ret = 0; host = platform_get_drvdata(to_platform_device(dev)); omap_hsmmc_context_save(host); @@ -2411,14 +2413,29 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) /* disable sdio irq handling to prevent race */ OMAP_HSMMC_WRITE(host->base, ISE, 0); OMAP_HSMMC_WRITE(host->base, IE, 0); - OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); + + if (!(OMAP_HSMMC_READ(host->base, PSTATE) & BIT(21))) { + /* + * dat1 line low, pending sdio irq + * race condition: possible irq handler running on + * multi-core, abort + */ + dev_dbg(dev, "pending sdio irq, abort suspend\n"); + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); + OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN); + OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN); + pm_runtime_mark_last_busy(dev); + ret = -EBUSY; + goto abort; + } WARN_ON(host->flags & HSMMC_WAKE_IRQ_ENABLED); enable_irq(host->wake_irq); host->flags |= HSMMC_WAKE_IRQ_ENABLED; } +abort: spin_unlock_irqrestore(&host->irq_lock, flags); - return 0; + return ret; } static int omap_hsmmc_runtime_resume(struct device *dev)
on multicores, an sdio irq handler could be running in parallel to runtime suspend. In the worst case it could be waiting for the spinlock held by the runtime suspend. When runtime suspend is complete and the functional clock (fclk) turned off, the irq handler will continue and cause a SIGBUS on the first register access. Signed-off-by: Andreas Fenkart <afenkart@gmail.com>