1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) 2020, Western Digital Corporation. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Intel Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "spdk/nvme_zns.h" 34 #include "nvme_internal.h" 35 36 const struct spdk_nvme_zns_ns_data * 37 spdk_nvme_zns_ns_get_data(struct spdk_nvme_ns *ns) 38 { 39 return ns->ctrlr->nsdata_zns[ns->id - 1]; 40 } 41 42 uint64_t 43 spdk_nvme_zns_ns_get_zone_size(struct spdk_nvme_ns *ns) 44 { 45 const struct spdk_nvme_zns_ns_data *nsdata_zns = spdk_nvme_zns_ns_get_data(ns); 46 const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns); 47 48 return nsdata_zns->lbafe[nsdata->flbas.format].zsze * spdk_nvme_ns_get_sector_size(ns); 49 } 50 51 uint64_t 52 spdk_nvme_zns_ns_get_num_zones(struct spdk_nvme_ns *ns) 53 { 54 return spdk_nvme_ns_get_size(ns) / spdk_nvme_zns_ns_get_zone_size(ns); 55 } 56 57 const struct spdk_nvme_zns_ctrlr_data * 58 spdk_nvme_zns_ctrlr_get_data(struct spdk_nvme_ctrlr *ctrlr) 59 { 60 return ctrlr->cdata_zns; 61 } 62 63 uint32_t 64 spdk_nvme_zns_ctrlr_get_max_zone_append_size(const struct spdk_nvme_ctrlr *ctrlr) 65 { 66 return ctrlr->max_zone_append_size; 67 } 68 69 static int 70 nvme_zns_zone_mgmt_recv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 71 void *payload, uint32_t payload_size, uint64_t slba, 72 uint8_t zone_recv_action, uint8_t zra_spec_field, bool zra_spec_feats, 73 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 74 { 75 struct nvme_request *req; 76 struct spdk_nvme_cmd *cmd; 77 78 req = nvme_allocate_request_user_copy(qpair, payload, payload_size, cb_fn, cb_arg, false); 79 if (req == NULL) { 80 return -ENOMEM; 81 } 82 83 cmd = &req->cmd; 84 cmd->opc = SPDK_NVME_OPC_ZONE_MGMT_RECV; 85 cmd->nsid = ns->id; 86 87 *(uint64_t *)&cmd->cdw10 = slba; 88 cmd->cdw12 = spdk_nvme_bytes_to_numd(payload_size); 89 cmd->cdw13 = zone_recv_action | zra_spec_field << 8 | zra_spec_feats << 16; 90 91 return nvme_qpair_submit_request(qpair, req); 92 } 93 94 int 95 spdk_nvme_zns_report_zones(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 96 void *payload, uint32_t payload_size, uint64_t slba, 97 enum spdk_nvme_zns_zra_report_opts report_opts, bool partial_report, 98 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 99 { 100 return nvme_zns_zone_mgmt_recv(ns, qpair, payload, payload_size, slba, 101 SPDK_NVME_ZONE_REPORT, report_opts, partial_report, 102 cb_fn, cb_arg); 103 } 104 105 static int 106 nvme_zns_zone_mgmt_send(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 107 uint64_t slba, bool select_all, uint8_t zone_send_action, 108 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 109 { 110 struct nvme_request *req; 111 struct spdk_nvme_cmd *cmd; 112 113 req = nvme_allocate_request_null(qpair, cb_fn, cb_arg); 114 if (req == NULL) { 115 return -ENOMEM; 116 } 117 118 cmd = &req->cmd; 119 cmd->opc = SPDK_NVME_OPC_ZONE_MGMT_SEND; 120 cmd->nsid = ns->id; 121 122 if (!select_all) { 123 *(uint64_t *)&cmd->cdw10 = slba; 124 } 125 126 cmd->cdw13 = zone_send_action | select_all << 8; 127 128 return nvme_qpair_submit_request(qpair, req); 129 } 130 131 int 132 spdk_nvme_zns_close_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, 133 bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) 134 { 135 return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_CLOSE, 136 cb_fn, cb_arg); 137 } 138 139 int 140 spdk_nvme_zns_finish_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, 141 bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) 142 { 143 return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_FINISH, 144 cb_fn, cb_arg); 145 } 146 147 int 148 spdk_nvme_zns_open_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, 149 bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) 150 { 151 return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_OPEN, 152 cb_fn, cb_arg); 153 } 154 155 int 156 spdk_nvme_zns_reset_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, 157 bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) 158 { 159 return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_RESET, 160 cb_fn, cb_arg); 161 } 162 163 int 164 spdk_nvme_zns_offline_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, 165 bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) 166 { 167 return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_OFFLINE, 168 cb_fn, cb_arg); 169 } 170