diff options
Diffstat (limited to 'drivers/memstick/host/tifm_ms.c')
-rw-r--r-- | drivers/memstick/host/tifm_ms.c | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 8577de4ebb0e..d32d6ad8f3fc 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c | |||
@@ -71,6 +71,7 @@ struct tifm_ms { | |||
71 | struct tifm_dev *dev; | 71 | struct tifm_dev *dev; |
72 | struct timer_list timer; | 72 | struct timer_list timer; |
73 | struct memstick_request *req; | 73 | struct memstick_request *req; |
74 | struct tasklet_struct notify; | ||
74 | unsigned int mode_mask; | 75 | unsigned int mode_mask; |
75 | unsigned int block_pos; | 76 | unsigned int block_pos; |
76 | unsigned long timeout_jiffies; | 77 | unsigned long timeout_jiffies; |
@@ -455,49 +456,51 @@ static void tifm_ms_card_event(struct tifm_dev *sock) | |||
455 | return; | 456 | return; |
456 | } | 457 | } |
457 | 458 | ||
458 | static void tifm_ms_request(struct memstick_host *msh) | 459 | static void tifm_ms_req_tasklet(unsigned long data) |
459 | { | 460 | { |
461 | struct memstick_host *msh = (struct memstick_host *)data; | ||
460 | struct tifm_ms *host = memstick_priv(msh); | 462 | struct tifm_ms *host = memstick_priv(msh); |
461 | struct tifm_dev *sock = host->dev; | 463 | struct tifm_dev *sock = host->dev; |
462 | unsigned long flags; | 464 | unsigned long flags; |
463 | int rc; | 465 | int rc; |
464 | 466 | ||
465 | spin_lock_irqsave(&sock->lock, flags); | 467 | spin_lock_irqsave(&sock->lock, flags); |
466 | if (host->req) { | 468 | if (!host->req) { |
467 | printk(KERN_ERR "%s : unfinished request detected\n", | 469 | if (host->eject) { |
468 | sock->dev.bus_id); | 470 | do { |
469 | spin_unlock_irqrestore(&sock->lock, flags); | 471 | rc = memstick_next_req(msh, &host->req); |
470 | tifm_eject(host->dev); | 472 | if (!rc) |
471 | return; | 473 | host->req->error = -ETIME; |
472 | } | 474 | } while (!rc); |
475 | spin_unlock_irqrestore(&sock->lock, flags); | ||
476 | return; | ||
477 | } | ||
473 | 478 | ||
474 | if (host->eject) { | ||
475 | do { | 479 | do { |
476 | rc = memstick_next_req(msh, &host->req); | 480 | rc = memstick_next_req(msh, &host->req); |
477 | if (!rc) | 481 | } while (!rc && tifm_ms_issue_cmd(host)); |
478 | host->req->error = -ETIME; | ||
479 | } while (!rc); | ||
480 | spin_unlock_irqrestore(&sock->lock, flags); | ||
481 | return; | ||
482 | } | 482 | } |
483 | |||
484 | do { | ||
485 | rc = memstick_next_req(msh, &host->req); | ||
486 | } while (!rc && tifm_ms_issue_cmd(host)); | ||
487 | |||
488 | spin_unlock_irqrestore(&sock->lock, flags); | 483 | spin_unlock_irqrestore(&sock->lock, flags); |
484 | } | ||
485 | |||
486 | static void tifm_ms_dummy_submit(struct memstick_host *msh) | ||
487 | { | ||
489 | return; | 488 | return; |
490 | } | 489 | } |
491 | 490 | ||
492 | static void tifm_ms_set_param(struct memstick_host *msh, | 491 | static void tifm_ms_submit_req(struct memstick_host *msh) |
493 | enum memstick_param param, | ||
494 | int value) | ||
495 | { | 492 | { |
496 | struct tifm_ms *host = memstick_priv(msh); | 493 | struct tifm_ms *host = memstick_priv(msh); |
497 | struct tifm_dev *sock = host->dev; | ||
498 | unsigned long flags; | ||
499 | 494 | ||
500 | spin_lock_irqsave(&sock->lock, flags); | 495 | tasklet_schedule(&host->notify); |
496 | } | ||
497 | |||
498 | static int tifm_ms_set_param(struct memstick_host *msh, | ||
499 | enum memstick_param param, | ||
500 | int value) | ||
501 | { | ||
502 | struct tifm_ms *host = memstick_priv(msh); | ||
503 | struct tifm_dev *sock = host->dev; | ||
501 | 504 | ||
502 | switch (param) { | 505 | switch (param) { |
503 | case MEMSTICK_POWER: | 506 | case MEMSTICK_POWER: |
@@ -512,7 +515,8 @@ static void tifm_ms_set_param(struct memstick_host *msh, | |||
512 | writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, | 515 | writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, |
513 | sock->addr + SOCK_MS_SYSTEM); | 516 | sock->addr + SOCK_MS_SYSTEM); |
514 | writel(0xffffffff, sock->addr + SOCK_MS_STATUS); | 517 | writel(0xffffffff, sock->addr + SOCK_MS_STATUS); |
515 | } | 518 | } else |
519 | return -EINVAL; | ||
516 | break; | 520 | break; |
517 | case MEMSTICK_INTERFACE: | 521 | case MEMSTICK_INTERFACE: |
518 | if (value == MEMSTICK_SERIAL) { | 522 | if (value == MEMSTICK_SERIAL) { |
@@ -525,11 +529,12 @@ static void tifm_ms_set_param(struct memstick_host *msh, | |||
525 | writel(TIFM_CTRL_FAST_CLK | 529 | writel(TIFM_CTRL_FAST_CLK |
526 | | readl(sock->addr + SOCK_CONTROL), | 530 | | readl(sock->addr + SOCK_CONTROL), |
527 | sock->addr + SOCK_CONTROL); | 531 | sock->addr + SOCK_CONTROL); |
528 | } | 532 | } else |
533 | return -EINVAL; | ||
529 | break; | 534 | break; |
530 | }; | 535 | }; |
531 | 536 | ||
532 | spin_unlock_irqrestore(&sock->lock, flags); | 537 | return 0; |
533 | } | 538 | } |
534 | 539 | ||
535 | static void tifm_ms_abort(unsigned long data) | 540 | static void tifm_ms_abort(unsigned long data) |
@@ -570,8 +575,9 @@ static int tifm_ms_probe(struct tifm_dev *sock) | |||
570 | host->timeout_jiffies = msecs_to_jiffies(1000); | 575 | host->timeout_jiffies = msecs_to_jiffies(1000); |
571 | 576 | ||
572 | setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); | 577 | setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); |
578 | tasklet_init(&host->notify, tifm_ms_req_tasklet, (unsigned long)msh); | ||
573 | 579 | ||
574 | msh->request = tifm_ms_request; | 580 | msh->request = tifm_ms_submit_req; |
575 | msh->set_param = tifm_ms_set_param; | 581 | msh->set_param = tifm_ms_set_param; |
576 | sock->card_event = tifm_ms_card_event; | 582 | sock->card_event = tifm_ms_card_event; |
577 | sock->data_event = tifm_ms_data_event; | 583 | sock->data_event = tifm_ms_data_event; |
@@ -593,6 +599,8 @@ static void tifm_ms_remove(struct tifm_dev *sock) | |||
593 | int rc = 0; | 599 | int rc = 0; |
594 | unsigned long flags; | 600 | unsigned long flags; |
595 | 601 | ||
602 | msh->request = tifm_ms_dummy_submit; | ||
603 | tasklet_kill(&host->notify); | ||
596 | spin_lock_irqsave(&sock->lock, flags); | 604 | spin_lock_irqsave(&sock->lock, flags); |
597 | host->eject = 1; | 605 | host->eject = 1; |
598 | if (host->req) { | 606 | if (host->req) { |