diff options
| author | Alex Dubov <oakad@yahoo.com> | 2008-07-25 22:45:02 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-26 15:00:04 -0400 |
| commit | f1d82698029b92a88f5500b99f66514b6dee2bc3 (patch) | |
| tree | eaedb613a05e1471fbeca212b3b1229ab252627d /drivers/memstick | |
| parent | 17017d8d2c005734d7088d8281ce2daab8fcb097 (diff) | |
memstick: use fully asynchronous request processing
Instead of using a separate thread to pump requests from block layer queue
to memstick, do so inline, utilizing the callback design of the memstick.
[akpm@linux-foundation.org: fix warnings]
Signed-off-by: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/memstick')
| -rw-r--r-- | drivers/memstick/core/memstick.c | 7 | ||||
| -rw-r--r-- | drivers/memstick/core/mspro_block.c | 344 | ||||
| -rw-r--r-- | drivers/memstick/host/jmb38x_ms.c | 35 | ||||
| -rw-r--r-- | drivers/memstick/host/tifm_ms.c | 49 |
4 files changed, 218 insertions, 217 deletions
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 7162f772bbfb..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 | ||
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 004ac4d176d9..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,90 +656,120 @@ 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 void mspro_block_stop(struct memstick_dev *card) | 775 | static void mspro_block_stop(struct memstick_dev *card) |
| @@ -783,54 +803,37 @@ static void mspro_block_start(struct memstick_dev *card) | |||
| 783 | spin_unlock_irqrestore(&msb->q_lock, flags); | 803 | spin_unlock_irqrestore(&msb->q_lock, flags); |
| 784 | } | 804 | } |
| 785 | 805 | ||
| 786 | static int mspro_block_queue_thread(void *data) | 806 | static int mspro_block_prepare_req(struct request_queue *q, struct request *req) |
| 787 | { | 807 | { |
| 788 | struct memstick_dev *card = data; | 808 | if (!blk_fs_request(req) && !blk_pc_request(req)) { |
| 789 | struct memstick_host *host = card->host; | 809 | blk_dump_rq_flags(req, "MSPro unsupported request"); |
| 790 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 810 | return BLKPREP_KILL; |
| 791 | struct request *req; | 811 | } |
| 792 | unsigned long flags; | ||
| 793 | |||
| 794 | while (1) { | ||
| 795 | wait_event(msb->q_wait, mspro_block_has_request(msb)); | ||
| 796 | dev_dbg(&card->dev, "thread iter\n"); | ||
| 797 | 812 | ||
| 798 | spin_lock_irqsave(&msb->q_lock, flags); | 813 | req->cmd_flags |= REQ_DONTPREP; |
| 799 | req = elv_next_request(msb->queue); | ||
| 800 | dev_dbg(&card->dev, "next req %p\n", req); | ||
| 801 | if (!req) { | ||
| 802 | msb->has_request = 0; | ||
| 803 | if (kthread_should_stop()) { | ||
| 804 | spin_unlock_irqrestore(&msb->q_lock, flags); | ||
| 805 | break; | ||
| 806 | } | ||
| 807 | } else | ||
| 808 | msb->has_request = 1; | ||
| 809 | spin_unlock_irqrestore(&msb->q_lock, flags); | ||
| 810 | 814 | ||
| 811 | if (req) { | 815 | return BLKPREP_OK; |
| 812 | mutex_lock(&host->lock); | ||
| 813 | mspro_block_process_request(card, req); | ||
| 814 | mutex_unlock(&host->lock); | ||
| 815 | } | ||
| 816 | } | ||
| 817 | dev_dbg(&card->dev, "thread finished\n"); | ||
| 818 | return 0; | ||
| 819 | } | 816 | } |
| 820 | 817 | ||
| 821 | static void mspro_block_request(struct request_queue *q) | 818 | static void mspro_block_submit_req(struct request_queue *q) |
| 822 | { | 819 | { |
| 823 | struct memstick_dev *card = q->queuedata; | 820 | struct memstick_dev *card = q->queuedata; |
| 824 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 821 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
| 825 | struct request *req = NULL; | 822 | struct request *req = NULL; |
| 826 | 823 | ||
| 827 | if (msb->q_thread) { | 824 | if (msb->has_request) |
| 828 | msb->has_request = 1; | 825 | return; |
| 829 | wake_up_all(&msb->q_wait); | 826 | |
| 830 | } else { | 827 | if (msb->eject) { |
| 831 | while ((req = elv_next_request(q)) != NULL) | 828 | while ((req = elv_next_request(q)) != NULL) |
| 832 | end_queued_request(req, -ENODEV); | 829 | end_queued_request(req, -ENODEV); |
| 830 | |||
| 831 | return; | ||
| 833 | } | 832 | } |
| 833 | |||
| 834 | msb->has_request = 1; | ||
| 835 | if (mspro_block_issue_req(card, 0)) | ||
| 836 | msb->has_request = 0; | ||
| 834 | } | 837 | } |
| 835 | 838 | ||
| 836 | /*** Initialization ***/ | 839 | /*** Initialization ***/ |
| @@ -1200,16 +1203,14 @@ static int mspro_block_init_disk(struct memstick_dev *card) | |||
| 1200 | goto out_release_id; | 1203 | goto out_release_id; |
| 1201 | } | 1204 | } |
| 1202 | 1205 | ||
| 1203 | spin_lock_init(&msb->q_lock); | 1206 | msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock); |
| 1204 | init_waitqueue_head(&msb->q_wait); | ||
| 1205 | |||
| 1206 | msb->queue = blk_init_queue(mspro_block_request, &msb->q_lock); | ||
| 1207 | if (!msb->queue) { | 1207 | if (!msb->queue) { |
| 1208 | rc = -ENOMEM; | 1208 | rc = -ENOMEM; |
| 1209 | goto out_put_disk; | 1209 | goto out_put_disk; |
| 1210 | } | 1210 | } |
| 1211 | 1211 | ||
| 1212 | msb->queue->queuedata = card; | 1212 | msb->queue->queuedata = card; |
| 1213 | blk_queue_prep_rq(msb->queue, mspro_block_prepare_req); | ||
| 1213 | 1214 | ||
| 1214 | blk_queue_bounce_limit(msb->queue, limit); | 1215 | blk_queue_bounce_limit(msb->queue, limit); |
| 1215 | blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); | 1216 | blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); |
| @@ -1235,14 +1236,8 @@ static int mspro_block_init_disk(struct memstick_dev *card) | |||
| 1235 | capacity *= msb->page_size >> 9; | 1236 | capacity *= msb->page_size >> 9; |
| 1236 | set_capacity(msb->disk, capacity); | 1237 | set_capacity(msb->disk, capacity); |
| 1237 | dev_dbg(&card->dev, "capacity set %ld\n", capacity); | 1238 | dev_dbg(&card->dev, "capacity set %ld\n", capacity); |
| 1238 | msb->q_thread = kthread_run(mspro_block_queue_thread, card, | ||
| 1239 | DRIVER_NAME"d"); | ||
| 1240 | if (IS_ERR(msb->q_thread)) | ||
| 1241 | goto out_put_disk; | ||
| 1242 | 1239 | ||
| 1243 | mutex_unlock(&host->lock); | ||
| 1244 | add_disk(msb->disk); | 1240 | add_disk(msb->disk); |
| 1245 | mutex_lock(&host->lock); | ||
| 1246 | msb->active = 1; | 1241 | msb->active = 1; |
| 1247 | return 0; | 1242 | return 0; |
| 1248 | 1243 | ||
| @@ -1290,6 +1285,7 @@ static int mspro_block_probe(struct memstick_dev *card) | |||
| 1290 | return -ENOMEM; | 1285 | return -ENOMEM; |
| 1291 | memstick_set_drvdata(card, msb); | 1286 | memstick_set_drvdata(card, msb); |
| 1292 | msb->card = card; | 1287 | msb->card = card; |
| 1288 | spin_lock_init(&msb->q_lock); | ||
| 1293 | 1289 | ||
| 1294 | rc = mspro_block_init_card(card); | 1290 | rc = mspro_block_init_card(card); |
| 1295 | 1291 | ||
| @@ -1319,26 +1315,17 @@ out_free: | |||
| 1319 | static void mspro_block_remove(struct memstick_dev *card) | 1315 | static void mspro_block_remove(struct memstick_dev *card) |
| 1320 | { | 1316 | { |
| 1321 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 1317 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
| 1322 | struct task_struct *q_thread = NULL; | ||
| 1323 | unsigned long flags; | 1318 | unsigned long flags; |
| 1324 | 1319 | ||
| 1325 | del_gendisk(msb->disk); | 1320 | del_gendisk(msb->disk); |
| 1326 | dev_dbg(&card->dev, "mspro block remove\n"); | 1321 | dev_dbg(&card->dev, "mspro block remove\n"); |
| 1327 | spin_lock_irqsave(&msb->q_lock, flags); | 1322 | spin_lock_irqsave(&msb->q_lock, flags); |
| 1328 | q_thread = msb->q_thread; | 1323 | msb->eject = 1; |
| 1329 | msb->q_thread = NULL; | 1324 | blk_start_queue(msb->queue); |
| 1330 | msb->active = 0; | ||
| 1331 | spin_unlock_irqrestore(&msb->q_lock, flags); | 1325 | spin_unlock_irqrestore(&msb->q_lock, flags); |
| 1332 | 1326 | ||
| 1333 | if (q_thread) { | ||
| 1334 | mutex_unlock(&card->host->lock); | ||
| 1335 | kthread_stop(q_thread); | ||
| 1336 | mutex_lock(&card->host->lock); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | dev_dbg(&card->dev, "queue thread stopped\n"); | ||
| 1340 | |||
| 1341 | blk_cleanup_queue(msb->queue); | 1327 | blk_cleanup_queue(msb->queue); |
| 1328 | msb->queue = NULL; | ||
| 1342 | 1329 | ||
| 1343 | sysfs_remove_group(&card->dev.kobj, &msb->attr_group); | 1330 | sysfs_remove_group(&card->dev.kobj, &msb->attr_group); |
| 1344 | 1331 | ||
| @@ -1355,19 +1342,13 @@ static void mspro_block_remove(struct memstick_dev *card) | |||
| 1355 | 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) |
| 1356 | { | 1343 | { |
| 1357 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 1344 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
| 1358 | struct task_struct *q_thread = NULL; | ||
| 1359 | unsigned long flags; | 1345 | unsigned long flags; |
| 1360 | 1346 | ||
| 1361 | spin_lock_irqsave(&msb->q_lock, flags); | 1347 | spin_lock_irqsave(&msb->q_lock, flags); |
| 1362 | q_thread = msb->q_thread; | ||
| 1363 | msb->q_thread = NULL; | ||
| 1364 | msb->active = 0; | ||
| 1365 | blk_stop_queue(msb->queue); | 1348 | blk_stop_queue(msb->queue); |
| 1349 | msb->active = 0; | ||
| 1366 | spin_unlock_irqrestore(&msb->q_lock, flags); | 1350 | spin_unlock_irqrestore(&msb->q_lock, flags); |
| 1367 | 1351 | ||
| 1368 | if (q_thread) | ||
| 1369 | kthread_stop(q_thread); | ||
| 1370 | |||
| 1371 | return 0; | 1352 | return 0; |
| 1372 | } | 1353 | } |
| 1373 | 1354 | ||
| @@ -1406,14 +1387,7 @@ static int mspro_block_resume(struct memstick_dev *card) | |||
| 1406 | if (memcmp(s_attr->data, r_attr->data, s_attr->size)) | 1387 | if (memcmp(s_attr->data, r_attr->data, s_attr->size)) |
| 1407 | break; | 1388 | break; |
| 1408 | 1389 | ||
| 1409 | memstick_set_drvdata(card, msb); | 1390 | msb->active = 1; |
| 1410 | msb->q_thread = kthread_run(mspro_block_queue_thread, | ||
| 1411 | card, DRIVER_NAME"d"); | ||
| 1412 | if (IS_ERR(msb->q_thread)) | ||
| 1413 | msb->q_thread = NULL; | ||
| 1414 | else | ||
| 1415 | msb->active = 1; | ||
| 1416 | |||
| 1417 | break; | 1391 | break; |
| 1418 | } | 1392 | } |
| 1419 | } | 1393 | } |
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 9d82e67737db..3485c63d20b0 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c | |||
| @@ -50,6 +50,7 @@ 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[32]; | 55 | char host_id[32]; |
| 55 | int irq; | 56 | int irq; |
| @@ -590,25 +591,35 @@ 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 | ||
| 611 | static void jmb38x_ms_dummy_submit(struct memstick_host *msh) | ||
| 612 | { | ||
| 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 | |||
| 612 | static int jmb38x_ms_reset(struct jmb38x_ms_host *host) | 623 | static int jmb38x_ms_reset(struct jmb38x_ms_host *host) |
| 613 | { | 624 | { |
| 614 | int cnt; | 625 | int cnt; |
| @@ -816,7 +827,9 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) | |||
| 816 | host->id); | 827 | host->id); |
| 817 | host->irq = jm->pdev->irq; | 828 | host->irq = jm->pdev->irq; |
| 818 | host->timeout_jiffies = msecs_to_jiffies(1000); | 829 | host->timeout_jiffies = msecs_to_jiffies(1000); |
| 819 | 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; | ||
| 820 | msh->set_param = jmb38x_ms_set_param; | 833 | msh->set_param = jmb38x_ms_set_param; |
| 821 | 834 | ||
| 822 | msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; | 835 | msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; |
| @@ -928,6 +941,8 @@ static void jmb38x_ms_remove(struct pci_dev *dev) | |||
| 928 | 941 | ||
| 929 | host = memstick_priv(jm->hosts[cnt]); | 942 | host = memstick_priv(jm->hosts[cnt]); |
| 930 | 943 | ||
| 944 | jm->hosts[cnt]->request = jmb38x_ms_dummy_submit; | ||
| 945 | tasklet_kill(&host->notify); | ||
| 931 | writel(0, host->addr + INT_SIGNAL_ENABLE); | 946 | writel(0, host->addr + INT_SIGNAL_ENABLE); |
| 932 | writel(0, host->addr + INT_STATUS_ENABLE); | 947 | writel(0, host->addr + INT_STATUS_ENABLE); |
| 933 | mmiowb(); | 948 | mmiowb(); |
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 14458764588c..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,40 +456,45 @@ 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 | ||
| 491 | static void tifm_ms_submit_req(struct memstick_host *msh) | ||
| 492 | { | ||
| 493 | struct tifm_ms *host = memstick_priv(msh); | ||
| 494 | |||
| 495 | tasklet_schedule(&host->notify); | ||
| 496 | } | ||
| 497 | |||
| 492 | static int tifm_ms_set_param(struct memstick_host *msh, | 498 | static int tifm_ms_set_param(struct memstick_host *msh, |
| 493 | enum memstick_param param, | 499 | enum memstick_param param, |
| 494 | int value) | 500 | int value) |
| @@ -569,8 +575,9 @@ static int tifm_ms_probe(struct tifm_dev *sock) | |||
| 569 | host->timeout_jiffies = msecs_to_jiffies(1000); | 575 | host->timeout_jiffies = msecs_to_jiffies(1000); |
| 570 | 576 | ||
| 571 | 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); | ||
| 572 | 579 | ||
| 573 | msh->request = tifm_ms_request; | 580 | msh->request = tifm_ms_submit_req; |
| 574 | msh->set_param = tifm_ms_set_param; | 581 | msh->set_param = tifm_ms_set_param; |
| 575 | sock->card_event = tifm_ms_card_event; | 582 | sock->card_event = tifm_ms_card_event; |
| 576 | sock->data_event = tifm_ms_data_event; | 583 | sock->data_event = tifm_ms_data_event; |
| @@ -592,6 +599,8 @@ static void tifm_ms_remove(struct tifm_dev *sock) | |||
| 592 | int rc = 0; | 599 | int rc = 0; |
| 593 | unsigned long flags; | 600 | unsigned long flags; |
| 594 | 601 | ||
| 602 | msh->request = tifm_ms_dummy_submit; | ||
| 603 | tasklet_kill(&host->notify); | ||
| 595 | spin_lock_irqsave(&sock->lock, flags); | 604 | spin_lock_irqsave(&sock->lock, flags); |
| 596 | host->eject = 1; | 605 | host->eject = 1; |
| 597 | if (host->req) { | 606 | if (host->req) { |
