diff options
-rw-r--r-- | drivers/mmc/core/host.c | 3 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_irq.c | 8 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 8 |
3 files changed, 18 insertions, 1 deletions
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 2c7ce8f43a9a..37b761891d67 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
@@ -100,6 +100,9 @@ int mmc_add_host(struct mmc_host *host) | |||
100 | { | 100 | { |
101 | int err; | 101 | int err; |
102 | 102 | ||
103 | WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && | ||
104 | !host->ops->enable_sdio_irq); | ||
105 | |||
103 | if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) | 106 | if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) |
104 | return -ENOMEM; | 107 | return -ENOMEM; |
105 | 108 | ||
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 01922d29241d..01daee934d16 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c | |||
@@ -70,7 +70,8 @@ static int sdio_irq_thread(void *_host) | |||
70 | * asynchronous notification of pending SDIO card interrupts | 70 | * asynchronous notification of pending SDIO card interrupts |
71 | * hence we poll for them in that case. | 71 | * hence we poll for them in that case. |
72 | */ | 72 | */ |
73 | period = msecs_to_jiffies(10); | 73 | period = (host->caps & MMC_CAP_SDIO_IRQ) ? |
74 | MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(10); | ||
74 | 75 | ||
75 | pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n", | 76 | pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n", |
76 | mmc_hostname(host), period); | 77 | mmc_hostname(host), period); |
@@ -104,11 +105,16 @@ static int sdio_irq_thread(void *_host) | |||
104 | ssleep(1); | 105 | ssleep(1); |
105 | 106 | ||
106 | set_task_state(current, TASK_INTERRUPTIBLE); | 107 | set_task_state(current, TASK_INTERRUPTIBLE); |
108 | if (host->caps & MMC_CAP_SDIO_IRQ) | ||
109 | host->ops->enable_sdio_irq(host, 1); | ||
107 | if (!kthread_should_stop()) | 110 | if (!kthread_should_stop()) |
108 | schedule_timeout(period); | 111 | schedule_timeout(period); |
109 | set_task_state(current, TASK_RUNNING); | 112 | set_task_state(current, TASK_RUNNING); |
110 | } while (!kthread_should_stop()); | 113 | } while (!kthread_should_stop()); |
111 | 114 | ||
115 | if (host->caps & MMC_CAP_SDIO_IRQ) | ||
116 | host->ops->enable_sdio_irq(host, 0); | ||
117 | |||
112 | pr_debug("%s: IRQ thread exiting with code %d\n", | 118 | pr_debug("%s: IRQ thread exiting with code %d\n", |
113 | mmc_hostname(host), ret); | 119 | mmc_hostname(host), ret); |
114 | 120 | ||
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 00dc1809494c..3fd197962f73 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -51,6 +51,7 @@ struct mmc_host_ops { | |||
51 | void (*request)(struct mmc_host *host, struct mmc_request *req); | 51 | void (*request)(struct mmc_host *host, struct mmc_request *req); |
52 | void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); | 52 | void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); |
53 | int (*get_ro)(struct mmc_host *host); | 53 | int (*get_ro)(struct mmc_host *host); |
54 | void (*enable_sdio_irq)(struct mmc_host *host, int enable); | ||
54 | }; | 55 | }; |
55 | 56 | ||
56 | struct mmc_card; | 57 | struct mmc_card; |
@@ -89,6 +90,7 @@ struct mmc_host { | |||
89 | #define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */ | 90 | #define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */ |
90 | #define MMC_CAP_MMC_HIGHSPEED (1 << 2) /* Can do MMC high-speed timing */ | 91 | #define MMC_CAP_MMC_HIGHSPEED (1 << 2) /* Can do MMC high-speed timing */ |
91 | #define MMC_CAP_SD_HIGHSPEED (1 << 3) /* Can do SD high-speed timing */ | 92 | #define MMC_CAP_SD_HIGHSPEED (1 << 3) /* Can do SD high-speed timing */ |
93 | #define MMC_CAP_SDIO_IRQ (1 << 4) /* Can signal pending SDIO IRQs */ | ||
92 | 94 | ||
93 | /* host specific block data */ | 95 | /* host specific block data */ |
94 | unsigned int max_seg_size; /* see blk_queue_max_segment_size */ | 96 | unsigned int max_seg_size; /* see blk_queue_max_segment_size */ |
@@ -150,5 +152,11 @@ extern int mmc_resume_host(struct mmc_host *); | |||
150 | extern void mmc_detect_change(struct mmc_host *, unsigned long delay); | 152 | extern void mmc_detect_change(struct mmc_host *, unsigned long delay); |
151 | extern void mmc_request_done(struct mmc_host *, struct mmc_request *); | 153 | extern void mmc_request_done(struct mmc_host *, struct mmc_request *); |
152 | 154 | ||
155 | static inline void mmc_signal_sdio_irq(struct mmc_host *host) | ||
156 | { | ||
157 | host->ops->enable_sdio_irq(host, 0); | ||
158 | wake_up_process(host->sdio_irq_thread); | ||
159 | } | ||
160 | |||
153 | #endif | 161 | #endif |
154 | 162 | ||