Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2018 Intel Corporation.
3 : * All rights reserved.
4 : */
5 :
6 : #include "spdk/nvme_ocssd.h"
7 : #include "nvme_internal.h"
8 :
9 : int
10 2 : spdk_nvme_ocssd_ns_cmd_vector_reset(struct spdk_nvme_ns *ns,
11 : struct spdk_nvme_qpair *qpair,
12 : uint64_t *lba_list, uint32_t num_lbas,
13 : struct spdk_ocssd_chunk_information_entry *chunk_info,
14 : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
15 : {
16 : struct nvme_request *req;
17 : struct spdk_nvme_cmd *cmd;
18 :
19 2 : if (!lba_list || (num_lbas == 0) ||
20 : (num_lbas > SPDK_NVME_OCSSD_MAX_LBAL_ENTRIES)) {
21 0 : return -EINVAL;
22 : }
23 :
24 2 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
25 2 : if (req == NULL) {
26 0 : return -ENOMEM;
27 : }
28 :
29 2 : cmd = &req->cmd;
30 2 : cmd->opc = SPDK_OCSSD_OPC_VECTOR_RESET;
31 2 : cmd->nsid = ns->id;
32 :
33 2 : if (chunk_info != NULL) {
34 0 : cmd->mptr = spdk_vtophys(chunk_info, NULL);
35 : }
36 :
37 : /*
38 : * Dword 10 and 11 store a pointer to the list of logical block addresses.
39 : * If there is a single entry in the LBA list, the logical block
40 : * address should be stored instead.
41 : */
42 2 : if (num_lbas == 1) {
43 1 : *(uint64_t *)&cmd->cdw10 = *lba_list;
44 : } else {
45 1 : *(uint64_t *)&cmd->cdw10 = spdk_vtophys(lba_list, NULL);
46 : }
47 :
48 2 : cmd->cdw12 = num_lbas - 1;
49 :
50 2 : return nvme_qpair_submit_request(qpair, req);
51 : }
52 :
53 : static int
54 8 : _nvme_ocssd_ns_cmd_vector_rw_with_md(struct spdk_nvme_ns *ns,
55 : struct spdk_nvme_qpair *qpair,
56 : void *buffer, void *metadata,
57 : uint64_t *lba_list, uint32_t num_lbas,
58 : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
59 : enum spdk_ocssd_io_opcode opc,
60 : uint32_t io_flags)
61 : {
62 : struct nvme_request *req;
63 : struct spdk_nvme_cmd *cmd;
64 8 : struct nvme_payload payload;
65 8 : uint32_t valid_flags = SPDK_OCSSD_IO_FLAGS_LIMITED_RETRY;
66 :
67 8 : if (io_flags & ~valid_flags) {
68 0 : return -EINVAL;
69 : }
70 :
71 8 : if (!buffer || !lba_list || (num_lbas == 0) ||
72 : (num_lbas > SPDK_NVME_OCSSD_MAX_LBAL_ENTRIES)) {
73 0 : return -EINVAL;
74 : }
75 :
76 8 : payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
77 :
78 8 : req = nvme_allocate_request(qpair, &payload, num_lbas * ns->sector_size, num_lbas * ns->md_size,
79 : cb_fn, cb_arg);
80 8 : if (req == NULL) {
81 0 : return -ENOMEM;
82 : }
83 :
84 8 : cmd = &req->cmd;
85 8 : cmd->opc = opc;
86 8 : cmd->nsid = ns->id;
87 :
88 : /*
89 : * Dword 10 and 11 store a pointer to the list of logical block addresses.
90 : * If there is a single entry in the LBA list, the logical block
91 : * address should be stored instead.
92 : */
93 8 : if (num_lbas == 1) {
94 4 : *(uint64_t *)&cmd->cdw10 = *lba_list;
95 : } else {
96 4 : *(uint64_t *)&cmd->cdw10 = spdk_vtophys(lba_list, NULL);
97 : }
98 :
99 8 : cmd->cdw12 = num_lbas - 1;
100 8 : cmd->cdw12 |= io_flags;
101 :
102 8 : return nvme_qpair_submit_request(qpair, req);
103 : }
104 :
105 : int
106 2 : spdk_nvme_ocssd_ns_cmd_vector_write_with_md(struct spdk_nvme_ns *ns,
107 : struct spdk_nvme_qpair *qpair,
108 : void *buffer, void *metadata,
109 : uint64_t *lba_list, uint32_t num_lbas,
110 : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
111 : uint32_t io_flags)
112 : {
113 2 : return _nvme_ocssd_ns_cmd_vector_rw_with_md(ns, qpair, buffer, metadata, lba_list,
114 : num_lbas, cb_fn, cb_arg, SPDK_OCSSD_OPC_VECTOR_WRITE, io_flags);
115 : }
116 :
117 : int
118 2 : spdk_nvme_ocssd_ns_cmd_vector_write(struct spdk_nvme_ns *ns,
119 : struct spdk_nvme_qpair *qpair,
120 : void *buffer,
121 : uint64_t *lba_list, uint32_t num_lbas,
122 : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
123 : uint32_t io_flags)
124 : {
125 2 : return _nvme_ocssd_ns_cmd_vector_rw_with_md(ns, qpair, buffer, NULL, lba_list,
126 : num_lbas, cb_fn, cb_arg, SPDK_OCSSD_OPC_VECTOR_WRITE, io_flags);
127 : }
128 :
129 : int
130 2 : spdk_nvme_ocssd_ns_cmd_vector_read_with_md(struct spdk_nvme_ns *ns,
131 : struct spdk_nvme_qpair *qpair,
132 : void *buffer, void *metadata,
133 : uint64_t *lba_list, uint32_t num_lbas,
134 : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
135 : uint32_t io_flags)
136 : {
137 2 : return _nvme_ocssd_ns_cmd_vector_rw_with_md(ns, qpair, buffer, metadata, lba_list,
138 : num_lbas, cb_fn, cb_arg, SPDK_OCSSD_OPC_VECTOR_READ, io_flags);
139 : }
140 :
141 : int
142 2 : spdk_nvme_ocssd_ns_cmd_vector_read(struct spdk_nvme_ns *ns,
143 : struct spdk_nvme_qpair *qpair,
144 : void *buffer,
145 : uint64_t *lba_list, uint32_t num_lbas,
146 : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
147 : uint32_t io_flags)
148 : {
149 2 : return _nvme_ocssd_ns_cmd_vector_rw_with_md(ns, qpair, buffer, NULL, lba_list,
150 : num_lbas, cb_fn, cb_arg, SPDK_OCSSD_OPC_VECTOR_READ, io_flags);
151 : }
152 :
153 : int
154 2 : spdk_nvme_ocssd_ns_cmd_vector_copy(struct spdk_nvme_ns *ns,
155 : struct spdk_nvme_qpair *qpair,
156 : uint64_t *dst_lba_list,
157 : uint64_t *src_lba_list,
158 : uint32_t num_lbas,
159 : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
160 : uint32_t io_flags)
161 : {
162 : struct nvme_request *req;
163 : struct spdk_nvme_cmd *cmd;
164 :
165 2 : uint32_t valid_flags = SPDK_OCSSD_IO_FLAGS_LIMITED_RETRY;
166 :
167 2 : if (io_flags & ~valid_flags) {
168 0 : return -EINVAL;
169 : }
170 :
171 2 : if (!dst_lba_list || !src_lba_list || (num_lbas == 0) ||
172 : (num_lbas > SPDK_NVME_OCSSD_MAX_LBAL_ENTRIES)) {
173 0 : return -EINVAL;
174 : }
175 :
176 2 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
177 2 : if (req == NULL) {
178 0 : return -ENOMEM;
179 : }
180 :
181 2 : cmd = &req->cmd;
182 2 : cmd->opc = SPDK_OCSSD_OPC_VECTOR_COPY;
183 2 : cmd->nsid = ns->id;
184 :
185 : /*
186 : * Dword 10 and 11 store a pointer to the list of source logical
187 : * block addresses.
188 : * Dword 14 and 15 store a pointer to the list of destination logical
189 : * block addresses.
190 : * If there is a single entry in the LBA list, the logical block
191 : * address should be stored instead.
192 : */
193 2 : if (num_lbas == 1) {
194 1 : *(uint64_t *)&cmd->cdw10 = *src_lba_list;
195 1 : *(uint64_t *)&cmd->cdw14 = *dst_lba_list;
196 : } else {
197 1 : *(uint64_t *)&cmd->cdw10 = spdk_vtophys(src_lba_list, NULL);
198 1 : *(uint64_t *)&cmd->cdw14 = spdk_vtophys(dst_lba_list, NULL);
199 : }
200 :
201 2 : cmd->cdw12 = num_lbas - 1;
202 2 : cmd->cdw12 |= io_flags;
203 :
204 2 : return nvme_qpair_submit_request(qpair, req);
205 : }
|