forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/nvme/host/fabrics.c
....@@ -1,15 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * NVMe over Fabrics common host code.
34 * Copyright (c) 2015-2016 HGST, a Western Digital Company.
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms and conditions of the GNU General Public License,
7
- * version 2, as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope it will be useful, but WITHOUT
10
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
- * more details.
135 */
146 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
157 #include <linux/init.h>
....@@ -113,14 +105,14 @@
113105 int len = 0;
114106
115107 if (ctrl->opts->mask & NVMF_OPT_TRADDR)
116
- len += snprintf(buf, size, "traddr=%s", ctrl->opts->traddr);
108
+ len += scnprintf(buf, size, "traddr=%s", ctrl->opts->traddr);
117109 if (ctrl->opts->mask & NVMF_OPT_TRSVCID)
118
- len += snprintf(buf + len, size - len, "%strsvcid=%s",
110
+ len += scnprintf(buf + len, size - len, "%strsvcid=%s",
119111 (len) ? "," : "", ctrl->opts->trsvcid);
120112 if (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)
121
- len += snprintf(buf + len, size - len, "%shost_traddr=%s",
113
+ len += scnprintf(buf + len, size - len, "%shost_traddr=%s",
122114 (len) ? "," : "", ctrl->opts->host_traddr);
123
- len += snprintf(buf + len, size - len, "\n");
115
+ len += scnprintf(buf + len, size - len, "\n");
124116
125117 return len;
126118 }
....@@ -158,8 +150,8 @@
158150 cmd.prop_get.fctype = nvme_fabrics_type_property_get;
159151 cmd.prop_get.offset = cpu_to_le32(off);
160152
161
- ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res, NULL, 0, 0,
162
- NVME_QID_ANY, 0, 0);
153
+ ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, 0,
154
+ NVME_QID_ANY, 0, 0, false);
163155
164156 if (ret >= 0)
165157 *val = le64_to_cpu(res.u64);
....@@ -205,8 +197,8 @@
205197 cmd.prop_get.attrib = 1;
206198 cmd.prop_get.offset = cpu_to_le32(off);
207199
208
- ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res, NULL, 0, 0,
209
- NVME_QID_ANY, 0, 0);
200
+ ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, 0,
201
+ NVME_QID_ANY, 0, 0, false);
210202
211203 if (ret >= 0)
212204 *val = le64_to_cpu(res.u64);
....@@ -251,8 +243,8 @@
251243 cmd.prop_set.offset = cpu_to_le32(off);
252244 cmd.prop_set.value = cpu_to_le64(val);
253245
254
- ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, NULL, NULL, 0, 0,
255
- NVME_QID_ANY, 0, 0);
246
+ ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, NULL, NULL, 0, 0,
247
+ NVME_QID_ANY, 0, 0, false);
256248 if (unlikely(ret))
257249 dev_err(ctrl->device,
258250 "Property Set error: %d, offset %#x\n",
....@@ -394,8 +386,11 @@
394386 * Set keep-alive timeout in seconds granularity (ms * 1000)
395387 * and add a grace period for controller kato enforcement
396388 */
397
- cmd.connect.kato = ctrl->opts->discovery_nqn ? 0 :
398
- cpu_to_le32((ctrl->kato + NVME_KATO_GRACE) * 1000);
389
+ cmd.connect.kato = ctrl->kato ?
390
+ cpu_to_le32((ctrl->kato + NVME_KATO_GRACE) * 1000) : 0;
391
+
392
+ if (ctrl->opts->disable_sqflow)
393
+ cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
399394
400395 data = kzalloc(sizeof(*data), GFP_KERNEL);
401396 if (!data)
....@@ -406,9 +401,9 @@
406401 strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
407402 strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
408403
409
- ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res,
404
+ ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res,
410405 data, sizeof(*data), 0, NVME_QID_ANY, 1,
411
- BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
406
+ BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT, false);
412407 if (ret) {
413408 nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
414409 &cmd, data);
....@@ -432,6 +427,7 @@
432427 * @qid: NVMe I/O queue number for the new I/O connection between
433428 * host and target (note qid == 0 is illegal as this is
434429 * the Admin queue, per NVMe standard).
430
+ * @poll: Whether or not to poll for the completion of the connect cmd.
435431 *
436432 * This function issues a fabrics-protocol connection
437433 * of a NVMe I/O queue (via NVMe Fabrics "Connect" command)
....@@ -443,7 +439,7 @@
443439 * > 0: NVMe error status code
444440 * < 0: Linux errno error code
445441 */
446
-int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
442
+int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid, bool poll)
447443 {
448444 struct nvme_command cmd;
449445 struct nvmf_connect_data *data;
....@@ -456,6 +452,9 @@
456452 cmd.connect.qid = cpu_to_le16(qid);
457453 cmd.connect.sqsize = cpu_to_le16(ctrl->sqsize);
458454
455
+ if (ctrl->opts->disable_sqflow)
456
+ cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
457
+
459458 data = kzalloc(sizeof(*data), GFP_KERNEL);
460459 if (!data)
461460 return -ENOMEM;
....@@ -467,7 +466,7 @@
467466
468467 ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res,
469468 data, sizeof(*data), 0, qid, 1,
470
- BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
469
+ BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT, poll);
471470 if (ret) {
472471 nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
473472 &cmd, data);
....@@ -553,7 +552,7 @@
553552 blk_status_t nvmf_fail_nonready_command(struct nvme_ctrl *ctrl,
554553 struct request *rq)
555554 {
556
- if (ctrl->state != NVME_CTRL_DELETING &&
555
+ if (ctrl->state != NVME_CTRL_DELETING_NOIO &&
557556 ctrl->state != NVME_CTRL_DEAD &&
558557 !blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH))
559558 return BLK_STS_RESOURCE;
....@@ -571,10 +570,14 @@
571570 struct nvme_request *req = nvme_req(rq);
572571
573572 /*
574
- * If we are in some state of setup or teardown only allow
575
- * internally generated commands.
573
+ * currently we have a problem sending passthru commands
574
+ * on the admin_q if the controller is not LIVE because we can't
575
+ * make sure that they are going out after the admin connect,
576
+ * controller enable and/or other commands in the initialization
577
+ * sequence. until the controller will be LIVE, fail with
578
+ * BLK_STS_RESOURCE so that they will be rescheduled.
576579 */
577
- if (!blk_rq_is_passthrough(rq) || (req->flags & NVME_REQ_USERCMD))
580
+ if (rq->q == ctrl->admin_q && (req->flags & NVME_REQ_USERCMD))
578581 return false;
579582
580583 /*
....@@ -583,7 +586,7 @@
583586 */
584587 switch (ctrl->state) {
585588 case NVME_CTRL_CONNECTING:
586
- if (req->cmd->common.opcode == nvme_fabrics_command &&
589
+ if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) &&
587590 req->cmd->fabrics.fctype == nvme_fabrics_type_connect)
588591 return true;
589592 break;
....@@ -611,6 +614,12 @@
611614 { NVMF_OPT_HOST_TRADDR, "host_traddr=%s" },
612615 { NVMF_OPT_HOST_ID, "hostid=%s" },
613616 { NVMF_OPT_DUP_CONNECT, "duplicate_connect" },
617
+ { NVMF_OPT_DISABLE_SQFLOW, "disable_sqflow" },
618
+ { NVMF_OPT_HDR_DIGEST, "hdr_digest" },
619
+ { NVMF_OPT_DATA_DIGEST, "data_digest" },
620
+ { NVMF_OPT_NR_WRITE_QUEUES, "nr_write_queues=%d" },
621
+ { NVMF_OPT_NR_POLL_QUEUES, "nr_poll_queues=%d" },
622
+ { NVMF_OPT_TOS, "tos=%d" },
614623 { NVMF_OPT_ERR, NULL }
615624 };
616625
....@@ -630,6 +639,9 @@
630639 opts->reconnect_delay = NVMF_DEF_RECONNECT_DELAY;
631640 opts->kato = NVME_DEFAULT_KATO;
632641 opts->duplicate_connect = false;
642
+ opts->hdr_digest = false;
643
+ opts->data_digest = false;
644
+ opts->tos = -1; /* < 0 == use transport default */
633645
634646 options = o = kstrdup(buf, GFP_KERNEL);
635647 if (!options)
....@@ -736,13 +748,6 @@
736748 pr_warn("keep_alive_tmo 0 won't execute keep alives!!!\n");
737749 }
738750 opts->kato = token;
739
-
740
- if (opts->discovery_nqn && opts->kato) {
741
- pr_err("Discovery controllers cannot accept KATO != 0\n");
742
- ret = -EINVAL;
743
- goto out;
744
- }
745
-
746751 break;
747752 case NVMF_OPT_CTRL_LOSS_TMO:
748753 if (match_int(args, &token)) {
....@@ -821,6 +826,55 @@
821826 case NVMF_OPT_DUP_CONNECT:
822827 opts->duplicate_connect = true;
823828 break;
829
+ case NVMF_OPT_DISABLE_SQFLOW:
830
+ opts->disable_sqflow = true;
831
+ break;
832
+ case NVMF_OPT_HDR_DIGEST:
833
+ opts->hdr_digest = true;
834
+ break;
835
+ case NVMF_OPT_DATA_DIGEST:
836
+ opts->data_digest = true;
837
+ break;
838
+ case NVMF_OPT_NR_WRITE_QUEUES:
839
+ if (match_int(args, &token)) {
840
+ ret = -EINVAL;
841
+ goto out;
842
+ }
843
+ if (token <= 0) {
844
+ pr_err("Invalid nr_write_queues %d\n", token);
845
+ ret = -EINVAL;
846
+ goto out;
847
+ }
848
+ opts->nr_write_queues = token;
849
+ break;
850
+ case NVMF_OPT_NR_POLL_QUEUES:
851
+ if (match_int(args, &token)) {
852
+ ret = -EINVAL;
853
+ goto out;
854
+ }
855
+ if (token <= 0) {
856
+ pr_err("Invalid nr_poll_queues %d\n", token);
857
+ ret = -EINVAL;
858
+ goto out;
859
+ }
860
+ opts->nr_poll_queues = token;
861
+ break;
862
+ case NVMF_OPT_TOS:
863
+ if (match_int(args, &token)) {
864
+ ret = -EINVAL;
865
+ goto out;
866
+ }
867
+ if (token < 0) {
868
+ pr_err("Invalid type of service %d\n", token);
869
+ ret = -EINVAL;
870
+ goto out;
871
+ }
872
+ if (token > 255) {
873
+ pr_warn("Clamping type of service to 255\n");
874
+ token = 255;
875
+ }
876
+ opts->tos = token;
877
+ break;
824878 default:
825879 pr_warn("unknown parameter or missing value '%s' in ctrl creation request\n",
826880 p);
....@@ -830,8 +884,9 @@
830884 }
831885
832886 if (opts->discovery_nqn) {
833
- opts->kato = 0;
834887 opts->nr_io_queues = 0;
888
+ opts->nr_write_queues = 0;
889
+ opts->nr_poll_queues = 0;
835890 opts->duplicate_connect = true;
836891 }
837892 if (ctrl_loss_tmo < 0)
....@@ -872,6 +927,36 @@
872927 return 0;
873928 }
874929
930
+bool nvmf_ip_options_match(struct nvme_ctrl *ctrl,
931
+ struct nvmf_ctrl_options *opts)
932
+{
933
+ if (!nvmf_ctlr_matches_baseopts(ctrl, opts) ||
934
+ strcmp(opts->traddr, ctrl->opts->traddr) ||
935
+ strcmp(opts->trsvcid, ctrl->opts->trsvcid))
936
+ return false;
937
+
938
+ /*
939
+ * Checking the local address is rough. In most cases, none is specified
940
+ * and the host port is selected by the stack.
941
+ *
942
+ * Assume no match if:
943
+ * - local address is specified and address is not the same
944
+ * - local address is not specified but remote is, or vice versa
945
+ * (admin using specific host_traddr when it matters).
946
+ */
947
+ if ((opts->mask & NVMF_OPT_HOST_TRADDR) &&
948
+ (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)) {
949
+ if (strcmp(opts->host_traddr, ctrl->opts->host_traddr))
950
+ return false;
951
+ } else if ((opts->mask & NVMF_OPT_HOST_TRADDR) ||
952
+ (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)) {
953
+ return false;
954
+ }
955
+
956
+ return true;
957
+}
958
+EXPORT_SYMBOL_GPL(nvmf_ip_options_match);
959
+
875960 static int nvmf_check_allowed_opts(struct nvmf_ctrl_options *opts,
876961 unsigned int allowed_opts)
877962 {
....@@ -907,10 +992,11 @@
907992 #define NVMF_REQUIRED_OPTS (NVMF_OPT_TRANSPORT | NVMF_OPT_NQN)
908993 #define NVMF_ALLOWED_OPTS (NVMF_OPT_QUEUE_SIZE | NVMF_OPT_NR_IO_QUEUES | \
909994 NVMF_OPT_KATO | NVMF_OPT_HOSTNQN | \
910
- NVMF_OPT_HOST_ID | NVMF_OPT_DUP_CONNECT)
995
+ NVMF_OPT_HOST_ID | NVMF_OPT_DUP_CONNECT |\
996
+ NVMF_OPT_DISABLE_SQFLOW)
911997
912998 static struct nvme_ctrl *
913
-nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
999
+nvmf_create_ctrl(struct device *dev, const char *buf)
9141000 {
9151001 struct nvmf_ctrl_options *opts;
9161002 struct nvmf_transport_ops *ops;
....@@ -1005,7 +1091,7 @@
10051091 goto out_unlock;
10061092 }
10071093
1008
- ctrl = nvmf_create_ctrl(nvmf_device, buf, count);
1094
+ ctrl = nvmf_create_ctrl(nvmf_device, buf);
10091095 if (IS_ERR(ctrl)) {
10101096 ret = PTR_ERR(ctrl);
10111097 goto out_unlock;
....@@ -1120,6 +1206,7 @@
11201206 class_destroy(nvmf_class);
11211207 nvmf_host_put(nvmf_default_host);
11221208
1209
+ BUILD_BUG_ON(sizeof(struct nvmf_common_command) != 64);
11231210 BUILD_BUG_ON(sizeof(struct nvmf_connect_command) != 64);
11241211 BUILD_BUG_ON(sizeof(struct nvmf_property_get_command) != 64);
11251212 BUILD_BUG_ON(sizeof(struct nvmf_property_set_command) != 64);