diff options
author | Jens Axboe <axboe@fb.com> | 2015-11-03 22:37:26 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-11-07 12:40:47 -0500 |
commit | a0fa9647a54e81883abd57c5c865d1747f68a577 (patch) | |
tree | f017a7459fd6e0cc36b0e004c7d4a059b5a04c15 /drivers/nvme | |
parent | 05229beeddf7e75e2e616ddaad4b70e7fca9528d (diff) |
NVMe: add blk polling support
Add nvme_poll(), which will check a specific completion queue for
command completions. Wire that up to the new block layer poll
mechanism.
Signed-off-by: Jens Axboe <axboe@fb.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Keith Busch <keith.busch@intel.com>
Diffstat (limited to 'drivers/nvme')
-rw-r--r-- | drivers/nvme/host/pci.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index e878590e71b6..4a715f49f5db 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c | |||
@@ -90,7 +90,7 @@ static struct class *nvme_class; | |||
90 | 90 | ||
91 | static int __nvme_reset(struct nvme_dev *dev); | 91 | static int __nvme_reset(struct nvme_dev *dev); |
92 | static int nvme_reset(struct nvme_dev *dev); | 92 | static int nvme_reset(struct nvme_dev *dev); |
93 | static int nvme_process_cq(struct nvme_queue *nvmeq); | 93 | static void nvme_process_cq(struct nvme_queue *nvmeq); |
94 | static void nvme_dead_ctrl(struct nvme_dev *dev); | 94 | static void nvme_dead_ctrl(struct nvme_dev *dev); |
95 | 95 | ||
96 | struct async_cmd_info { | 96 | struct async_cmd_info { |
@@ -935,7 +935,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
935 | return BLK_MQ_RQ_QUEUE_BUSY; | 935 | return BLK_MQ_RQ_QUEUE_BUSY; |
936 | } | 936 | } |
937 | 937 | ||
938 | static int nvme_process_cq(struct nvme_queue *nvmeq) | 938 | static void __nvme_process_cq(struct nvme_queue *nvmeq, unsigned int *tag) |
939 | { | 939 | { |
940 | u16 head, phase; | 940 | u16 head, phase; |
941 | 941 | ||
@@ -953,6 +953,8 @@ static int nvme_process_cq(struct nvme_queue *nvmeq) | |||
953 | head = 0; | 953 | head = 0; |
954 | phase = !phase; | 954 | phase = !phase; |
955 | } | 955 | } |
956 | if (tag && *tag == cqe.command_id) | ||
957 | *tag = -1; | ||
956 | ctx = nvme_finish_cmd(nvmeq, cqe.command_id, &fn); | 958 | ctx = nvme_finish_cmd(nvmeq, cqe.command_id, &fn); |
957 | fn(nvmeq, ctx, &cqe); | 959 | fn(nvmeq, ctx, &cqe); |
958 | } | 960 | } |
@@ -964,14 +966,18 @@ static int nvme_process_cq(struct nvme_queue *nvmeq) | |||
964 | * a big problem. | 966 | * a big problem. |
965 | */ | 967 | */ |
966 | if (head == nvmeq->cq_head && phase == nvmeq->cq_phase) | 968 | if (head == nvmeq->cq_head && phase == nvmeq->cq_phase) |
967 | return 0; | 969 | return; |
968 | 970 | ||
969 | writel(head, nvmeq->q_db + nvmeq->dev->db_stride); | 971 | writel(head, nvmeq->q_db + nvmeq->dev->db_stride); |
970 | nvmeq->cq_head = head; | 972 | nvmeq->cq_head = head; |
971 | nvmeq->cq_phase = phase; | 973 | nvmeq->cq_phase = phase; |
972 | 974 | ||
973 | nvmeq->cqe_seen = 1; | 975 | nvmeq->cqe_seen = 1; |
974 | return 1; | 976 | } |
977 | |||
978 | static void nvme_process_cq(struct nvme_queue *nvmeq) | ||
979 | { | ||
980 | __nvme_process_cq(nvmeq, NULL); | ||
975 | } | 981 | } |
976 | 982 | ||
977 | static irqreturn_t nvme_irq(int irq, void *data) | 983 | static irqreturn_t nvme_irq(int irq, void *data) |
@@ -995,6 +1001,23 @@ static irqreturn_t nvme_irq_check(int irq, void *data) | |||
995 | return IRQ_WAKE_THREAD; | 1001 | return IRQ_WAKE_THREAD; |
996 | } | 1002 | } |
997 | 1003 | ||
1004 | static int nvme_poll(struct blk_mq_hw_ctx *hctx, unsigned int tag) | ||
1005 | { | ||
1006 | struct nvme_queue *nvmeq = hctx->driver_data; | ||
1007 | |||
1008 | if ((le16_to_cpu(nvmeq->cqes[nvmeq->cq_head].status) & 1) == | ||
1009 | nvmeq->cq_phase) { | ||
1010 | spin_lock_irq(&nvmeq->q_lock); | ||
1011 | __nvme_process_cq(nvmeq, &tag); | ||
1012 | spin_unlock_irq(&nvmeq->q_lock); | ||
1013 | |||
1014 | if (tag == -1) | ||
1015 | return 1; | ||
1016 | } | ||
1017 | |||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
998 | /* | 1021 | /* |
999 | * Returns 0 on success. If the result is negative, it's a Linux error code; | 1022 | * Returns 0 on success. If the result is negative, it's a Linux error code; |
1000 | * if the result is positive, it's an NVM Express status code | 1023 | * if the result is positive, it's an NVM Express status code |
@@ -1654,6 +1677,7 @@ static struct blk_mq_ops nvme_mq_ops = { | |||
1654 | .init_hctx = nvme_init_hctx, | 1677 | .init_hctx = nvme_init_hctx, |
1655 | .init_request = nvme_init_request, | 1678 | .init_request = nvme_init_request, |
1656 | .timeout = nvme_timeout, | 1679 | .timeout = nvme_timeout, |
1680 | .poll = nvme_poll, | ||
1657 | }; | 1681 | }; |
1658 | 1682 | ||
1659 | static void nvme_dev_remove_admin(struct nvme_dev *dev) | 1683 | static void nvme_dev_remove_admin(struct nvme_dev *dev) |