diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/sdio_irq.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index b3001617e67d..03ead028d2ce 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c | |||
@@ -31,6 +31,17 @@ static int process_sdio_pending_irqs(struct mmc_card *card) | |||
31 | { | 31 | { |
32 | int i, ret, count; | 32 | int i, ret, count; |
33 | unsigned char pending; | 33 | unsigned char pending; |
34 | struct sdio_func *func; | ||
35 | |||
36 | /* | ||
37 | * Optimization, if there is only 1 function interrupt registered | ||
38 | * call irq handler directly | ||
39 | */ | ||
40 | func = card->sdio_single_irq; | ||
41 | if (func) { | ||
42 | func->irq_handler(func); | ||
43 | return 1; | ||
44 | } | ||
34 | 45 | ||
35 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending); | 46 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending); |
36 | if (ret) { | 47 | if (ret) { |
@@ -42,7 +53,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card) | |||
42 | count = 0; | 53 | count = 0; |
43 | for (i = 1; i <= 7; i++) { | 54 | for (i = 1; i <= 7; i++) { |
44 | if (pending & (1 << i)) { | 55 | if (pending & (1 << i)) { |
45 | struct sdio_func *func = card->sdio_func[i - 1]; | 56 | func = card->sdio_func[i - 1]; |
46 | if (!func) { | 57 | if (!func) { |
47 | printk(KERN_WARNING "%s: pending IRQ for " | 58 | printk(KERN_WARNING "%s: pending IRQ for " |
48 | "non-existent function\n", | 59 | "non-existent function\n", |
@@ -186,6 +197,24 @@ static int sdio_card_irq_put(struct mmc_card *card) | |||
186 | return 0; | 197 | return 0; |
187 | } | 198 | } |
188 | 199 | ||
200 | /* If there is only 1 function registered set sdio_single_irq */ | ||
201 | static void sdio_single_irq_set(struct mmc_card *card) | ||
202 | { | ||
203 | struct sdio_func *func; | ||
204 | int i; | ||
205 | |||
206 | card->sdio_single_irq = NULL; | ||
207 | if ((card->host->caps & MMC_CAP_SDIO_IRQ) && | ||
208 | card->host->sdio_irqs == 1) | ||
209 | for (i = 0; i < card->sdio_funcs; i++) { | ||
210 | func = card->sdio_func[i]; | ||
211 | if (func && func->irq_handler) { | ||
212 | card->sdio_single_irq = func; | ||
213 | break; | ||
214 | } | ||
215 | } | ||
216 | } | ||
217 | |||
189 | /** | 218 | /** |
190 | * sdio_claim_irq - claim the IRQ for a SDIO function | 219 | * sdio_claim_irq - claim the IRQ for a SDIO function |
191 | * @func: SDIO function | 220 | * @func: SDIO function |
@@ -227,6 +256,7 @@ int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) | |||
227 | ret = sdio_card_irq_get(func->card); | 256 | ret = sdio_card_irq_get(func->card); |
228 | if (ret) | 257 | if (ret) |
229 | func->irq_handler = NULL; | 258 | func->irq_handler = NULL; |
259 | sdio_single_irq_set(func->card); | ||
230 | 260 | ||
231 | return ret; | 261 | return ret; |
232 | } | 262 | } |
@@ -251,6 +281,7 @@ int sdio_release_irq(struct sdio_func *func) | |||
251 | if (func->irq_handler) { | 281 | if (func->irq_handler) { |
252 | func->irq_handler = NULL; | 282 | func->irq_handler = NULL; |
253 | sdio_card_irq_put(func->card); | 283 | sdio_card_irq_put(func->card); |
284 | sdio_single_irq_set(func->card); | ||
254 | } | 285 | } |
255 | 286 | ||
256 | ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, ®); | 287 | ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, ®); |