diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/nvme-core.c | 39 |
1 files changed, 16 insertions, 23 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 95f2310255ce..e92bdf4c68fc 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
@@ -621,24 +621,15 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
621 | struct nvme_cmd_info *cmd = blk_mq_rq_to_pdu(req); | 621 | struct nvme_cmd_info *cmd = blk_mq_rq_to_pdu(req); |
622 | struct nvme_iod *iod; | 622 | struct nvme_iod *iod; |
623 | int psegs = req->nr_phys_segments; | 623 | int psegs = req->nr_phys_segments; |
624 | int result = BLK_MQ_RQ_QUEUE_BUSY; | ||
625 | enum dma_data_direction dma_dir; | 624 | enum dma_data_direction dma_dir; |
626 | unsigned size = !(req->cmd_flags & REQ_DISCARD) ? blk_rq_bytes(req) : | 625 | unsigned size = !(req->cmd_flags & REQ_DISCARD) ? blk_rq_bytes(req) : |
627 | sizeof(struct nvme_dsm_range); | 626 | sizeof(struct nvme_dsm_range); |
628 | 627 | ||
629 | /* | ||
630 | * Requeued IO has already been prepped | ||
631 | */ | ||
632 | iod = req->special; | ||
633 | if (iod) | ||
634 | goto submit_iod; | ||
635 | |||
636 | iod = nvme_alloc_iod(psegs, size, ns->dev, GFP_ATOMIC); | 628 | iod = nvme_alloc_iod(psegs, size, ns->dev, GFP_ATOMIC); |
637 | if (!iod) | 629 | if (!iod) |
638 | return result; | 630 | return BLK_MQ_RQ_QUEUE_BUSY; |
639 | 631 | ||
640 | iod->private = req; | 632 | iod->private = req; |
641 | req->special = iod; | ||
642 | 633 | ||
643 | if (req->cmd_flags & REQ_DISCARD) { | 634 | if (req->cmd_flags & REQ_DISCARD) { |
644 | void *range; | 635 | void *range; |
@@ -651,7 +642,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
651 | GFP_ATOMIC, | 642 | GFP_ATOMIC, |
652 | &iod->first_dma); | 643 | &iod->first_dma); |
653 | if (!range) | 644 | if (!range) |
654 | goto finish_cmd; | 645 | goto retry_cmd; |
655 | iod_list(iod)[0] = (__le64 *)range; | 646 | iod_list(iod)[0] = (__le64 *)range; |
656 | iod->npages = 0; | 647 | iod->npages = 0; |
657 | } else if (psegs) { | 648 | } else if (psegs) { |
@@ -659,22 +650,22 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
659 | 650 | ||
660 | sg_init_table(iod->sg, psegs); | 651 | sg_init_table(iod->sg, psegs); |
661 | iod->nents = blk_rq_map_sg(req->q, req, iod->sg); | 652 | iod->nents = blk_rq_map_sg(req->q, req, iod->sg); |
662 | if (!iod->nents) { | 653 | if (!iod->nents) |
663 | result = BLK_MQ_RQ_QUEUE_ERROR; | 654 | goto error_cmd; |
664 | goto finish_cmd; | ||
665 | } | ||
666 | 655 | ||
667 | if (!dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir)) | 656 | if (!dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir)) |
668 | goto finish_cmd; | 657 | goto retry_cmd; |
669 | 658 | ||
670 | if (blk_rq_bytes(req) != nvme_setup_prps(nvmeq->dev, iod, | 659 | if (blk_rq_bytes(req) != |
671 | blk_rq_bytes(req), GFP_ATOMIC)) | 660 | nvme_setup_prps(nvmeq->dev, iod, blk_rq_bytes(req), GFP_ATOMIC)) { |
672 | goto finish_cmd; | 661 | dma_unmap_sg(&nvmeq->dev->pci_dev->dev, iod->sg, |
662 | iod->nents, dma_dir); | ||
663 | goto retry_cmd; | ||
664 | } | ||
673 | } | 665 | } |
674 | 666 | ||
675 | blk_mq_start_request(req); | 667 | blk_mq_start_request(req); |
676 | 668 | ||
677 | submit_iod: | ||
678 | nvme_set_info(cmd, iod, req_completion); | 669 | nvme_set_info(cmd, iod, req_completion); |
679 | spin_lock_irq(&nvmeq->q_lock); | 670 | spin_lock_irq(&nvmeq->q_lock); |
680 | if (req->cmd_flags & REQ_DISCARD) | 671 | if (req->cmd_flags & REQ_DISCARD) |
@@ -688,10 +679,12 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
688 | spin_unlock_irq(&nvmeq->q_lock); | 679 | spin_unlock_irq(&nvmeq->q_lock); |
689 | return BLK_MQ_RQ_QUEUE_OK; | 680 | return BLK_MQ_RQ_QUEUE_OK; |
690 | 681 | ||
691 | finish_cmd: | 682 | error_cmd: |
692 | nvme_finish_cmd(nvmeq, req->tag, NULL); | ||
693 | nvme_free_iod(nvmeq->dev, iod); | 683 | nvme_free_iod(nvmeq->dev, iod); |
694 | return result; | 684 | return BLK_MQ_RQ_QUEUE_ERROR; |
685 | retry_cmd: | ||
686 | nvme_free_iod(nvmeq->dev, iod); | ||
687 | return BLK_MQ_RQ_QUEUE_BUSY; | ||
695 | } | 688 | } |
696 | 689 | ||
697 | static int nvme_process_cq(struct nvme_queue *nvmeq) | 690 | static int nvme_process_cq(struct nvme_queue *nvmeq) |