xref: /spdk/lib/nvme/nvme_zns.c (revision 7bbeb80a31e95ff1865f2ba384823403c1703bcb)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) 2020, Western Digital Corporation. All rights reserved.
3  *   Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
4  */
5 
6 #include "spdk/nvme_zns.h"
7 #include "nvme_internal.h"
8 
9 const struct spdk_nvme_zns_ns_data *
spdk_nvme_zns_ns_get_data(struct spdk_nvme_ns * ns)10 spdk_nvme_zns_ns_get_data(struct spdk_nvme_ns *ns)
11 {
12 	return ns->nsdata_zns;
13 }
14 
15 uint64_t
spdk_nvme_zns_ns_get_zone_size_sectors(struct spdk_nvme_ns * ns)16 spdk_nvme_zns_ns_get_zone_size_sectors(struct spdk_nvme_ns *ns)
17 {
18 	const struct spdk_nvme_zns_ns_data *nsdata_zns = spdk_nvme_zns_ns_get_data(ns);
19 	const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
20 	uint32_t format_index;
21 
22 	format_index = spdk_nvme_ns_get_format_index(nsdata);
23 
24 	return nsdata_zns->lbafe[format_index].zsze;
25 }
26 
27 uint64_t
spdk_nvme_zns_ns_get_zone_size(struct spdk_nvme_ns * ns)28 spdk_nvme_zns_ns_get_zone_size(struct spdk_nvme_ns *ns)
29 {
30 	return spdk_nvme_zns_ns_get_zone_size_sectors(ns) * spdk_nvme_ns_get_sector_size(ns);
31 }
32 
33 uint64_t
spdk_nvme_zns_ns_get_num_zones(struct spdk_nvme_ns * ns)34 spdk_nvme_zns_ns_get_num_zones(struct spdk_nvme_ns *ns)
35 {
36 	return spdk_nvme_ns_get_num_sectors(ns) / spdk_nvme_zns_ns_get_zone_size_sectors(ns);
37 }
38 
39 uint32_t
spdk_nvme_zns_ns_get_max_open_zones(struct spdk_nvme_ns * ns)40 spdk_nvme_zns_ns_get_max_open_zones(struct spdk_nvme_ns *ns)
41 {
42 	const struct spdk_nvme_zns_ns_data *nsdata_zns = spdk_nvme_zns_ns_get_data(ns);
43 
44 	return nsdata_zns->mor + 1;
45 }
46 
47 uint32_t
spdk_nvme_zns_ns_get_max_active_zones(struct spdk_nvme_ns * ns)48 spdk_nvme_zns_ns_get_max_active_zones(struct spdk_nvme_ns *ns)
49 {
50 	const struct spdk_nvme_zns_ns_data *nsdata_zns = spdk_nvme_zns_ns_get_data(ns);
51 
52 	return nsdata_zns->mar + 1;
53 }
54 
55 const struct spdk_nvme_zns_ctrlr_data *
spdk_nvme_zns_ctrlr_get_data(struct spdk_nvme_ctrlr * ctrlr)56 spdk_nvme_zns_ctrlr_get_data(struct spdk_nvme_ctrlr *ctrlr)
57 {
58 	return ctrlr->cdata_zns;
59 }
60 
61 uint32_t
spdk_nvme_zns_ctrlr_get_max_zone_append_size(const struct spdk_nvme_ctrlr * ctrlr)62 spdk_nvme_zns_ctrlr_get_max_zone_append_size(const struct spdk_nvme_ctrlr *ctrlr)
63 {
64 	return ctrlr->max_zone_append_size;
65 }
66 
67 int
spdk_nvme_zns_zone_append(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,void * buffer,uint64_t zslba,uint32_t lba_count,spdk_nvme_cmd_cb cb_fn,void * cb_arg,uint32_t io_flags)68 spdk_nvme_zns_zone_append(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
69 			  void *buffer, uint64_t zslba,
70 			  uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
71 			  uint32_t io_flags)
72 {
73 	return nvme_ns_cmd_zone_append_with_md(ns, qpair, buffer, NULL, zslba, lba_count,
74 					       cb_fn, cb_arg, io_flags, 0, 0);
75 }
76 
77 int
spdk_nvme_zns_zone_append_with_md(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,void * buffer,void * metadata,uint64_t zslba,uint32_t lba_count,spdk_nvme_cmd_cb cb_fn,void * cb_arg,uint32_t io_flags,uint16_t apptag_mask,uint16_t apptag)78 spdk_nvme_zns_zone_append_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
79 				  void *buffer, void *metadata, uint64_t zslba,
80 				  uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
81 				  uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
82 {
83 	return nvme_ns_cmd_zone_append_with_md(ns, qpair, buffer, metadata, zslba, lba_count,
84 					       cb_fn, cb_arg, io_flags, apptag_mask, apptag);
85 }
86 
87 int
spdk_nvme_zns_zone_appendv(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t zslba,uint32_t lba_count,spdk_nvme_cmd_cb cb_fn,void * cb_arg,uint32_t io_flags,spdk_nvme_req_reset_sgl_cb reset_sgl_fn,spdk_nvme_req_next_sge_cb next_sge_fn)88 spdk_nvme_zns_zone_appendv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
89 			   uint64_t zslba, uint32_t lba_count,
90 			   spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
91 			   spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
92 			   spdk_nvme_req_next_sge_cb next_sge_fn)
93 {
94 	return nvme_ns_cmd_zone_appendv_with_md(ns, qpair, zslba, lba_count, cb_fn, cb_arg,
95 						io_flags, reset_sgl_fn, next_sge_fn,
96 						NULL, 0, 0);
97 }
98 
99 int
spdk_nvme_zns_zone_appendv_with_md(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t zslba,uint32_t lba_count,spdk_nvme_cmd_cb cb_fn,void * cb_arg,uint32_t io_flags,spdk_nvme_req_reset_sgl_cb reset_sgl_fn,spdk_nvme_req_next_sge_cb next_sge_fn,void * metadata,uint16_t apptag_mask,uint16_t apptag)100 spdk_nvme_zns_zone_appendv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
101 				   uint64_t zslba, uint32_t lba_count,
102 				   spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
103 				   spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
104 				   spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
105 				   uint16_t apptag_mask, uint16_t apptag)
106 {
107 	return nvme_ns_cmd_zone_appendv_with_md(ns, qpair, zslba, lba_count, cb_fn, cb_arg,
108 						io_flags, reset_sgl_fn, next_sge_fn,
109 						metadata, apptag_mask, apptag);
110 }
111 
112 static int
nvme_zns_zone_mgmt_recv(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,void * payload,uint32_t payload_size,uint64_t slba,uint8_t zone_recv_action,uint8_t zra_spec_field,bool zra_spec_feats,spdk_nvme_cmd_cb cb_fn,void * cb_arg)113 nvme_zns_zone_mgmt_recv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
114 			void *payload, uint32_t payload_size, uint64_t slba,
115 			uint8_t zone_recv_action, uint8_t zra_spec_field, bool zra_spec_feats,
116 			spdk_nvme_cmd_cb cb_fn, void *cb_arg)
117 {
118 	struct nvme_request *req;
119 	struct spdk_nvme_cmd *cmd;
120 
121 	req = nvme_allocate_request_user_copy(qpair, payload, payload_size, cb_fn, cb_arg, false);
122 	if (req == NULL) {
123 		return -ENOMEM;
124 	}
125 
126 	cmd = &req->cmd;
127 	cmd->opc = SPDK_NVME_OPC_ZONE_MGMT_RECV;
128 	cmd->nsid = ns->id;
129 
130 	*(uint64_t *)&cmd->cdw10 = slba;
131 	cmd->cdw12 = spdk_nvme_bytes_to_numd(payload_size);
132 	cmd->cdw13 = zone_recv_action | zra_spec_field << 8 | zra_spec_feats << 16;
133 
134 	return nvme_qpair_submit_request(qpair, req);
135 }
136 
137 int
spdk_nvme_zns_report_zones(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,void * payload,uint32_t payload_size,uint64_t slba,enum spdk_nvme_zns_zra_report_opts report_opts,bool partial_report,spdk_nvme_cmd_cb cb_fn,void * cb_arg)138 spdk_nvme_zns_report_zones(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
139 			   void *payload, uint32_t payload_size, uint64_t slba,
140 			   enum spdk_nvme_zns_zra_report_opts report_opts, bool partial_report,
141 			   spdk_nvme_cmd_cb cb_fn, void *cb_arg)
142 {
143 	return nvme_zns_zone_mgmt_recv(ns, qpair, payload, payload_size, slba,
144 				       SPDK_NVME_ZONE_REPORT, report_opts, partial_report,
145 				       cb_fn, cb_arg);
146 }
147 
148 int
spdk_nvme_zns_ext_report_zones(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,void * payload,uint32_t payload_size,uint64_t slba,enum spdk_nvme_zns_zra_report_opts report_opts,bool partial_report,spdk_nvme_cmd_cb cb_fn,void * cb_arg)149 spdk_nvme_zns_ext_report_zones(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
150 			       void *payload, uint32_t payload_size, uint64_t slba,
151 			       enum spdk_nvme_zns_zra_report_opts report_opts, bool partial_report,
152 			       spdk_nvme_cmd_cb cb_fn, void *cb_arg)
153 {
154 	return nvme_zns_zone_mgmt_recv(ns, qpair, payload, payload_size, slba,
155 				       SPDK_NVME_ZONE_EXTENDED_REPORT, report_opts, partial_report,
156 				       cb_fn, cb_arg);
157 }
158 
159 static int
nvme_zns_zone_mgmt_send(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t slba,bool select_all,uint8_t zone_send_action,spdk_nvme_cmd_cb cb_fn,void * cb_arg)160 nvme_zns_zone_mgmt_send(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
161 			uint64_t slba, bool select_all, uint8_t zone_send_action,
162 			spdk_nvme_cmd_cb cb_fn, void *cb_arg)
163 {
164 	struct nvme_request *req;
165 	struct spdk_nvme_cmd *cmd;
166 
167 	req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
168 	if (req == NULL) {
169 		return -ENOMEM;
170 	}
171 
172 	cmd = &req->cmd;
173 	cmd->opc = SPDK_NVME_OPC_ZONE_MGMT_SEND;
174 	cmd->nsid = ns->id;
175 
176 	if (!select_all) {
177 		*(uint64_t *)&cmd->cdw10 = slba;
178 	}
179 
180 	cmd->cdw13 = zone_send_action | select_all << 8;
181 
182 	return nvme_qpair_submit_request(qpair, req);
183 }
184 
185 int
spdk_nvme_zns_close_zone(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t slba,bool select_all,spdk_nvme_cmd_cb cb_fn,void * cb_arg)186 spdk_nvme_zns_close_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
187 			 bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
188 {
189 	return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_CLOSE,
190 				       cb_fn, cb_arg);
191 }
192 
193 int
spdk_nvme_zns_finish_zone(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t slba,bool select_all,spdk_nvme_cmd_cb cb_fn,void * cb_arg)194 spdk_nvme_zns_finish_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
195 			  bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
196 {
197 	return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_FINISH,
198 				       cb_fn, cb_arg);
199 }
200 
201 int
spdk_nvme_zns_open_zone(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t slba,bool select_all,spdk_nvme_cmd_cb cb_fn,void * cb_arg)202 spdk_nvme_zns_open_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
203 			bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
204 {
205 	return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_OPEN,
206 				       cb_fn, cb_arg);
207 }
208 
209 int
spdk_nvme_zns_reset_zone(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t slba,bool select_all,spdk_nvme_cmd_cb cb_fn,void * cb_arg)210 spdk_nvme_zns_reset_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
211 			 bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
212 {
213 	return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_RESET,
214 				       cb_fn, cb_arg);
215 }
216 
217 int
spdk_nvme_zns_offline_zone(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t slba,bool select_all,spdk_nvme_cmd_cb cb_fn,void * cb_arg)218 spdk_nvme_zns_offline_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
219 			   bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
220 {
221 	return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_OFFLINE,
222 				       cb_fn, cb_arg);
223 }
224 
225 int
spdk_nvme_zns_set_zone_desc_ext(struct spdk_nvme_ns * ns,struct spdk_nvme_qpair * qpair,uint64_t slba,void * buffer,uint32_t payload_size,spdk_nvme_cmd_cb cb_fn,void * cb_arg)226 spdk_nvme_zns_set_zone_desc_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
227 				uint64_t slba, void *buffer, uint32_t payload_size,
228 				spdk_nvme_cmd_cb cb_fn, void *cb_arg)
229 {
230 	struct nvme_request *req;
231 	struct spdk_nvme_cmd *cmd;
232 
233 	if (payload_size == 0) {
234 		return -EINVAL;
235 	}
236 
237 	if (buffer == NULL) {
238 		return -EINVAL;
239 	}
240 
241 	req = nvme_allocate_request_user_copy(qpair, buffer, payload_size, cb_fn, cb_arg, true);
242 	if (req == NULL) {
243 		return -ENOMEM;
244 	}
245 
246 	cmd = &req->cmd;
247 	cmd->opc = SPDK_NVME_OPC_ZONE_MGMT_SEND;
248 	cmd->nsid = ns->id;
249 
250 	*(uint64_t *)&cmd->cdw10 = slba;
251 
252 	cmd->cdw13 = SPDK_NVME_ZONE_SET_ZDE;
253 
254 	return nvme_qpair_submit_request(qpair, req);
255 }
256