Skip to content

Commit bf3b5ec

Browse files
Russell Kingcjb
Russell King
authored andcommitted
mmc: sdio_irq: rework sdio irq handling
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 <[email protected]> Tested-by: Markus Pargmann <[email protected]> Tested-by: Stephen Warren <[email protected]> [Ulf Hansson] Resolved conflict Signed-off-by: Ulf Hansson <[email protected]> Signed-off-by: Chris Ball <[email protected]>
1 parent 197160d commit bf3b5ec

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

drivers/mmc/core/sdio_irq.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
9090
return ret;
9191
}
9292

93+
void sdio_run_irqs(struct mmc_host *host)
94+
{
95+
mmc_claim_host(host);
96+
host->sdio_irq_pending = true;
97+
process_sdio_pending_irqs(host);
98+
mmc_release_host(host);
99+
}
100+
EXPORT_SYMBOL_GPL(sdio_run_irqs);
101+
93102
static int sdio_irq_thread(void *_host)
94103
{
95104
struct mmc_host *host = _host;
@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)
189198
WARN_ON(!host->claimed);
190199

191200
if (!host->sdio_irqs++) {
192-
atomic_set(&host->sdio_irq_thread_abort, 0);
193-
host->sdio_irq_thread =
194-
kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
195-
mmc_hostname(host));
196-
if (IS_ERR(host->sdio_irq_thread)) {
197-
int err = PTR_ERR(host->sdio_irq_thread);
198-
host->sdio_irqs--;
199-
return err;
201+
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
202+
atomic_set(&host->sdio_irq_thread_abort, 0);
203+
host->sdio_irq_thread =
204+
kthread_run(sdio_irq_thread, host,
205+
"ksdioirqd/%s", mmc_hostname(host));
206+
if (IS_ERR(host->sdio_irq_thread)) {
207+
int err = PTR_ERR(host->sdio_irq_thread);
208+
host->sdio_irqs--;
209+
return err;
210+
}
211+
} else {
212+
mmc_host_clk_hold(host);
213+
host->ops->enable_sdio_irq(host, 1);
214+
mmc_host_clk_release(host);
200215
}
201216
}
202217

@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)
211226
BUG_ON(host->sdio_irqs < 1);
212227

213228
if (!--host->sdio_irqs) {
214-
atomic_set(&host->sdio_irq_thread_abort, 1);
215-
kthread_stop(host->sdio_irq_thread);
229+
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
230+
atomic_set(&host->sdio_irq_thread_abort, 1);
231+
kthread_stop(host->sdio_irq_thread);
232+
} else {
233+
mmc_host_clk_hold(host);
234+
host->ops->enable_sdio_irq(host, 0);
235+
mmc_host_clk_release(host);
236+
}
216237
}
217238

218239
return 0;

include/linux/mmc/host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ struct mmc_host {
282282
#define MMC_CAP2_HS400_1_2V (1 << 16) /* Can support HS400 1.2V */
283283
#define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \
284284
MMC_CAP2_HS400_1_2V)
285+
#define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
285286

286287
mmc_pm_flag_t pm_caps; /* supported pm features */
287288

@@ -397,6 +398,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
397398
wake_up_process(host->sdio_irq_thread);
398399
}
399400

401+
void sdio_run_irqs(struct mmc_host *host);
402+
400403
#ifdef CONFIG_REGULATOR
401404
int mmc_regulator_get_ocrmask(struct regulator *supply);
402405
int mmc_regulator_set_ocr(struct mmc_host *mmc,

0 commit comments

Comments
 (0)