aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2010-11-24 05:05:12 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-11-25 02:26:30 -0500
commitaa0787a90c70587db6934547bb7687efc30062c7 (patch)
tree3875077ae94563c77db873381d25bc2214fa2e91 /drivers/mmc
parent2d3e4e7652f1db2de0fe8798a1a9be460ac9057b (diff)
mmc: sh_mmcif: switch to completion, fix flags
In sh_mmcif.c an event is used as a completion, switch over. When a wait_for_completion*_timeout() returns, it suffices to check the remaining time, setting an additional flag before waking up the waiting task only reduces the race window, but does not eliminate it. This patch switches the driver to use a completion to signal an interrupt, the only case, when an interrupt should not wake up the waiter, is when an automatic CMD12 completes. Also fix MODULE_ALIAS. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sh_mmcif.c117
1 files changed, 46 insertions, 71 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 3f492730ec05..74e7aca271d4 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -16,6 +16,8 @@
16 * 16 *
17 */ 17 */
18 18
19#include <linux/clk.h>
20#include <linux/completion.h>
19#include <linux/dma-mapping.h> 21#include <linux/dma-mapping.h>
20#include <linux/mmc/host.h> 22#include <linux/mmc/host.h>
21#include <linux/mmc/card.h> 23#include <linux/mmc/card.h>
@@ -24,7 +26,6 @@
24#include <linux/mmc/sdio.h> 26#include <linux/mmc/sdio.h>
25#include <linux/delay.h> 27#include <linux/delay.h>
26#include <linux/platform_device.h> 28#include <linux/platform_device.h>
27#include <linux/clk.h>
28#include <linux/mmc/sh_mmcif.h> 29#include <linux/mmc/sh_mmcif.h>
29 30
30#define DRIVER_NAME "sh_mmcif" 31#define DRIVER_NAME "sh_mmcif"
@@ -158,11 +159,10 @@ struct sh_mmcif_host {
158 struct clk *hclk; 159 struct clk *hclk;
159 unsigned int clk; 160 unsigned int clk;
160 int bus_width; 161 int bus_width;
161 u16 wait_int; 162 bool sd_error;
162 u16 sd_error;
163 long timeout; 163 long timeout;
164 void __iomem *addr; 164 void __iomem *addr;
165 wait_queue_head_t intr_wait; 165 struct completion intr_wait;
166}; 166};
167 167
168 168
@@ -216,8 +216,7 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
216 u32 state1, state2; 216 u32 state1, state2;
217 int ret, timeout = 10000000; 217 int ret, timeout = 10000000;
218 218
219 host->sd_error = 0; 219 host->sd_error = false;
220 host->wait_int = 0;
221 220
222 state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1); 221 state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1);
223 state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2); 222 state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2);
@@ -264,17 +263,13 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host,
264 long time; 263 long time;
265 u32 blocksize, i, *p = sg_virt(data->sg); 264 u32 blocksize, i, *p = sg_virt(data->sg);
266 265
267 host->wait_int = 0;
268
269 /* buf read enable */ 266 /* buf read enable */
270 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); 267 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
271 time = wait_event_interruptible_timeout(host->intr_wait, 268 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
272 host->wait_int == 1 || 269 host->timeout);
273 host->sd_error == 1, host->timeout); 270 if (time <= 0 || host->sd_error)
274 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
275 return sh_mmcif_error_manage(host); 271 return sh_mmcif_error_manage(host);
276 272
277 host->wait_int = 0;
278 blocksize = (BLOCK_SIZE_MASK & 273 blocksize = (BLOCK_SIZE_MASK &
279 sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; 274 sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
280 for (i = 0; i < blocksize / 4; i++) 275 for (i = 0; i < blocksize / 4; i++)
@@ -282,13 +277,11 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host,
282 277
283 /* buffer read end */ 278 /* buffer read end */
284 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); 279 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
285 time = wait_event_interruptible_timeout(host->intr_wait, 280 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
286 host->wait_int == 1 || 281 host->timeout);
287 host->sd_error == 1, host->timeout); 282 if (time <= 0 || host->sd_error)
288 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
289 return sh_mmcif_error_manage(host); 283 return sh_mmcif_error_manage(host);
290 284
291 host->wait_int = 0;
292 return 0; 285 return 0;
293} 286}
294 287
@@ -303,19 +296,15 @@ static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
303 MMCIF_CE_BLOCK_SET); 296 MMCIF_CE_BLOCK_SET);
304 for (j = 0; j < data->sg_len; j++) { 297 for (j = 0; j < data->sg_len; j++) {
305 p = sg_virt(data->sg); 298 p = sg_virt(data->sg);
306 host->wait_int = 0;
307 for (sec = 0; sec < data->sg->length / blocksize; sec++) { 299 for (sec = 0; sec < data->sg->length / blocksize; sec++) {
308 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); 300 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
309 /* buf read enable */ 301 /* buf read enable */
310 time = wait_event_interruptible_timeout(host->intr_wait, 302 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
311 host->wait_int == 1 || 303 host->timeout);
312 host->sd_error == 1, host->timeout);
313 304
314 if (host->wait_int != 1 && 305 if (time <= 0 || host->sd_error)
315 (time == 0 || host->sd_error != 0))
316 return sh_mmcif_error_manage(host); 306 return sh_mmcif_error_manage(host);
317 307
318 host->wait_int = 0;
319 for (i = 0; i < blocksize / 4; i++) 308 for (i = 0; i < blocksize / 4; i++)
320 *p++ = sh_mmcif_readl(host->addr, 309 *p++ = sh_mmcif_readl(host->addr,
321 MMCIF_CE_DATA); 310 MMCIF_CE_DATA);
@@ -333,17 +322,14 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host,
333 long time; 322 long time;
334 u32 blocksize, i, *p = sg_virt(data->sg); 323 u32 blocksize, i, *p = sg_virt(data->sg);
335 324
336 host->wait_int = 0;
337 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); 325 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
338 326
339 /* buf write enable */ 327 /* buf write enable */
340 time = wait_event_interruptible_timeout(host->intr_wait, 328 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
341 host->wait_int == 1 || 329 host->timeout);
342 host->sd_error == 1, host->timeout); 330 if (time <= 0 || host->sd_error)
343 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
344 return sh_mmcif_error_manage(host); 331 return sh_mmcif_error_manage(host);
345 332
346 host->wait_int = 0;
347 blocksize = (BLOCK_SIZE_MASK & 333 blocksize = (BLOCK_SIZE_MASK &
348 sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; 334 sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
349 for (i = 0; i < blocksize / 4; i++) 335 for (i = 0; i < blocksize / 4; i++)
@@ -352,13 +338,11 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host,
352 /* buffer write end */ 338 /* buffer write end */
353 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); 339 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
354 340
355 time = wait_event_interruptible_timeout(host->intr_wait, 341 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
356 host->wait_int == 1 || 342 host->timeout);
357 host->sd_error == 1, host->timeout); 343 if (time <= 0 || host->sd_error)
358 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
359 return sh_mmcif_error_manage(host); 344 return sh_mmcif_error_manage(host);
360 345
361 host->wait_int = 0;
362 return 0; 346 return 0;
363} 347}
364 348
@@ -374,19 +358,15 @@ static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
374 358
375 for (j = 0; j < data->sg_len; j++) { 359 for (j = 0; j < data->sg_len; j++) {
376 p = sg_virt(data->sg); 360 p = sg_virt(data->sg);
377 host->wait_int = 0;
378 for (sec = 0; sec < data->sg->length / blocksize; sec++) { 361 for (sec = 0; sec < data->sg->length / blocksize; sec++) {
379 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); 362 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
380 /* buf write enable*/ 363 /* buf write enable*/
381 time = wait_event_interruptible_timeout(host->intr_wait, 364 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
382 host->wait_int == 1 || 365 host->timeout);
383 host->sd_error == 1, host->timeout);
384 366
385 if (host->wait_int != 1 && 367 if (time <= 0 || host->sd_error)
386 (time == 0 || host->sd_error != 0))
387 return sh_mmcif_error_manage(host); 368 return sh_mmcif_error_manage(host);
388 369
389 host->wait_int = 0;
390 for (i = 0; i < blocksize / 4; i++) 370 for (i = 0; i < blocksize / 4; i++)
391 sh_mmcif_writel(host->addr, 371 sh_mmcif_writel(host->addr,
392 MMCIF_CE_DATA, *p++); 372 MMCIF_CE_DATA, *p++);
@@ -556,13 +536,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
556 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); 536 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
557 /* set arg */ 537 /* set arg */
558 sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); 538 sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
559 host->wait_int = 0;
560 /* set cmd */ 539 /* set cmd */
561 sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); 540 sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
562 541
563 time = wait_event_interruptible_timeout(host->intr_wait, 542 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
564 host->wait_int == 1 || host->sd_error == 1, host->timeout); 543 host->timeout);
565 if (host->wait_int != 1 && time == 0) { 544 if (time <= 0) {
566 cmd->error = sh_mmcif_error_manage(host); 545 cmd->error = sh_mmcif_error_manage(host);
567 return; 546 return;
568 } 547 }
@@ -579,19 +558,14 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
579 cmd->error = sh_mmcif_error_manage(host); 558 cmd->error = sh_mmcif_error_manage(host);
580 break; 559 break;
581 } 560 }
582 host->sd_error = 0; 561 host->sd_error = false;
583 host->wait_int = 0;
584 return; 562 return;
585 } 563 }
586 if (!(cmd->flags & MMC_RSP_PRESENT)) { 564 if (!(cmd->flags & MMC_RSP_PRESENT)) {
587 cmd->error = ret; 565 cmd->error = ret;
588 host->wait_int = 0;
589 return; 566 return;
590 } 567 }
591 if (host->wait_int == 1) { 568 sh_mmcif_get_response(host, cmd);
592 sh_mmcif_get_response(host, cmd);
593 host->wait_int = 0;
594 }
595 if (host->data) { 569 if (host->data) {
596 ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); 570 ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
597 if (ret < 0) 571 if (ret < 0)
@@ -618,15 +592,13 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
618 return; 592 return;
619 } 593 }
620 594
621 time = wait_event_interruptible_timeout(host->intr_wait, 595 time = wait_for_completion_interruptible_timeout(&host->intr_wait,
622 host->wait_int == 1 || 596 host->timeout);
623 host->sd_error == 1, host->timeout); 597 if (time <= 0 || host->sd_error) {
624 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) {
625 cmd->error = sh_mmcif_error_manage(host); 598 cmd->error = sh_mmcif_error_manage(host);
626 return; 599 return;
627 } 600 }
628 sh_mmcif_get_cmd12response(host, cmd); 601 sh_mmcif_get_cmd12response(host, cmd);
629 host->wait_int = 0;
630 cmd->error = 0; 602 cmd->error = 0;
631} 603}
632 604
@@ -712,7 +684,7 @@ static void sh_mmcif_detect(struct mmc_host *mmc)
712static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) 684static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
713{ 685{
714 struct sh_mmcif_host *host = dev_id; 686 struct sh_mmcif_host *host = dev_id;
715 u32 state = 0; 687 u32 state;
716 int err = 0; 688 int err = 0;
717 689
718 state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); 690 state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
@@ -757,11 +729,13 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
757 err = 1; 729 err = 1;
758 } 730 }
759 if (err) { 731 if (err) {
760 host->sd_error = 1; 732 host->sd_error = true;
761 pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state); 733 pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state);
762 } 734 }
763 host->wait_int = 1; 735 if (state & ~(INT_CMD12RBE | INT_CMD12CRE))
764 wake_up(&host->intr_wait); 736 complete(&host->intr_wait);
737 else
738 dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state);
765 739
766 return IRQ_HANDLED; 740 return IRQ_HANDLED;
767} 741}
@@ -819,7 +793,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
819 host->clk = clk_get_rate(host->hclk); 793 host->clk = clk_get_rate(host->hclk);
820 host->pd = pdev; 794 host->pd = pdev;
821 795
822 init_waitqueue_head(&host->intr_wait); 796 init_completion(&host->intr_wait);
823 797
824 mmc->ops = &sh_mmcif_ops; 798 mmc->ops = &sh_mmcif_ops;
825 mmc->f_max = host->clk; 799 mmc->f_max = host->clk;
@@ -880,20 +854,21 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
880 struct sh_mmcif_host *host = platform_get_drvdata(pdev); 854 struct sh_mmcif_host *host = platform_get_drvdata(pdev);
881 int irq[2]; 855 int irq[2];
882 856
883 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); 857 mmc_remove_host(host->mmc);
884
885 irq[0] = platform_get_irq(pdev, 0);
886 irq[1] = platform_get_irq(pdev, 1);
887 858
888 if (host->addr) 859 if (host->addr)
889 iounmap(host->addr); 860 iounmap(host->addr);
890 861
891 platform_set_drvdata(pdev, NULL); 862 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
892 mmc_remove_host(host->mmc); 863
864 irq[0] = platform_get_irq(pdev, 0);
865 irq[1] = platform_get_irq(pdev, 1);
893 866
894 free_irq(irq[0], host); 867 free_irq(irq[0], host);
895 free_irq(irq[1], host); 868 free_irq(irq[1], host);
896 869
870 platform_set_drvdata(pdev, NULL);
871
897 clk_disable(host->hclk); 872 clk_disable(host->hclk);
898 mmc_free_host(host->mmc); 873 mmc_free_host(host->mmc);
899 874
@@ -924,5 +899,5 @@ module_exit(sh_mmcif_exit);
924 899
925MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); 900MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver");
926MODULE_LICENSE("GPL"); 901MODULE_LICENSE("GPL");
927MODULE_ALIAS(DRIVER_NAME); 902MODULE_ALIAS("platform:" DRIVER_NAME);
928MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>"); 903MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>");