diff options
Diffstat (limited to 'drivers/memstick')
-rw-r--r-- | drivers/memstick/core/memstick.c | 36 | ||||
-rw-r--r-- | drivers/memstick/core/mspro_block.c | 365 | ||||
-rw-r--r-- | drivers/memstick/host/jmb38x_ms.c | 106 | ||||
-rw-r--r-- | drivers/memstick/host/tifm_ms.c | 66 |
4 files changed, 325 insertions, 248 deletions
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 61b98c333cb0..a38005008a20 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c | |||
@@ -249,8 +249,11 @@ EXPORT_SYMBOL(memstick_next_req); | |||
249 | */ | 249 | */ |
250 | void memstick_new_req(struct memstick_host *host) | 250 | void memstick_new_req(struct memstick_host *host) |
251 | { | 251 | { |
252 | host->retries = cmd_retries; | 252 | if (host->card) { |
253 | host->request(host); | 253 | host->retries = cmd_retries; |
254 | INIT_COMPLETION(host->card->mrq_complete); | ||
255 | host->request(host); | ||
256 | } | ||
254 | } | 257 | } |
255 | EXPORT_SYMBOL(memstick_new_req); | 258 | EXPORT_SYMBOL(memstick_new_req); |
256 | 259 | ||
@@ -415,10 +418,14 @@ err_out: | |||
415 | return NULL; | 418 | return NULL; |
416 | } | 419 | } |
417 | 420 | ||
418 | static void memstick_power_on(struct memstick_host *host) | 421 | static int memstick_power_on(struct memstick_host *host) |
419 | { | 422 | { |
420 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); | 423 | int rc = host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); |
421 | host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); | 424 | |
425 | if (!rc) | ||
426 | rc = host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); | ||
427 | |||
428 | return rc; | ||
422 | } | 429 | } |
423 | 430 | ||
424 | static void memstick_check(struct work_struct *work) | 431 | static void memstick_check(struct work_struct *work) |
@@ -429,8 +436,11 @@ static void memstick_check(struct work_struct *work) | |||
429 | 436 | ||
430 | dev_dbg(&host->dev, "memstick_check started\n"); | 437 | dev_dbg(&host->dev, "memstick_check started\n"); |
431 | mutex_lock(&host->lock); | 438 | mutex_lock(&host->lock); |
432 | if (!host->card) | 439 | if (!host->card) { |
433 | memstick_power_on(host); | 440 | if (memstick_power_on(host)) |
441 | goto out_power_off; | ||
442 | } else | ||
443 | host->card->stop(host->card); | ||
434 | 444 | ||
435 | card = memstick_alloc_card(host); | 445 | card = memstick_alloc_card(host); |
436 | 446 | ||
@@ -448,7 +458,8 @@ static void memstick_check(struct work_struct *work) | |||
448 | || !(host->card->check(host->card))) { | 458 | || !(host->card->check(host->card))) { |
449 | device_unregister(&host->card->dev); | 459 | device_unregister(&host->card->dev); |
450 | host->card = NULL; | 460 | host->card = NULL; |
451 | } | 461 | } else |
462 | host->card->start(host->card); | ||
452 | } | 463 | } |
453 | 464 | ||
454 | if (!host->card) { | 465 | if (!host->card) { |
@@ -461,6 +472,7 @@ static void memstick_check(struct work_struct *work) | |||
461 | kfree(card); | 472 | kfree(card); |
462 | } | 473 | } |
463 | 474 | ||
475 | out_power_off: | ||
464 | if (!host->card) | 476 | if (!host->card) |
465 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); | 477 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); |
466 | 478 | ||
@@ -573,11 +585,15 @@ EXPORT_SYMBOL(memstick_suspend_host); | |||
573 | */ | 585 | */ |
574 | void memstick_resume_host(struct memstick_host *host) | 586 | void memstick_resume_host(struct memstick_host *host) |
575 | { | 587 | { |
588 | int rc = 0; | ||
589 | |||
576 | mutex_lock(&host->lock); | 590 | mutex_lock(&host->lock); |
577 | if (host->card) | 591 | if (host->card) |
578 | memstick_power_on(host); | 592 | rc = memstick_power_on(host); |
579 | mutex_unlock(&host->lock); | 593 | mutex_unlock(&host->lock); |
580 | memstick_detect_change(host); | 594 | |
595 | if (!rc) | ||
596 | memstick_detect_change(host); | ||
581 | } | 597 | } |
582 | EXPORT_SYMBOL(memstick_resume_host); | 598 | EXPORT_SYMBOL(memstick_resume_host); |
583 | 599 | ||
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 477d0fb6e588..44b1817f2f2f 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
@@ -136,9 +136,8 @@ struct mspro_block_data { | |||
136 | unsigned int caps; | 136 | unsigned int caps; |
137 | struct gendisk *disk; | 137 | struct gendisk *disk; |
138 | struct request_queue *queue; | 138 | struct request_queue *queue; |
139 | struct request *block_req; | ||
139 | spinlock_t q_lock; | 140 | spinlock_t q_lock; |
140 | wait_queue_head_t q_wait; | ||
141 | struct task_struct *q_thread; | ||
142 | 141 | ||
143 | unsigned short page_size; | 142 | unsigned short page_size; |
144 | unsigned short cylinders; | 143 | unsigned short cylinders; |
@@ -147,9 +146,10 @@ struct mspro_block_data { | |||
147 | 146 | ||
148 | unsigned char system; | 147 | unsigned char system; |
149 | unsigned char read_only:1, | 148 | unsigned char read_only:1, |
150 | active:1, | 149 | eject:1, |
151 | has_request:1, | 150 | has_request:1, |
152 | data_dir:1; | 151 | data_dir:1, |
152 | active:1; | ||
153 | unsigned char transfer_cmd; | 153 | unsigned char transfer_cmd; |
154 | 154 | ||
155 | int (*mrq_handler)(struct memstick_dev *card, | 155 | int (*mrq_handler)(struct memstick_dev *card, |
@@ -160,12 +160,14 @@ struct mspro_block_data { | |||
160 | struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; | 160 | struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; |
161 | unsigned int seg_count; | 161 | unsigned int seg_count; |
162 | unsigned int current_seg; | 162 | unsigned int current_seg; |
163 | unsigned short current_page; | 163 | unsigned int current_page; |
164 | }; | 164 | }; |
165 | 165 | ||
166 | static DEFINE_IDR(mspro_block_disk_idr); | 166 | static DEFINE_IDR(mspro_block_disk_idr); |
167 | static DEFINE_MUTEX(mspro_block_disk_lock); | 167 | static DEFINE_MUTEX(mspro_block_disk_lock); |
168 | 168 | ||
169 | static int mspro_block_complete_req(struct memstick_dev *card, int error); | ||
170 | |||
169 | /*** Block device ***/ | 171 | /*** Block device ***/ |
170 | 172 | ||
171 | static int mspro_block_bd_open(struct inode *inode, struct file *filp) | 173 | static int mspro_block_bd_open(struct inode *inode, struct file *filp) |
@@ -197,8 +199,10 @@ static int mspro_block_disk_release(struct gendisk *disk) | |||
197 | 199 | ||
198 | mutex_lock(&mspro_block_disk_lock); | 200 | mutex_lock(&mspro_block_disk_lock); |
199 | 201 | ||
200 | if (msb->usage_count) { | 202 | if (msb) { |
201 | msb->usage_count--; | 203 | if (msb->usage_count) |
204 | msb->usage_count--; | ||
205 | |||
202 | if (!msb->usage_count) { | 206 | if (!msb->usage_count) { |
203 | kfree(msb); | 207 | kfree(msb); |
204 | disk->private_data = NULL; | 208 | disk->private_data = NULL; |
@@ -523,11 +527,13 @@ static int h_mspro_block_req_init(struct memstick_dev *card, | |||
523 | static int h_mspro_block_default(struct memstick_dev *card, | 527 | static int h_mspro_block_default(struct memstick_dev *card, |
524 | struct memstick_request **mrq) | 528 | struct memstick_request **mrq) |
525 | { | 529 | { |
526 | complete(&card->mrq_complete); | 530 | return mspro_block_complete_req(card, (*mrq)->error); |
527 | if (!(*mrq)->error) | 531 | } |
528 | return -EAGAIN; | 532 | |
529 | else | 533 | static int h_mspro_block_default_bad(struct memstick_dev *card, |
530 | return (*mrq)->error; | 534 | struct memstick_request **mrq) |
535 | { | ||
536 | return -ENXIO; | ||
531 | } | 537 | } |
532 | 538 | ||
533 | static int h_mspro_block_get_ro(struct memstick_dev *card, | 539 | static int h_mspro_block_get_ro(struct memstick_dev *card, |
@@ -535,44 +541,30 @@ static int h_mspro_block_get_ro(struct memstick_dev *card, | |||
535 | { | 541 | { |
536 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 542 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
537 | 543 | ||
538 | if ((*mrq)->error) { | 544 | if (!(*mrq)->error) { |
539 | complete(&card->mrq_complete); | 545 | if ((*mrq)->data[offsetof(struct ms_status_register, status0)] |
540 | return (*mrq)->error; | 546 | & MEMSTICK_STATUS0_WP) |
547 | msb->read_only = 1; | ||
548 | else | ||
549 | msb->read_only = 0; | ||
541 | } | 550 | } |
542 | 551 | ||
543 | if ((*mrq)->data[offsetof(struct ms_status_register, status0)] | 552 | return mspro_block_complete_req(card, (*mrq)->error); |
544 | & MEMSTICK_STATUS0_WP) | ||
545 | msb->read_only = 1; | ||
546 | else | ||
547 | msb->read_only = 0; | ||
548 | |||
549 | complete(&card->mrq_complete); | ||
550 | return -EAGAIN; | ||
551 | } | 553 | } |
552 | 554 | ||
553 | static int h_mspro_block_wait_for_ced(struct memstick_dev *card, | 555 | static int h_mspro_block_wait_for_ced(struct memstick_dev *card, |
554 | struct memstick_request **mrq) | 556 | struct memstick_request **mrq) |
555 | { | 557 | { |
556 | if ((*mrq)->error) { | ||
557 | complete(&card->mrq_complete); | ||
558 | return (*mrq)->error; | ||
559 | } | ||
560 | |||
561 | dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]); | 558 | dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]); |
562 | 559 | ||
563 | if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) { | 560 | if (!(*mrq)->error) { |
564 | card->current_mrq.error = -EFAULT; | 561 | if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) |
565 | complete(&card->mrq_complete); | 562 | (*mrq)->error = -EFAULT; |
566 | return card->current_mrq.error; | 563 | else if (!((*mrq)->data[0] & MEMSTICK_INT_CED)) |
564 | return 0; | ||
567 | } | 565 | } |
568 | 566 | ||
569 | if (!((*mrq)->data[0] & MEMSTICK_INT_CED)) | 567 | return mspro_block_complete_req(card, (*mrq)->error); |
570 | return 0; | ||
571 | else { | ||
572 | card->current_mrq.error = 0; | ||
573 | complete(&card->mrq_complete); | ||
574 | return -EAGAIN; | ||
575 | } | ||
576 | } | 568 | } |
577 | 569 | ||
578 | static int h_mspro_block_transfer_data(struct memstick_dev *card, | 570 | static int h_mspro_block_transfer_data(struct memstick_dev *card, |
@@ -583,10 +575,8 @@ static int h_mspro_block_transfer_data(struct memstick_dev *card, | |||
583 | struct scatterlist t_sg = { 0 }; | 575 | struct scatterlist t_sg = { 0 }; |
584 | size_t t_offset; | 576 | size_t t_offset; |
585 | 577 | ||
586 | if ((*mrq)->error) { | 578 | if ((*mrq)->error) |
587 | complete(&card->mrq_complete); | 579 | return mspro_block_complete_req(card, (*mrq)->error); |
588 | return (*mrq)->error; | ||
589 | } | ||
590 | 580 | ||
591 | switch ((*mrq)->tpc) { | 581 | switch ((*mrq)->tpc) { |
592 | case MS_TPC_WRITE_REG: | 582 | case MS_TPC_WRITE_REG: |
@@ -617,8 +607,8 @@ has_int_reg: | |||
617 | 607 | ||
618 | if (msb->current_seg == msb->seg_count) { | 608 | if (msb->current_seg == msb->seg_count) { |
619 | if (t_val & MEMSTICK_INT_CED) { | 609 | if (t_val & MEMSTICK_INT_CED) { |
620 | complete(&card->mrq_complete); | 610 | return mspro_block_complete_req(card, |
621 | return -EAGAIN; | 611 | 0); |
622 | } else { | 612 | } else { |
623 | card->next_request | 613 | card->next_request |
624 | = h_mspro_block_wait_for_ced; | 614 | = h_mspro_block_wait_for_ced; |
@@ -666,140 +656,184 @@ has_int_reg: | |||
666 | 656 | ||
667 | /*** Data transfer ***/ | 657 | /*** Data transfer ***/ |
668 | 658 | ||
669 | static void mspro_block_process_request(struct memstick_dev *card, | 659 | static int mspro_block_issue_req(struct memstick_dev *card, int chunk) |
670 | struct request *req) | ||
671 | { | 660 | { |
672 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 661 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
673 | struct mspro_param_register param; | ||
674 | int rc, chunk, cnt; | ||
675 | unsigned short page_count; | ||
676 | sector_t t_sec; | 662 | sector_t t_sec; |
677 | unsigned long flags; | 663 | unsigned int count; |
664 | struct mspro_param_register param; | ||
678 | 665 | ||
679 | do { | 666 | try_again: |
680 | page_count = 0; | 667 | while (chunk) { |
668 | msb->current_page = 0; | ||
681 | msb->current_seg = 0; | 669 | msb->current_seg = 0; |
682 | msb->seg_count = blk_rq_map_sg(req->q, req, msb->req_sg); | 670 | msb->seg_count = blk_rq_map_sg(msb->block_req->q, |
671 | msb->block_req, | ||
672 | msb->req_sg); | ||
683 | 673 | ||
684 | if (msb->seg_count) { | 674 | if (!msb->seg_count) { |
685 | msb->current_page = 0; | 675 | chunk = __blk_end_request(msb->block_req, -ENOMEM, |
686 | for (rc = 0; rc < msb->seg_count; rc++) | 676 | blk_rq_cur_bytes(msb->block_req)); |
687 | page_count += msb->req_sg[rc].length | 677 | continue; |
688 | / msb->page_size; | 678 | } |
689 | |||
690 | t_sec = req->sector; | ||
691 | sector_div(t_sec, msb->page_size >> 9); | ||
692 | param.system = msb->system; | ||
693 | param.data_count = cpu_to_be16(page_count); | ||
694 | param.data_address = cpu_to_be32((uint32_t)t_sec); | ||
695 | param.tpc_param = 0; | ||
696 | |||
697 | msb->data_dir = rq_data_dir(req); | ||
698 | msb->transfer_cmd = msb->data_dir == READ | ||
699 | ? MSPRO_CMD_READ_DATA | ||
700 | : MSPRO_CMD_WRITE_DATA; | ||
701 | |||
702 | dev_dbg(&card->dev, "data transfer: cmd %x, " | ||
703 | "lba %x, count %x\n", msb->transfer_cmd, | ||
704 | be32_to_cpu(param.data_address), | ||
705 | page_count); | ||
706 | |||
707 | card->next_request = h_mspro_block_req_init; | ||
708 | msb->mrq_handler = h_mspro_block_transfer_data; | ||
709 | memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, | ||
710 | ¶m, sizeof(param)); | ||
711 | memstick_new_req(card->host); | ||
712 | wait_for_completion(&card->mrq_complete); | ||
713 | rc = card->current_mrq.error; | ||
714 | 679 | ||
715 | if (rc || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { | 680 | t_sec = msb->block_req->sector << 9; |
716 | for (cnt = 0; cnt < msb->current_seg; cnt++) | 681 | sector_div(t_sec, msb->page_size); |
717 | page_count += msb->req_sg[cnt].length | ||
718 | / msb->page_size; | ||
719 | |||
720 | if (msb->current_page) | ||
721 | page_count += msb->current_page - 1; | ||
722 | |||
723 | if (page_count && (msb->data_dir == READ)) | ||
724 | rc = msb->page_size * page_count; | ||
725 | else | ||
726 | rc = -EIO; | ||
727 | } else | ||
728 | rc = msb->page_size * page_count; | ||
729 | } else | ||
730 | rc = -EFAULT; | ||
731 | 682 | ||
732 | spin_lock_irqsave(&msb->q_lock, flags); | 683 | count = msb->block_req->nr_sectors << 9; |
733 | if (rc >= 0) | 684 | count /= msb->page_size; |
734 | chunk = __blk_end_request(req, 0, rc); | ||
735 | else | ||
736 | chunk = __blk_end_request(req, rc, 0); | ||
737 | 685 | ||
738 | dev_dbg(&card->dev, "end chunk %d, %d\n", rc, chunk); | 686 | param.system = msb->system; |
739 | spin_unlock_irqrestore(&msb->q_lock, flags); | 687 | param.data_count = cpu_to_be16(count); |
740 | } while (chunk); | 688 | param.data_address = cpu_to_be32((uint32_t)t_sec); |
689 | param.tpc_param = 0; | ||
690 | |||
691 | msb->data_dir = rq_data_dir(msb->block_req); | ||
692 | msb->transfer_cmd = msb->data_dir == READ | ||
693 | ? MSPRO_CMD_READ_DATA | ||
694 | : MSPRO_CMD_WRITE_DATA; | ||
695 | |||
696 | dev_dbg(&card->dev, "data transfer: cmd %x, " | ||
697 | "lba %x, count %x\n", msb->transfer_cmd, | ||
698 | be32_to_cpu(param.data_address), count); | ||
699 | |||
700 | card->next_request = h_mspro_block_req_init; | ||
701 | msb->mrq_handler = h_mspro_block_transfer_data; | ||
702 | memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, | ||
703 | ¶m, sizeof(param)); | ||
704 | memstick_new_req(card->host); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | dev_dbg(&card->dev, "elv_next\n"); | ||
709 | msb->block_req = elv_next_request(msb->queue); | ||
710 | if (!msb->block_req) { | ||
711 | dev_dbg(&card->dev, "issue end\n"); | ||
712 | return -EAGAIN; | ||
713 | } | ||
714 | |||
715 | dev_dbg(&card->dev, "trying again\n"); | ||
716 | chunk = 1; | ||
717 | goto try_again; | ||
741 | } | 718 | } |
742 | 719 | ||
743 | static int mspro_block_has_request(struct mspro_block_data *msb) | 720 | static int mspro_block_complete_req(struct memstick_dev *card, int error) |
744 | { | 721 | { |
745 | int rc = 0; | 722 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
723 | int chunk, cnt; | ||
724 | unsigned int t_len = 0; | ||
746 | unsigned long flags; | 725 | unsigned long flags; |
747 | 726 | ||
748 | spin_lock_irqsave(&msb->q_lock, flags); | 727 | spin_lock_irqsave(&msb->q_lock, flags); |
749 | if (kthread_should_stop() || msb->has_request) | 728 | dev_dbg(&card->dev, "complete %d, %d\n", msb->has_request ? 1 : 0, |
750 | rc = 1; | 729 | error); |
730 | |||
731 | if (msb->has_request) { | ||
732 | /* Nothing to do - not really an error */ | ||
733 | if (error == -EAGAIN) | ||
734 | error = 0; | ||
735 | |||
736 | if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { | ||
737 | if (msb->data_dir == READ) { | ||
738 | for (cnt = 0; cnt < msb->current_seg; cnt++) | ||
739 | t_len += msb->req_sg[cnt].length | ||
740 | / msb->page_size; | ||
741 | |||
742 | if (msb->current_page) | ||
743 | t_len += msb->current_page - 1; | ||
744 | |||
745 | t_len *= msb->page_size; | ||
746 | } | ||
747 | } else | ||
748 | t_len = msb->block_req->nr_sectors << 9; | ||
749 | |||
750 | dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error); | ||
751 | |||
752 | if (error && !t_len) | ||
753 | t_len = blk_rq_cur_bytes(msb->block_req); | ||
754 | |||
755 | chunk = __blk_end_request(msb->block_req, error, t_len); | ||
756 | |||
757 | error = mspro_block_issue_req(card, chunk); | ||
758 | |||
759 | if (!error) | ||
760 | goto out; | ||
761 | else | ||
762 | msb->has_request = 0; | ||
763 | } else { | ||
764 | if (!error) | ||
765 | error = -EAGAIN; | ||
766 | } | ||
767 | |||
768 | card->next_request = h_mspro_block_default_bad; | ||
769 | complete_all(&card->mrq_complete); | ||
770 | out: | ||
751 | spin_unlock_irqrestore(&msb->q_lock, flags); | 771 | spin_unlock_irqrestore(&msb->q_lock, flags); |
752 | return rc; | 772 | return error; |
753 | } | 773 | } |
754 | 774 | ||
755 | static int mspro_block_queue_thread(void *data) | 775 | static void mspro_block_stop(struct memstick_dev *card) |
756 | { | 776 | { |
757 | struct memstick_dev *card = data; | ||
758 | struct memstick_host *host = card->host; | ||
759 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 777 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
760 | struct request *req; | 778 | int rc = 0; |
761 | unsigned long flags; | 779 | unsigned long flags; |
762 | 780 | ||
763 | while (1) { | 781 | while (1) { |
764 | wait_event(msb->q_wait, mspro_block_has_request(msb)); | ||
765 | dev_dbg(&card->dev, "thread iter\n"); | ||
766 | |||
767 | spin_lock_irqsave(&msb->q_lock, flags); | 782 | spin_lock_irqsave(&msb->q_lock, flags); |
768 | req = elv_next_request(msb->queue); | 783 | if (!msb->has_request) { |
769 | dev_dbg(&card->dev, "next req %p\n", req); | 784 | blk_stop_queue(msb->queue); |
770 | if (!req) { | 785 | rc = 1; |
771 | msb->has_request = 0; | 786 | } |
772 | if (kthread_should_stop()) { | ||
773 | spin_unlock_irqrestore(&msb->q_lock, flags); | ||
774 | break; | ||
775 | } | ||
776 | } else | ||
777 | msb->has_request = 1; | ||
778 | spin_unlock_irqrestore(&msb->q_lock, flags); | 787 | spin_unlock_irqrestore(&msb->q_lock, flags); |
779 | 788 | ||
780 | if (req) { | 789 | if (rc) |
781 | mutex_lock(&host->lock); | 790 | break; |
782 | mspro_block_process_request(card, req); | 791 | |
783 | mutex_unlock(&host->lock); | 792 | wait_for_completion(&card->mrq_complete); |
784 | } | ||
785 | } | 793 | } |
786 | dev_dbg(&card->dev, "thread finished\n"); | ||
787 | return 0; | ||
788 | } | 794 | } |
789 | 795 | ||
790 | static void mspro_block_request(struct request_queue *q) | 796 | static void mspro_block_start(struct memstick_dev *card) |
797 | { | ||
798 | struct mspro_block_data *msb = memstick_get_drvdata(card); | ||
799 | unsigned long flags; | ||
800 | |||
801 | spin_lock_irqsave(&msb->q_lock, flags); | ||
802 | blk_start_queue(msb->queue); | ||
803 | spin_unlock_irqrestore(&msb->q_lock, flags); | ||
804 | } | ||
805 | |||
806 | static int mspro_block_prepare_req(struct request_queue *q, struct request *req) | ||
807 | { | ||
808 | if (!blk_fs_request(req) && !blk_pc_request(req)) { | ||
809 | blk_dump_rq_flags(req, "MSPro unsupported request"); | ||
810 | return BLKPREP_KILL; | ||
811 | } | ||
812 | |||
813 | req->cmd_flags |= REQ_DONTPREP; | ||
814 | |||
815 | return BLKPREP_OK; | ||
816 | } | ||
817 | |||
818 | static void mspro_block_submit_req(struct request_queue *q) | ||
791 | { | 819 | { |
792 | struct memstick_dev *card = q->queuedata; | 820 | struct memstick_dev *card = q->queuedata; |
793 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 821 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
794 | struct request *req = NULL; | 822 | struct request *req = NULL; |
795 | 823 | ||
796 | if (msb->q_thread) { | 824 | if (msb->has_request) |
797 | msb->has_request = 1; | 825 | return; |
798 | wake_up_all(&msb->q_wait); | 826 | |
799 | } else { | 827 | if (msb->eject) { |
800 | while ((req = elv_next_request(q)) != NULL) | 828 | while ((req = elv_next_request(q)) != NULL) |
801 | end_queued_request(req, -ENODEV); | 829 | end_queued_request(req, -ENODEV); |
830 | |||
831 | return; | ||
802 | } | 832 | } |
833 | |||
834 | msb->has_request = 1; | ||
835 | if (mspro_block_issue_req(card, 0)) | ||
836 | msb->has_request = 0; | ||
803 | } | 837 | } |
804 | 838 | ||
805 | /*** Initialization ***/ | 839 | /*** Initialization ***/ |
@@ -1169,16 +1203,14 @@ static int mspro_block_init_disk(struct memstick_dev *card) | |||
1169 | goto out_release_id; | 1203 | goto out_release_id; |
1170 | } | 1204 | } |
1171 | 1205 | ||
1172 | spin_lock_init(&msb->q_lock); | 1206 | msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock); |
1173 | init_waitqueue_head(&msb->q_wait); | ||
1174 | |||
1175 | msb->queue = blk_init_queue(mspro_block_request, &msb->q_lock); | ||
1176 | if (!msb->queue) { | 1207 | if (!msb->queue) { |
1177 | rc = -ENOMEM; | 1208 | rc = -ENOMEM; |
1178 | goto out_put_disk; | 1209 | goto out_put_disk; |
1179 | } | 1210 | } |
1180 | 1211 | ||
1181 | msb->queue->queuedata = card; | 1212 | msb->queue->queuedata = card; |
1213 | blk_queue_prep_rq(msb->queue, mspro_block_prepare_req); | ||
1182 | 1214 | ||
1183 | blk_queue_bounce_limit(msb->queue, limit); | 1215 | blk_queue_bounce_limit(msb->queue, limit); |
1184 | blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); | 1216 | blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); |
@@ -1204,14 +1236,8 @@ static int mspro_block_init_disk(struct memstick_dev *card) | |||
1204 | capacity *= msb->page_size >> 9; | 1236 | capacity *= msb->page_size >> 9; |
1205 | set_capacity(msb->disk, capacity); | 1237 | set_capacity(msb->disk, capacity); |
1206 | dev_dbg(&card->dev, "capacity set %ld\n", capacity); | 1238 | dev_dbg(&card->dev, "capacity set %ld\n", capacity); |
1207 | msb->q_thread = kthread_run(mspro_block_queue_thread, card, | ||
1208 | DRIVER_NAME"d"); | ||
1209 | if (IS_ERR(msb->q_thread)) | ||
1210 | goto out_put_disk; | ||
1211 | 1239 | ||
1212 | mutex_unlock(&host->lock); | ||
1213 | add_disk(msb->disk); | 1240 | add_disk(msb->disk); |
1214 | mutex_lock(&host->lock); | ||
1215 | msb->active = 1; | 1241 | msb->active = 1; |
1216 | return 0; | 1242 | return 0; |
1217 | 1243 | ||
@@ -1259,6 +1285,7 @@ static int mspro_block_probe(struct memstick_dev *card) | |||
1259 | return -ENOMEM; | 1285 | return -ENOMEM; |
1260 | memstick_set_drvdata(card, msb); | 1286 | memstick_set_drvdata(card, msb); |
1261 | msb->card = card; | 1287 | msb->card = card; |
1288 | spin_lock_init(&msb->q_lock); | ||
1262 | 1289 | ||
1263 | rc = mspro_block_init_card(card); | 1290 | rc = mspro_block_init_card(card); |
1264 | 1291 | ||
@@ -1272,6 +1299,8 @@ static int mspro_block_probe(struct memstick_dev *card) | |||
1272 | rc = mspro_block_init_disk(card); | 1299 | rc = mspro_block_init_disk(card); |
1273 | if (!rc) { | 1300 | if (!rc) { |
1274 | card->check = mspro_block_check_card; | 1301 | card->check = mspro_block_check_card; |
1302 | card->stop = mspro_block_stop; | ||
1303 | card->start = mspro_block_start; | ||
1275 | return 0; | 1304 | return 0; |
1276 | } | 1305 | } |
1277 | 1306 | ||
@@ -1286,26 +1315,17 @@ out_free: | |||
1286 | static void mspro_block_remove(struct memstick_dev *card) | 1315 | static void mspro_block_remove(struct memstick_dev *card) |
1287 | { | 1316 | { |
1288 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 1317 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
1289 | struct task_struct *q_thread = NULL; | ||
1290 | unsigned long flags; | 1318 | unsigned long flags; |
1291 | 1319 | ||
1292 | del_gendisk(msb->disk); | 1320 | del_gendisk(msb->disk); |
1293 | dev_dbg(&card->dev, "mspro block remove\n"); | 1321 | dev_dbg(&card->dev, "mspro block remove\n"); |
1294 | spin_lock_irqsave(&msb->q_lock, flags); | 1322 | spin_lock_irqsave(&msb->q_lock, flags); |
1295 | q_thread = msb->q_thread; | 1323 | msb->eject = 1; |
1296 | msb->q_thread = NULL; | 1324 | blk_start_queue(msb->queue); |
1297 | msb->active = 0; | ||
1298 | spin_unlock_irqrestore(&msb->q_lock, flags); | 1325 | spin_unlock_irqrestore(&msb->q_lock, flags); |
1299 | 1326 | ||
1300 | if (q_thread) { | ||
1301 | mutex_unlock(&card->host->lock); | ||
1302 | kthread_stop(q_thread); | ||
1303 | mutex_lock(&card->host->lock); | ||
1304 | } | ||
1305 | |||
1306 | dev_dbg(&card->dev, "queue thread stopped\n"); | ||
1307 | |||
1308 | blk_cleanup_queue(msb->queue); | 1327 | blk_cleanup_queue(msb->queue); |
1328 | msb->queue = NULL; | ||
1309 | 1329 | ||
1310 | sysfs_remove_group(&card->dev.kobj, &msb->attr_group); | 1330 | sysfs_remove_group(&card->dev.kobj, &msb->attr_group); |
1311 | 1331 | ||
@@ -1322,19 +1342,13 @@ static void mspro_block_remove(struct memstick_dev *card) | |||
1322 | static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) | 1342 | static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) |
1323 | { | 1343 | { |
1324 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 1344 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
1325 | struct task_struct *q_thread = NULL; | ||
1326 | unsigned long flags; | 1345 | unsigned long flags; |
1327 | 1346 | ||
1328 | spin_lock_irqsave(&msb->q_lock, flags); | 1347 | spin_lock_irqsave(&msb->q_lock, flags); |
1329 | q_thread = msb->q_thread; | ||
1330 | msb->q_thread = NULL; | ||
1331 | msb->active = 0; | ||
1332 | blk_stop_queue(msb->queue); | 1348 | blk_stop_queue(msb->queue); |
1349 | msb->active = 0; | ||
1333 | spin_unlock_irqrestore(&msb->q_lock, flags); | 1350 | spin_unlock_irqrestore(&msb->q_lock, flags); |
1334 | 1351 | ||
1335 | if (q_thread) | ||
1336 | kthread_stop(q_thread); | ||
1337 | |||
1338 | return 0; | 1352 | return 0; |
1339 | } | 1353 | } |
1340 | 1354 | ||
@@ -1373,14 +1387,7 @@ static int mspro_block_resume(struct memstick_dev *card) | |||
1373 | if (memcmp(s_attr->data, r_attr->data, s_attr->size)) | 1387 | if (memcmp(s_attr->data, r_attr->data, s_attr->size)) |
1374 | break; | 1388 | break; |
1375 | 1389 | ||
1376 | memstick_set_drvdata(card, msb); | 1390 | msb->active = 1; |
1377 | msb->q_thread = kthread_run(mspro_block_queue_thread, | ||
1378 | card, DRIVER_NAME"d"); | ||
1379 | if (IS_ERR(msb->q_thread)) | ||
1380 | msb->q_thread = NULL; | ||
1381 | else | ||
1382 | msb->active = 1; | ||
1383 | |||
1384 | break; | 1391 | break; |
1385 | } | 1392 | } |
1386 | } | 1393 | } |
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index a054668eda16..3485c63d20b0 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c | |||
@@ -50,8 +50,9 @@ struct jmb38x_ms_host { | |||
50 | struct jmb38x_ms *chip; | 50 | struct jmb38x_ms *chip; |
51 | void __iomem *addr; | 51 | void __iomem *addr; |
52 | spinlock_t lock; | 52 | spinlock_t lock; |
53 | struct tasklet_struct notify; | ||
53 | int id; | 54 | int id; |
54 | char host_id[DEVICE_ID_SIZE]; | 55 | char host_id[32]; |
55 | int irq; | 56 | int irq; |
56 | unsigned int block_pos; | 57 | unsigned int block_pos; |
57 | unsigned long timeout_jiffies; | 58 | unsigned long timeout_jiffies; |
@@ -590,55 +591,97 @@ static void jmb38x_ms_abort(unsigned long data) | |||
590 | spin_unlock_irqrestore(&host->lock, flags); | 591 | spin_unlock_irqrestore(&host->lock, flags); |
591 | } | 592 | } |
592 | 593 | ||
593 | static void jmb38x_ms_request(struct memstick_host *msh) | 594 | static void jmb38x_ms_req_tasklet(unsigned long data) |
594 | { | 595 | { |
596 | struct memstick_host *msh = (struct memstick_host *)data; | ||
595 | struct jmb38x_ms_host *host = memstick_priv(msh); | 597 | struct jmb38x_ms_host *host = memstick_priv(msh); |
596 | unsigned long flags; | 598 | unsigned long flags; |
597 | int rc; | 599 | int rc; |
598 | 600 | ||
599 | spin_lock_irqsave(&host->lock, flags); | 601 | spin_lock_irqsave(&host->lock, flags); |
600 | if (host->req) { | 602 | if (!host->req) { |
601 | spin_unlock_irqrestore(&host->lock, flags); | 603 | do { |
602 | BUG(); | 604 | rc = memstick_next_req(msh, &host->req); |
603 | return; | 605 | dev_dbg(&host->chip->pdev->dev, "tasklet req %d\n", rc); |
606 | } while (!rc && jmb38x_ms_issue_cmd(msh)); | ||
604 | } | 607 | } |
605 | |||
606 | do { | ||
607 | rc = memstick_next_req(msh, &host->req); | ||
608 | } while (!rc && jmb38x_ms_issue_cmd(msh)); | ||
609 | spin_unlock_irqrestore(&host->lock, flags); | 608 | spin_unlock_irqrestore(&host->lock, flags); |
610 | } | 609 | } |
611 | 610 | ||
612 | static void jmb38x_ms_reset(struct jmb38x_ms_host *host) | 611 | static void jmb38x_ms_dummy_submit(struct memstick_host *msh) |
613 | { | 612 | { |
614 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); | 613 | return; |
614 | } | ||
615 | |||
616 | static void jmb38x_ms_submit_req(struct memstick_host *msh) | ||
617 | { | ||
618 | struct jmb38x_ms_host *host = memstick_priv(msh); | ||
619 | |||
620 | tasklet_schedule(&host->notify); | ||
621 | } | ||
622 | |||
623 | static int jmb38x_ms_reset(struct jmb38x_ms_host *host) | ||
624 | { | ||
625 | int cnt; | ||
626 | |||
627 | writel(HOST_CONTROL_RESET_REQ | HOST_CONTROL_CLOCK_EN | ||
628 | | readl(host->addr + HOST_CONTROL), | ||
629 | host->addr + HOST_CONTROL); | ||
630 | mmiowb(); | ||
631 | |||
632 | for (cnt = 0; cnt < 20; ++cnt) { | ||
633 | if (!(HOST_CONTROL_RESET_REQ | ||
634 | & readl(host->addr + HOST_CONTROL))) | ||
635 | goto reset_next; | ||
615 | 636 | ||
616 | writel(HOST_CONTROL_RESET_REQ, host->addr + HOST_CONTROL); | 637 | ndelay(20); |
638 | } | ||
639 | dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); | ||
640 | return -EIO; | ||
641 | |||
642 | reset_next: | ||
643 | writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN | ||
644 | | readl(host->addr + HOST_CONTROL), | ||
645 | host->addr + HOST_CONTROL); | ||
646 | mmiowb(); | ||
647 | |||
648 | for (cnt = 0; cnt < 20; ++cnt) { | ||
649 | if (!(HOST_CONTROL_RESET | ||
650 | & readl(host->addr + HOST_CONTROL))) | ||
651 | goto reset_ok; | ||
617 | 652 | ||
618 | while (HOST_CONTROL_RESET_REQ | ||
619 | & (host_ctl = readl(host->addr + HOST_CONTROL))) { | ||
620 | ndelay(20); | 653 | ndelay(20); |
621 | dev_dbg(&host->chip->pdev->dev, "reset %08x\n", host_ctl); | ||
622 | } | 654 | } |
655 | dev_dbg(&host->chip->pdev->dev, "reset timeout\n"); | ||
656 | return -EIO; | ||
623 | 657 | ||
624 | writel(HOST_CONTROL_RESET, host->addr + HOST_CONTROL); | 658 | reset_ok: |
625 | mmiowb(); | 659 | mmiowb(); |
626 | writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); | 660 | writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); |
627 | writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); | 661 | writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); |
662 | return 0; | ||
628 | } | 663 | } |
629 | 664 | ||
630 | static void jmb38x_ms_set_param(struct memstick_host *msh, | 665 | static int jmb38x_ms_set_param(struct memstick_host *msh, |
631 | enum memstick_param param, | 666 | enum memstick_param param, |
632 | int value) | 667 | int value) |
633 | { | 668 | { |
634 | struct jmb38x_ms_host *host = memstick_priv(msh); | 669 | struct jmb38x_ms_host *host = memstick_priv(msh); |
635 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); | 670 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); |
636 | unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; | 671 | unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; |
672 | int rc = 0; | ||
637 | 673 | ||
638 | switch (param) { | 674 | switch (param) { |
639 | case MEMSTICK_POWER: | 675 | case MEMSTICK_POWER: |
640 | if (value == MEMSTICK_POWER_ON) { | 676 | if (value == MEMSTICK_POWER_ON) { |
641 | jmb38x_ms_reset(host); | 677 | rc = jmb38x_ms_reset(host); |
678 | if (rc) | ||
679 | return rc; | ||
680 | |||
681 | host_ctl = 7; | ||
682 | host_ctl |= HOST_CONTROL_POWER_EN | ||
683 | | HOST_CONTROL_CLOCK_EN; | ||
684 | writel(host_ctl, host->addr + HOST_CONTROL); | ||
642 | 685 | ||
643 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 | 686 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 |
644 | : PAD_PU_PD_ON_MS_SOCK0, | 687 | : PAD_PU_PD_ON_MS_SOCK0, |
@@ -647,11 +690,7 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, | |||
647 | writel(PAD_OUTPUT_ENABLE_MS, | 690 | writel(PAD_OUTPUT_ENABLE_MS, |
648 | host->addr + PAD_OUTPUT_ENABLE); | 691 | host->addr + PAD_OUTPUT_ENABLE); |
649 | 692 | ||
650 | host_ctl = 7; | 693 | msleep(10); |
651 | host_ctl |= HOST_CONTROL_POWER_EN | ||
652 | | HOST_CONTROL_CLOCK_EN; | ||
653 | writel(host_ctl, host->addr + HOST_CONTROL); | ||
654 | |||
655 | dev_dbg(&host->chip->pdev->dev, "power on\n"); | 694 | dev_dbg(&host->chip->pdev->dev, "power on\n"); |
656 | } else if (value == MEMSTICK_POWER_OFF) { | 695 | } else if (value == MEMSTICK_POWER_OFF) { |
657 | host_ctl &= ~(HOST_CONTROL_POWER_EN | 696 | host_ctl &= ~(HOST_CONTROL_POWER_EN |
@@ -660,7 +699,8 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, | |||
660 | writel(0, host->addr + PAD_OUTPUT_ENABLE); | 699 | writel(0, host->addr + PAD_OUTPUT_ENABLE); |
661 | writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); | 700 | writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); |
662 | dev_dbg(&host->chip->pdev->dev, "power off\n"); | 701 | dev_dbg(&host->chip->pdev->dev, "power off\n"); |
663 | } | 702 | } else |
703 | return -EINVAL; | ||
664 | break; | 704 | break; |
665 | case MEMSTICK_INTERFACE: | 705 | case MEMSTICK_INTERFACE: |
666 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); | 706 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); |
@@ -686,12 +726,14 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, | |||
686 | host_ctl &= ~HOST_CONTROL_REI; | 726 | host_ctl &= ~HOST_CONTROL_REI; |
687 | clock_ctl = CLOCK_CONTROL_60MHZ; | 727 | clock_ctl = CLOCK_CONTROL_60MHZ; |
688 | clock_delay = 0; | 728 | clock_delay = 0; |
689 | } | 729 | } else |
730 | return -EINVAL; | ||
690 | writel(host_ctl, host->addr + HOST_CONTROL); | 731 | writel(host_ctl, host->addr + HOST_CONTROL); |
691 | writel(clock_ctl, host->addr + CLOCK_CONTROL); | 732 | writel(clock_ctl, host->addr + CLOCK_CONTROL); |
692 | writel(clock_delay, host->addr + CLOCK_DELAY); | 733 | writel(clock_delay, host->addr + CLOCK_DELAY); |
693 | break; | 734 | break; |
694 | }; | 735 | }; |
736 | return 0; | ||
695 | } | 737 | } |
696 | 738 | ||
697 | #ifdef CONFIG_PM | 739 | #ifdef CONFIG_PM |
@@ -781,11 +823,13 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) | |||
781 | 823 | ||
782 | spin_lock_init(&host->lock); | 824 | spin_lock_init(&host->lock); |
783 | host->id = cnt; | 825 | host->id = cnt; |
784 | snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", | 826 | snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d", |
785 | host->id); | 827 | host->id); |
786 | host->irq = jm->pdev->irq; | 828 | host->irq = jm->pdev->irq; |
787 | host->timeout_jiffies = msecs_to_jiffies(1000); | 829 | host->timeout_jiffies = msecs_to_jiffies(1000); |
788 | msh->request = jmb38x_ms_request; | 830 | |
831 | tasklet_init(&host->notify, jmb38x_ms_req_tasklet, (unsigned long)msh); | ||
832 | msh->request = jmb38x_ms_submit_req; | ||
789 | msh->set_param = jmb38x_ms_set_param; | 833 | msh->set_param = jmb38x_ms_set_param; |
790 | 834 | ||
791 | msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; | 835 | msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; |
@@ -897,6 +941,8 @@ static void jmb38x_ms_remove(struct pci_dev *dev) | |||
897 | 941 | ||
898 | host = memstick_priv(jm->hosts[cnt]); | 942 | host = memstick_priv(jm->hosts[cnt]); |
899 | 943 | ||
944 | jm->hosts[cnt]->request = jmb38x_ms_dummy_submit; | ||
945 | tasklet_kill(&host->notify); | ||
900 | writel(0, host->addr + INT_SIGNAL_ENABLE); | 946 | writel(0, host->addr + INT_SIGNAL_ENABLE); |
901 | writel(0, host->addr + INT_STATUS_ENABLE); | 947 | writel(0, host->addr + INT_STATUS_ENABLE); |
902 | mmiowb(); | 948 | mmiowb(); |
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) { |