Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nvmet: Introduce nvmet_sq_create() and nvmet_cq_create()

Introduce the new functions nvmet_sq_create() and nvmet_cq_create() to
allow a target driver to initialize and setup admin and IO queues
directly, without needing to execute connect fabrics commands.
The helper functions nvmet_check_cqid() and nvmet_check_sqid() are
implemented to check the correctness of SQ and CQ IDs when
nvmet_sq_create() and nvmet_cq_create() are called.

nvmet_sq_create() and nvmet_cq_create() are primarily intended for use
with PCI target controller drivers and thus are not well integrated
with the current queue creation of fabrics controllers using the connect
command. These fabrices drivers are not modified to use these functions.
This simple implementation of SQ and CQ management for PCI target
controller drivers does not allow multiple SQs to share the same CQ,
similarly to other fabrics transports. This is a specification
violation. A more involved set of changes will follow to add support for
this required completion queue sharing feature.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>

authored by

Damien Le Moal and committed by
Keith Busch
1eb380ca 43043c9b

+89
+83
drivers/nvme/target/core.c
··· 818 818 complete(&sq->confirm_done); 819 819 } 820 820 821 + u16 nvmet_check_cqid(struct nvmet_ctrl *ctrl, u16 cqid) 822 + { 823 + if (!ctrl->sqs) 824 + return NVME_SC_INTERNAL | NVME_STATUS_DNR; 825 + 826 + if (cqid > ctrl->subsys->max_qid) 827 + return NVME_SC_QID_INVALID | NVME_STATUS_DNR; 828 + 829 + /* 830 + * Note: For PCI controllers, the NVMe specifications allows multiple 831 + * SQs to share a single CQ. However, we do not support this yet, so 832 + * check that there is no SQ defined for a CQ. If one exist, then the 833 + * CQ ID is invalid for creation as well as when the CQ is being 834 + * deleted (as that would mean that the SQ was not deleted before the 835 + * CQ). 836 + */ 837 + if (ctrl->sqs[cqid]) 838 + return NVME_SC_QID_INVALID | NVME_STATUS_DNR; 839 + 840 + return NVME_SC_SUCCESS; 841 + } 842 + 843 + u16 nvmet_cq_create(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, 844 + u16 qid, u16 size) 845 + { 846 + u16 status; 847 + 848 + status = nvmet_check_cqid(ctrl, qid); 849 + if (status != NVME_SC_SUCCESS) 850 + return status; 851 + 852 + nvmet_cq_setup(ctrl, cq, qid, size); 853 + 854 + return NVME_SC_SUCCESS; 855 + } 856 + EXPORT_SYMBOL_GPL(nvmet_cq_create); 857 + 858 + u16 nvmet_check_sqid(struct nvmet_ctrl *ctrl, u16 sqid, 859 + bool create) 860 + { 861 + if (!ctrl->sqs) 862 + return NVME_SC_INTERNAL | NVME_STATUS_DNR; 863 + 864 + if (sqid > ctrl->subsys->max_qid) 865 + return NVME_SC_QID_INVALID | NVME_STATUS_DNR; 866 + 867 + if ((create && ctrl->sqs[sqid]) || 868 + (!create && !ctrl->sqs[sqid])) 869 + return NVME_SC_QID_INVALID | NVME_STATUS_DNR; 870 + 871 + return NVME_SC_SUCCESS; 872 + } 873 + 874 + u16 nvmet_sq_create(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, 875 + u16 sqid, u16 size) 876 + { 877 + u16 status; 878 + int ret; 879 + 880 + if (!kref_get_unless_zero(&ctrl->ref)) 881 + return NVME_SC_INTERNAL | NVME_STATUS_DNR; 882 + 883 + status = nvmet_check_sqid(ctrl, sqid, true); 884 + if (status != NVME_SC_SUCCESS) 885 + return status; 886 + 887 + ret = nvmet_sq_init(sq); 888 + if (ret) { 889 + status = NVME_SC_INTERNAL | NVME_STATUS_DNR; 890 + goto ctrl_put; 891 + } 892 + 893 + nvmet_sq_setup(ctrl, sq, sqid, size); 894 + sq->ctrl = ctrl; 895 + 896 + return NVME_SC_SUCCESS; 897 + 898 + ctrl_put: 899 + nvmet_ctrl_put(ctrl); 900 + return status; 901 + } 902 + EXPORT_SYMBOL_GPL(nvmet_sq_create); 903 + 821 904 void nvmet_sq_destroy(struct nvmet_sq *sq) 822 905 { 823 906 struct nvmet_ctrl *ctrl = sq->ctrl;
+6
drivers/nvme/target/nvmet.h
··· 545 545 void nvmet_execute_get_features(struct nvmet_req *req); 546 546 void nvmet_execute_keep_alive(struct nvmet_req *req); 547 547 548 + u16 nvmet_check_cqid(struct nvmet_ctrl *ctrl, u16 cqid); 548 549 void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, u16 qid, 549 550 u16 size); 551 + u16 nvmet_cq_create(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, u16 qid, 552 + u16 size); 553 + u16 nvmet_check_sqid(struct nvmet_ctrl *ctrl, u16 sqid, bool create); 550 554 void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, u16 qid, 555 + u16 size); 556 + u16 nvmet_sq_create(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, u16 qid, 551 557 u16 size); 552 558 void nvmet_sq_destroy(struct nvmet_sq *sq); 553 559 int nvmet_sq_init(struct nvmet_sq *sq);