[PATCH 01/38] mmc: sdio_irq: rework sdio irq handling
Ulf Hansson
ulf.hansson at linaro.org
Thu Apr 24 00:58:55 PDT 2014
On 23 April 2014 21:06, Russell King <rmk+kernel at arm.linux.org.uk> wrote:
> Rather than the SDIO support spawning it's own thread for handling card
> interrupts, use the generic IRQ infrastructure for this, triggering it
> from the host interface's interrupt handling directly.
>
> This avoids a race between the parent thread waiting to receive an
> interrupt response from the card, and the slow startup from the sdio
> irq thread, which can occur as a result of high system load (eg, while
> udev is running.)
>
> Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> ---
> drivers/mmc/core/sdio_irq.c | 41 +++++++++++++++++++++++++++++++----------
> include/linux/mmc/host.h | 3 +++
> 2 files changed, 34 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
> index aaa90460ed23..f23d73993dc6 100644
> --- a/drivers/mmc/core/sdio_irq.c
> +++ b/drivers/mmc/core/sdio_irq.c
> @@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
> return ret;
> }
>
> +void sdio_run_irqs(struct mmc_host *host)
> +{
> + mmc_claim_host(host);
> + host->sdio_irq_pending = true;
> + process_sdio_pending_irqs(host);
> + mmc_release_host(host);
> +}
> +EXPORT_SYMBOL_GPL(sdio_run_irqs);
> +
> static int sdio_irq_thread(void *_host)
> {
> struct mmc_host *host = _host;
> @@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)
> WARN_ON(!host->claimed);
>
> if (!host->sdio_irqs++) {
> - atomic_set(&host->sdio_irq_thread_abort, 0);
> - host->sdio_irq_thread =
> - kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
> - mmc_hostname(host));
> - if (IS_ERR(host->sdio_irq_thread)) {
> - int err = PTR_ERR(host->sdio_irq_thread);
> - host->sdio_irqs--;
> - return err;
> + if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
> + atomic_set(&host->sdio_irq_thread_abort, 0);
> + host->sdio_irq_thread =
> + kthread_run(sdio_irq_thread, host,
> + "ksdioirqd/%s", mmc_hostname(host));
> + if (IS_ERR(host->sdio_irq_thread)) {
> + int err = PTR_ERR(host->sdio_irq_thread);
> + host->sdio_irqs--;
> + return err;
> + }
> + } else {
I suppose you need to check for MMC_CAP_SDIO_IRQ here?
> + mmc_host_clk_hold(host);
> + host->ops->enable_sdio_irq(host, 1);
> + mmc_host_clk_release(host);
> }
> }
>
> @@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)
> BUG_ON(host->sdio_irqs < 1);
>
> if (!--host->sdio_irqs) {
> - atomic_set(&host->sdio_irq_thread_abort, 1);
> - kthread_stop(host->sdio_irq_thread);
> + if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
> + atomic_set(&host->sdio_irq_thread_abort, 1);
> + kthread_stop(host->sdio_irq_thread);
> + } else {
I suppose you need to check for MMC_CAP_SDIO_IRQ here?
> + mmc_host_clk_hold(host);
> + host->ops->enable_sdio_irq(host, 0);
> + mmc_host_clk_release(host);
> + }
> }
>
> return 0;
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index cb61ea4d6945..28c5e796292f 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -278,6 +278,7 @@ struct mmc_host {
> #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
> MMC_CAP2_PACKED_WR)
> #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */
> +#define MMC_CAP2_SDIO_NOTHREAD (1 << 15)
>
> mmc_pm_flag_t pm_caps; /* supported pm features */
>
> @@ -391,6 +392,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
> wake_up_process(host->sdio_irq_thread);
> }
>
> +void sdio_run_irqs(struct mmc_host *host);
> +
> #ifdef CONFIG_REGULATOR
> int mmc_regulator_get_ocrmask(struct regulator *supply);
> int mmc_regulator_set_ocr(struct mmc_host *mmc,
> --
> 1.8.3.1
Kind regards
Ulf Hansson
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the linux-arm-kernel
mailing list