Branch data 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 : 8 : 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 [ + - + - : 8 : if (!lba_list || (num_lbas == 0) ||
- + ]
20 : : (num_lbas > SPDK_NVME_OCSSD_MAX_LBAL_ENTRIES)) {
21 : 0 : return -EINVAL;
22 : : }
23 : :
24 : 8 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
25 [ - + ]: 8 : if (req == NULL) {
26 : 0 : return -ENOMEM;
27 : : }
28 : :
29 : 8 : cmd = &req->cmd;
30 : 8 : cmd->opc = SPDK_OCSSD_OPC_VECTOR_RESET;
31 : 8 : cmd->nsid = ns->id;
32 : :
33 [ - + ]: 8 : 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 [ + + ]: 8 : if (num_lbas == 1) {
43 : 4 : *(uint64_t *)&cmd->cdw10 = *lba_list;
44 : : } else {
45 : 4 : *(uint64_t *)&cmd->cdw10 = spdk_vtophys(lba_list, NULL);
46 : : }
47 : :
48 : 8 : cmd->cdw12 = num_lbas - 1;
49 : :
50 : 8 : return nvme_qpair_submit_request(qpair, req);
51 : : }
52 : :
53 : : static int
54 : 32 : _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 : 32 : struct nvme_payload payload;
65 : 32 : uint32_t valid_flags = SPDK_OCSSD_IO_FLAGS_LIMITED_RETRY;
66 : :
67 [ - + ]: 32 : if (io_flags & ~valid_flags) {
68 : 0 : return -EINVAL;
69 : : }
70 : :
71 [ + - + - : 32 : if (!buffer || !lba_list || (num_lbas == 0) ||
+ - - + ]
72 : : (num_lbas > SPDK_NVME_OCSSD_MAX_LBAL_ENTRIES)) {
73 : 0 : return -EINVAL;
74 : : }
75 : :
76 : 32 : payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
77 : :
78 : 32 : req = nvme_allocate_request(qpair, &payload, num_lbas * ns->sector_size, num_lbas * ns->md_size,
79 : : cb_fn, cb_arg);
80 [ - + ]: 32 : if (req == NULL) {
81 : 0 : return -ENOMEM;
82 : : }
83 : :
84 : 32 : cmd = &req->cmd;
85 : 32 : cmd->opc = opc;
86 : 32 : 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 [ + + ]: 32 : if (num_lbas == 1) {
94 : 16 : *(uint64_t *)&cmd->cdw10 = *lba_list;
95 : : } else {
96 : 16 : *(uint64_t *)&cmd->cdw10 = spdk_vtophys(lba_list, NULL);
97 : : }
98 : :
99 : 32 : cmd->cdw12 = num_lbas - 1;
100 : 32 : cmd->cdw12 |= io_flags;
101 : :
102 : 32 : return nvme_qpair_submit_request(qpair, req);
103 : : }
104 : :
105 : : int
106 : 8 : 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 : 8 : 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 : 8 : 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 : 8 : 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 : 8 : 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 : 8 : 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 : 8 : 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 : 8 : 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 : 8 : 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 : 8 : uint32_t valid_flags = SPDK_OCSSD_IO_FLAGS_LIMITED_RETRY;
166 : :
167 [ - + ]: 8 : if (io_flags & ~valid_flags) {
168 : 0 : return -EINVAL;
169 : : }
170 : :
171 [ + - + - : 8 : 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 : 8 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
177 [ - + ]: 8 : if (req == NULL) {
178 : 0 : return -ENOMEM;
179 : : }
180 : :
181 : 8 : cmd = &req->cmd;
182 : 8 : cmd->opc = SPDK_OCSSD_OPC_VECTOR_COPY;
183 : 8 : 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 [ + + ]: 8 : if (num_lbas == 1) {
194 : 4 : *(uint64_t *)&cmd->cdw10 = *src_lba_list;
195 : 4 : *(uint64_t *)&cmd->cdw14 = *dst_lba_list;
196 : : } else {
197 : 4 : *(uint64_t *)&cmd->cdw10 = spdk_vtophys(src_lba_list, NULL);
198 : 4 : *(uint64_t *)&cmd->cdw14 = spdk_vtophys(dst_lba_list, NULL);
199 : : }
200 : :
201 : 8 : cmd->cdw12 = num_lbas - 1;
202 : 8 : cmd->cdw12 |= io_flags;
203 : :
204 : 8 : return nvme_qpair_submit_request(qpair, req);
205 : : }
|